Skip to content
/linux-syscalls

Mémoire · Section 2

mmap(2)

Projette un fichier ou de la mémoire anonyme dans l'espace d'adressage du processus.

Signature

#include <sys/mman.h>

void * mmap(void * addr, size_t length, int prot, int flags, int fd, off_t offset);
addr
Indication (ou exigence avec MAP_FIXED) de l'adresse de placement. Généralement NULL.
length
Taille de la projection en octets. Arrondie au multiple supérieur de la taille de page.
prot
OU bit-à-bit de PROT_READ, PROT_WRITE, PROT_EXEC ou PROT_NONE. Doit être compatible avec le mode d'ouverture du fichier.
flags
Drapeau de partage (MAP_SHARED ou MAP_PRIVATE — exactement un) OU avec des modificateurs (MAP_ANONYMOUS, MAP_FIXED, MAP_HUGETLB, MAP_STACK, etc.).
fd
Descripteur du fichier à projeter ; ignoré si MAP_ANONYMOUS est positionné (passer -1 par convention).
offset
Décalage en octets dans le fichier ; doit être un multiple de la taille de page.

Description

mmap() crée une nouvelle projection dans l'espace d'adressage virtuel du processus appelant. addr est une indication d'adresse de départ ; avec MAP_FIXED elle devient impérative. length est arrondi au multiple supérieur de la taille de page. prot décrit la protection mémoire souhaitée (combinaison de PROT_READ, PROT_WRITE, PROT_EXEC ou PROT_NONE) et flags choisit la sémantique de partage (MAP_SHARED ou MAP_PRIVATE) plus des modificateurs. Si fd désigne un fichier, celui-ci est projeté à partir de offset ; avec MAP_ANONYMOUS la projection est adossée à des pages remplies de zéros et fd est ignoré. mmap() retourne l'adresse de la projection ou MAP_FAILED ((void *) -1) en cas d'erreur.

Numéros par architecture

ArchitectureNuméroABIPoint d'entrée
x86 (i386)90i386sys_old_mmap
x64 (x86_64)9commonsys_mmap
ARM64 (aarch64)222—sys_mmap

Historique noyau

Introduit dans Linux 1.0.

  1. 2.4.0

    MAP_ANONYMOUS a été clarifié et standardisé comme moyen portable d'allouer de la mémoire à zéros ; il a largement remplacé l'ancien idiome /dev/zero.

  2. 2.6.32

    MAP_STACK a été introduit comme indication pour les allocations de pile de threads ; sur certaines architectures il influence la gestion des pages de garde.

  3. 3.10

    Le codage MAP_HUGE_2MB / MAP_HUGE_1GB a été ajouté pour permettre de demander une taille de grande page spécifique via les bits hauts de flags.

  4. 4.17

    MAP_FIXED_NOREPLACE a été ajouté pour permettre la sélection d'une adresse fixe sans détruire silencieusement une projection existante — un piège historique de MAP_FIXED.

seccomp & conteneurs

Docker default profile

Autorisé

Podman default profile

Autorisé

mmap() figure dans les profils par défaut de Docker et Podman et est en pratique impossible à bloquer — tout chargeur dynamique, malloc glibc au-dessus du seuil brk, et compilateur JIT l'utilise. Un durcissement utile est d'autoriser mmap() sauf si PROT_EXEC est demandé sur une projection anonyme (signal fort de génération de code en-cours-de-processus, utilisée par les JIT comme par les exploits). Pour appliquer W^X à un conteneur, contraindre mprotect() avec le même masque.

libseccomp

// Allow mmap but block PROT_EXEC anonymous mappings (W^X enforcement)
seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mmap),
    1, SCMP_A2(SCMP_CMP_MASKED_EQ, PROT_EXEC, 0));

Exemple strace

$ strace -e mmap cat /etc/hostname
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f9b3c4f3000
mmap(NULL, 65536, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f9b3c4e3000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f9b3c4e2000

strace affiche les arguments de mmap décompressés — flags devient MAP_PRIVATE|MAP_ANONYMOUS|… et prot devient PROT_READ|PROT_WRITE|… — ce qui rend les allocations PROT_EXEC|PROT_WRITE suspectes immédiatement visibles. Filtrer avec -e trace=mmap.

Sécurité & observabilité

mmap() est le vecteur principal de génération de code in-process : un shellcode est typiquement projeté via mmap(NULL, …, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) avant d'être appelé. Le tracepoint eBPF sys_enter_mmap se déclenche à chaque appel ; filtrer par prot=PROT_EXEC et flags & MAP_ANONYMOUS donne un flux à fort signal. Certains rootkits utilisent aussi mmap() de /dev/mem ou /proc/kcore pour inspecter la mémoire noyau sur des systèmes mal configurés. Surveiller les mmap() avec prot=PROT_EXEC depuis des processus qui ne devraient jamais faire de JIT.

Erreurs

EACCES
fd désigne un fichier non ouvert pour le mode demandé, ou MAP_SHARED a été demandé sur un fd en lecture seule.
EAGAIN
RLIMIT_MEMLOCK serait dépassé (MAP_LOCKED) ou épuisement temporaire de ressources.
EBADF
fd n'est pas un descripteur valide et MAP_ANONYMOUS n'est pas positionné.
EEXIST
—
EINVAL
Mauvaise combinaison de flags, length, offset ou addr (ex. addr non aligné sur la page avec MAP_FIXED).
ENFILE
—
ENODEV
—
ENOMEM
Mémoire indisponible, RLIMIT_AS dépassé, ou nombre maximum de projections (vm.max_map_count) atteint.
EOVERFLOW
—
EPERM
—
ETXTBSY
MAP_DENYWRITE sur un fichier ouvert en écriture.

Drapeaux

MAP_SHARED
0x01
Les modifications sont visibles par les autres processus projetant le même fichier et persistées au disque lors de l'écriture différée.
MAP_PRIVATE
0x02
Projection en copie-à-l'écriture ; les modifications ne sont pas propagées au fichier ni aux autres projecteurs.
MAP_SHARED_VALIDATE
0x03
—
MAP_FIXED
0x10
Placer la projection exactement à addr, écrasant toute projection existante. Rarement sûr ; préférer MAP_FIXED_NOREPLACE.
MAP_FIXED_NOREPLACE
0x100000
Comme MAP_FIXED mais échoue avec EEXIST plutôt que d'écraser une projection existante (ajouté en 4.17).
MAP_ANONYMOUS
0x20
La projection n'est adossée à aucun fichier ; les pages sont initialisées à zéro. fd est ignoré.
MAP_GROWSDOWN
0x0100
—
MAP_HUGETLB
0x40000
Alloue la projection en grandes pages. À combiner avec MAP_HUGE_2MB ou MAP_HUGE_1GB encodé dans les bits hauts de flags.
MAP_LOCKED
0x2000
—
MAP_NORESERVE
0x4000
—
MAP_POPULATE
0x8000
Pré-charge les tables de pages de toute la projection (utile pour réduire la latence des défauts de page ultérieurs).
MAP_STACK
0x20000
Indique que la projection servira de pile de thread ; influence le placement des pages de garde.
PROT_READ
0x1
—
PROT_WRITE
0x2
—
PROT_EXEC
0x4
Les pages peuvent être exécutées comme du code. Dangereux combiné à PROT_WRITE — voir W^X.
PROT_NONE
0x0
—

Syscalls liés