Вопрос или проблема
Я совсем новичок в Linux и поэтому буду признателен за любые советы по пониманию системных вызовов и возможности, знания и инструменты для обратной разработки их происхождения или их процесса выполнения.
Как следует из названия, я представляю пример, являющийся моим анализом процесса Xorg, который я отслеживал в моем окружении рабочего стола Linux. Таким образом, я пытаюсь понять процесс выполнения вызовов DRM_IOCTL, в данном случае специфического системного вызова DRM_IOCTL_CURSOR2, который происходит в этом процессе. Моя цель – понять, что вызывает этот вызов в этом окружении рабочего стола, или скорее, какие шаги я могу предпринять в общем, чтобы исследовать подобные вопросы.
Из моего ограниченного понимания я знаю, что Xorg запускается как подпроцесс SDDM, но помимо инициации сервера Xorg, у меня нет представления о том, как пройти через процесс и определить триггеры для некоторых процессных вызовов или, возможно, использовать инструменты для этого. Таким образом, это концептуальный вопрос о том, как подойти к анализу таких вопросов в общем. Потребуются ли здесь какие-то специфические знания о текущем процессе и его архитектуре. Могу ли я воспользоваться какими-либо общими подходами на моей системе для отслеживания системных вызовов, подобно выявлению ppids процессов для моего собственного интереса.
На данный момент я слабо знаком с использованием таких инструментов, как strace, bpftrace и общие командные инструменты, такие как ps и lsof. Извиняюсь, если это общий вопрос, если так, я буду рад сузить его еще больше.
Да, это звучит хорошо: bpftrace
, чтобы определить, как часто делается системный вызов и кем, а также strace
, чтобы выяснить, какие системные вызовы делает конкретный процесс. Значительная часть достигнута!
Следующая часть – это выяснить, какие функции в вашем процессе выполняют системные вызовы – и единственный способ сделать это – подключиться к отладчику.
По умолчанию отладчик в Linux – это gdb
. Давайте проведем вас через это.
Предварительное условие (пока): Наличие отладочных символов для вашего процесса. Это легко, если вы что-то создали сами и включены отладочные символы (но тогда, что же вы декомпилируете); это легко, если вы можете использовать возможности вашей системы для загрузки для вас отладочной информации. Мне нравится, что Fedora (и другие основные дистрибутивы Linux, такие как Debian или Ubuntu) предлагают символы debuginfod
, это делает данный процесс значительно проще.
- Установите
gdb
. - Установите переменную среды, указывающую
gdb
, где найти данные debuginfod (необязательно, но делает вещи намного читабельнее для начала; отрегулируйте URL для вашего дистрибутива):export DEBUGINFOD_URLS=https://ubuntu.com/server/docs/about-debuginfod
- найдите ID процесса (pid) процесса, с которым вы хотите работать (например, с помощью
bpftrace
) - подключите
gdb
к этому PID:gdb --pid the_pid_you_care_about
. На этом этапе, возможно, потребуется загрузить много отладочной информации. - скажите
gdb
поймать все системные вызовы, которые являютсяioctl
, а затем продолжите выполнение:(gdb) catch syscall ioctl (gdb) continue
- вас вернут к интерфейсу gdb каждый раз, когда вызывается ioctl; в этот момент вы можете сделать, например,
backtrace
, чтобы увидеть стек вызовов, включая имена функций, иprint
переменные из текущего кадра стека (если они не были оптимизированы компилятором) - вы можете
detach
от процесса илиquit
(и убить его)
В любом случае, то, как работает пункт 5, немного неудобно: вы на самом деле не хотите останавливаться на каждом ioctl
, только на ioctl
с конкретными аргументами, и вы не очень хотите останавливаться, вы хотите сделать обратный трассировку и записать это в файл, возможно. Так что, вместо 4-го пункта вы могли бы сделать:
(gdb) set logging on
(gdb) set logging file ~/mylog.txt
(gdb) catch syscall ioctl
(gdb) commands
backtrace
continue
end
(gdb) continue
Конечно, ситуация, когда у вас есть отладочные символы, очень роскошна, но для начала давайте не усложнять себе жизнь больше, чем необходимо ^^.
Если вы столкнетесь с программой, для которой вы не можете получить отладочные символы, вы, вероятно, будете использовать сочетание живой отладки, дизассемблирования, пошагового выполнения и присвоения имен адресам памяти, например, в достаточно мощном инструменте ghidra
.
.
Ответ или решение
Конечно, для глубокого понимания и обратного проектирования системных вызовов, например, в окружении Linux, необходим подход, сочетающий использование инструментов, таких как strace
, bpftrace
, gdb
, и понимание архитектуры процесса. Рассмотрим шаги, которые помогут вам разобраться с проблемой изучения системных вызовов, на примере аналитики DRM_IOCTL_CURSOR2
вызова в процессе Xorg
вашего десктопного окружения.
Шаги для Анализа
1. Подготовка рабочей среды
Убедитесь, что у вас установлены все необходимые инструменты для анализа: gdb
, bpftrace
, strace
. Эти инструменты предоставят возможность отслеживать и анализировать системные вызовы.
2. Определение идентификатора процесса
Используйте командные инструменты, такие как ps
или bpftrace
, чтобы определить PID процесса Xorg
. Это можно сделать, выполнив команду ps aux | grep Xorg
.
3. Работа с strace
Запустите strace
, чтобы получить информацию о системных вызовах, выполняемых процессом. Например:
strace -p [PID]
Так вы сможете увидеть, когда вызывается DRM_IOCTL_CURSOR2
, и какие параметры ему передаются.
4. Использование bpftrace
для анализа паттернов
При помощи bpftrace
вы можете наблюдать за частотой вызова конкретных системных вызовов и их источниками:
bpftrace -e 'tracepoint:syscalls:sys_enter_ioctl /pid == [PID]/ { @[comm] = count(); }'
Это позволит вам увидеть, какие команды чаще всего инициируют вызов ioctl
.
5. Глубокий анализ с gdb
Теперь, для детального исследования, используйте gdb
:
-
Подключитесь к процессу:
gdb --pid [PID]
-
Установите отлов вызова
ioctl
:(gdb) catch syscall ioctl
-
Продолжите выполнение программы:
(gdb) continue
Каждый раз при срабатывании
ioctl
вы будете возвращаться в интерфейсgdb
, где сможете использовать командуbacktrace
, чтобы увидеть стек вызовов. -
Настройте логирование, чтобы автоматизировать процесс:
(gdb) set logging on (gdb) set logging file ~/mylog.txt (gdb) catch syscall ioctl (gdb) commands (gdb) backtrace (gdb) continue (gdb) end (gdb) continue
Альтернативные подходы
Если отладочные символы недоступны, вам может понадобиться погрузиться в дизассемблирование и отладку с использованием инструментов, таких как ghidra
. Это усложнит задачу, так как придётся вручную исследовать машинный код и проводить обратное проектирование для определения логики.
Заключение
Процесс понимания и обратного проектирования системных вызовов требует сочетания нескольких техник и инструментов. На первом этапе можно использовать высокоуровневые утилиты для получения общего представления, и затем перейти к более низкоуровневым инструментам для детального анализа. Это комплексный подход позволит вам глубже понять взаимодействие процессов и системных вызовов в среде Linux.
Такой детальный анализ поможет вам, как специалисту, точно определить триггеры вызовов и построить понимание внутренней логики работы процесса, особенно в контексте таких сложных экосистем, как десктопные окружения на базе Linux.