Skip to content

Commit b6f477c

Browse files
Martijn Coenenpundiramit
authored andcommitted
ANDROID: binder: fix transaction leak.
If a call to put_user() fails, we failed to properly free a transaction and send a failed reply (if necessary). Bug: 63117588 Test: binderLibTest Change-Id: Ia98db8cd82ce354a4cdc8811c969988d585c7e31 Signed-off-by: Martijn Coenen <maco@android.com>
1 parent 823e6ab commit b6f477c

1 file changed

Lines changed: 31 additions & 9 deletions

File tree

drivers/android/binder.c

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2106,6 +2106,26 @@ static void binder_send_failed_reply(struct binder_transaction *t,
21062106
}
21072107
}
21082108

2109+
/**
2110+
* binder_cleanup_transaction() - cleans up undelivered transaction
2111+
* @t: transaction that needs to be cleaned up
2112+
* @reason: reason the transaction wasn't delivered
2113+
* @error_code: error to return to caller (if synchronous call)
2114+
*/
2115+
static void binder_cleanup_transaction(struct binder_transaction *t,
2116+
const char *reason,
2117+
uint32_t error_code)
2118+
{
2119+
if (t->buffer->target_node && !(t->flags & TF_ONE_WAY)) {
2120+
binder_send_failed_reply(t, error_code);
2121+
} else {
2122+
binder_debug(BINDER_DEBUG_DEAD_TRANSACTION,
2123+
"undelivered transaction %d, %s\n",
2124+
t->debug_id, reason);
2125+
binder_free_transaction(t);
2126+
}
2127+
}
2128+
21092129
/**
21102130
* binder_validate_object() - checks for a valid metadata object in a buffer.
21112131
* @buffer: binder_buffer that we're parsing.
@@ -4188,12 +4208,20 @@ static int binder_thread_read(struct binder_proc *proc,
41884208
if (put_user(cmd, (uint32_t __user *)ptr)) {
41894209
if (t_from)
41904210
binder_thread_dec_tmpref(t_from);
4211+
4212+
binder_cleanup_transaction(t, "put_user failed",
4213+
BR_FAILED_REPLY);
4214+
41914215
return -EFAULT;
41924216
}
41934217
ptr += sizeof(uint32_t);
41944218
if (copy_to_user(ptr, &tr, sizeof(tr))) {
41954219
if (t_from)
41964220
binder_thread_dec_tmpref(t_from);
4221+
4222+
binder_cleanup_transaction(t, "copy_to_user failed",
4223+
BR_FAILED_REPLY);
4224+
41974225
return -EFAULT;
41984226
}
41994227
ptr += sizeof(tr);
@@ -4263,15 +4291,9 @@ static void binder_release_work(struct binder_proc *proc,
42634291
struct binder_transaction *t;
42644292

42654293
t = container_of(w, struct binder_transaction, work);
4266-
if (t->buffer->target_node &&
4267-
!(t->flags & TF_ONE_WAY)) {
4268-
binder_send_failed_reply(t, BR_DEAD_REPLY);
4269-
} else {
4270-
binder_debug(BINDER_DEBUG_DEAD_TRANSACTION,
4271-
"undelivered transaction %d\n",
4272-
t->debug_id);
4273-
binder_free_transaction(t);
4274-
}
4294+
4295+
binder_cleanup_transaction(t, "process died.",
4296+
BR_DEAD_REPLY);
42754297
} break;
42764298
case BINDER_WORK_RETURN_ERROR: {
42774299
struct binder_error *e = container_of(

0 commit comments

Comments
 (0)