Binder is designed such that a binder_proc never has references to
itself. If this rule is violated, memory corruption can occur when a
process sends a transaction to itself; see e.g.
<https://syzkaller.appspot.com/bug?extid=09e05aba06723a94d43d>.

There is a remaining edgecase through which such a transaction-to-self
can still occur from the context of a task with BINDER_SET_CONTEXT_MGR
access:

 - task A opens /dev/binder twice, creating binder_proc instances P1
   and P2
 - P1 becomes context manager
 - P2 calls ACQUIRE on the magic handle 0, allocating index 0 in its
   handle table
 - P1 dies (by closing the /dev/binder fd and waiting a bit)
 - P2 becomes context manager
 - P2 calls ACQUIRE on the magic handle 0, allocating index 1 in its
   handle table
   [this triggers a warning: "binder: 1974:1974 tried to acquire
   reference to desc 0, got 1 instead"]
 - task B opens /dev/binder once, creating binder_proc instance P3
 - P3 calls P2 (via magic handle 0) with (void*)1 as argument (two-way
   transaction)
 - P2 receives the handle and uses it to call P3 (two-way transaction)
 - P3 calls P2 (via magic handle 0) (two-way transaction)
 - P2 calls P2 (via handle 1) (two-way transaction)

And then, if P2 does *NOT* accept the incoming transaction work, but
instead closes the binder fd, we get a crash.

Solve it by preventing the context manager from using ACQUIRE on ref 0.
There shouldn't be any legitimate reason for the context manager to do
that.

Additionally, print a warning if someone manages to find another way to
trigger a transaction-to-self bug in the future.

Cc: [email protected]
Fixes: 457b9a6f09f0 ("Staging: android: add binder driver")
Acked-by: Todd Kjos <[email protected]>
Signed-off-by: Jann Horn <[email protected]>
---
fixed that broken binder_user_error() from the first version...
I sent v1 while I had a dirty tree containing the missing fix. whoops.

 drivers/android/binder.c | 15 ++++++++++++++-
 1 file changed, 14 insertions(+), 1 deletion(-)

diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index f50c5f182bb5..5b310eea9e52 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -2982,6 +2982,12 @@ static void binder_transaction(struct binder_proc *proc,
                        goto err_dead_binder;
                }
                e->to_node = target_node->debug_id;
+               if (WARN_ON(proc == target_proc)) {
+                       return_error = BR_FAILED_REPLY;
+                       return_error_param = -EINVAL;
+                       return_error_line = __LINE__;
+                       goto err_invalid_target_handle;
+               }
                if (security_binder_transaction(proc->tsk,
                                                target_proc->tsk) < 0) {
                        return_error = BR_FAILED_REPLY;
@@ -3635,10 +3641,17 @@ static int binder_thread_write(struct binder_proc *proc,
                                struct binder_node *ctx_mgr_node;
                                mutex_lock(&context->context_mgr_node_lock);
                                ctx_mgr_node = context->binder_context_mgr_node;
-                               if (ctx_mgr_node)
+                               if (ctx_mgr_node) {
+                                       if (ctx_mgr_node->proc == proc) {
+                                               binder_user_error("%d:%d 
context manager tried to acquire desc 0\n",
+                                                                 proc->pid, 
thread->pid);
+                                               
mutex_unlock(&context->context_mgr_node_lock);
+                                               return -EINVAL;
+                                       }
                                        ret = binder_inc_ref_for_node(
                                                        proc, ctx_mgr_node,
                                                        strong, NULL, &rdata);
+                               }
                                mutex_unlock(&context->context_mgr_node_lock);
                        }
                        if (ret)

base-commit: 2a89b99f580371b86ae9bafd6cbeccd3bfab524a
-- 
2.28.0.rc0.142.g3c755180ce-goog

Reply via email to