Débogage & Trace · Section 2
ptrace(2)
Observer et contrôler un autre processus — la primitive noyau derrière gdb, strace et l'injection malveillante.
Signature
#include <sys/ptrace.h>
long ptrace(enum __ptrace_request request, pid_t pid, void * addr, void * data);- request
- Opération à effectuer. Voir ptrace(2) pour la liste complète (40+ requêtes sur les noyaux récents).
- pid
- PID du processus tracé. Ignoré pour PTRACE_TRACEME (qui opère sur l'appelant).
- addr
- Adresse argument propre à l'opération (par ex. emplacement mémoire à lire/écrire).
- data
- Argument de données propre à l'opération (valeur à écrire, pointeur de structure, numéro de signal…).
Description
ptrace() permet à un processus traceur d'observer et de modifier l'exécution d'un tracé : lire ou écrire sa mémoire et ses registres, intercepter ses signaux, le suspendre avant ou après chaque appel système, et le reprendre sous contrôle. L'argument request choisit l'opération (PTRACE_ATTACH, PTRACE_PEEKDATA, PTRACE_SYSCALL…) ; pid identifie le tracé ; addr et data portent les arguments propres à l'opération. ptrace() est privilégié : le traceur doit soit se tracer lui-même (PTRACE_TRACEME), soit disposer de CAP_SYS_PTRACE dans l'espace utilisateur du tracé, soit passer le contrôle Yama ptrace_scope (1 par défaut : seuls les ancêtres peuvent s'attacher). C'est la base de tout débogueur et de tout traceur sous Linux.
Numéros par architecture
| Architecture | Numéro | ABI | Point d'entrée |
|---|---|---|---|
| x86 (i386) | 26 | i386 | sys_ptrace |
| x64 (x86_64) | 101 | 64 | sys_ptrace |
| ARM64 (aarch64) | 117 | — | — |
Historique noyau
Introduit dans Linux 1.0.
1.0
ptrace() est présent dans Linux depuis 1.0, avec une sémantique largement héritée de BSD/SysV mais fortement étendue au fil des décennies.
2.6.34
Le LSM Yama a été ajouté pour contraindre ptrace par relation : kernel.yama.ptrace_scope règle qui peut s'attacher (0 = classique, 1 = ancêtres uniquement, 2 = admin uniquement, 3 = désactivé). Valeur par défaut 1 sur Ubuntu, Debian, Fedora.
3.4
PTRACE_SEIZE a été introduit pour s'attacher sans stopper le tracé — nécessaire à un attachement sans course et utilisé par les débogueurs modernes.
4.10
Les interactions ptrace avec l'exec de binaires set-UID et AT_SECURE ont été durcies pour empêcher les astuces d'élévation où un traceur modifie le binaire pendant la brève fenêtre de chargement.
seccomp & conteneurs
Docker default profile
Bloqué
Podman default profile
Bloqué
ptrace() est BLOQUÉ par défaut dans les profils seccomp Docker et Podman. L'autoriser dans un conteneur revient pratiquement à accorder CAP_SYS_PTRACE dans l'espace utilisateur du conteneur et laisse une charge compromise injecter du code dans les processus voisins. À n'activer que pour des conteneurs de débogage (--cap-add=SYS_PTRACE --security-opt seccomp=unconfined, jamais en production). Dans un pod de charge sans besoin légitime de débogueur, une tentative d'appel à ptrace() est un signal d'incident fort.
libseccomp
// ptrace is denied by default in Docker/Podman; explicitly block it for safety
seccomp_rule_add(ctx, SCMP_ACT_ERRNO(EPERM), SCMP_SYS(ptrace), 0);Exemple strace
$ strace -e ptrace strace -e read true 2>&1 | head -5
ptrace(PTRACE_TRACEME) = 0
ptrace(PTRACE_SETOPTIONS, 14723, NULL, PTRACE_O_TRACESYSGOOD|PTRACE_O_TRACEEXEC|PTRACE_O_TRACEEXIT) = 0
ptrace(PTRACE_SYSCALL, 14723, NULL, 0) = 0
ptrace(PTRACE_GETREGSET, 14723, NT_PRSTATUS, [{iov_base=…, iov_len=216}]) = 0Tracer strace en train de tracer une commande montre directement la boucle ptrace — chaque arrêt PTRACE_SYSCALL devient une ligne d'appel système imprimée. Utiliser -e trace=ptrace pour filtrer lors d'enquêtes. Deux strace ne peuvent pas tracer la même cible (EBUSY).
Sécurité & observabilité
ptrace est la primitive canonique d'injection de processus sous Linux, utilisée tant par les red teams que par les APT : PTRACE_ATTACH sur un voisin, PTRACE_POKEDATA du shellcode dans son espace, positionner le pointeur d'instruction avec PTRACE_SETREGS, PTRACE_DETACH. Le tracepoint eBPF sys_enter_ptrace se déclenche à chaque appel ; corréler avec /proc/<pid>/status TracerPid pour une vue complète. ptrace_scope de Yama est l'atténuation simple et efficace : la régler à 2 (admin uniquement) sur les hôtes de production sauf besoin spécifique. Sur les hôtes systemd, ProtectKernelModules et SystemCallFilter au niveau unité peuvent réduire davantage la surface de débogage.
Erreurs
- EBUSY
- La cible est déjà tracée par un autre traceur.
- EFAULT
- —
- EINVAL
- —
- EIO
- request invalide, ou addr / data invalide pour l'opération demandée.
- EPERM
- Le traceur n'a pas la permission de tracer la cible (Yama ptrace_scope, mauvaise capacité ou espace de noms, ou cible set-UID sans CAP_SYS_PTRACE).
- ESRCH
- Aucun processus avec pid, ou cible non arrêtée alors que l'opération l'exige.
Drapeaux
- PTRACE_TRACEME
- 0
- Indique que ce processus doit être tracé par son parent. Utilisé par le tracé avant exec.
- PTRACE_PEEKTEXT
- 1
- —
- PTRACE_PEEKDATA
- 2
- Lit un mot dans le segment de données du tracé à l'adresse addr.
- PTRACE_POKETEXT
- 4
- —
- PTRACE_POKEDATA
- 5
- Écrit data dans le segment de données du tracé à addr — primitive principale d'injection.
- PTRACE_CONT
- 7
- —
- PTRACE_KILL
- 8
- —
- PTRACE_SINGLESTEP
- 9
- —
- PTRACE_ATTACH
- 16
- S'attache à un processus existant et démarre le traçage. Envoie SIGSTOP au tracé.
- PTRACE_DETACH
- 17
- Arrête le traçage et reprend le tracé. Équivalent à PTRACE_CONT suivi d'un detach.
- PTRACE_SYSCALL
- 24
- Reprend le tracé jusqu'à l'entrée ou la sortie du prochain appel système — la brique de base de strace.
- PTRACE_SETOPTIONS
- 0x4200
- Configure le comportement du traceur : PTRACE_O_TRACESYSGOOD, PTRACE_O_TRACEEXEC, PTRACE_O_EXITKILL…
- PTRACE_GETSIGINFO
- 0x4202
- —
- PTRACE_SEIZE
- 0x4206
- Comme ATTACH mais ne stoppe pas le tracé ; permet de configurer des options avant tout arrêt (ajouté en 3.4).
- PTRACE_INTERRUPT
- 0x4207
- —