Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

binder: fix possible UAF when freeing buffer

There is a race between the binder driver cleaning
up a completed transaction via binder_free_transaction()
and a user calling binder_ioctl(BC_FREE_BUFFER) to
release a buffer. It doesn't matter which is first but
they need to be protected against running concurrently
which can result in a UAF.

Signed-off-by: Todd Kjos <tkjos@google.com>
Cc: stable <stable@vger.kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Todd Kjos and committed by
Greg Kroah-Hartman
a370003c b7108486

+14 -2
+14 -2
drivers/android/binder.c
··· 1941 1941 1942 1942 static void binder_free_transaction(struct binder_transaction *t) 1943 1943 { 1944 - if (t->buffer) 1945 - t->buffer->transaction = NULL; 1944 + struct binder_proc *target_proc = t->to_proc; 1945 + 1946 + if (target_proc) { 1947 + binder_inner_proc_lock(target_proc); 1948 + if (t->buffer) 1949 + t->buffer->transaction = NULL; 1950 + binder_inner_proc_unlock(target_proc); 1951 + } 1952 + /* 1953 + * If the transaction has no target_proc, then 1954 + * t->buffer->transaction has already been cleared. 1955 + */ 1946 1956 binder_free_txn_fixups(t); 1947 1957 kfree(t); 1948 1958 binder_stats_deleted(BINDER_STAT_TRANSACTION); ··· 3561 3551 static void 3562 3552 binder_free_buf(struct binder_proc *proc, struct binder_buffer *buffer) 3563 3553 { 3554 + binder_inner_proc_lock(proc); 3564 3555 if (buffer->transaction) { 3565 3556 buffer->transaction->buffer = NULL; 3566 3557 buffer->transaction = NULL; 3567 3558 } 3559 + binder_inner_proc_unlock(proc); 3568 3560 if (buffer->async_transaction && buffer->target_node) { 3569 3561 struct binder_node *buf_node; 3570 3562 struct binder_work *w;