[PATCH 4/4] rust_binder: reject duplicate BC_ENTER_LOOPER in looper_enter
From: Yunseong Kim
Date: Wed Jun 03 2026 - 14:03:18 EST
The Rust binder's looper_enter() unconditionally sets LOOPER_ENTERED
without checking whether the flag is already set. A userspace process
can send BC_ENTER_LOOPER multiple times, corrupting the thread pool
state: the kernel believes more looper threads are available than
actually exist, leading to incorrect thread pool management.
Add a guard: if LOOPER_ENTERED is already set, mark the thread as
LOOPER_INVALID and return early without re-entering. This matches the
fix applied to the C binder.
kcov-dataflow tracking (before):
ENTRY ThreadInner::looper_enter()
self.looper_flags = 0x00
self.looper_flags |= LOOPER_ENTERED ← first call: 0x02
RET looper_enter()
ENTRY ThreadInner::looper_enter()
self.looper_flags = 0x02
self.looper_flags |= LOOPER_ENTERED ← duplicate: still 0x02, no error
RET looper_enter()
kcov-dataflow tracking (after):
ENTRY ThreadInner::looper_enter()
self.looper_flags = 0x00
self.looper_flags |= LOOPER_ENTERED ← first call: 0x02
RET looper_enter()
ENTRY ThreadInner::looper_enter()
self.looper_flags = 0x02
LOOPER_ENTERED already set → |= LOOPER_INVALID, return
RET looper_enter() ← early exit, thread invalidated
Reproduction:
# CONFIG_ANDROID_BINDER_IPC_RUST=y
$ ./To-Ulimit-and-Beyond
First BC_ENTER_LOOPER: ret=0 (OK)
Second BC_ENTER_LOOPER: ret=0 (thread now INVALID internally)
Link: https://lore.kernel.org/all/20260603-kcov-dataflow-next-20260603-v2-0-fee0939de2c4@xxxxxxxx/
Signed-off-by: Yunseong Kim <yunseong.kim@xxxxxxxx>
---
drivers/android/binder/thread.rs | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/drivers/android/binder/thread.rs b/drivers/android/binder/thread.rs
index 97d5f31e8fe3..1d114fa2b4e6 100644
--- a/drivers/android/binder/thread.rs
+++ b/drivers/android/binder/thread.rs
@@ -373,6 +373,10 @@ fn pop_transaction_replied(&mut self, transaction: &DArc<Transaction>) -> bool {
}
fn looper_enter(&mut self) {
+ if self.looper_flags & LOOPER_ENTERED != 0 {
+ self.looper_flags |= LOOPER_INVALID;
+ return;
+ }
self.looper_flags |= LOOPER_ENTERED;
if self.looper_flags & LOOPER_REGISTERED != 0 {
self.looper_flags |= LOOPER_INVALID;
--
2.43.0