Может дочерний процесс использовать ptrace
системный вызов для трассировки его родителя?
OS является linux 2.6
Спасибо.
upd1: Я хочу проследить process1 от "себя". Это невозможно, таким образом, я действительно разветвляю и пытаюсь сделать ptrace(process1_pid, PTRACE_ATTACH)
от дочернего процесса. Но я не могу, существует странная ошибка, как ядро мешает ребенку прослеживать их родительские процессы
UPD2: такая трассировка может быть запрещена политикой безопасности. Какие полицейские делают это? Где код проверки в ядре?
UPD3: на моем встроенном Linux у меня нет ошибок с PEEKDATA, но не с GETREGS:
child: getregs parent: -1
errno is 1, strerror is Operation not permitted
errno = EPERM
Меня очень заинтересовал этот вопрос. Поэтому я написал код, чтобы опробовать его.
Во-первых, имейте в виду, что при трассировке процесса процесс трассировки становится родительским для большинства целей, за исключением названия (например, getppid ()
). Во-первых, полезен отрывок из раздела PTRACE_ATTACH
руководства:
PTRACE_ATTACH
Attaches to the process specified in pid, making it a traced
"child" of the calling process; the behavior of the child is as
if it had done a PTRACE_TRACEME. The calling process actually
becomes the parent of the child process for most purposes (e.g.,
it will receive notification of child events and appears in
ps(1) output as the child's parent), but a getppid(2) by the
child will still return the PID of the original parent. The
child is sent a SIGSTOP, but will not necessarily have stopped
by the completion of this call; use wait(2) to wait for the
child to stop. (addr and data are ignored.)
Вот код, который я написал, чтобы проверить и убедиться, что вы действительно можете ptrace ()
ваш родитель (вы можете создать это, выгрузив его в файл с именем blah.c
и запустив make blah
:
#include <assert.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/ptrace.h>
int main()
{
pid_t pid = fork();
assert(pid != -1);
int status;
long readme = 0;
if (pid)
{
readme = 42;
printf("parent: child pid is %d\n", pid);
assert(pid == wait(&status));
printf("parent: child terminated?\n");
assert(0 == status);
}
else
{
pid_t tracee = getppid();
printf("child: parent pid is %d\n", tracee);
sleep(1); // give parent time to set readme
assert(0 == ptrace(PTRACE_ATTACH, tracee));
assert(tracee == waitpid(tracee, &status, 0));
printf("child: parent should be stopped\n");
printf("child: peeking at parent: %ld\n", ptrace(PTRACE_PEEKDATA, tracee, &readme));
}
return 0;
}
Обратите внимание, что я использую репликацию виртуального адресного пространства родителя для знаю, где искать. Также обратите внимание, что когда потомок завершается, я подозреваю, что есть неявное отключение, которое должно позволить родителю продолжить, я не проводил дальнейших исследований.
Да, возможно ... Даже GETREGS работает. Проверено на x86 (на основе кода Мэтта Джойнера, спасибо ему)
#include <assert.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/ptrace.h>
#include <sys/types.h>
#include <sys/user.h>
int main()
{
pid_t pid = fork();
// assert(pid != -1);
int status;
long readme = 0;
struct user_regs_struct regs;
if (pid)
{
readme = 42;
printf("parent: child pid is %d\n", pid);
assert(pid == wait(&status));
printf("parent: child terminated?\n");
assert(0 == status);
}
else
{
pid_t tracee = getppid();
printf("child: parent pid is %d\n", tracee);
sleep(1); // give parent time to set readme
assert(0 == ptrace(PTRACE_ATTACH, tracee));
assert(tracee == waitpid(tracee, &status, 0));
printf("child: parent should be stopped\n");
printf("child: peeking at parent: %ld\n", ptrace(PTRACE_PEEKDATA, tracee, &readme, NULL));
printf("Regs was %p, %p, %p, %p; &status is %p \n", regs.eax, regs.ebx, regs.ecx, regs.edx, &status);
printf("child: getregs parent: %ld\n", ptrace(PTRACE_GETREGS, tracee, NULL, ®s));
printf("Regs is %p, %p, %p, %p; &status is %p \n", regs.eax, regs.ebx, regs.ecx, regs.edx, &status);
}
return 0;
}
результат:
child: parent pid is 1188
parent: child pid is 1189
child: parent should be stopped
child: peeking at parent: 42
Regs was (nil), (nil), (nil), (nil); &status is 0xbfffea50
child: getregs parent: 0
Regs is 0xfffffe00, 0xffffffff, 0xbfffea50, (nil); &status is 0xbfffea50
parent: child terminated?