Как отследить только системные вызовы с помощью ftrace, не показывая никаких других функций в ядре Linux? - PullRequest
0 голосов

Например, для отслеживания всех сделанных mkdir вызовов лучшее, что я мог придумать, было:

#!/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"

# Enable tracing mkdir
echo sys_enter_mkdir > "${d}/set_event"

# Set tracer type.
echo function > "${d}/current_tracer"

# Filter only sys_mkdir as a workaround.
echo SyS_mkdir > "${d}/set_ftrace_filter"

# Start tracing.
echo 1 > "${d}/tracing_on"

# Generate two mkdir calls.
rm -rf /tmp/a
rm -rf /tmp/b
mkdir /tmp/a
mkdir /tmp/b

# View the trace.
cat "${d}/trace"

# Stop tracing.
echo 0 > "${d}/tracing_on"

umount debug

А затем после запуска с sudo выдает:

# tracer: function
#
# entries-in-buffer/entries-written: 4/4   #P:16
#
#                              _-----=> irqs-off
#                             / _----=> need-resched
#                            | / _---=> hardirq/softirq
#                            || / _--=> preempt-depth
#                            ||| /     delay
#           TASK-PID   CPU#  ||||    TIMESTAMP  FUNCTION
#              | |       |   ||||       |         |
           mkdir-31254 [015] .... 2010985.576760: sys_mkdir(pathname: 7ffc54b32c77, mode: 1ff)
           mkdir-31254 [015] .... 2010985.576763: SyS_mkdir <-tracesys_phase2
           mkdir-31255 [007] .... 2010985.578363: sys_mkdir(pathname: 7fff02d90c77, mode: 1ff)
           mkdir-31255 [007] .... 2010985.578365: SyS_mkdir <-tracesys_phase2

Моя проблема с этим заключается в том, что он выводит две строки для каждого системного вызова:

  • sys_mkdir, это событие, которое я хочу
  • SyS_mkdir, которое является отфильтрованной функциейОбходной путь, который я не хочу видеть

Если я вместо этого попытаюсь сделать:

echo > "${d}/set_ftrace_filter"

или вообще не трогать этот файл, то он показываеттонны функций и затрудняют написание системного вызова вообще.

Если есть лучший способ отключить обычные функции и сохранять только события системного вызова?

Я мог бы использовать только SyS_mkdir иЯ полагаю, отключить событие syscall, но мне кажется, что я могу использовать более конкретное событие?Также:

  • событие показывает аргументы, что лучше.
  • Имена функций системного вызова меняются в зависимости от версии ядра.Например, это уже __x64_sys_mkdir вместо SyS_mkdir в Linux v4.18.

Связано:

Протестировано на Ubuntu 18.04, ядро ​​Linux 4.15.

Ответы [ 2 ]

0 голосов
/ 12 октября 2018

Кроме того, стоит упомянуть еще один лаконичный способ получения такой информации.Можно сделать что-то вроде:

stap -e 'probe syscall.mkdir { printf("%s[%d] -> %s(%s)\n", execname(), pid(), name, argstr) }'

Выход :

systemd-journal[318] -> mkdir("/var/log/journal/c8d2562a041649cdbfd1ac5e24dbe0db", 0755)
systemd-journal[318] -> mkdir("/var/log/journal/c8d2562a041649cdbfd1ac5e24dbe0db", 0755)
mkdir[4870] -> mkdir("wtf", 0777)
...

Другой способ:

stap -e 'probe kernel.function("sys_mkdir") { printf("%s[%d] (%s)\n", execname(), pid(), $$parms) }'

Выход:

systemd-journal[318] (pathname=0x55b74f7ab8b0 mode=0x1ed)
systemd-journal[318] (pathname=0x55b74f7ab8b0 mode=0x1ed)
mkdir[8532] (pathname=0x7ffcf30af761 mode=0x1ff)
...

Вы можете настроить вывод по своему усмотрению.

PS Systemtap основан на kprobes. Архитектура Doc поможет понять его внутренности.

Подробнее о SystemTap .

0 голосов

Используйте nop трассировщик

В качестве , предложенного sruffell , все, что нам нужно сделать, это использовать nop трассировщик вместо function, и это отключит следы функций, но не события.

Запуск с 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

Это дает желаемый результат:

   mkdir-26064 [007] .... 2014370.909743: sys_mkdir(pathname: 7fffbd461c77, mode: 1ff)
   mkdir-26065 [014] .... 2014370.911615: sys_mkdir(pathname: 7ffea53bac77, mode: 1ff)

Альтернативное не лучшее решение

Это также работает, но определенно менее приятно, замените:

echo SyS_mkdir > "${d}/set_ftrace_filter"

на:

echo '*' > "${d}/set_ftrace_notrace"

Это отключаетсявсе функции, упомянутые в документации: https://www.kernel.org/doc/html/v4.18/trace/ftrace.html#the-file-system

set_ftrace_notrace:

Это имеет эффект, противоположный эффекту set_ftrace_filter.Любая добавленная здесь функция не будет отслеживаться.Если функция существует как в set_ftrace_filter, так и в set_ftrace_notrace, функция будет не отслеживаться.

...