Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754286AbcKYJJq (ORCPT ); Fri, 25 Nov 2016 04:09:46 -0500 Received: from mx2.suse.de ([195.135.220.15]:45213 "EHLO mx2.suse.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751494AbcKYIaw (ORCPT ); Fri, 25 Nov 2016 03:30:52 -0500 X-Amavis-Alert: BAD HEADER SECTION, Duplicate header field: "References" From: Jiri Slaby To: stable@vger.kernel.org Cc: linux-kernel@vger.kernel.org, =?UTF-8?q?Arve=20Hj=C3=B8nnev=C3=A5g?= , Martijn Coenen , Jiri Slaby Subject: [PATCH 3.12 014/127] ANDROID: binder: Add strong ref checks Date: Fri, 25 Nov 2016 09:28:47 +0100 Message-Id: <4d0ee2bb0e06f8abe29f85fb5075eaf955e2e886.1480062521.git.jslaby@suse.cz> X-Mailer: git-send-email 2.10.2 In-Reply-To: References: In-Reply-To: References: MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 3684 Lines: 106 From: Arve Hjønnevåg 3.12-stable review patch. If anyone has any objections, please let me know. =============== commit 0a3ffab93fe52530602fe47cd74802cffdb19c05 upstream. Prevent using a binder_ref with only weak references where a strong reference is required. Signed-off-by: Arve Hjønnevåg Signed-off-by: Martijn Coenen Signed-off-by: Jiri Slaby --- drivers/staging/android/binder.c | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/drivers/staging/android/binder.c b/drivers/staging/android/binder.c index 69fd236345cb..8a436dae9b77 100644 --- a/drivers/staging/android/binder.c +++ b/drivers/staging/android/binder.c @@ -994,7 +994,7 @@ static int binder_dec_node(struct binder_node *node, int strong, int internal) static struct binder_ref *binder_get_ref(struct binder_proc *proc, - uint32_t desc) + u32 desc, bool need_strong_ref) { struct rb_node *n = proc->refs_by_desc.rb_node; struct binder_ref *ref; @@ -1002,12 +1002,16 @@ static struct binder_ref *binder_get_ref(struct binder_proc *proc, while (n) { ref = rb_entry(n, struct binder_ref, rb_node_desc); - if (desc < ref->desc) + if (desc < ref->desc) { n = n->rb_left; - else if (desc > ref->desc) + } else if (desc > ref->desc) { n = n->rb_right; - else + } else if (need_strong_ref && !ref->strong) { + binder_user_error("tried to use weak ref as strong ref\n"); + return NULL; + } else { return ref; + } } return NULL; } @@ -1270,7 +1274,10 @@ static void binder_transaction_buffer_release(struct binder_proc *proc, } break; case BINDER_TYPE_HANDLE: case BINDER_TYPE_WEAK_HANDLE: { - struct binder_ref *ref = binder_get_ref(proc, fp->handle); + struct binder_ref *ref; + + ref = binder_get_ref(proc, fp->handle, + fp->type == BINDER_TYPE_HANDLE); if (ref == NULL) { pr_err("transaction release %d bad handle %d\n", debug_id, fp->handle); @@ -1362,7 +1369,7 @@ static void binder_transaction(struct binder_proc *proc, } else { if (tr->target.handle) { struct binder_ref *ref; - ref = binder_get_ref(proc, tr->target.handle); + ref = binder_get_ref(proc, tr->target.handle, true); if (ref == NULL) { binder_user_error("%d:%d got transaction to invalid handle\n", proc->pid, thread->pid); @@ -1546,7 +1553,10 @@ static void binder_transaction(struct binder_proc *proc, } break; case BINDER_TYPE_HANDLE: case BINDER_TYPE_WEAK_HANDLE: { - struct binder_ref *ref = binder_get_ref(proc, fp->handle); + struct binder_ref *ref; + + ref = binder_get_ref(proc, fp->handle, + fp->type == BINDER_TYPE_HANDLE); if (ref == NULL) { binder_user_error("%d:%d got transaction with invalid handle, %d\n", proc->pid, @@ -1739,7 +1749,9 @@ int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread, ref->desc); } } else - ref = binder_get_ref(proc, target); + ref = binder_get_ref(proc, target, + cmd == BC_ACQUIRE || + cmd == BC_RELEASE); if (ref == NULL) { binder_user_error("%d:%d refcount change on invalid ref %d\n", proc->pid, thread->pid, target); @@ -1934,7 +1946,7 @@ int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread, if (get_user(cookie, (void __user * __user *)ptr)) return -EFAULT; ptr += sizeof(void *); - ref = binder_get_ref(proc, target); + ref = binder_get_ref(proc, target, false); if (ref == NULL) { binder_user_error("%d:%d %s invalid ref %d\n", proc->pid, thread->pid, -- 2.10.2