Linux Kernel Patches Rust Binder Flaw with Proper Lock Handling Fix
CVE-2026-23400 hit rust_binder with a deadlock Rust's borrow checker couldn't prevent, exposing the limits of memory safety in real kernel code.

Rust's borrow checker is famously thorough about memory. It will not let you use freed memory, race on unprotected data, or alias a mutable reference. What it cannot do is read your mind about which locks you meant to hold when you called a function. CVE-2026-23400 makes that gap concrete.
The flaw lives in rust_binder, Google's Rust reimplementation of Android's Binder IPC driver, which merged into Linux 6.18 carrying with it the weight of every Android app's inter-process communication. When a remote process dies and sends a BR_DEAD_BINDER message, the local process issues a BC_CLEAR_DEATH_NOTIFICATION command followed by BC_DEAD_BINDER_DONE. The kernel responds with a BR_CLEAR_DEATH_NOTIFICATION_DONE reply routed through push_work_if_looper(). That sequence works fine when the current thread is a looper. It deadlocks when it is not.
The root cause is a lock-ordering mistake buried inside dead_binder_done(). That function held the proc lock while calling set_notification_done(), which in turn called push_work_if_looper(). Normally, push_work_if_looper() acquires the thread lock, which is legal to take while already holding the proc lock. But when the calling thread is not a looper, the function falls back to delivering the reply through the process work queue, a path that tries to take the proc lock. Since the proc lock was already held, the result was a classic recursive deadlock. The description of the fix is unsparing: "It was not intentional that it was held during that function to begin with."
That sentence is worth sitting with. It means the locking design was muddled from the start, an unintentional holdover that compiled cleanly, passed the type system, and shipped into 6.18. The fix was to release the proc lock before entering set_notification_done(), eliminating the contested path entirely.
This is the category of bug that makes Rust kernel advocates nervous for exactly the right reasons. The previous rust_binder CVE, CVE-2025-68260, involved an unsafe block with intrusive list manipulation that outran the borrow checker's reach, earning the distinction of the first Rust kernel CVE from stable maintainer Greg Kroah-Hartman. CVE-2026-23400 is different: it is a logic bug in otherwise safe code, in locking discipline, in the class of concurrency reasoning that no type system fully automates. Unsafe blocks and FFI boundaries get most of the security attention in Rust kernel discussions, but lock-ordering mistakes require human-specified invariants that the compiler cannot enforce. Both CVEs landing in the same subsystem within months of its upstream merge is a signal about where Rust kernel code still needs the most scrutiny.

For anyone running kernel 6.18, the patch traces to three fix commits originating from eafedbc7c050c44744fbdf80bdf3315e860b7513 and landing before dd109e3442817bc03ad1f3ffd541092f8c428141, 3be72099067d2cd4a0e089696f19780f75b2b88a, and 2e303f0febb65a434040774b793ba8356698802b across stable trees. Semver records mark 6.18.19 and 6.19.9 as unaffected, and 7.0-rc4 carries the fix. Kernels older than 6.18 never ran rust_binder and are not in scope.
Reading the patch itself is instructive for hobbyists getting into kernel Rust security diffs. The core change removed the proc lock hold from around the set_notification_done() call site inside dead_binder_done(). In a Rust kernel diff, look for lock guard variables going out of scope: a drop() call or a closing brace that ends a guard's lifetime signals when a lock is released. If a guard persists across a call into another function, and that function can recursively acquire the same lock, you have the skeleton of CVE-2026-23400. The fix narrows the critical section so the guard expires before set_notification_done() is entered. That pattern of "guard survives longer than the reviewer expected" is one of the most common locking mistakes in Rust kernel code precisely because the type system enforces that the lock is eventually dropped, but says nothing about when.
NVD received the CVE from kernel.org on March 29, 2026, and currently marks it awaiting full analysis. Given that rust_binder underpins Android's IPC stack on any device opting into the Rust implementation, confirming your stable tree has landed the relevant point release is the practical first step. The broader takeaway is that Rust subsystems in the kernel are maturing through the same friction every new subsystem goes through: the memory safety wins are real, but locking correctness remains a discipline the language can only partially audit.
Know something we missed? Have a correction or additional information?
Submit a Tip

