NOM¶
mprotect - Changer la protection d'une partie de la mémoire
SYNOPSIS¶
#include <sys/mman.h>
int mprotect(void *addr, size_t len, int prot);
DESCRIPTION¶
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-1] 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).
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_READ) == -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.44 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¶
Depuis 2010, cette traduction est maintenue à l'aide de l'outil po4a
<
http://po4a.alioth.debian.org/> par l'équipe de traduction
francophone au sein du projet perkamon
<
http://perkamon.alioth.debian.org/>.
Christophe Blaess <
http://www.blaess.fr/christophe/> (1996-2003), Alain
Portal <
http://manpagesfr.free.fr/> (2003-2006). Julien Cristau et
l'équipe francophone de traduction de Debian (2006-2009).
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> ».