$RodHat_
Syscall reference · File descriptors

pidfd_getfd(2)

Duplicate a file descriptor out of another process, addressed by its pidfd.

Since
Linux 5.6check your kernel →
glibc
glibc 2.36
System
Linux
Man page
pidfd_getfd(2)

Synopsis

#include <sys/syscall.h>
#include <unistd.h>

int syscall(SYS_pidfd_getfd, int pidfd, int targetfd,
            unsigned int flags);

Rod's take

The /proc/<pid>/fd/N trick is a path lookup keyed on a PID, so it inherits every reuse race PIDs have. pidfd_getfd goes through the stable handle and drops a duplicate of the target's descriptor into your table, sharing offset and flags exactly like dup(2). Unlike SCM_RIGHTS, the other process doesn't get a vote, which is precisely why it's gated on a ptrace attach check. Supervisors and container runtimes want this. Everyone else should be mildly alarmed that it exists.

Flags and arguments that matter

NameWhat it does
targetfdThe descriptor number in the target process to duplicate; the copy shares its open file description.
flagsReserved; must be 0, otherwise EINVAL.
FD_CLOEXECAlways set on the returned descriptor.
PTRACE_MODE_ATTACH_REALCREDSPermission check applied: you need ptrace-attach rights over the target.

Errors you will actually hit

errnoMeaning
EPERMCaller lacks PTRACE_MODE_ATTACH_REALCREDS permission over the target process.
EBADFpidfd is not a PID fd, or targetfd is not open in the target process.
ESRCHThe target process has terminated and been waited on.
EINVALflags is not 0.
EMFILEPer-process open file descriptor limit reached.

Example

int pfd = syscall(SYS_pidfd_open, pid, 0);
if (pfd < 0)
    err(1, "pidfd_open");

/* copy the target's fd 0; needs ptrace-attach rights over it */
int fd = syscall(SYS_pidfd_getfd, pfd, 0, 0);
if (fd < 0)
    err(1, "pidfd_getfd");   /* EPERM, EBADF, ESRCH */

/* fd shares the open file description; FD_CLOEXEC is set */
close(pfd);

Trimmed from the full walkthrough in pidfd: Unix finally has a handle on your processes (only took 50 years).

BSD equivalent

none; on FreeBSD and OpenBSD the closest is passing the descriptor with SCM_RIGHTS over a unix(4) socket, which needs the owner's cooperation.

The long version, from the console

Sources

  1. pidfd_getfd(2), man7.org
  2. unix(4), FreeBSD
  3. unix(4), OpenBSD
  4. glibc 2.36 NEWS (pidfd_open, pidfd_getfd, pidfd_send_signal added)

Version numbers are read off the cited man pages, not memory. Spot one that's wrong? Tell Rod.