remove_waiter() in kernel/locking/rtmutex.c is used by the slowlock paths but also for proxy-lock rollback in rt_mutex_start_proxy_lock() when invoked from futex_requeue().
In the proxy-lock case waiter::task is not current, but remove_waiter() incorrectly operates on current. This causes three problems:
- The rbtree dequeue happens without
waiter::task::pi_lockbeing held. - The waiter task's
pi_blocked_onis not cleared, leaving a dangling pointer primed for use-after-free. rt_mutex_adjust_prio_chain()operates on the wrong task.
CWE-416 (Use After Free). CVSS 3.1: 7.8 HIGH (Local, Low complexity, Low privileges required).
Affected: Linux 2.6.39 through 6.18.x; patched in 6.1.175, 6.6.140, 6.12.86, 6.18.27, 7.0.4.
Prerequisites: Android NDK 27, CMake ≥ 3.22, adb.
cmake -B build -G Ninja
cmake --build build
adb push build/trigger /data/local/tmp/trigger
adb shell chmod +x /data/local/tmp/trigger
adb shell /data/local/tmp/triggerExpected output on a vulnerable device ends with a kernel panic:
Unable to handle kernel write to read-only memory
Reported by:
- Yuan Tan
- Yifan Wu
- Juefei Pu
- Xin Liu
Fix authored by: Keenan Dong
Fix committed by: Thomas Gleixner
Commit: 3bfdc63 — rtmutex: Use waiter::task instead of current in remove_waiter()