Provided by: manpages-fr-dev_4.26.0-1_all bug

NOM

       mprotect, pkey_mprotect - Définir la protection d'une partie de la mémoire

BIBLIOTHÈQUE

       Bibliothèque C standard (libc, -lc)

SYNOPSIS

       #include <sys/mman.h>

       int mprotect(void addr[.len], size_t len, int prot);

       #define _GNU_SOURCE             /* Consultez feature_test_macros(7) */
       #include <sys/mman.h>

       int pkey_mprotect(void addr[.len], size_t len, int prot, int pkey);

DESCRIPTION

       mprotect()  change  les  protections  d'accès  pour  la  (les)  page(s)  de mémoire du processus appelant
       contenant tout ou une partie de l'intervalle [addr, addr+len-1]. addr doit être aligné sur une limite  de
       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 est une combinaison des attributs d'accès suivants : PROT_NONE ou le résultat d’une opération OU bit
       à bit parmi les autres valeurs de la liste suivante :

       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.

       PROT_SEM (depuis Linux 2.5.7)
              La mémoire peut être utilisée pour des opérations atomiques. Cet attribut  a  été  introduit  dans
              l'implémentation de futex(2) (afin de garantir la possibilité d'effectuer des opérations atomiques
              exigées  par  des  commandes  comme  FUTEX_WAIT),  mais  il  n'est actuellement utilisé sur aucune
              architecture.

       PROT_SAO (depuis Linux 2.6.26)
              La mémoire devrait avoir une forte organisation de son accès. Cette fonctionnalité est  spécifique
              à l'architecture PowerPC (la version 2.06 de la spécification de l'architecture ajoute la fonction
              SAO du processeur, disponible par exemple sur POWER 7 ou PowerPC A2).

       En outre (depuis Linux 2.6.0), il est possible de positionner les attributs suivants sur prot :

       PROT_GROWSUP
              Appliquer  le  mode  de  protection  jusqu'à  la fin d'une projection qui grandit vers le haut (de
              telles projections sont créées pour la zone  de  la  pile  sur  une  architecture  —  par  exemple
              HP-PARISC — dont la pile a tendance à s'accroître vers le haut).

       PROT_GROWSDOWN
              Appliquer  le  mode  de protection vers le bas jusqu'au début d'une projection qui grandit vers le
              bas (il pourrait s'agir d'un segment de pile ou d'un segment projeté avec un drapeau MAP_GROWSDOWN
              positionné).

       Comme mprotect(), pkey_mprotect() modifie la protection des pages indiquées par addr et len. Le paramètre
       pkey indique la clé de protection (voir pkeys(7))) à assigner à la mémoire. La  clé  de  protection  doit
       être  allouée  avec pkey_alloc(2) avant d'être passée à pkey_mprotect(). Pour un exemple d'utilisation de
       cet appel système, voir pkeys(7).

VALEUR RENVOYÉE

       mprotect() et pkey_mprotect() renvoient  0  s'ils  réussissent.  En  cas  d'erreur,  ces  appels  système
       renvoient -1 et errno est défini pour indiquer l'erreur.

ERREURS

       EACCES L'accès  spécifié  n'est  pas possible sur ce type de mémoire. Cela se produit par exemple si vous
              utilisez mmap(2) pour représenter un fichier en lecture seule en  mémoire,  et  puis  demandez  de
              marquer cette zone avec PROT_WRITE.

       EINVAL addr n'est pas un pointeur valable, ou ce n'est pas un multiple de la taille de page du système.

       EINVAL (pkey_mprotect()) pkey n'a pas été alloué avec pkey_alloc(2)

       EINVAL PROT_GROWSUP et PROT_GROWSDOWN étaient indiqués tous les deux dans prot.

       EINVAL Drapeaux non valables indiqués dans prot.

       EINVAL (Architecture  PowerPC)  PROT_SAO  était  indiqué dans prot, mais la fonctionnalité matérielle SAO
              n'est pas disponible.

       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 (avant Linux 2.4.19, l'erreur
              EFAULT était produite à tort dans ce cas).

       ENOMEM La modification de la protection d'une zone de  la  mémoire  ferait  dépasser  le  nombre  maximal
              autorisé  de  projections  avec  des  attributs  différents  (comme  la  protection  en lecture vs
              lecture/écriture) (par exemple, positionner une protection d'une plage PROT_READ au  milieu  d'une
              zone  protégée par PROT_READ|PROT_WRITE donnerait trois projections : deux en lecture/écriture aux
              extrémités et une en lecture seule au milieu).

