dwww Home | Manual pages | Find package

mprotect(2)                   System Calls Manual                  mprotect(2)

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'inter-
       valle [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  ac-
              tuellement 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 at-
       tributs 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-PA-
              RISC — 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 seg-
              ment  de pile ou d'un segment projeté avec un drapeau MAP_GROWS-
              DOWN positionné).

       Comme mprotect(), pkey_mprotect() modifie la protection des pages indi-
       qué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 in-
       diquer 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 mar-
              quer 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'er-
              reur 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  at-
              tributs  différents  (comme  la  protection  en  lecture vs lec-
              ture/é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  lec-
              ture/écriture aux extrémités et une en lecture seule au milieu).

VERSIONS
       pkey_mprotect()  est  apparu  dans Linux 4.9 ; la bibliothèque glibc le
       gère depuis la version 2.27.

STANDARDS
       mprotect() : POSIX.1-2001, POSIX.1-2008, SVr4.  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).

       pkey_mprotect() est une extension Linux non portable.

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, 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 im-
       plique 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 écri-
       ture 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'uti-
       lisation de mprotect() et de pkey_mprotect(). Sur x86, quand mprotect()
       est  utilisé avec prot positionné sur PROT_EXEC, une pkey peut être al-
       loué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_mpro-
       tect() est équivalente à mprotect().

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  al-
       loué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é. */

       static void
           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 Chris-
       tophe Blaess <https://www.blaess.fr/christophe/>, Stéphan  Rafin  <ste-
       phan.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.cou-
       lon@wanadoo.fr>, Julien Cristau <jcristau@debian.org>,  Thomas  Huriaux
       <thomas.huriaux@gmail.com>,  Nicolas François <nicolas.francois@centra-
       liens.net>, Florentin Duneau <fduneau@gmail.com>, Simon  Paillard  <si-
       mon.paillard@resel.enst-bretagne.fr>,    Denis   Barbier   <barbier@de-
       bian.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
       ⟨https://www.gnu.org/licenses/gpl-3.0.html⟩  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.03   5 février 2023                     mprotect(2)

Generated by dwww version 1.15 on Sat Jun 29 01:48:42 CEST 2024.