1.\" 2.\" Copyright (c) 2009-2010, 2012-2013 Robert N. M. Watson 3.\" All rights reserved. 4.\" 5.\" This software was developed at the University of Cambridge Computer 6.\" Laboratory with support from a grant from Google, Inc. 7.\" 8.\" This software was developed by SRI International and the University of 9.\" Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237) 10.\" ("CTSRD"), as part of the DARPA CRASH research programme. 11.\" 12.\" Redistribution and use in source and binary forms, with or without 13.\" modification, are permitted provided that the following conditions 14.\" are met: 15.\" 1. Redistributions of source code must retain the above copyright 16.\" notice, this list of conditions and the following disclaimer. 17.\" 2. Redistributions in binary form must reproduce the above copyright 18.\" notice, this list of conditions and the following disclaimer in the 19.\" documentation and/or other materials provided with the distribution. 20.\" 21.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 22.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 25.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31.\" SUCH DAMAGE. 32.\" 33.Dd April 19, 2026 34.Dt PDFORK 2 35.Os 36.Sh NAME 37.Nm pdfork , 38.Nm pdrfork , 39.Nm pdopenpid , 40.Nm pdgetpid , 41.Nm pdkill , 42.Nm pdwait , 43.Nm pddupfd 44.Nd System calls to manage process descriptors 45.Sh LIBRARY 46.Lb libc 47.Sh SYNOPSIS 48.In sys/procdesc.h 49.Ft pid_t 50.Fn pdfork "int *fdp" "int pdflags" 51.Ft pid_t 52.Fn pdrfork "int *fdp" "int pdflags" "int rfflags" 53.Ft int 54.Fn pdopenpid "pid_t pid" "int pdflags" 55.Ft int 56.Fn pdgetpid "int fd" "pid_t *pidp" 57.Ft int 58.Fn pdkill "int fd" "int signum" 59.Ft int 60.Fo pdwait 61.Fa "int fd" 62.Fa "int *status" 63.Fa "int options" 64.Fa "struct __wrusage *wrusage" 65.Fa "struct __siginfo *info" 66.Fc 67.Ft int 68.Fn pddupfd "int fd" "int remotefd" "int flags" 69.Sh DESCRIPTION 70Process descriptors are special file descriptors that represent processes, 71and are created using 72.Fn pdfork , 73a variant of 74.Xr fork 2 , 75which, if successful, returns a process descriptor in the integer pointed to 76by 77.Fa fdp . 78Processes created via 79.Fn pdfork 80will not cause 81.Dv SIGCHLD 82on termination. 83.Fn pdfork 84can accept the 85.Fa pdflags: 86.Bl -tag -width PD_CLOEXEC 87.It Dv PD_DAEMON 88Instead of the default terminate-on-close behaviour, allow the process to 89live until it is explicitly killed with 90.Xr kill 2 . 91.Pp 92This option is not permitted in 93.Xr capsicum 4 94capability mode (see 95.Xr cap_enter 2 ) . 96.Pp 97Note: the option changes the behavior of 98.Xr close 2 99for the process descriptor returned by the operation. 100If there is another process descriptor for the same process, created without 101specifying the 102.Dv PD_DAEMON 103flag, closing that descriptor kills the process. 104.It Dv PD_CLOEXEC 105Set close-on-exec on process descriptor. 106.It Dv PD_NOWAITPID 107The parent cannot obtain the child's status with 108.Xr waitpid 2 . 109.El 110.Pp 111The 112.Fn pdrfork 113system call is a variant of 114.Fn pdfork 115that also takes the 116.Fa rfflags 117argument to control sharing of process resources between the caller 118and the new process. 119Like 120.Fn pdfork , 121the function writes the process descriptor referencing the created 122process into the location pointed to by the 123.Fa fdp 124argument. 125See 126.Xr rfork 2 127for a description of the possible 128.Fa rfflag 129flags. 130The 131.Fn pdrfork 132system call requires that both the 133.Va RFPROC 134and 135.Va RFPROCDESC 136flags, or 137.Va RFSPAWN 138flag are specified. 139.Pp 140The 141.Fn pdopenpid 142function opens the process descriptor for the process 143specified by the argument 144.Fa pid . 145It takes the same flags in the 146.Fa pdflags 147argument as 148.Fn pdfork . 149The caller must have permission to debug the target process in order for 150.Fn pdopenpid 151to succeed. 152Zombie processes cannot be opened. 153.Pp 154There might be more that one file descriptor referencing the process. 155After the zombie is reaped, calls to 156.Fn pdwait 157specifying any file descriptors for the same process fail with the 158.Er ESRCH 159error. 160.Pp 161.Fn pdgetpid 162queries the process ID (PID) in the process descriptor 163.Fa fd . 164.Pp 165.Fn pdkill 166is functionally identical to 167.Xr kill 2 , 168except that it accepts a process descriptor, 169.Fa fd , 170rather than a PID. 171.Pp 172The 173.Fn pdwait 174system call allows the calling thread to wait and retrieve 175the status information on the process referenced by the 176.Fa fd 177process descriptor. 178See the description of the 179.Xr wait6 2 180system call for the behavior specification. 181.Pp 182The 183.Fn pddupfd 184function allows the caller to duplicate a file descriptor 185across the process boundaries. 186The function returns the new file descriptor that points to the same file 187as the file descriptor 188.Fa remotefd 189in the process specified by the 190.Fa fd 191process descriptor. 192The returned file descriptor has the 193.Va O_CLOEXEC 194flag set. 195The 196.Fa flags 197argument is reserved and must be zero. 198Certain file descriptor types cannot be copied this way, namely 199kqueues. 200.Sh INTERACTION OF PROCESS DESCRIPTORS AND Xr WAITPID 2 201.Pp 202The 203.Fn pdwait 204system call may be called on a process descriptor 205an unlimited number of times. 206In particular, it does not reap the target process, 207even if that process has exited. 208Each time, it returns the same status. 209.Bl -dash 210.It 211If the process was forked with 212.Fn pdfork , 213and the 214.Dv PD_NOWAITPID 215flag was specified, then the process is automatically reaped after the 216last process descriptor referencing that process is closed. 217No 218.Xr waitpid 2 219call 220.Pq or a call from the same family of the wait functions which operate on PIDs 221are needed to reap the zombie process. 222.It 223If the process was created by 224.Fn pdfork , 225and the 226.Dv PD_NOWAITPID 227flag was not specified, then after exiting, 228the process will not be reaped until the parent or reaper has called 229.Xr waitpid 2 230and all process descriptors referencing the process are closed. 231.It 232If the process was created by the 233.Xr fork 2 234system call 235.Pq which does not allocate a process descriptor for the child , 236and later the process was opened by 237.Fn pdopenpid , 238then a 239.Xr waitpid 2 240call from the parent is needed to reap the exited child. 241.El 242.Pp 243In any case, the PID of the process is not reused until its zombie 244is reaped, and all its process descriptors are closed. 245.Pp 246A debugger attached by 247.Xr ptrace 2 248can execute the 249.Fn waitpid 250calls against the alive target regardless of the way 251the target process was forked. 252.Sh INTERACTION OF PROCESS DESCRIPTORS WITH OTHER SYSTEM CALLS 253.Pp 254The following system calls also have effects specific to process descriptors: 255.Pp 256.Xr fstat 2 257queries status of a process descriptor; currently only the 258.Fa st_mode , 259.Fa st_birthtime , 260.Fa st_atime , 261.Fa st_ctime 262and 263.Fa st_mtime 264fields are defined. 265If the owner read, write, and execute bits are set then the 266process represented by the process descriptor is still alive. 267.Pp 268.Xr poll 2 269and 270.Xr select 2 271allow waiting for process state transitions; currently only 272.Dv POLLHUP 273is defined, and will be raised when the process dies. 274Process state transitions can also be monitored using 275.Xr kqueue 2 276filter 277.Dv EVFILT_PROCDESC ; 278currently only 279.Dv NOTE_EXIT 280is implemented. 281.Pp 282.Xr close 2 283will close the process descriptor unless 284.Dv PD_DAEMON 285is set; if the process is still alive and this is 286the last reference to the process descriptor, the process will be terminated 287with the signal 288.Dv SIGKILL . 289The PID of the referenced process is not reused until the process 290descriptor is closed, 291whether or not the zombie process is reaped by 292.Fn pdwait , 293.Xr wait6 , 294or similar system calls. 295.Sh RETURN VALUES 296.Fn pdfork 297and 298.Fn pdrfork 299return a PID, 0 or -1, as 300.Xr fork 2 301does. 302.Pp 303.Fn pdopenpid , 304.Fn pdgetpid , 305.Fn pdkill , 306.Fn pdwait , 307and 308.Fn pddupfd 309return 0 on success and -1 on failure. 310.Sh ERRORS 311These functions may return the same error numbers as their PID-based equivalents 312(e.g. 313.Fn pdfork 314may return the same error numbers as 315.Xr fork 2 ) , 316with the following additions: 317.Bl -tag -width Er 318.It Bq Er EFAULT 319The copyout of the resulting file descriptor value to the memory pointed 320to by 321.Fa fdp 322failed. 323.Pp 324Note that the child process was already created when this condition 325is detected, 326and the child continues execution, same as the parent. 327If this error must be handled, it is advisable to memoize the 328.Fn getpid 329result before the call to 330.Fn pdfork 331or 332.Fn pdrfork , 333and compare it to the value returned by 334.Fn getpid 335after, to see if code is executing in parent or child. 336.It Bq Er EINVAL 337The signal number given to 338.Fn pdkill 339is invalid. 340.It Bq Er ENOTCAPABLE 341The process descriptor being operated on has insufficient rights (e.g. 342.Dv CAP_PDKILL 343for 344.Fn pdkill ) . 345.It Bq Er EINVAL 346The 347.Fn pdwait 348function is called with reserved bits set in 349.Fa options . 350.El 351.Pp 352The 353.Fn pdopenpid 354might return the same errors as 355.Xr open 2 , 356related to the file descriptor allocation problems, as well as the 357following specific errors: 358.Bl -tag -width Er 359.It Bq Er EINVAL 360The 361.Fa flags 362argument has reserved bits set. 363.It Bq Er ECAPMODE 364.Fn pdopenpid 365is called by the process in capability mode. 366.It Bq Er EBUSY 367The process specified by the 368.Fa pid 369argument already terminated. 370.It Bq Er ESRCH 371The process specified by the 372.Fa pid 373argument does not exist, or the caller does not have enough privileges 374to open the process. 375.It Bq Er EMFILE 376The calling process already reached its limit for open file descriptors. 377.Pp 378Current implementation installs the opened process descriptor into the 379calling process's file descriptors table. 380If the descriptor cannot be installed, the process descriptor is closed, 381which executes all actions performed by 382.Xr close 2 383on it. 384.El 385.Pp 386The 387.Fn pddupfd 388returns the following errors: 389.Bl -tag -width Er 390.It Bq Er EINVAL 391The 392.Fa flags 393argument is not zero. 394.It Bq Er EINVAL 395The file descriptor 396.Fa fd 397is not a process file descriptor. 398.It Bq Er ESRCH 399The process specified by the file descriptor 400.Fa fd 401exited. 402.It Bq Er EBADF 403The file descriptor 404.Fa remotefd 405is not a valid file descriptor in the specified process. 406.It Bq Er ENOENT 407The specified process does not have a file descriptor table. 408.It Bq Er EOPNOTSUPP 409.Fa remotefd 410refers to a file that cannot be duplicated across a process boundary, 411such as a kqueue. 412.El 413.Sh SEE ALSO 414.Xr close 2 , 415.Xr fork 2 , 416.Xr fstat 2 , 417.Xr kill 2 , 418.Xr kqueue 2 , 419.Xr poll 2 , 420.Xr wait4 2 , 421.Xr capsicum 4 , 422.Xr procdesc 4 423.Sh HISTORY 424The 425.Fn pdfork , 426.Fn pdgetpid , 427and 428.Fn pdkill 429system calls first appeared in 430.Fx 9.0 . 431The 432.Fn pdrfork 433and 434.Fn pdwait 435system calls first appeared in 436.Fx 15.1 . 437The 438.Fn pdopenpid 439and 440.Fn pddupfd 441system calls first appeared in 442.Fx 16.0 . 443.Pp 444Support for process descriptors mode was developed as part of the 445.Tn TrustedBSD 446Project. 447.Sh AUTHORS 448.An -nosplit 449These functions and the capability facility were created by 450.An Robert N. M. Watson Aq Mt rwatson@FreeBSD.org 451and 452.An Jonathan Anderson Aq Mt jonathan@FreeBSD.org 453at the University of Cambridge Computer Laboratory with support from a grant 454from Google, Inc. 455The 456.Fn pdrfork 457and 458.Fn pdwait 459functions were developed by 460.An Konstantin Belousov Aq Mt kib@FreeBSD.org 461with input from 462.An Alan Somers Aq Mt asomers@FreeBSD.org . 463The 464.Fn pdopenpid 465and 466.Fn pddupfd 467functions were developed by 468.An Konstantin Belousov Aq Mt kib@FreeBSD.org . 469