Skip to content
/linux-syscalls

Memory · Section 2

brk(2)

Set the end of the data segment (program break) — the legacy heap-growth primitive.

Signature

#include <unistd.h>

int brk(void * addr);
addr
Desired new program break. NULL queries the current break without changing it; non-NULL is the target address. The kernel may round to page boundaries.

Description

brk() sets the program break — the address marking the end of the process's data segment (informally, the top of the heap). Called with addr == NULL, it returns the current break; called with a higher address, it grows the heap; called with a lower address, it shrinks it. The kernel actually invokes brk() as part of glibc's malloc() arena management for small allocations (below the MMAP_THRESHOLD, default 128 KiB); larger allocations bypass brk() and use mmap() directly. brk() is one of the oldest syscalls (V7 Unix); modern code rarely calls it directly — glibc's sbrk() and the underlying syscall are an internal detail. The two-call pattern (brk(NULL) to learn the current break, brk(new) to set) is universal.

Architecture mapping

ArchitectureNumberABIEntry point
x86 (i386)45i386sys_brk
x64 (x86_64)12commonsys_brk
ARM64 (aarch64)214sys_brk

Kernel history

Introduced in Linux 1.0.

  1. 1.0

    brk() has been part of Linux since 1.0 — directly inherited from V7 Unix where it was the only heap-growth mechanism. Modern allocators use mmap() for large allocations and reserve brk() for the small-block arena.

seccomp & containers

Docker default profile

Allowed

Podman default profile

Allowed

brk() is allowed by every default profile and is impossible to block usefully — glibc's malloc cannot function without it. No useful argument-level filtering.

libseccomp

seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(brk), 0);

strace example

$ strace -e brk /bin/true 2>&1 | head -3
brk(NULL)                               = 0x5650c4a6a000
brk(0x5650c4a8b000)                     = 0x5650c4a8b000

brk() appears in any program start-up — typically two calls back-to-back: brk(NULL) to read, brk(new) to set. The first set is glibc reserving its initial small-allocation arena. A sequence of growing brk() targets reveals heap growth over the program's lifetime; strace -c summary shows the total brk-time as a proxy for malloc churn.

Security & observability

brk() is rarely security-relevant on its own. The historical pattern that matters: in pre-ASLR (or partial-ASLR) systems, the heap location was predictable, which made heap-overflow exploits much easier. Modern ASLR randomises the brk() base, so heap addresses are unpredictable. eBPF tracepoint sys_enter_brk is extremely noisy and never useful in production monitoring. The one specific thing worth noting: a process that suddenly does many brk() calls expanding the heap rapidly is usually leaking memory or being abused for memory-exhaustion DoS — but rss-based detection in cgroups catches this earlier.

Errors

ENOMEM
Insufficient memory to satisfy the request, or the requested address would collide with another mapping (the heap cannot grow into mmap regions).

Related syscalls