Re: [RFC PATCH 12/24] fork: let kernel callers create embryonic tasks

Andy Lutomirski <[email protected]> Thu, 16 Jul 2026 08:57:58 -0700
Newsgroups org.kernel.vger.audit,org.kernel.vger.linux-api,org.kernel.vger.linux-arch,org.kernel.vger.linux-doc,org.kernel.vger.linux-fsdevel,org.kernel.vger.linux-kernel,org.kernel.vger.linux-kselftest,org.kernel.vger.linux-security-module,org.kvack.linux-mm
Message-ID <CALCETrU2sCf_Ab2oDcUuJV53mhaDHTtf7QNqPJuFxV_ESHkbtg@mail.gmail.com>
On Thu, Jul 16, 2026 at 8:52=E2=80=AFAM 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 tas=
k
> through ptrace can disclose kernel setup state.
>
> Add a task-local embryonic flag and an internal clone argument for caller=
s
> that need this lifecycle. Reject ptrace access until the creator clears t=
he
> 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) !=3D current)
>                 return false;
> +       if (task_is_embryonic_exec(tsk))
> +               return false;
>         es =3D task_exec_state_rcu(tsk);
>         return READ_ONCE(es->dumpable) =3D=3D TASK_DUMPABLE_OWNER ||
>                ptracer_capable(tsk, es->user_ns);
> @@ -312,6 +314,8 @@ static int __ptrace_may_access(struct task_struct *ta=
sk, 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