Provided by: manpages-fr_4.27.0-1_all bug

NOM

       pkeys – Aperçu des clés de protection de la mémoire

DESCRIPTION

       Les  clés de protection de la mémoire (Memory Protection Keys — pkeys) sont une extension des permissions
       de la mémoire basées sur les pages. Les permissions normales  de  page  nécessitent  des  appels  système
       coûteux  et  des invalidations du TLB (Translation Lookaside Buffer) lors de modifications de permission.
       Les clés de protection de la mémoire fournissent un mécanisme pour changer  les  protections  sans  avoir
       besoin de modifier la table des pages lors de chaque modification de permission.

       Pour  utiliser  pkeys,  le  logiciel doit d’abord « étiqueter » une page dans la table des pages avec une
       pkey. Une fois cette étiquette posée, une application a seulement à changer le contenu d’un registre pour
       retirer l’accès en écriture ou tous les accès à une page étiquetée.

       Les clés de protection de  la  mémoire  fonctionnent  en  conjonction  avec  les  permissions  PROT_READ,
       PROT_WRITE  et  PROT_EXEC  existantes  passées  aux  appels système tels que mprotect(2) et mmap(2), mais
       agissent toujours pour restreindre encore plus ces mécanismes de permission traditionnels.

       Si un processus réalise un accès qui enfreint les restrictions de pkey,  il  reçoit  un  signal  SIGSEGV.
       Consultez sigaction(2) pour des détails sur l’information disponible avec ce signal.

       Pour  utiliser  la  fonctionnalité  de  pkeys,  le  processeur doit la prendre en charge et le noyau doit
       contenir une prise en charge pour la fonctionnalité d’un processeur donné. Au tout début de  2016,  seuls
       les  processeurs  x86 d’Intel à venir étaient pris en charge et ceux-ci géraient 16 clés de protection de
       la mémoire pour chaque processus. Cependant, la pkey 0 est utilisée comme clé par défaut, donc un maximum
       de 15 sont disponibles pour une utilisation effective d’application. La clé par  défaut  est  affectée  à
       n’importe  quelle région de la mémoire pour laquelle une pkey n’a pas été assignée explicitement à l’aide
       de pkey_mprotect(2).

       Les clés de protection ont la capacité d’ajouter une couche de sécurité et de fiabilité aux applications,
       mais elles n’ont pas été conçues principalement pour une fonctionnalité de sécurité. Par exemple,  WRPKRU
       est  une  instruction  entièrement non privilégiée, aussi les pkeys sont inutiles dans tous les cas où un
       attaquant contrôle le registre PKRU ou peut exécuter des instructions arbitraires.

       Les applications doivent être très précautionneuses pour assurer de ne pas faire « fuiter » leurs clés de
       protection. Par exemple, avant d’appeler pkey_free(2), l’application doit être sûre qu’aucune  mémoire  a
       cette  pkey  assignée. Si l’application laisse la pkey libérée assignée, un prochain utilisateur de cette
       pkey peut par inadvertance modifier  les  permissions  d’une  structure  de  données  étrangère,  pouvant
       impacter  la  sécurité  ou  la  stabilité.  Le  noyau  permet  actuellement  aux  pkeys  en cours d’avoir
       pkey_free(2) appelée sur elles, car cela pourrait avoir des implications de performance de processeur  ou
       de  mémoire  pour  réaliser  des  vérifications  supplémentaires  nécessaires  pour désactiver cet appel.
       L’implémentation des vérifications nécessaires est laissée aux applications. Celles-ci peuvent mettre  en
       œuvre  ces vérifications en parcourant le fichier /proc/pid/smaps pour des régions de la mémoire ayant la
       pkey assignée. Plus de détails sont fournis dans proc(5).

       Toute application voulant utiliser les clés de protection  doivent  être  capables  de  fonctionner  sans
       elles. Elles peuvent être indisponibles parce que le matériel exécutant cette application ne les prennent
       pas  en  charge,  le  code  du  noyau  ne  fournit  aucune prise en charge ou cette prise en charge a été
       désactivée, ou parce que les clés  ont  été  allouées,  peut  être  par  une  bibliothèque  utilisée  par
       l’application.  Il  est recommandé aux applications voulant utiliser les clés de protection de simplement
       appeler pkey_alloc(2) et de tester si l’appel réussit au lieu d’essayer de détecter une prise  en  charge
       de la fonctionnalité par tout autre moyen.

       Quoique  non  nécessaire,  la  prise  en  charge matérielle des clés de protection peut être déterminée à
       l’aide de l’instruction cpuid. La  manière  de  réaliser  cela  est  décrite  dans  le  manuel  pour  les
       développeurs  de  logiciels pour Intel. Le noyau réalise ce dénombrement et expose cette information dans
       le champ « flags » de /proc/cpuinfo. La chaîne «  pku  »  dans  ce  champ  indique  la  prise  en  charge
       matérielle  des clés de protection et la chaîne « ospke » indique que le noyau gère et active la prise en
       charge des clés de protection.

       Les applications  utilisant  les  threads  et  les  clés  de  protection  doivent  être  particulièrement
       attentives.  Les  threads  héritent des droits des clés de protection de leur parent au moment de l’appel
       système clone(2). Les applications doivent aussi s’assurer que leurs propres permissions sont appropriées
       pour les threads enfant au moment de l’appel clone(2) ou de  s’assurer  que  chaque  thread  enfant  peut
       réaliser sa propre initialisation des droits de clés de protection.

   Comportement du gestionnaire de signal
       Chaque  fois  qu’un  gestionnaire de signal est invoqué (y compris pour les signaux imbriqués), le thread
       obtient temporairement un nouvel ensemble par défaut de droits de clés de protection qui  outrepasse  les
       droits du contexte interrompu. Cela signifie que les applications doivent rétablir les droits désirés des
       clés  de protection lors de l’utilisation d’un gestionnaire de signal si ces droits différent de ceux par
       défaut. Les droits de n’importe quel contexte sont restaurés lors du renvoi du gestionnaire de signal.

       Ce comportement de signal est inhabituel et est dû au fait que le  registre  PKRU  x86  (qui  stocke  les
       droits  d’accès  des  clés  de  protection) est géré avec le même mécanisme matériel (XSAVE) qui gère les
       registres de virgule flottante. Le comportement du signal est le même que celui des registres de  virgule
       flottante.

   Appels système des clés de protection
       Le   noyau  Linux  met  en  œuvre  les  appels  système  suivants  relatifs  aux  clés  de  protection  :
       pkey_mprotect(2), pkey_alloc(2) et pkey_free(2).

       Les appels système de Linux pour pkey sont  disponibles  uniquement  si  le  noyau  a  été  configuré  et
       construit avec l’option CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS.

