Я пытаюсь использовать ptrace для отслеживания всех системных вызовов, выполненных отдельным процессом, будь то 32-разрядный (IA-32) или 64-разрядный (x86-64).Мой трассировщик будет работать на 64-битной установке x86 с включенной эмуляцией IA-32, но в идеале сможет отслеживать как 64-битные, так и 32-битные приложения, в том числе, если 64-битное приложение разветвляется и исполняет 32-битный процесс.
Проблема в том, что, поскольку 32-разрядные и 64-разрядные номера системных вызовов различаются, мне нужно знать, является ли процесс 32-разрядным или 64-разрядным, чтобы определить, какой системный вызов он использовал, даже если у меня естьномер системного вызова.Кажется, есть несовершенные методы , такие как проверка /proc/<pid>/exec
или (как это делает strace) размер структуры регистров, но ничего надежного.
Сложность в том, что 64-битныйпроцессы могут переключаться из длинного режима для непосредственного выполнения 32-битного кода.Они также могут делать 32-битные int $0x80
системные вызовы , которые, конечно, используют 32-битные числа системных вызовов.Я не «доверяю» процессам, которые отслеживаю, чтобы не использовать эти уловки, поэтому я хочу правильно их обнаружить.И я независимо проверил, что, по крайней мере, в последнем случае, ptrace видит 32-битные числа системных вызовов и назначения регистров аргументов, а не 64-битные.
Я покопался в исходном коде ядра и наткнулся нафлаг TS_COMPAT
в arch/x86/include/asm/processor.h
, который представляется установленным всякий раз, когда 32-битный системный вызов выполняется 64-битным процессом.Единственная проблема в том, что я понятия не имею, как получить доступ к этому флагу из пользовательского пространства, или если это вообще возможно.
Я также думал о чтении %cs
и сравнении его с $0x23
или $0x33
Вдохновленный этим методом для переключения битности в работающем процессе.Но это только обнаруживает 32-битные процессы , не обязательно 32-битные системные вызовы (те, которые сделаны с int $0x80
) из 64-битного процесса.Он также хрупок, поскольку полагается на недокументированное поведение ядра.
Наконец, я заметил, что в архитектуре x86 есть немного для длинного режима в MSR регистра расширенных возможностей.Но ptrace не может прочитать MSR из трассировки, и я чувствую, что чтение изнутри моего трассировщика будет неадекватным, потому что мой трассировщик всегда работает в длинном режиме.
Я в растерянности.Возможно, я мог бы попытаться использовать один из этих хаков - на данный момент я склоняюсь к %cs
или к /proc/<pid>/exec
методу - но я хочу что-то долговечное, что на самом деле будет отличать 32-битные и 64-битные системные вызовы. Как процесс, использующий ptrace под x86-64, который обнаружил, что его трассировка сделала системный вызов, надежно определяет, был ли этот системный вызов выполнен с 32-разрядным (int $0x80
) или 64-разрядным (syscall
)ABI? Есть ли какой-то другой способ для пользовательского процесса получить эту информацию о другом процессе, для которого он авторизован ptrace?