NOM
mprotect - Changer la protection d’une partie de la mémoire
SYNOPSIS
#include <sys/mman.h>
int mprotect(const void *addr, size_t len, int prot);
mprotect() change la protection pour la (les) page(s) mémoire du
processus appelant contenant tout ou une partie de l’intervalle
[addr,addr+len-1]. addr doit être aligné sur une page.
Si le processus appelant essaie d’accéder à la mémoire en violant la
protection, le noyau génère un signal SIGSEGV pour ce processus.
prot soit PROT_NONE, soit un OU binaire « | » entre les valeurs
suivantes :
PROT_NONE On ne peut pas accéder du tout à la zone de mémoire.
PROT_READ On peut lire la zone de mémoire.
PROT_WRITE On peut modifier la zone de mémoire.
PROT_EXEC La zone de mémoire peut contenir du code exécutable.
VALEUR RENVOYÉE
mprotect() renvoie 0 s’il réussit, ou -1 s’il échoue, auquel cas errno
contient le code d’erreur.
ERREURS
EACCES L’accès spécifié n’est pas possible sur ce type de mémoire. Ceci
se produit par exemple si vous utilisez mmap(2) pour représenter
un fichier en lecture seule en mémoire, et si vous demandez de
marquer cette zone avec PROT_WRITE.
EINVAL addr n’est pas un pointeur valide, ou ce n’est pas un multiple
de la taille de page du système.
ENOMEM Impossible d’allouer des structures internes au noyau.
ENOMEM Les adresses dans l’intervalle [addr, addr+len] ne sont pas
valables dans l’espace d’adressage du processus, ou l’intervalle
s’étend sur des pages non projetées (dans les noyaux antérieurs
à 2.4.19, l’erreur EFAULT était produite à tort dans ce cas).
CONFORMITÉ
SVr4, POSIX.1-2001. POSIX précise que le comportement de mprotect()
n’est pas spécifié s’il est appliqué sur des zones de mémoire non
obtenues avec mmap(2).
NOTES
Sous Linux, il est toujours autorisé d’appeler mprotect() sur une
adresse de l’espace d’adressage du processus (excepté pour la zone
vsyscall du noyau). En particulier, il peut être utilisé pour rendre
une projection de code existante accessible en écriture.
La différence entre PROT_EXEC et PROT_READ dépend de l’architecture et
de la version du noyau. Sur certaines architectures matérielles (par
exemple, i386), PROT_WRITE implique PROT_READ.
POSIX.1-2001 indique qu’une implémentation peut autoriser un accès
autre que celui donné dans prot, mais doit au minimum autoriser l’accès
en écriture si PROT_WRITE était passé, et ne doit autoriser aucun accès
si PROT_NONE était passé.
EXEMPLE
Le programme ci‐dessous alloue quatre pages de mémoire, rend la
troisième accessible en lecture seule, puis exécute une boucle qui se
déplace en avançant dans la région allouée et en modifiant son contenu.
Voici un exemple d’exécution de ce programme :
$ ./a.out
Début de la région : 0x804c000
Reçu SIGSEGV à l’adresse : 0x804e000
Source du programme
#include <unistd.h>
#include <signal.h>
#include <stdio.h>
#include <malloc.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/mman.h>
#define handle_error(msg) \
do { perror(msg); exit(EXIT_FAILURE); } while (0)
char *buffer;
static void
handler(int sig, siginfo_t *si, void *unused)
{
printf("Reçu SIGSEGV à l’adresse : 0x%lx\n",
(long) si->si_addr);
exit(EXIT_FAILURE);
}
int
main(int argc, char *argv[])
{
char *p;
int pagesize;
struct sigaction sa;
sa.sa_flags = SA_SIGINFO;
sigemptyset(&sa.sa_mask);
sa.sa_sigaction = handler;
if (sigaction(SIGSEGV, &sa, NULL) == -1)
handle_error("sigaction");
pagesize = sysconf(_SC_PAGE_SIZE);
if (pagesize == -1)
handle_error("sysconf");
/* Allouer un tampon aligné sur une page ;
la protection initiale est PROT_READ | PROT_WRITE */
buffer = memalign(pagesize, 4 * pagesize);
if (buffer == NULL)
handle_error("memalign");
printf("Début de la région : 0x%lx\n", (long) buffer);
if (mprotect(buffer + pagesize * 2, pagesize,
PROT_NONE) == -1)
handle_error("mprotect");
for (p = buffer ; ; )
*(p++) = 'a';
printf("Boucle terminée\n"); /* Ne devrait jamais arriver */
exit(EXIT_SUCCESS);
}
VOIR AUSSI
mmap(2), sysconf(3)
COLOPHON
Cette page fait partie de la publication 3.23 du projet man-pages
Linux. Une description du projet et des instructions pour signaler des
anomalies peuvent être trouvées à l’adresse
http://www.kernel.org/doc/man-pages/.
TRADUCTION
Cette page de manuel a été traduite et mise à jour par Christophe
Blaess <http://www.blaess.fr/christophe/> entre 1996 et 2003, puis par
Alain Portal <aportal AT univ-montp2 DOT fr> jusqu’en 2006, et mise à
disposition sur http://manpagesfr.free.fr/.
Les mises à jour et corrections de la version présente dans Debian sont
directement gérées par Julien Cristau <jcristau@debian.org> et l’équipe
francophone de traduction de Debian.
Veuillez signaler toute erreur de traduction en écrivant à
<debian-l10n-french@lists.debian.org> ou par un rapport de bogue sur le
paquet manpages-fr.
Vous pouvez toujours avoir accès à la version anglaise de ce document
en utilisant la commande « man -L C <section> <page_de_man> ».