EXEMPLES

       Le  programme  ci-dessous alloue une page de mémoire avec les permissions en lecture et écriture. Puis il
       écrit quelques données dans la mémoire et les relit avec succès. Après cela, il essaie d’allouer une  clé
       de protection et désactive l’accès à la page en utilisant l’instruction WRPKRU. Il essaie alors d’accéder
       à la page qui est supposée provoquer un signal fatal pour l’application.

           $ ./a.out
           le buffer contient : 73
           sur le point de lire le buffer de nouveau...
           Segmentation fault (core dumped)

   Source du programme

       #define _GNU_SOURCE
       #include <err.h>
       #include <unistd.h>
       #include <stdio.h>
       #include <stdlib.h>
       #include <sys/mman.h>

       int
       main(void)
       {
           int status;
           int pkey;
           int *buffer;

           /*
            * Allocation d’une page de mémoire.
            */
           buffer = mmap(NULL, getpagesize(), PROT_READ | PROT_WRITE,
                         MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
           if (buffer == MAP_FAILED)
               err(EXIT_FAILURE, "mmap");

           /*
            * Mise de données aléatoires dans la page (toujours OK à affecter).
            */
           *buffer = __LINE__;
           printf("le buffer contient : %d\n", *buffer);

           /*
            * Allocation d’une clé de protection :
            */
           pkey = pkey_alloc(0, 0);
           if (pkey == -1)
               err(EXIT_FAILURE, "pkey_alloc");

           /*
            * Désactivation de l’accès à toute mémoire avec l’ensemble
            * « pkey », même si aucun droit n’existe à ce moment.
            */
           status = pkey_set(pkey, PKEY_DISABLE_ACCESS);
           if (status)
               err(EXIT_FAILURE, "pkey_set");

           /*
            * Mettre la clé de protection dans « buffer ».
            * Noter que c’est toujours lect./écrit. aussi longtemps que mprotect()
            * est concerné et que le pkey_set() précédent l’écrase.
            */
           status = pkey_mprotect(buffer, getpagesize(),
                                  PROT_READ | PROT_WRITE, pkey);
           if (status == -1)
               err(EXIT_FAILURE, "pkey_mprotect");

           printf("sur le point de lire le buffer de nouveau...\n");

           /*
            * Cela va planter car l’accès a été désactivé.
            */
           printf("le buffer contient : %d\n", *buffer);

           status = pkey_free(pkey);
           if (status == -1)
               err(EXIT_FAILURE, "pkey_free");

           exit(EXIT_SUCCESS);
       }

VOIR AUSSI

       pkey_alloc(2), pkey_free(2), pkey_mprotect(2), sigaction(2)

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-Paul Guillonneau <guillonneau.jeanpaul@free.fr>

       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                                          pkeys(7)