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
| Architecture | Numéro | ABI | Point d'entrée |
|---|---|---|---|
| x86 (i386) | 90 | i386 | sys_old_mmap |
| x64 (x86_64) | 9 | common | sys_mmap |
| ARM64 (aarch64) | 222 | — | sys_mmap |
Historique noyau
Introduit dans Linux 1.0.
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.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.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.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) = 0x7f9b3c4e2000strace 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
- —