Loading

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> ».