Man page - pkey_mprotect(2)

Packages contains this manual

Available languages:

en fr ja ru

Manual

mprotect

NOM
BIBLIOTHÈQUE
SYNOPSIS
DESCRIPTION
VALEUR RENVOYÉE
ERREURS
VERSIONS
STANDARDS
HISTORIQUE
NOTES
EXEMPLES
Source du programme
VOIR AUSSI
TRADUCTION

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 .