File & I/O · Section 2
read(2)
Read up to count bytes from a file descriptor into a buffer.
Signature
#include <unistd.h>
ssize_t read(int fd, void * buf, size_t count);- fd
- Open file descriptor in O_RDONLY or O_RDWR mode (or any descriptor type that supports reading, e.g. a socket or pipe).
- buf
- User-space buffer of at least count bytes. The kernel writes to it.
- count
- Maximum number of bytes to read. The kernel caps this at 0x7ffff000 per call; partial reads are explicitly allowed.
Description
read() attempts to read up to count bytes from the file referred to by fd into the buffer starting at buf. The number of bytes actually read is returned; this may be less than count for many reasons — the file is shorter than the request, the underlying medium is slow, a signal interrupts the call, the file is a pipe whose writer hasn't produced more data yet, or the descriptor was opened with O_NONBLOCK. A return of 0 means end of file. -1 with errno set indicates failure. read() is the highest-frequency syscall on most Linux systems and the canonical foundation of every input path: files, sockets, pipes, terminals, character devices.
Architecture mapping
| Architecture | Number | ABI | Entry point |
|---|---|---|---|
| x86 (i386) | 3 | i386 | sys_read |
| x64 (x86_64) | 0 | common | sys_read |
| ARM64 (aarch64) | 63 | — | sys_read |
Kernel history
Introduced in Linux 1.0.
1.0
read() has been part of Linux since 1.0 and follows POSIX.1, with small Linux-specific extensions around the 0x7ffff000 per-call cap and the behaviour of /proc files (which can return -1/EAGAIN or short reads in surprising ways).
seccomp & containers
Docker default profile
Allowed
Podman default profile
Allowed
read() is on every default profile and is in practice un-blockable: every input path on Linux flows through it. The seccomp lever for I/O is not read() itself — it's restricting *what fds get opened* (via openat() filtering, Landlock, or a chroot/bind-mount sandbox). If you must filter at read time, do it in userspace with a small wrapper that audits fd identity.
libseccomp
seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(read), 0);strace example
$ strace -e read head -c 16 /etc/hostname
read(3, "linux-syscalls\n", 4096) = 15
read(3, "", 4081) = 0strace truncates buffer contents at 32 bytes by default — use -s 4096 (or more) to see full reads. -e read=<fd_set> shows the buffer contents of reads on specific fds. To find why a program is blocked, attach with -p <pid> and watch for an unfinished read(N, ...) — that's the call holding things up.
Security & observability
read() shows up in three security contexts. (1) Information disclosure: data exfiltration ultimately reads it before write()ing it elsewhere — but since both syscalls are universal, monitoring at this level is noisy. (2) Side-channel exploits often involve read()ing /proc/self/maps, /proc/self/mem, or /proc/<pid>/auxv to learn ASLR offsets — flagging /proc reads from unusual contexts is high-signal. (3) Rootkits that hook read() can filter file contents in flight (e.g. removing their own entries from /proc/net/tcp). eBPF tracepoint sys_enter_read fires for every call; for monitoring, sample or filter by fd category (correlate fd to /proc/<pid>/fd) to avoid drowning. lsm/file_read is a more curated observation point.
Errors
- EAGAIN
- The fd was opened O_NONBLOCK and no data was immediately available. The caller should poll, epoll_wait, or io_uring for readiness.
- EBADF
- fd is not a valid descriptor or is not open for reading.
- EFAULT
- buf points outside the calling process's address space.
- EINTR
- The call was interrupted by a signal before any data was read.
- EINVAL
- —
- EIO
- I/O error — bad block on disk, hung NFS server, etc.
- EISDIR
- fd refers to a directory. Use getdents()/getdents64() to read directory entries.