Skip to content

Commit 4b836a1

Browse files
thejhgregkh
authored andcommitted
binder: Prevent context manager from incrementing ref 0
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: 457b9a6 ("Staging: android: add binder driver") Acked-by: Todd Kjos <[email protected]> Signed-off-by: Jann Horn <[email protected]> Reviewed-by: Martijn Coenen <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 37b8b73 commit 4b836a1

File tree

1 file changed

+14
-1
lines changed

1 file changed

+14
-1
lines changed

drivers/android/binder.c

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2982,6 +2982,12 @@ static void binder_transaction(struct binder_proc *proc,
29822982
goto err_dead_binder;
29832983
}
29842984
e->to_node = target_node->debug_id;
2985+
if (WARN_ON(proc == target_proc)) {
2986+
return_error = BR_FAILED_REPLY;
2987+
return_error_param = -EINVAL;
2988+
return_error_line = __LINE__;
2989+
goto err_invalid_target_handle;
2990+
}
29852991
if (security_binder_transaction(proc->tsk,
29862992
target_proc->tsk) < 0) {
29872993
return_error = BR_FAILED_REPLY;
@@ -3635,10 +3641,17 @@ static int binder_thread_write(struct binder_proc *proc,
36353641
struct binder_node *ctx_mgr_node;
36363642
mutex_lock(&context->context_mgr_node_lock);
36373643
ctx_mgr_node = context->binder_context_mgr_node;
3638-
if (ctx_mgr_node)
3644+
if (ctx_mgr_node) {
3645+
if (ctx_mgr_node->proc == proc) {
3646+
binder_user_error("%d:%d context manager tried to acquire desc 0\n",
3647+
proc->pid, thread->pid);
3648+
mutex_unlock(&context->context_mgr_node_lock);
3649+
return -EINVAL;
3650+
}
36393651
ret = binder_inc_ref_for_node(
36403652
proc, ctx_mgr_node,
36413653
strong, NULL, &rdata);
3654+
}
36423655
mutex_unlock(&context->context_mgr_node_lock);
36433656
}
36443657
if (ret)

0 commit comments

Comments
 (0)