Skip to content
/linux-syscalls

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

ArchitectureNumberABIEntry point
x86 (i386)3i386sys_read
x64 (x86_64)0commonsys_read
ARM64 (aarch64)63sys_read

Kernel history

Introduced in Linux 1.0.

  1. 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)                       = 0

strace 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.

Related syscalls