Skip to content
/linux-syscalls

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

ArchitectureNuméroABIPoint d'entrée
x86 (i386)26i386sys_ptrace
x64 (x86_64)10164sys_ptrace
ARM64 (aarch64)117——

Historique noyau

Introduit dans Linux 1.0.

  1. 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. 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. 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. 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}]) = 0

Tracer 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
—

Syscalls liés