=== Process Descriptor API completion 2

Contact: Konstantin Belousov <kib@FreeBSD.org>

Links: +
link:https://reviews.freebsd.org/D57124[sys: add pdopenpid(2)] URL: link:https://reviews.freebsd.org/D57124[] +
link https://reviews.freebsd.org/D57163[pddupfd(2)] https://reviews.freebsd.org/D57163[]

Following the addition of man:pdwait[2] and man:pdrfork[2] system calls, I looked at the other missing features that are requested by application programmers.
The largest feature asked for seems to be an ability to obtain a process descriptor for an existing process.

Currently only one file descriptor may reference an internal struct procdesc in kernel, which in part explains why the interface to open the process by pid is not yet done.
The work added the ability for procdescs to be pointed to by more than one file.
Attributes controlling the procdesc behavior, e.g. the daemon (closing the file does not terminate the process) were moved from procdesc to the file.

This change allowed to extend the procdesc internal interfaces to implement the man:pdopenid(2) system call.

A facility implemented e.g. by the Linux pidfd descriptors is the pidfd_getfd() system call, that duplicates specified file descriptor from the target process, into the caller.
The implementation of it for FreeBSD, named man:pddupfd(2) is relatively straightforward once we get the fget_remote(9) helper.

A problem with it started when the algorithm to check for privileges required to allow the operation was developed.
The kernel checks the result of p_candebug() to see if something should be allowed that directly accesses programming resources of the remote process.
But p_candebug() result is only valid while the target process lock is owned.
Besides, p_candebug() denies actions if the target process changes the executing program with man:execve(2), which might change the privileges of the process if the image is set-uid or set-gid.
Overall, this makes the plain check with p_candebug() inadequate, because we cannot own the process lock over fget_remote().

For that, a facility was developed that provides mutual exclusion for execing in the target process vs. the caller, called execblock.
Also, helpers to reference the current vmspace for a process were added, to avoid using execblock when only a consistent target address space is required for the action, like reading of the process strings or copying the process memory.
Existing places in system that are affected by the race were identified, and the usage of execblock or vmspace referencing interfaces applied as needed.

Then, the man:pddupfd(2) was implemented with the help of fget_remote() and execblock.

Sponsor: The FreeBSD Foundation
