home | help
PDFORK(2)		       System Calls Manual		       PDFORK(2)

NAME
     pdfork,  pdrfork,	pdopenpid,  pdgetpid,  pdkill, pdwait, pddupfd -- System
     calls to manage process descriptors

LIBRARY
     Standard C Library (libc, -lc)

SYNOPSIS
     #include <sys/procdesc.h>

     pid_t
     pdfork(int *fdp, int pdflags);

     pid_t
     pdrfork(int *fdp, int pdflags, int rfflags);

     int
     pdopenpid(pid_t pid, int pdflags);

     int
     pdgetpid(int fd, pid_t *pidp);

     int
     pdkill(int fd, int signum);

     int
     pdwait(int fd, int *status, int options, struct __wrusage *wrusage,
	 struct __siginfo *info);

     int
     pddupfd(int fd, int remotefd, int flags);

     int
     pdptrace(int req, int fd, int lwpid, void *addr, int data);

DESCRIPTION
     Process descriptors are special file descriptors that represent  processes,
     and are created using pdfork(), a variant of fork(2), which, if successful,
     returns  a  process descriptor in the integer pointed to by fdp.  Processes
     created via pdfork() will not cause SIGCHLD on termination.   pdfork()  can
     accept the pdflags:

     PD_DAEMON	    Instead  of  the default terminate-on-close behaviour, allow
		    the process to live  until	it  is	explicitly  killed  with
		    kill(2).

		    This  option is not permitted in capsicum(4) capability mode
		    (see cap_enter(2)).

		    Note: the option changes the behavior of  close(2)	for  the
		    process  descriptor  returned by the operation.  If there is
		    another process descriptor for  the  same  process,  created
		    without specifying the PD_DAEMON flag, closing that descrip-
		    tor kills the process.

     PD_CLOEXEC     Set close-on-exec on process descriptor.

     PD_NOWAITPID   The parent cannot obtain the child's status with waitpid(2).

     PD_PTRACE_CAP  Enable  pdptrace(2)  requests on the resulting file descrip-
		    tor.  Otherwise the descriptor cannot be used to  debug  the
		    child  process.   See  rights(4)  for the description of the
		    CAP_PTRACE capability.

     The pdrfork() system call is a variant of	pdfork()  that	also  takes  the
     rfflags argument to control sharing of process resources between the caller
     and  the  new  process.  Like pdfork(), the function writes the process de-
     scriptor referencing the created process into the location  pointed  to  by
     the  fdp  argument.   See rfork(2) for a description of the possible rfflag
     flags.  The pdrfork()  system  call  requires  that  both	the  RFPROC  and
     RFPROCDESC flags, or RFSPAWN flag are specified.

     The pdopenpid() function opens the process descriptor for the process spec-
     ified by the argument pid.  It takes the same flags in the pdflags argument
     as  pdfork().   The caller must have permission to debug the target process
     in order for pdopenpid() to succeed.  Zombie processes cannot be opened.

     There might be more that one file descriptor referencing the process.   Af-
     ter the zombie is reaped, calls to pdwait() specifying any file descriptors
     for the same process fail with the ESRCH error.

     The  pdopenpid()  system  call  is allowed in the capability mode (see cap-
     sicum(4)) when the target process is the child of the calling  process,  or
     when the calling process is the debugger of the target process.  The debug-
     ger is attached to its target by ptrace(2), pdptrace(2), or by other means,
     e.g.,  by debugging the target process' parent with the follow-on-fork mode
     enabled.

     pdgetpid() queries the process ID (PID) in the process descriptor fd.

     pdkill() is functionally identical to kill(2), except  that  it  accepts  a
     process descriptor, fd, rather than a PID.

     The pdwait() system call allows the calling thread to wait and retrieve the
     status  information on the process referenced by the fd process descriptor.
     See the description of the wait6(2) system call for the behavior specifica-
     tion.

     The pddupfd() function allows the caller to  duplicate  a	file  descriptor
     across  the process boundaries.  The function returns the new file descrip-
     tor that points to the same file as the file  descriptor  remotefd  in  the
     process specified by the fd process descriptor.  The returned file descrip-
     tor has the O_CLOEXEC flag set.  The flags argument is reserved and must be
     zero.   Certain  file  descriptor	types  cannot be copied this way, namely
     kqueues.

     The pdptrace() function enables execution	of  ptrace(2)  requests  on  the
     process specified by the process descriptor fd.

     In addition to the arguments taken by the ptrace(2), system call, the lwpid
     thread  identifier can designate the thread on which the request must oper-
     ate.  The lwpid argument can be specified as -1 if the call is not  thread-
     specific, or kernel is allowed to select some thread on its own.

     Unlike  the  ptrace(2)  implementation, pdptrace() does not clear the errno
     variable before executing the system call.

INTERACTION OF PROCESS DESCRIPTORS AND WAITPID(2)
     The pdwait() system call may be called on a process descriptor an unlimited
     number of times.  In particular, it does not reap the target process,  even
     if that process has exited.  Each time, it returns the same status.

     -	 If  the process was forked with pdfork(), and the PD_NOWAITPID flag was
	 specified, then the process is  automatically	reaped	after  the  last
	 process  descriptor  referencing that process is closed.  No waitpid(2)
	 call (or a call from the  same  family  of  the  wait	functions  which
	 operate on PIDs) are needed to reap the zombie process.

     -	 If  the  process was created by pdfork(), and the PD_NOWAITPID flag was
	 not specified, then after exiting, the process will not be reaped until
	 the parent or reaper has called waitpid(2) and all process  descriptors
	 referencing the process are closed.

     -	 If  the  process was created by the fork(2) system call (which does not
	 allocate a process descriptor for the child), and later the process was
	 opened by pdopenpid(), then a waitpid(2) call from the parent is needed
	 to reap the exited child.

     In any case, the PID of the process is  not  reused  until  its  zombie  is
     reaped, and all its process descriptors are closed.

     A	debugger  attached  by ptrace(2) can execute the waitpid() calls against
     the alive target regardless of the way the target process was forked.

