Первый kprobe на eBPF: следим за открытием файлов

19 апреля 2026 · 6 минут

Задача простая: увидеть, какие процессы какие файлы открывают, не перезапуская их и не трогая strace. eBPF позволяет повесить обработчик на функцию ядра и получать события почти без накладных расходов.

Одной строкой

В современных ядрах все варианты open сходятся в do_sys_openat2. Её второй аргумент — указатель на имя файла в пространстве пользователя:

sudo bpftrace -e 'kprobe:do_sys_openat2 {
    printf("%-16s %s\n", comm, str(arg1));
}'

arg0 здесь — дескриптор каталога, arg1 — путь, arg2 — указатель на struct open_how. Функция появилась в ядре 5.6; на более старых ядрах нужно цепляться к do_sys_open, где путь тоже лежит во втором аргументе.

Почему kprobe хрупкий

kprobe цепляется к внутренней функции ядра, а у неё нет стабильного интерфейса: её могут переименовать, заинлайнить или поменять порядок аргументов. Для долгоживущих инструментов надёжнее tracepoint:

sudo bpftrace -e 'tracepoint:syscalls:sys_enter_openat {
    printf("%-16s %s\n", comm, str(args.filename));
}'

Tracepoint описан форматом в /sys/kernel/tracing/events/syscalls/sys_enter_openat/format, и поля там именованные — гадать, в каком регистре что лежит, не нужно.

Дальше

bpftrace хорош для разведки, но для постоянного сервиса я переписал то же самое на libbpf с CO-RE: один бинарник работает на разных ядрах без пересборки. Об этом — в следующей заметке, когда доберусь.

ebpflinuxtracing