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