Why not fix process ids?
Why not fix process ids?
Posted Sep 14, 2023 14:50 UTC (Thu) by ksandstr (guest, #60862)In reply to: Why not fix process ids? by epa
Parent article: Race-free process creation in the GNU C Library
Another substitute solution to pidfds would make process IDs a capability of sorts, such that they're created by fork/spawn, transferred to other processes by unspecified means[0], and invalidated at wait() so they subsequently raise an error upon use. This would ensure that stale PIDs, being those that refer to a since-deceased process, don't end up referring to a different process. However the cost of doing this is a slight API break because kill() etc. would raise "unknown PID" while that PID might actually have come to exist again. Also the question of validating such a capability from e.g. command line parameters will need an answer.
Considering that any use of a PID is an instant TOCTOU hazard to any but the parent process (because it's the only one that can call wait() on that PID), the idea of "just fix the call sites" can be recognized unworkable in a great many cases. Analoguously to the capability idea above, pidfds provide a process-local identifier in the file descriptor[1] and a means to communicate process termination at time of use. And their cost isn't even an ABI break -- just that the old API will be creaky and the new API will be both nonportable, so extensive as to cover every POSIX call that takes a pid_t, and any pidfd_getpid() band-aid call will be another instant TOCTOU hazard (unless). Out of these approaches, pidfds certainly seem like an attractive solution since they mainly require lots of footwork and the creation of a "pre-horizon" category of vulnerable programs that process PIDs in any way.
[-1] this one would be soluble by invalidating wrapped PIDs in processes whose lifecycle intersects the wraparound point, another mild API break and perhaps the bane of init(8) in an interstellar probe or something.
[0] perhaps a general two-stage mechanism to validate a PID and then confirm its correct identity (using e.g. the program's fsid/inode# pair), or an unix domain socket faff not unlike fd transfer.
[1] though transferring these to another process would seem to require a unix domain socket between the two.
[2] there is no 4th footnote; I'm just using this space to point out that I'm currently unemployed but capable of spitting out this kind of off-hand analysis, and a suitably impressed reader's employer could almost certainly use a mad lad like me. *wink* *wink*