Wprowadzenie
W świecie Linuksa istnieje wiele narzędzi do debugowania i monitorowania procesów. Jednak u podstaw większości z nich leży jedno wywołanie systemowe: ptrace.
To właśnie ono umożliwia debuggerowi zatrzymanie programu, odczytanie jego rejestrów, ustawienie breakpointów czy śledzenie wywołań systemowych.
Co to jest ptrace?
ptrace (process trace) to system call, który pozwala jednemu procesowi (tzw. tracer) kontrolować inny proces (tracee). Najważniejsze możliwości:
- Odczyt i zapis pamięci procesu – można podejrzeć zmienne, stos czy dane w heapie.
- Odczyt i modyfikacja rejestrów CPU – np. zmiana wartości licznika instrukcji.
- Kontrola wykonania – zatrzymywanie, wznawianie, pojedyncze kroki.
- Śledzenie wywołań systemowych – np. wszystkie
open(),read(),write(). - Monitorowanie sygnałów – np. SIGSEGV, SIGKILL.
Dlaczego warto znać ptrace?
- Debugowanie – to fundament działania
gdb. - Analiza bezpieczeństwa – pozwala na sandboxing i kontrolę procesów.
- Reverse engineering – śledzenie zachowania binarek bez kodu źródłowego.
- Tworzenie własnych narzędzi – np. mini-strace w C.
Podstawowa składnia
Wywołanie systemowe:
#include <sys/ptrace.h>
long ptrace(enum __ptrace_request request, pid_t pid,
void *addr, void *data);
Najczęściej używane wywołania:
PTRACE_TRACEME– proces zgadza się być śledzony.PTRACE_ATTACH– dołączenie do istniejącego procesu.PTRACE_SYSCALL– zatrzymywanie przy każdym syscallu.PTRACE_PEEKDATA/PTRACE_POKEDATA– odczyt/zapis pamięci.PTRACE_GETREGS/PTRACE_SETREGS– odczyt/zapis rejestrów.
Przykład: prosty tracer w C
#include <sys/ptrace.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdio.h>
int main() {
pid_t child = fork();
if (child == 0) {
ptrace(PTRACE_TRACEME, 0, NULL, NULL);
execl("/bin/ls", "ls", NULL);
} else {
int status;
wait(&status);
ptrace(PTRACE_SYSCALL, child, NULL, NULL);
while (!WIFEXITED(status)) {
wait(&status);
printf("Syscall!\n");
ptrace(PTRACE_SYSCALL, child, NULL, NULL);
}
}
}
Ten kod uruchamia ls i wypisuje komunikat przy każdym syscallu.
Przykłady użycia w praktyce
strace– śledzi wszystkie wywołania systemowe procesu.gdb– debugger, który dzięki ptrace może zatrzymywać program i odczytywać pamięć.ltrace– śledzi wywołania funkcji bibliotecznych.- Sandboxing – np. ograniczanie procesów w środowisku testowym.
Wyzwania i ograniczenia
- Bezpieczeństwo – ptrace może być używany do ataków (np. odczytanie pamięci procesu).
- Wydajność – intensywne śledzenie syscalli spowalnia program.
- Uprawnienia – wymaga zwykle roota lub odpowiednich capabilities.
Podsumowanie
ptrace to fundament debugowania w Linuksie. Choć na co dzień korzystamy z narzędzi takich jak gdb czy strace, warto wiedzieć, że wszystkie one bazują na tym jednym system callu. Zrozumienie ptrace pozwala tworzyć własne narzędzia, lepiej rozumieć działanie systemu i skuteczniej diagnozować problemy.