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.Ft int 70.Fo pdptrace 71.Fa "int req" 72.Fa "int fd" 73.Fa "int lwpid" 74.Fa "void *addr" 75.Fa "int data" 76.Fc 77.Sh DESCRIPTION 78Process descriptors are special file descriptors that represent processes, 79and are created using 80.Fn pdfork , 81a variant of 82.Xr fork 2 , 83which, if successful, returns a process descriptor in the integer pointed to 84by 85.Fa fdp . 86Processes created via 87.Fn pdfork 88will not cause 89.Dv SIGCHLD 90on termination. 91.Fn pdfork 92can accept the 93.Fa pdflags: 94.Bl -tag -width PD_PTRACE_CAP 95.It Dv PD_DAEMON 96Instead of the default terminate-on-close behaviour, allow the process to 97live until it is explicitly killed with 98.Xr kill 2 . 99.Pp 100This option is not permitted in 101.Xr capsicum 4 102capability mode (see 103.Xr cap_enter 2 ) . 104.Pp 105Note: the option changes the behavior of 106.Xr close 2 107for the process descriptor returned by the operation. 108If there is another process descriptor for the same process, created without 109specifying the 110.Dv PD_DAEMON 111flag, closing that descriptor kills the process. 112.It Dv PD_CLOEXEC 113Set close-on-exec on process descriptor. 114.It Dv PD_NOWAITPID 115The parent cannot obtain the child's status with 116.Xr waitpid 2 . 117.It Dv PD_PTRACE_CAP 118Enable 119.Xr pdptrace 2 120requests on the resulting file descriptor. 121Otherwise the descriptor cannot be used to debug the child process. 122See 123.Xr rights 4 124for the description of the 125.Dv CAP_PTRACE 126capability. 127.El 128.Pp 129The 130.Fn pdrfork 131system call is a variant of 132.Fn pdfork 133that also takes the 134.Fa rfflags 135argument to control sharing of process resources between the caller 136and the new process. 137Like 138.Fn pdfork , 139the function writes the process descriptor referencing the created 140process into the location pointed to by the 141.Fa fdp 142argument. 143See 144.Xr rfork 2 145for a description of the possible 146.Fa rfflag 147flags. 148The 149.Fn pdrfork 150system call requires that both the 151.Va RFPROC 152and 153.Va RFPROCDESC 154flags, or 155.Va RFSPAWN 156flag are specified. 157.Pp 158The 159.Fn pdopenpid 160function opens the process descriptor for the process 161specified by the argument 162.Fa pid . 163It takes the same flags in the 164.Fa pdflags 165argument as 166.Fn pdfork . 167The caller must have permission to debug the target process in order for 168.Fn pdopenpid 169to succeed. 170Zombie processes cannot be opened. 171.Pp 172There might be more that one file descriptor referencing the process. 173After the zombie is reaped, calls to 174.Fn pdwait 175specifying any file descriptors for the same process fail with the 176.Er ESRCH 177error. 178.Pp 179The 180.Fn pdopenpid 181system call is allowed in the capability mode 182.Pq see Xr capsicum 4 183when the target process is the child of the calling process, or 184when the calling process is the debugger of the target process. 185The debugger is attached to its target by 186.Xr ptrace 2 , 187.Xr pdptrace 2 , 188or by other means, e.g., by debugging the target process' parent with 189the follow-on-fork mode enabled. 190.Pp 191.Fn pdgetpid 192queries the process ID (PID) in the process descriptor 193.Fa fd . 194.Pp 195.Fn pdkill 196is functionally identical to 197.Xr kill 2 , 198except that it accepts a process descriptor, 199.Fa fd , 200rather than a PID. 201.Pp 202The 203.Fn pdwait 204system call allows the calling thread to wait and retrieve 205the status information on the process referenced by the 206.Fa fd 207process descriptor. 208See the description of the 209.Xr wait6 2 210system call for the behavior specification. 211.Pp 212The 213.Fn pddupfd 214function allows the caller to duplicate a file descriptor 215across the process boundaries. 216The function returns the new file descriptor that points to the same file 217as the file descriptor 218.Fa remotefd 219in the process specified by the 220.Fa fd 221process descriptor. 222The returned file descriptor has the 223.Va O_CLOEXEC 224flag set. 225The 226.Fa flags 227argument is reserved and must be zero. 228Certain file descriptor types cannot be copied this way, namely 229kqueues. 230.Pp 231The 232.Fn pdptrace 233function enables execution of 234.Xr ptrace 2 235requests on the process specified by the process descriptor 236.Fa fd . 237.Pp 238In addition to the arguments taken by the 239.Xr ptrace 2 , 240system call, the 241.Fa lwpid 242thread identifier can designate the thread on which the request 243must operate. 244The 245.Fa lwpid 246argument can be specified as \-1 if the call is not thread-specific, 247or kernel is allowed to select some thread on its own. 248.Pp 249Unlike the 250.Xr ptrace 2 251implementation, 252.Fn pdptrace 253does not clear the 254.Dv errno 255variable before executing the system call. 256.Sh INTERACTION OF PROCESS DESCRIPTORS AND Xr WAITPID 2 257.Pp 258The 259.Fn pdwait 260system call may be called on a process descriptor 261an unlimited number of times. 262In particular, it does not reap the target process, 263even if that process has exited. 264Each time, it returns the same status. 265.Bl -dash 266.It 267If the process was forked with 268.Fn pdfork , 269and the 270.Dv PD_NOWAITPID 271flag was specified, then the process is automatically reaped after the 272last process descriptor referencing that process is closed. 273No 274.Xr waitpid 2 275call 276.Pq or a call from the same family of the wait functions which operate on PIDs 277are needed to reap the zombie process. 278.It 279If the process was created by 280.Fn pdfork , 281and the 282.Dv PD_NOWAITPID 283flag was not specified, then after exiting, 284the process will not be reaped until the parent or reaper has called 285.Xr waitpid 2 286and all process descriptors referencing the process are closed. 287.It 288If the process was created by the 289.Xr fork 2 290system call 291.Pq which does not allocate a process descriptor for the child , 292and later the process was opened by 293.Fn pdopenpid , 294then a 295.Xr waitpid 2 296call from the parent is needed to reap the exited child. 297.El 298.Pp 299In any case, the PID of the process is not reused until its zombie 300is reaped, and all its process descriptors are closed. 301.Pp 302A debugger attached by 303.Xr ptrace 2 304can execute the 305.Fn waitpid 306calls against the alive target regardless of the way 307the target process was forked. 308.Sh INTERACTION OF PROCESS DESCRIPTORS WITH OTHER SYSTEM CALLS 309.Pp 310The following system calls also have effects specific to process descriptors: 311.Pp 312.Xr fstat 2 313queries status of a process descriptor; currently only the 314.Fa st_mode , 315.Fa st_birthtime , 316.Fa st_atime , 317.Fa st_ctime 318and 319.Fa st_mtime 320fields are defined. 321If the owner read, write, and execute bits are set then the 322process represented by the process descriptor is still alive. 323.Pp 324.Xr poll 2 325and 326.Xr select 2 327allow waiting for process state transitions; currently only 328.Dv POLLHUP 329is defined, and will be raised when the process dies. 330Process state transitions can also be monitored using 331.Xr kqueue 2 332filter 333.Dv EVFILT_PROCDESC ; 334currently only 335.Dv NOTE_EXIT 336is implemented. 337.Pp 338.Xr close 2 339will close the process descriptor unless 340.Dv PD_DAEMON 341is set; if the process is still alive and this is 342the last reference to the process descriptor, the process will be terminated 343with the signal 344.Dv SIGKILL . 345The PID of the referenced process is not reused until the process 346descriptor is closed, 347whether or not the zombie process is reaped by 348.Fn pdwait , 349.Xr wait6 , 350or similar system calls. 351.Sh RETURN VALUES 352.Fn pdfork 353and 354.Fn pdrfork 355return a PID, 0 or -1, as 356.Xr fork 2 357does. 358.Pp 359.Fn pdopenpid , 360.Fn pdgetpid , 361.Fn pdkill , 362.Fn pdwait , 363and 364.Fn pddupfd 365return 0 on success and -1 on failure. 366.Sh ERRORS 367These functions may return the same error numbers as their PID-based equivalents 368(e.g. 369.Fn pdfork 370may return the same error numbers as 371.Xr fork 2 ) , 372with the following additions: 373.Bl -tag -width Er 374.It Bq Er EFAULT 375The copyout of the resulting file descriptor value to the memory pointed 376to by 377.Fa fdp 378failed. 379.Pp 380Note that the child process was already created when this condition 381is detected, 382and the child continues execution, same as the parent. 383If this error must be handled, it is advisable to memoize the 384.Fn getpid 385result before the call to 386.Fn pdfork 387or 388.Fn pdrfork , 389and compare it to the value returned by 390.Fn getpid 391after, to see if code is executing in parent or child. 392.It Bq Er EINVAL 393The signal number given to 394.Fn pdkill 395is invalid. 396.It Bq Er ENOTCAPABLE 397The process descriptor being operated on has insufficient rights (e.g. 398.Dv CAP_PDKILL 399for 400.Fn pdkill ) . 401.It Bq Er EINVAL 402The 403.Fn pdwait 404function is called with reserved bits set in 405.Fa options . 406.El 407.Pp 408The 409.Fn pdopenpid 410might return the same errors as 411.Xr open 2 , 412related to the file descriptor allocation problems, as well as the 413following specific errors: 414.Bl -tag -width Er 415.It Bq Er EINVAL 416The 417.Fa flags 418argument has reserved bits set. 419.It Bq Er ECAPMODE 420.Fn pdopenpid 421is called by the process in capability mode. 422.It Bq Er EBUSY 423The process specified by the 424.Fa pid 425argument already terminated. 426.It Bq Er ESRCH 427The process specified by the 428.Fa pid 429argument does not exist, or the caller does not have enough privileges 430to open the process. 431.It Bq Er EMFILE 432The calling process already reached its limit for open file descriptors. 433.Pp 434Current implementation installs the opened process descriptor into the 435calling process's file descriptors table. 436If the descriptor cannot be installed, the process descriptor is closed, 437which executes all actions performed by 438.Xr close 2 439on it. 440.El 441.Pp 442The 443.Fn pddupfd 444returns the following errors: 445.Bl -tag -width Er 446.It Bq Er EINVAL 447The 448.Fa flags 449argument is not zero. 450.It Bq Er EINVAL 451The file descriptor 452.Fa fd 453is not a process file descriptor. 454.It Bq Er ESRCH 455The process specified by the file descriptor 456.Fa fd 457exited. 458.It Bq Er EBADF 459The file descriptor 460.Fa remotefd 461is not a valid file descriptor in the specified process. 462.It Bq Er ENOENT 463The specified process does not have a file descriptor table. 464.It Bq Er EOPNOTSUPP 465.Fa remotefd 466refers to a file that cannot be duplicated across a process boundary, 467such as a kqueue. 468.El 469.Pp 470The 471.Fn pdptrace 472system call returns the same errors as 473.Xr ptrace 2 , 474as well as the following specific errors: 475.Bl -tag -width Er 476.It Bq Er ECAPMODE 477The process issuing the 478.Fn pdptrace 479call is in capability mode, 480and the 481.Dv security.bsd.allow_ptrace_in_cap_mode 482tunable is set to 483.Dv false . 484.It Bq Er ENOTCAPABLE 485The process called 486.Fn pdptrace 487on the process descriptor that does not have the 488.Dv CAP_PTRACE 489capability enabled. 490.Sh SEE ALSO 491.Xr close 2 , 492.Xr fork 2 , 493.Xr fstat 2 , 494.Xr kill 2 , 495.Xr kqueue 2 , 496.Xr poll 2 , 497.Xr wait4 2 , 498.Xr capsicum 4 , 499.Xr procdesc 4 500.Sh HISTORY 501The 502.Fn pdfork , 503.Fn pdgetpid , 504and 505.Fn pdkill 506system calls first appeared in 507.Fx 9.0 . 508The 509.Fn pdrfork 510and 511.Fn pdwait 512system calls first appeared in 513.Fx 15.1 . 514The 515.Fn pdopenpid 516and 517.Fn pddupfd 518system calls first appeared in 519.Fx 16.0 . 520.Pp 521Support for process descriptors mode was developed as part of the 522.Tn TrustedBSD 523Project. 524.Sh AUTHORS 525.An -nosplit 526These functions and the capability facility were created by 527.An Robert N. M. Watson Aq Mt rwatson@FreeBSD.org 528and 529.An Jonathan Anderson Aq Mt jonathan@FreeBSD.org 530at the University of Cambridge Computer Laboratory with support from a grant 531from Google, Inc. 532The 533.Fn pdrfork 534and 535.Fn pdwait 536functions were developed by 537.An Konstantin Belousov Aq Mt kib@FreeBSD.org 538with input from 539.An Alan Somers Aq Mt asomers@FreeBSD.org . 540The 541.Fn pdopenpid , 542.Fn pddupfd , 543and 544.Fn pdptrace 545functions were developed by 546.An Konstantin Belousov Aq Mt kib@FreeBSD.org . 547