IPC · Section 2
pipe2(2)
Create a unidirectional pipe and atomically set O_CLOEXEC / O_NONBLOCK on the resulting descriptors.
Signature
#include <unistd.h>
int pipe2(int [2] pipefd, int flags);- pipefd
- Out-parameter: a 2-element int array. The kernel writes the read end to pipefd[0] and the write end to pipefd[1].
- flags
- Bitwise OR of O_CLOEXEC (close on exec), O_NONBLOCK (non-blocking I/O), O_DIRECT (packet mode — each write becomes a discrete read).
Description
pipe2() creates a unidirectional data channel — a pair of file descriptors where data written to pipefd[1] (the write end) is read from pipefd[0] (the read end), in FIFO order. The kernel buffers up to /proc/sys/fs/pipe-max-size bytes (default 1 MiB; per-pipe size adjustable via fcntl(F_SETPIPE_SZ)). When the last write-end descriptor is closed, subsequent reads return 0 (EOF); when the last read-end descriptor is closed, writes to the write end raise SIGPIPE and return -1/EPIPE. The flags argument lets the caller set O_CLOEXEC and/or O_NONBLOCK atomically at create time — this is the whole reason pipe2() exists; the original pipe() forced a separate fcntl() that could race with a concurrent fork+exec.
Architecture mapping
| Architecture | Number | ABI | Entry point |
|---|---|---|---|
| x86 (i386) | 331 | i386 | sys_pipe2 |
| x64 (x86_64) | 293 | common | sys_pipe2 |
| ARM64 (aarch64) | 59 | — | sys_pipe2 |
Kernel history
Introduced in Linux 2.6.27.
2.6.27
pipe2() was added in 2.6.27 alongside the broader CLOEXEC-atomic family (accept4, dup3, socket SOCK_CLOEXEC, signalfd4, etc.) to close the long-standing race where fcntl(F_SETFD, FD_CLOEXEC) after a syscall could be observed mid-execve by a fork sibling.
3.4
O_DIRECT was added so callers can opt into packet-mode pipes (no message-boundary coalescing). Useful for protocols like dbus that need each write() to be a distinct read().
seccomp & containers
Docker default profile
Allowed
Podman default profile
Allowed
pipe() and pipe2() are on every default profile. Effectively un-blockable — every shell pipeline, every async stdout capture, every supervisor's signal pipe relies on them. No useful argument-level filtering.
libseccomp
seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(pipe), 0);
seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(pipe2), 0);strace example
$ strace -e pipe2 bash -c 'echo a | wc -c'
pipe2([3, 4], O_CLOEXEC) = 0pipe2() returns the two descriptors as an array — strace prints them as [3, 4]. Following both ends with -y and -e read,write,pipe2 reconstructs the entire pipe traffic. A program with hung pipes shows as a writer blocked on write(pipefd[1], …) and no matching read() on the other side — common in shell-pipeline diagnoses.
Security & observability
pipe() / pipe2() are the underlying mechanism of CVE-2022-0847 'Dirty Pipe' — a kernel bug where the splice path mis-merged pipe pages into the page cache, letting unprivileged users overwrite read-only files. The fix landed in 5.16.11/5.15.25/5.10.102. The CVE is patched in any kernel from mid-2022; verify your /proc/version. Beyond that, pipes are rarely a direct security signal — too universal to monitor usefully. For container forensics, /proc/<pid>/fd inspection shows pipe inodes that can be cross-referenced with the peer process to map IPC topology.
Errors
- EFAULT
- pipefd points outside the calling process's address space.
- EINVAL
- Invalid flags.
- EMFILE
- Per-process fd limit reached (each pipe consumes two descriptors).
- ENFILE
- System-wide fd limit reached.
Flags
- O_CLOEXEC
- 02000000
- Set close-on-exec on both descriptors. Essential — any pipe used internally that isn't supposed to leak to a forked child must have CLOEXEC.
- O_NONBLOCK
- 04000
- Both ends become non-blocking. read() returns EAGAIN when empty; write() returns EAGAIN when the buffer is full.
- O_DIRECT
- 040000
- Packet-mode pipe (since 3.4). Each write() becomes a separate read() boundary — useful for record-oriented protocols where you don't want the kernel to coalesce.