Man page - pkeys(7)

Packages contains this manual

Available languages:

en fr ru ro

Manual

pkeys

NOM
DESCRIPTION
Comportement du gestionnaire de signal
Appels systÚme des clés de protection
EXEMPLES
Source du programme
VOIR AUSSI
TRADUCTION

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 .