File descriptors are capabilities. A socket, open secret file, memfd, or device handle grants the holder an operation that does not depend on the original path name. pidfd_getfd() lets a process obtain a duplicate of a file descriptor in another process. The call is narrow and permission-checked, but it makes descriptor authority an explicit part of process inspection and container security.

What the system call changes

The manual describes pidfd_getfd() as obtaining a duplicate of another process's file descriptor. The caller supplies a pidfd that refers to the target process and the target descriptor number. The duplicate refers to the same open file description, so offsets and status flags are shared. This is not a copy of the underlying file and it is not a new path lookup. It is access to the same object the target process already holds.

The kernel applies a ptrace access check against the target task. A caller generally needs the relevant ptrace permission and may need CAP_SYS_PTRACE in the target's user namespace. Yama settings, user namespaces, and mandatory access control can further constrain the operation. Those controls matter because a process that can inspect another process may be able to duplicate a listening socket, an authenticated database connection, or a file handle containing credentials.

Treat debugger capability as high privilege

Debugging and profiling are legitimate needs, but they should not be available to every process in a shared namespace. Run debug tooling in a dedicated namespace or on a controlled copy of the workload. Keep CAP_SYS_PTRACE out of application containers. Use distinct users and user namespaces so a compromised service cannot attach to unrelated services on the same host.

Audit events should record the caller, target process, target descriptor type where available, and the outcome. A denied attempt is useful too. Alert when a workload that never used process inspection starts trying to duplicate descriptors. Do not store the contents of an arbitrary descriptor in logs.

Design for least authority

Applications can reduce the impact of descriptor duplication by closing descriptors they no longer need. A service should not retain a privileged file handle after initialization. Use O_CLOEXEC for descriptors that should not survive an execution, and drop capabilities after setup. Split a workload that needs both a public listener and a privileged control socket into separate processes when the API allows it.

An operator should know which containers share a pid namespace and which debug capabilities are enabled. That information is more useful than a generic "debug is disabled" checkbox. Test the effective policy with a harmless descriptor and a denied target, rather than testing only the positive case.

Keep the evidence

Store pidfd policy in the workload manifest and compare it after deployment. A debug sidecar added for an incident should have an owner and an end time. A temporary SYS_PTRACE grant left behind is a persistent path to duplicate credentials.

pidfd_getfd() is precise enough to be useful for controlled diagnostics. Its safety depends on the surrounding namespace and capability policy. Restrict who can call it, close descriptors that no longer need authority, and record attempts that cross a process boundary.

References

[1] pidfd_getfd(2) manual