portal: pin target mm with get_task_mm() before access_remote_vm#86
Merged
Conversation
handle_op_read_procargs() and handle_op_read_procenv() looked up the
target task with the unreferenced get_target_task_by_id() and then used
task->mm directly, calling access_remote_vm() without pinning the mm.
That faults when the target has no valid user mm (kernel thread), is
exiting (mm being torn down), or when its mm is reaped concurrently:
access_remote_vm() -> get_user_pages_remote() -> down_read() on a stale
mmap lock -> kernel Oops. On the signal/kill path the read runs in the
caller's syscall context, so when the caller is init the Oops panics the
whole system ("Attempted to kill init").
Mirror fs/proc/base.c: add get_target_task_mm(), which does the pid
lookup and get_task_mm() inside a single rcu read-side section.
get_task_mm() takes task_lock (no sleep, safe under rcu), returns NULL
for kernel-thread/already-exited tasks, and pins the mm with an mm_users
reference so it stays live until mmput(). Both readers now acquire the mm
this way and mmput() on every exit path. Include linux/sched/mm.h (>=4.11)
for get_task_mm/mmput.
Generic fix: any firmware whose userspace resolves a target process's
args/env on the signal-send path (e.g. lifeguard intercepting kill for
blocked signals) could trigger the fault.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
handle_op_read_procargs()andhandle_op_read_procenv()look up the target task with the unreferencedget_target_task_by_id()and then usetask->mmdirectly, callingaccess_remote_vm()without pinning the mm.That faults when the target:
The fault path is
access_remote_vm() -> get_user_pages_remote() -> down_read()on a stale mmap lock -> kernel Oops. Because these reads can run in the caller's syscall context on the signal-send path, when the caller is init the Oops panics the whole system (Attempted to kill init).Observed backtrace:
Fix
Mirror
fs/proc/base.c: addget_target_task_mm(), which does the pid lookup andget_task_mm()inside a single RCU read-side section.get_task_mm()takestask_lock(no sleep, safe under RCU), returns NULL for kernel-thread / already-exited tasks, and pins the mm with anmm_usersreference so it stays live untilmmput().Both readers now acquire the mm this way and
mmput()on every exit path. Adds a version-guarded#include <linux/sched/mm.h>(>=4.11) forget_task_mm/mmput.Impact
Generic: any firmware whose userspace resolves a target process's args/env on the signal-send path (e.g. lifeguard intercepting
killfor blocked signals) can trigger the original fault.Testing
SyS_kill) now boots fully with all services binding and zero read_procargs faults / Oops / panics across a full run.