On Thu, Jul 16, 2026 at 8:52 AM Li Chen <[email protected]> wrote: > > A kernel-created task can become visible before it has installed a new > executable image or a valid userspace register frame. Exposing such a task > through ptrace can disclose kernel setup state. > > Add a task-local embryonic flag and an internal clone argument for callers > that need this lifecycle. Reject ptrace access until the creator clears the > flag. Clear it with release ordering and observe it with acquire ordering. > This orders visibility of the completed exec state with the transition. > > Existing fork, vfork, clone, and kernel-thread callers leave the argument > unset and retain their current behavior. >
> --- a/kernel/ptrace.c > +++ b/kernel/ptrace.c > @@ -56,6 +56,8 @@ bool ptracer_access_allowed(struct task_struct *tsk) > guard(rcu)(); > if (ptrace_parent(tsk) != current) > return false; > + if (task_is_embryonic_exec(tsk)) > + return false; > es = task_exec_state_rcu(tsk); > return READ_ONCE(es->dumpable) == TASK_DUMPABLE_OWNER || > ptracer_capable(tsk, es->user_ns); > @@ -312,6 +314,8 @@ static int __ptrace_may_access(struct task_struct *task, > unsigned int mode) > WARN(1, "denying ptrace access check without > PTRACE_MODE_*CREDS\n"); > return -EPERM; > } > + if (task_is_embryonic_exec(task)) > + return -EPERM; Would it be better to use a different error code? -ECONNREFUSED? After all, this isn't a permission failure per se. There's a not-locally-obvious gotcha here: reading other process attributes prior to calling task_is_embryonic_exec may result in (security-relevant!) data races. This should at least be documented -- it's critical to check task_is_embryonic_exec *before* trying to read credentials. Also, I think /proc and many pidfd APIs have the same issue. --Andy

