Использование ptrace из многопоточных приложений

Я хочу использовать ptrace чтобы проверить, какие системные вызовы вызывает программа, созданная моей программой. Я начал с этот урок как это было объяснено в ответе на мой предыдущий вопрос. Я изменил код, адаптировав его к платформе, которую я использую (SLES 11 64 бит), и собрал следующий тестовый код, который распечатывает каждый системный вызов, создаваемый порожденным процессом:

#include <sys/ptrace.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/reg.h>
#include <sys/syscall.h>   /* For SYS_write etc */

pid_t child;

void run()
{
long orig_eax;
int status;

while(1) {
int pid = wait(&status);
if (pid == -1) {
perror("wait");
kill(child, SIGKILL);
return;
}
printf("Got event from %d.\n", pid);
if(WIFEXITED(status))
break;
orig_eax = ptrace(PTRACE_PEEKUSER,
pid, 8 * ORIG_RAX, NULL);
if (orig_eax == -1) {
perror("ptrace");
kill(child, SIGKILL);
return;
} else {
printf("Syscall %ld called.\n", orig_eax);
}
ptrace(PTRACE_SYSCALL,
pid, NULL, NULL);
}
}

int main(int /*argc*/, char* argv[])
{

child = fork();
if(child == 0) {
ptrace(PTRACE_TRACEME, 0, NULL, NULL);
execl(argv[1], argv[1], NULL);
}
else {
printf("Child process id = %d.\n", child);
run();

}
return 0;
}

Он работает довольно хорошо: он печатает идентификатор системных вызовов, сделанных программой (фактически он печатает каждый дважды, один раз при входе и один раз при выходе, но это не имеет значения сейчас). Тем не менее, моя программа должна делать другие вещи, кроме проверки системных вызовов, поэтому я решил перенести проверку в отдельный поток (мне удобнее с C ++, чем с C, поэтому я сделал это C ++, но я не думаю, что это имеет значение). Конечно, в этой программе я только запускаю поток и затем присоединяюсь к нему.

#include <sys/ptrace.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/reg.h>
#include <sys/syscall.h>   /* For SYS_write etc */

#include <boost/thread.hpp>pid_t child;

void run()
{
long orig_eax;
int status;

while(1) {
int pid = wait(&status);
if (pid == -1) {
perror("wait");
kill(child, SIGKILL);
return;
}
printf("Got event from %d.\n", pid);
if(WIFEXITED(status))
break;
orig_eax = ptrace(PTRACE_PEEKUSER,
pid, 8 * ORIG_RAX, NULL);
if (orig_eax == -1) {
perror("ptrace");
kill(child, SIGKILL);
return;
} else {
printf("Syscall %ld called.\n", orig_eax);
}
ptrace(PTRACE_SYSCALL,
pid, NULL, NULL);
}
}

int main(int /*argc*/, char* argv[])
{

child = fork();
if(child == 0) {
ptrace(PTRACE_TRACEME, 0, NULL, NULL);
execl(argv[1], argv[1], NULL);
}
else {
printf("Child process id = %d.\n", child);
boost::thread t(run);
t.join();
}
return 0;
}

На этот раз я получаю сообщение об ошибке:

Child process id = 24682.
Got event from 24682.
ptrace: No such process

Почему это? Я пытался найти ответ, но ничего подобного не нашел. я нашел это ptrace не будет отслеживать потоки, запущенные дочерним процессом, но об этом нужно поговорить позже. Можно ли вообще проверить дочерний процесс из другого терада?

Другая странная вещь заключается в том, что в моем реальном приложении я делаю в основном то же самое (но из гораздо более сложного контекста: классы, мьютексы и т. Д.) И получаю ошибку другого типа. Вместо ptrace возвращаясь с ошибкой, wait даже не возвращает системные вызовы дочернего процесса (и дочерний процесс даже не останавливается). С другой стороны, wait работает как положено при выходе из дочернего процесса.

5

Решение

Насколько я могу сказать, ptrace позволяет только один трассер на процесс. Это означает, что если вы попытаетесь присоединить, что вы можете попробовать и заставить его PTRACE_ATTACH, вы получите ошибку, сообщающую, что ptrace не удалось подключиться к указанному процессу.

Таким образом, ваша ошибка появляется потому, что ваш поток не привязан к дочернему процессу, и таким образом, когда вы пытаетесь ptrace это, это не удается, отправив -ESRCH код.

Кроме того, вы можете взглянуть на этот пост здесь, это может ответить на некоторые другие вопросы, которые у вас могут возникнуть, кроме этого.

1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]