| From 4b836a1426cb0f1ef2a6e211d7e553221594f8fc Mon Sep 17 00:00:00 2001 |
| From: Jann Horn <jannh@google.com> |
| Date: Mon, 27 Jul 2020 14:04:24 +0200 |
| Subject: binder: Prevent context manager from incrementing ref 0 |
| |
| From: Jann Horn <jannh@google.com> |
| |
| commit 4b836a1426cb0f1ef2a6e211d7e553221594f8fc upstream. |
| |
| 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: stable@vger.kernel.org |
| Fixes: 457b9a6f09f0 ("Staging: android: add binder driver") |
| Acked-by: Todd Kjos <tkjos@google.com> |
| Signed-off-by: Jann Horn <jannh@google.com> |
| Reviewed-by: Martijn Coenen <maco@android.com> |
| Link: https://lore.kernel.org/r/20200727120424.1627555-1-jannh@google.com |
| [manual backport: remove fine-grained locking and error reporting that |
| don't exist in <=4.9] |
| Signed-off-by: Jann Horn <jannh@google.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| drivers/android/binder.c | 9 +++++++++ |
| 1 file changed, 9 insertions(+) |
| |
| --- a/drivers/android/binder.c |
| +++ b/drivers/android/binder.c |
| @@ -1427,6 +1427,10 @@ static void binder_transaction(struct bi |
| return_error = BR_DEAD_REPLY; |
| goto err_dead_binder; |
| } |
| + if (WARN_ON(proc == target_proc)) { |
| + return_error = BR_FAILED_REPLY; |
| + goto err_invalid_target_handle; |
| + } |
| if (security_binder_transaction(proc->tsk, |
| target_proc->tsk) < 0) { |
| return_error = BR_FAILED_REPLY; |
| @@ -1830,6 +1834,11 @@ static int binder_thread_write(struct bi |
| ptr += sizeof(uint32_t); |
| if (target == 0 && binder_context_mgr_node && |
| (cmd == BC_INCREFS || cmd == BC_ACQUIRE)) { |
| + if (binder_context_mgr_node->proc == proc) { |
| + binder_user_error("%d:%d context manager tried to acquire desc 0\n", |
| + proc->pid, thread->pid); |
| + return -EINVAL; |
| + } |
| ref = binder_get_ref_for_node(proc, |
| binder_context_mgr_node); |
| if (ref->desc != target) { |