Я пытаюсь использовать 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
в _ 4_, который выглядит как установить всякий раз, когда 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? strong> Есть ли другой способ для пользовательского процесса получить эту информацию о другом процессе, для отслеживания которого он авторизован?