Как я могу следить за системным вызовом из ловушки в ядро, за тем, как передаются аргументы, за тем, как системный вызов находится в ядре, за фактической обработкой системного вызова в ядре, за возвратом обратно пользователю а как состояние восстанавливается?
Как отследить системный вызов в Linux?
Ответы (3)
SystemTap
Это самый мощный метод, который я нашел до сих пор. Он даже может отображать аргументы вызова: Разрешает ли ftrace перехват аргументов системного вызова для ядра Linux или только имён функций?
Использование:
sudo apt-get install systemtap
sudo stap -e 'probe syscall.mkdir { printf("%s[%d] -> %s(%s)\n", execname(), pid(), name, argstr) }'
Затем на другом терминале:
sudo rm -rf /tmp/a /tmp/b
mkdir /tmp/a
mkdir /tmp/b
Пример вывода:
mkdir[4590] -> mkdir("/tmp/a", 0777)
mkdir[4593] -> mkdir("/tmp/b", 0777)
Документация: https://sourceware.org/systemtap/documentation.html
Похоже, на основе kprobes: https://sourceware.org/systemtap/archpaper.pdf
Проверено на Ubuntu 18.04, ядро Linux 4.15.
ltrace -S
показывает как системные вызовы, так и вызовы библиотеки
Таким образом, этот замечательный инструмент дает еще больше информации о том, что делают исполняемые файлы.
Вот, например, я использовал его, чтобы проанализировать, какие системные вызовы делает dlopen
: https://unix.stackexchange.com/questions/226524/what-system-call-is-used-to-load-libraries-in-linux/462710#462710
ftrace
минимальный запускаемый пример
Упоминается на https://stackoverflow.com/a/29840482/895245, но здесь приводится минимальный работоспособный пример.
Запустите с sudo
:
#!/bin/sh
set -eux
d=debug/tracing
mkdir -p debug
if ! mountpoint -q debug; then
mount -t debugfs nodev debug
fi
# Stop tracing.
echo 0 > "${d}/tracing_on"
# Clear previous traces.
echo > "${d}/trace"
# Find the tracer name.
cat "${d}/available_tracers"
# Disable tracing functions, show only system call events.
echo nop > "${d}/current_tracer"
# Find the event name with.
grep mkdir "${d}/available_events"
# Enable tracing mkdir.
# Both statements below seem to do the exact same thing,
# just with different interfaces.
# https://www.kernel.org/doc/html/v4.18/trace/events.html
echo sys_enter_mkdir > "${d}/set_event"
# echo 1 > "${d}/events/syscalls/sys_enter_mkdir/enable"
# Start tracing.
echo 1 > "${d}/tracing_on"
# Generate two mkdir calls by two different processes.
rm -rf /tmp/a /tmp/b
mkdir /tmp/a
mkdir /tmp/b
# View the trace.
cat "${d}/trace"
# Stop tracing.
echo 0 > "${d}/tracing_on"
umount debug
Пример вывода:
# tracer: nop
#
# _-----=> irqs-offhttps://sourceware.org/systemtap/documentation.html
# / _----=> need-resched
# | / _---=> hardirq/softirq
# || / _--=> preempt-depth
# ||| / delay
# TASK-PID CPU# |||| TIMESTAMP FUNCTION
# | | | |||| | |
mkdir-5619 [005] .... 10249.262531: sys_mkdir(pathname: 7fff93cbfcb0, mode: 1ff)
mkdir-5620 [003] .... 10249.264613: sys_mkdir(pathname: 7ffcdc91ecb0, mode: 1ff)
В этом методе замечательно то, что он показывает вызов функции для всех процессов в системе одновременно, хотя вы также можете фильтровать интересующие PID с помощью set_ftrace_pid
.
Документация по адресу: https://www.kernel.org/doc/html/v4.18/trace/index.html
Проверено на Ubuntu 18.04, ядро Linux 4.15.
Шаг GDB отладка ядра Linux
В зависимости от необходимого уровня детализации внутренних компонентов это вариант: Как отлаживать ядро Linux с помощью GDB и QEMU?
strace
минимальный запускаемый пример
Вот минимальный исполняемый пример strace
: Как следует использовать strace? с отдельно стоящим приветственным миром, благодаря которому все работает совершенно ясно.
Дополнительная информация
https://en.pingcap.com/blog/how-to-trace-linux-system-calls-in-production-with-minimal-impact-on-performance, возможно, стоит прочитать, в нем упоминается:
perf top -F 49 -e raw_syscalls:sys_enter --sort comm,dso --show-nr-samples
и цикл трассировки на основе BPF: https://github.com/kinvolk/traceloop, о котором говорится в статье чтобы быть очень быстрым методом:
sudo -E ./traceloop cgroups --dump-on-exit /sys/fs/cgroup/system.slice/sshd.service
На самом деле это относительно легко использовать ftrace
. Вот классическая статья Стивена, "Mr. ftrace", Rostedt. Вторая часть находится здесь.
Есть бесплатное видео Ян -Simon Möller из Linux Foundation и многие другие хорошие вводные статьи, которые вы можете найти, используя такие условия поиска, как «ftrace tutorial» или «ftrace example».
Вы можете использовать опции -f и -ff. Что-то вроде этого:
strace -f -e trace=process bash -c 'ls; :'
-f Отслеживать дочерние процессы по мере их создания текущими отслеживаемыми процессами в результате системного вызова fork (2).
-ff Если действует опция -o filename, трассировка каждого процесса записывается в filename.pid, где pid - это числовой идентификатор каждого процесса. Это несовместимо с -c, поскольку не ведется подсчет для каждого процесса.