Adds a P_PROCDESC idtype naming the target by a process descriptor the
caller holds rather than by a pid, so process control stays available in
capability mode -- procctl(2) becomes CAPENABLED, and in capability
mode P_PROCDESC is the only identifier accepted. Guarded by a new
CAP_PROCCTL right, which is not granted on the output of pdfork(2) by
default; a caller opts in with the PD_PROCCTL_CAP flag.
This follows the direction of D58586, which reaches ptrace(2) operations
through a process descriptor rather than adding parallel syscalls. It
likewise made CAP_PTRACE not granted by default, too. Using the
existing multiplexer keeps the ABI addition to one idtype instead of one
syscall per operation, and it happens to be the natural fit for an
embryonic process: pdnew(2) yields a descriptor and no pid the caller
should have to use.
posix_spawn(3) uses it for POSIX_SPAWN_DISABLE_ASLR_NP, which is
already a procctl(PROC_ASLR_CTL) and so needs no new command, removing
that attribute from the set that still falls back to vfork(2).
Even for P_PROCDESC, not every command belongs in capability mode: the
reaping and group operations reach beyond the process the descriptor
names, which is more authority than holding that one descriptor should
grant. Each command therefore carries a cap_safe bit; in capability
mode only the ones marked so may be issued, and the machine-dependent
commands are denied there entirely for now. Everything else fails with
ECAPMODE. Erring on the side of prohibiting, only PROC_ASLR_CTL ---
what posix_spawn(3) needs --- is marked so far; the list can grow as
commands are audited.
A tiny kern_procctl_permit() is also factored out to make sure that
this one liner --- which now would have occured in three, not two
places, otherwise --- doesn't drift out of sync.
Depends on D58586
Assisted-by: Claude Code (Claude Opus 5)