binder: use atomic for transaction_log index

The log->next index for the transaction log was
not protected when incremented. This led to a
case where log->next++ resulted in an index
larger than ARRAY_SIZE(log->entry) and eventually
a bad access to memory.

Fixed by making the log index an atomic64 and
converting to an array by using "% ARRAY_SIZE(log->entry)"

Bug: 62038227
Test: tested manually
Change-Id: I1bb1c1a332a6ac458a626f5bedd05022b56b91f2
Signed-off-by: Todd Kjos <tkjos@google.com>
This commit is contained in:
Todd Kjos
2017-05-24 13:33:28 -07:00
committed by Pat Tjin
parent 17093f4ed7
commit a9bd05a7d2

View File

@@ -218,8 +218,7 @@ struct binder_transaction_log_entry {
const char *context_name;
};
struct binder_transaction_log {
int next;
int full;
atomic64_t cur;
struct binder_transaction_log_entry entry[32];
};
static struct binder_transaction_log binder_transaction_log;
@@ -229,14 +228,10 @@ static struct binder_transaction_log_entry *binder_transaction_log_add(
struct binder_transaction_log *log)
{
struct binder_transaction_log_entry *e;
uint64_t cur = atomic64_inc_return(&log->cur);
e = &log->entry[log->next];
e = &log->entry[cur % ARRAY_SIZE(log->entry)];
memset(e, 0, sizeof(*e));
log->next++;
if (log->next == ARRAY_SIZE(log->entry)) {
log->next = 0;
log->full = 1;
}
return e;
}
@@ -5069,14 +5064,14 @@ static void print_binder_transaction_log_entry(struct seq_file *m,
static int binder_transaction_log_show(struct seq_file *m, void *unused)
{
struct binder_transaction_log *log = m->private;
uint64_t count = atomic64_read(&log->cur);
uint64_t cur = count % ARRAY_SIZE(log->entry);
int i;
if (log->full) {
for (i = log->next; i < ARRAY_SIZE(log->entry); i++)
print_binder_transaction_log_entry(m, &log->entry[i]);
for (i = 0; i < ARRAY_SIZE(log->entry) && i < count; i++) {
uint64_t index = cur++ % ARRAY_SIZE(log->entry);
print_binder_transaction_log_entry(m, &log->entry[index]);
}
for (i = 0; i < log->next; i++)
print_binder_transaction_log_entry(m, &log->entry[i]);
return 0;
}
@@ -5131,6 +5126,8 @@ static int __init binder_init(void)
int ret, i;
atomic_set(&binder_seq_count, 0);
atomic64_set(&binder_transaction_log.cur, ~0ULL);
atomic64_set(&binder_transaction_log_failed.cur, ~0ULL);
binder_deferred_workqueue = create_singlethread_workqueue("binder");
if (!binder_deferred_workqueue)