[PATCH] binder: free transaction buffer in binder_release_work() on BINDER_THREAD_EXIT
From: Hui Peng
Date: Sat Sep 19 2026 - 17:43:01 EST
When a binder thread exits via `BINDER_THREAD_EXIT` (`binder_ioctl()` ->
`binder_thread_release()`) while the process itself is still alive
(`!proc->is_dead`), `binder_release_work(proc, &thread->todo)` drains
pending `BINDER_WORK_TRANSACTION` items queued specifically on
`thread->todo`.
For each `BINDER_WORK_TRANSACTION`, `binder_release_work()` calls
`binder_cleanup_transaction(t, "process died.", BR_DEAD_REPLY)` without
clearing `t->buffer->transaction` or calling `binder_free_buf(proc,
NULL, buffer, true)`. Because `allow_user_free` is still `0` (the
transaction was never read by userspace) and `proc` is still alive
(`binder_deferred_release()` will not run until the process exits),
`t->buffer` and all translated `binder_node`/`binder_ref` references
inside `t->buffer` are leaked in the active binder mmap pool, and
`t->buffer->transaction` is left as a dangling pointer to the freed `t`!
Clear `buffer->transaction = NULL` before
`binder_cleanup_transaction()`, and when `!proc->is_dead && buffer`,
free `buffer` via `binder_free_buf(proc, NULL, buffer, true)`.
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Assisted-by: LLM
Signed-off-by: Hui Peng <benquike@xxxxxxxxx>
---
drivers/android/binder.c | 18 +++++++++++++++++-
1 file changed, 17 insertions(+), 1 deletion(-)
diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index 8f2ef1bd539f..1c7218e599a1 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -5206,11 +5224,17 @@ static void binder_release_work(struct binder_proc *proc,
switch (wtype) {
case BINDER_WORK_TRANSACTION: {
struct binder_transaction *t;
+ struct binder_buffer *buffer;
t = container_of(w, struct binder_transaction, work);
+ buffer = t->buffer;
+ if (buffer)
+ buffer->transaction = NULL;
binder_cleanup_transaction(t, "process died.",
BR_DEAD_REPLY);
+ if (!proc->is_dead && buffer)
+ binder_free_buf(proc, NULL, buffer, true);
} break;
case BINDER_WORK_RETURN_ERROR: {
struct binder_error *e = container_of(