Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

mremap(2)

FieldValue
Numbers (x64 / i386 / arm64-generic / arm32)25 / 163 / 216 / 163
Since (kernel)2.0
Man pageman2/mremap.2 (cached, dated 2021-03-22)
glibc wrapperyes; _GNU_SOURCE; glibc did not expose MREMAP_FIXED or the fifth argument before glibc 2.4
Aliases coverednone
Ledger IDSC-mremap

Purpose

mremap() expands or shrinks an existing virtual memory mapping, optionally relocating it. It re-points page-table entries rather than copying pages, which is how glibc implements an efficient realloc(3) for large blocks, and powers the MREMAP_DONTUNMAP userfaultfd/GC relocation tricks.

Synopsis

#define _GNU_SOURCE
#include <sys/mman.h>
void *mremap(void *old_address, size_t old_size, size_t new_size,
             int flags, ... /* void *new_address */);

Arguments and behavior

old_address must be page-aligned. With old_size = 0 and a shareable (MAP_SHARED) mapping, mremap creates a new mapping of the same pages of size new_size (requires MREMAP_MAYMOVE). The optional fifth argument new_address is required by MREMAP_FIXED and gives the page-aligned destination. Locks from mlock(2) survive resize/relocation; population of the new area is best effort and never fails the call.

Return value and errors

Returns a pointer to the new virtual memory area; MAP_FAILED ((void *) -1) with errno on failure. EAGAIN: growing a locked segment would exceed RLIMIT_MEMLOCK. EFAULT: bad address in the old range (or mixed mapping types). EINVAL (man’s enumerated list): old_address not page-aligned; unknown flag bits; new_size = 0; new range overlapping the old; FIXED/DONTUNMAP without MAYMOVE; DONTUNMAP on non-private-anonymous pages or with old_size != new_size; old_size = 0 without a shareable mapping (since 4.14 – earlier kernels silently created an unrelated private mapping, man BUGS). ENOMEM: no room to expand in place without MAYMOVE, or the new mapping cannot be created.

Flags and constants

Values verified in glibc bits/mman-shared.h (#ifdef __USE_GNU) and kernel include/linux/mman.h:

FlagValueSinceMeaning
MREMAP_MAYMOVE12.0kernel may relocate the mapping if it cannot grow in place
MREMAP_FIXED22.3.31move to exact new_address (mmap MAP_FIXED analog); clobbers what is there; requires MAYMOVE
MREMAP_DONTUNMAP45.7move but keep source mapped (zero-fill or userfaultfd on later access); requires MAYMOVE

There is no MREMAP_MUSTMOVE flag. The fixed-address flag is MREMAP_FIXED; no constant named MREMAP_MUSTMOVE exists in the kernel UAPI, in glibc bits/mman-shared.h, or in include/linux/mman.h, and the man page never mentions one (verified in this repo’s sources; also stated in worklog Task 1-b). Likewise the MADV_* constants belong to madvise, not to mremap.

Security and notes

  • Moving a mapping invalidates absolute pointers into the old location; offsets relative to the mapping start stay valid.
  • MREMAP_FIXED silently unmaps anything at the destination – the same clobbering hazard as mmap(MAP_FIXED).
  • MREMAP_DONTUNMAP works only on private anonymous mappings and leaves the source range faulting; pair it with userfaultfd(2) for non-cooperative fault handling or GC (man use-case section).
  • Linux-specific; not portable. Locked segments keep their locks but the total locked amount may change (RLIMIT_MEMLOCK accounting).

References

  • Cached man page: source-cache/man-pages-sparse/man2/mremap.2 (DESCRIPTION, ERRORS, BUGS, NOTES).
  • Constants: /usr/include/x86_64-linux-gnu/bits/mman-shared.h; /usr/include/linux/mman.h (MREMAP_MAYMOVE 1, MREMAP_FIXED 2, MREMAP_DONTUNMAP 4; no other MREMAP_* names).
  • Numbers: hub overview; cached kernel syscall tables.
  • Worklog Task 1-b: MREMAP_MUSTMOVE-nonexistence finding reused here.