Sécurité & Identifiants · Section 2
prctl(2)
Multiplexeur de contrôle de processus : configure une centaine de leviers par processus — nom, capacités, no-new-privs, installation seccomp, dumpable, et plus.
Signature
#include <sys/prctl.h>
int prctl(int option, unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5);- option
- Opération à effectuer. Voir <sys/prctl.h> pour les constantes PR_* (>60 options).
- arg2
- Propre à l'opération. Souvent une valeur à positionner ou un pointeur de réception.
- arg3
- Propre à l'opération. Souvent une longueur de tampon ou un paramètre secondaire.
- arg4
- Propre à l'opération. La plupart des options ignorent arg4 et arg5 — doivent alors valoir 0.
- arg5
- Propre à l'opération. Idem arg4.
Description
prctl() est un appel système multiplexeur qui expose des opérations de contrôle par processus sous un même numéro. Le premier argument, option, choisit l'opération ; les autres sont propres à l'opération. Options importantes : PR_SET_NAME (positionne le nom 16 octets du processus, visible dans /proc/<pid>/comm et ps), PR_SET_DUMPABLE (contrôle si le processus peut être ptracé et s'il dump un core), PR_SET_NO_NEW_PRIVS (désactive irrévocablement l'élévation de privilèges via execve — prérequis pour installer un filtre seccomp non privilégié), PR_SET_SECCOMP (installe un filtre seccomp), PR_CAPBSET_READ / PR_CAPBSET_DROP (ensemble borne de capacités), PR_SET_PDEATHSIG (envoie un signal à ce processus quand son parent meurt). Beaucoup d'options spécifiques d'architecture existent (PR_PAC_*, PR_SVE_*, PR_SET_TAGGED_ADDR_CTRL sur aarch64 ; PR_MPX_* sur x86, retiré). Chaque option a sa propre sémantique de retour ; voir prctl(2).
Numéros par architecture
| Architecture | Numéro | ABI | Point d'entrée |
|---|---|---|---|
| x86 (i386) | 172 | i386 | sys_prctl |
| x64 (x86_64) | 157 | common | sys_prctl |
| ARM64 (aarch64) | 167 | — | sys_prctl |
Historique noyau
Introduit dans Linux 2.1.57.
2.1.57
prctl() a été ajouté en 2.1.57 pour multiplexer de nombreuses petites opérations par processus derrière un seul numéro d'appel, évitant l'ajout de nouveaux syscalls pour chaque réglage.
3.5
PR_SET_NO_NEW_PRIVS a été introduit comme pierre angulaire du sandboxing non privilégié. Avec no_new_privs, execve() ne peut élever les privilèges — sécurisant l'installation par un processus non privilégié de filtres seccomp sur ses propres enfants, sans root.
3.17
PR_SET_MM a été étendu avec des options comme PR_SET_MM_ARG_START pour permettre à l'espace utilisateur de réécrire les pointeurs argv/envv d'un processus — utilisé par setproctitle() et certains frameworks de live-patching.
5.6
PR_SET_TAGGED_ADDR_CTRL a été ajouté sur aarch64 pour activer Top Byte Ignore — l'espace utilisateur range alors 8 bits de métadonnées dans l'octet haut des pointeurs (utilisé par HWASan, MTE).
seccomp & conteneurs
Docker default profile
Autorisé
Podman default profile
Autorisé
prctl() est autorisé par défaut dans Docker / Podman. C'est aussi l'appel que tout bac à sable seccomp utilise pour s'installer lui-même (PR_SET_NO_NEW_PRIVS + PR_SET_SECCOMP), donc le bloquer entièrement se sabote soi-même. Le levier de durcissement est le filtrage d'arguments : autoriser uniquement les options PR_* dont la charge a réellement besoin (typiquement PR_SET_NAME et le duo seccomp / no-new-privs si elle se sandboxe). PR_SET_MM en particulier mérite d'être bloqué hors builds de debug — c'est un vecteur d'usurpation d'argv.
libseccomp
// Allow only the prctl options the workload actually needs.
seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(prctl),
1, SCMP_A0(SCMP_CMP_EQ, PR_SET_NAME));
seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(prctl),
1, SCMP_A0(SCMP_CMP_EQ, PR_SET_NO_NEW_PRIVS));
seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(prctl),
1, SCMP_A0(SCMP_CMP_EQ, PR_SET_SECCOMP));Exemple strace
$ strace -e prctl bash -c 'true'
prctl(PR_SET_NAME, "bash") = 0
prctl(PR_SET_DUMPABLE, SUID_DUMP_USER) = 0
prctl(PR_GET_NO_NEW_PRIVS, 0, 0, 0, 0) = 0strace décode les noms d'options PR_* et déballe leurs structures argument (par ex. PR_SET_NAME affiche le nouveau nom en chaîne). Utiliser -e prctl pour enquêter sur un binaire suspect. Le premier appel prctl(PR_SET_NAME, …) d'un processus est souvent une empreinte fiable de l'identité réelle du programme même quand le chemin du binaire a été masqué.
Sécurité & observabilité
prctl() est intéressant dans deux directions sécurité. (1) Resserrement de capacités : un init privilégié peut utiliser PR_CAPBSET_DROP pour retirer définitivement les capacités inutiles avant de forker des workers, réduisant la surface post-exploitation. PR_SET_NO_NEW_PRIVS empêche les enfants de regagner du privilège via des binaires set-UID. PR_SET_DUMPABLE(0) empêche les secrets de fuir dans les core dumps. (2) Anti-forensique : des malwares utilisent PR_SET_NAME pour se renommer en quelque chose d'inoffensif (kthread, systemd-…) dans /proc/<pid>/comm, et PR_SET_MM pour réécrire /proc/<pid>/cmdline ; ces réécritures se comparent aisément à /proc/<pid>/exe (le binaire réel, que prctl() ne peut pas réécrire). Le tracepoint eBPF sys_enter_prctl capture l'option, rendant l'activité PR_SET_NAME / PR_SET_MM très observable.
Erreurs
- EACCES
- Permission refusée — propre à l'opération, souvent lié aux champs mm (PR_SET_MM).
- EBADF
- —
- EBUSY
- —
- EFAULT
- —
- EINVAL
- option non reconnue par ce noyau, ou arg2..arg5 invalides pour l'option choisie.
- ENXIO
- —
- EPERM
- L'option requiert une capacité que l'appelant n'a pas (par ex. PR_SET_KEEPCAPS sans CAP_SETPCAP, ou PR_SET_SECUREBITS sans CAP_SETPCAP).
Drapeaux
- PR_SET_PDEATHSIG
- 1
- Délivre le signal indiqué au processus appelant lorsque son parent se termine. Utile pour le nettoyage de sous-processus détachés ; attention au recyclage de PID.
- PR_GET_DUMPABLE
- 3
- —
- PR_SET_DUMPABLE
- 4
- 0 = pas de core dump et non ptraçable ; 1 = normal ; 2 = ptraçable uniquement par root. Les binaires set-UID sont remis à 0 à l'exec — la plupart des démons en production devraient explicitement positionner 0 pour empêcher les core dumps contenant des secrets.
- PR_SET_KEEPCAPS
- 8
- —
- PR_SET_NAME
- 15
- Positionne le nom 16 octets du processus (visible dans /proc/<pid>/comm et ps). Tronqué silencieusement à 15 caractères + NUL.
- PR_GET_NAME
- 16
- —
- PR_SET_SECCOMP
- 22
- Installe un filtre seccomp. SECCOMP_MODE_FILTER attache un programme BPF ; SECCOMP_MODE_STRICT restreint à read/write/exit/sigreturn.
- PR_CAPBSET_READ
- 23
- —
- PR_CAPBSET_DROP
- 24
- Retire irrévocablement une capacité de l'ensemble borne pour ce processus et ses enfants. Essentiel pour construire un sous-processus à privilèges réduits.
- PR_GET_SECUREBITS
- 27
- —
- PR_SET_SECUREBITS
- 28
- —
- PR_SET_NO_NEW_PRIVS
- 38
- Positionne irrévocablement le bit no_new_privs. Après cela, execve() ignore set-UID, set-GID, capabilities de fichier, et AT_SECURE — prérequis dur pour les filtres seccomp non privilégiés.
- PR_GET_NO_NEW_PRIVS
- 39
- —
- PR_SET_THP_DISABLE
- 41
- —
- PR_CAP_AMBIENT
- 47
- —
- PR_SVE_SET_VL
- 50
- —
- PR_PAC_RESET_KEYS
- 54
- —
- PR_SET_TAGGED_ADDR_CTRL
- 55
- —
- PR_SET_VMA
- 0x53564d41
- —