VERSIONS

       POSIX indique que le comportement de mprotect() n'est pas spécifié s'il s'applique à une zone de  mémoire
       non obtenue à l'aide de mmap(2).

       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, de la version du noyau et de l'état
       du processus. Sur certaines, si READ_IMPLIES_EXEC est positionné dans les  drapeaux  de  la  personnalité
       d'un processus (voir personality(2)), le fait d'indiquer PROT_READ ajoutera implicitement PROT_EXEC.

       Sur certaines architectures matérielles (comme i386), PROT_WRITE implique PROT_READ.

       POSIX.1  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é.

       Les  applications  devraient  faire  attention  quand  elles  mélangent l'utilisation de mprotect() et de
       pkey_mprotect(). Sur x86, quand mprotect() est utilisé avec prot positionné sur PROT_EXEC, une pkey  peut
       être  allouée  et  positionnée  implicitement  sur la mémoire par le noyau, mais uniquement quand la pkey
       était de 0 précédemment.

       Sur les systèmes qui ne gèrent pas les clés de protection dans le matériel, pkey_mprotect() peut toujours
       être  utilisé,  mais  pkey  doit  être  positionné  sur  -1.  Si  elle  est  appelée  ainsi,  l'opération
       pkey_mprotect() est équivalente à mprotect().

STANDARDS

       mproject()
              POSIX.1-2008.

       pkey_mprotect()
              Linux.

HISTORIQUE

       mproject()
              POSIX.1-2001, SVr4.

       pkey_mprotect()
              Linux 4.9, glibc 2.27.

NOTES

EXEMPLES

       Le  programme  ci-dessous  montre l'utilisation de mprotect(). Il 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 <malloc.h>
       #include <signal.h>
       #include <stdio.h>
       #include <stdlib.h>
       #include <sys/mman.h>
       #include <unistd.h>

       #define handle_error(msg) \
           do { perror(msg); exit(EXIT_FAILURE); } while (0)

       static char *buffer;

       static void
       handler(int sig, siginfo_t *si, void *unused)
       {
           /* Remarque : appeler printf() à partir d'un gestionnaire de signal
              n'est pas sûr (vous ne devriez pas le faire dans des programmes en
              production) car printf() n'est pas async-signal-safe ; voir
              signal-safety(7). Cependant, nous utilisons printf() ici comme
              façon simple de montrer que le gestionnaire a été appelé. */

           printf("Reçu SIGSEGV à l'adresse : %p\n", si->si_addr);
           exit(EXIT_FAILURE);
       }

       int
       main(void)
       {
           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 limite de 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 :        %p\n", buffer);

           if (mprotect(buffer + pagesize * 2, pagesize,
                        PROT_READ) == -1)
               handle_error("mprotect");

           for (char *p = buffer ; ; )
               *(p++) = 'a';

           printf("Boucle terminée\n");     /* Ne devrait jamais arriver */
           exit(EXIT_SUCCESS);
       }

VOIR AUSSI

       mmap(2), sysconf(3), pkeys(7)

TRADUCTION

       La   traduction   française   de   cette   page   de   manuel   a   été   créée   par  Christophe  Blaess
       <https://www.blaess.fr/christophe/>,   Stéphan   Rafin   <stephan.rafin@laposte.net>,   Thierry   Vignaud
       <tvignaud@mandriva.com>,  François  Micaux,  Alain Portal <aportal@univ-montp2.fr>, Jean-Philippe Guérard
       <fevrier@tigreraye.org>,   Jean-Luc   Coulon   (f5ibh)   <jean-luc.coulon@wanadoo.fr>,   Julien   Cristau
       <jcristau@debian.org>,      Thomas      Huriaux      <thomas.huriaux@gmail.com>,     Nicolas     François
       <nicolas.francois@centraliens.net>,    Florentin    Duneau    <fduneau@gmail.com>,     Simon     Paillard
       <simon.paillard@resel.enst-bretagne.fr>,     Denis    Barbier    <barbier@debian.org>,    David    Prévot
       <david@tilapin.org> et Jean-Philippe MENGUAL <jpmengual@debian.org>

       Cette traduction est une documentation libre ; veuillez vous  reporter  à  la  GNU General Public License
       version 3 concernant les conditions de copie et de distribution. Il n'y a aucune RESPONSABILITÉ LÉGALE.

       Si  vous  découvrez  un  bogue  dans la traduction de cette page de manuel, veuillez envoyer un message à
       debian-l10n-french@lists.debian.org.

Pages du manuel de Linux 6.9.1                    15 juin 2024                                       mprotect(2)