INTERACTION OF PROCESS DESCRIPTORS WITH OTHER SYSTEM CALLS
     The following system calls also have effects specific to  process	descrip-
     tors:

     fstat(2)  queries	status	of  a  process	descriptor;  currently	only the
     st_mode, st_birthtime, st_atime, st_ctime and st_mtime fields are	defined.
     If  the owner read, write, and execute bits are set then the process repre-
     sented by the process descriptor is still alive.

     poll(2) and select(2) allow waiting for  process  state  transitions;  cur-
     rently  only  POLLHUP is defined, and will be raised when the process dies.
     Process state transitions can also  be  monitored	using  kqueue(2)  filter
     EVFILT_PROCDESC; currently only NOTE_EXIT is implemented.

     close(2)  will close the process descriptor unless PD_DAEMON is set; if the
     process is still alive and this is the last reference to  the  process  de-
     scriptor,	the process will be terminated with the signal SIGKILL.  The PID
     of the referenced process is not reused until  the  process  descriptor  is
     closed,  whether or not the zombie process is reaped by pdwait(), wait6, or
     similar system calls.

RETURN VALUES
     pdfork() and pdrfork() return a PID, 0 or -1, as fork(2) does.

     pdopenpid(), pdgetpid(), pdkill(), pdwait(), and pddupfd() return 0 on suc-
     cess and -1 on failure.

ERRORS
     These functions may return the same error numbers as their PID-based equiv-
     alents (e.g.  pdfork() may return the same error numbers as fork(2)),  with
     the following additions:

     [EFAULT]		The  copyout  of  the resulting file descriptor value to
			the memory pointed to by fdp failed.

			Note that the child process  was  already  created  when
			this condition is detected, and the child continues exe-
			cution,  same as the parent.  If this error must be han-
			dled, it is advisable to memoize the getpid() result be-
			fore the call to pdfork() or pdrfork(), and  compare  it
			to  the value returned by getpid() after, to see if code
			is executing in parent or child.

     [EINVAL]		The signal number given to pdkill() is invalid.

     [ENOTCAPABLE]	The process descriptor being operated  on  has	insuffi-
			cient rights (e.g.  CAP_PDKILL for pdkill()).

     [EINVAL]		The  pdwait()  function is called with reserved bits set
			in options.

     The pdopenpid() might return the same errors as  open(2),	related  to  the
     file  descriptor allocation problems, as well as the following specific er-
     rors:

     [EINVAL]		The flags argument has reserved bits set.

     [ECAPMODE] 	pdopenpid() is called by the process in capability mode.

     [EBUSY]		The process specified by the pid argument already termi-
			nated.

     [ESRCH]		The process specified by the pid argument does	not  ex-
			ist,  or  the  caller does not have enough privileges to
			open the process.

     [EMFILE]		The calling process already reached its limit  for  open
			file descriptors.

			Current  implementation  installs the opened process de-
			scriptor into the calling process's file descriptors ta-
			ble.  If the descriptor cannot be installed, the process
			descriptor is closed, which executes  all  actions  per-
			formed by close(2) on it.

     The pddupfd() returns the following errors:

     [EINVAL]		The flags argument is not zero.

     [EINVAL]		The file descriptor fd is not a process file descriptor.

     [ESRCH]		The process specified by the file descriptor fd exited.

     [EBADF]		The  file  descriptor  remotefd  is not a valid file de-
			scriptor in the specified process.

     [ENOENT]		The specified process does not have  a	file  descriptor
			table.

     [EOPNOTSUPP]	remotefd  refers  to  a  file  that cannot be duplicated
			across a process boundary, such as a kqueue.

     The pdptrace() system call returns the same errors as ptrace(2), as well as
     the following specific errors:

     [ECAPMODE] 	The process issuing the pdptrace() call is in capability
			mode, and the security.bsd.allow_ptrace_in_cap_mode tun-
			able is set to false.

     [ENOTCAPABLE]	The process called pdptrace() on the process  descriptor
			that does not have the CAP_PTRACE capability enabled.

SEE ALSO
     close(2),	fork(2),  fstat(2),  kill(2), kqueue(2), poll(2), wait4(2), cap-
     sicum(4), procdesc(4)

HISTORY
     The pdfork(), pdgetpid(), and  pdkill()  system  calls  first  appeared  in
     FreeBSD  9.0.   The  pdrfork()  and pdwait() system calls first appeared in
     FreeBSD 15.1.  The pdopenpid() and pddupfd() system calls first appeared in
     FreeBSD 16.0.

     Support  for  process  descriptors  mode  was  developed  as  part  of  the
     TrustedBSD Project.

AUTHORS
     These  functions  and  the capability facility were created by Robert N. M.
     Watson <rwatson@FreeBSD.org> and Jonathan	Anderson  <jonathan@FreeBSD.org>
     at  the  University  of  Cambridge  Computer Laboratory with support from a
     grant from Google, Inc.  The pdrfork() and pdwait() functions  were  devel-
     oped  by  Konstantin Belousov <kib@FreeBSD.org> with input from Alan Somers
     <asomers@FreeBSD.org>.  The pdopenpid(), pddupfd(),  and  pdptrace()  func-
     tions were developed by Konstantin Belousov <kib@FreeBSD.org>.

FreeBSD 16.0 CURRENT		 April 19, 2026 		       PDFORK(2)

home | help