summaryrefslogtreecommitdiff
path: root/drivers/android
diff options
context:
space:
mode:
authorTodd Kjos <tkjos@android.com>2017-06-29 12:01:48 -0700
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2017-07-17 14:47:29 +0200
commitccae6f676001d00efd1a4626773d1577e53188f7 (patch)
tree0770cf708b7e91b70c29c8b6e72f0546dc6ed989 /drivers/android
parent26b47d8a16a72878228aeaed573786825b7ca204 (diff)
binder: avoid race conditions when enqueuing txn
Currently, the transaction complete work item is queued after the transaction. This means that it is possible for the transaction to be handled and a reply to be enqueued in the current thread before the transaction complete is enqueued, which violates the protocol with userspace who may not expect the transaction complete. Fixed by always enqueing the transaction complete first. Also, once the transaction is enqueued, it is unsafe to access since it might be freed. Currently, t->flags is accessed to determine whether a sync wake is needed. Changed to access tr->flags instead. Signed-off-by: Todd Kjos <tkjos@google.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/android')
-rw-r--r--drivers/android/binder.c7
1 files changed, 4 insertions, 3 deletions
diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index f17d1dfa5b02..71faf548482d 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -1799,6 +1799,9 @@ static void binder_transaction(struct binder_proc *proc,
goto err_bad_object_type;
}
}
+ tcomplete->type = BINDER_WORK_TRANSACTION_COMPLETE;
+ list_add_tail(&tcomplete->entry, &thread->todo);
+
if (reply) {
BUG_ON(t->buffer->async_transaction != 0);
binder_pop_transaction(target_thread, in_reply_to);
@@ -1818,10 +1821,8 @@ static void binder_transaction(struct binder_proc *proc,
}
t->work.type = BINDER_WORK_TRANSACTION;
list_add_tail(&t->work.entry, target_list);
- tcomplete->type = BINDER_WORK_TRANSACTION_COMPLETE;
- list_add_tail(&tcomplete->entry, &thread->todo);
if (target_wait) {
- if (reply || !(t->flags & TF_ONE_WAY))
+ if (reply || !(tr->flags & TF_ONE_WAY))
wake_up_interruptible_sync(target_wait);
else
wake_up_interruptible(target_wait);