ptrace'ing родительского процесса

Может дочерний процесс использовать 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

9
задан osgx 8 February 2010 в 05:01
поделиться

2 ответа

Меня очень заинтересовал этот вопрос. Поэтому я написал код, чтобы опробовать его.

Во-первых, имейте в виду, что при трассировке процесса процесс трассировки становится родительским для большинства целей, за исключением названия (например, 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;
}

Обратите внимание, что я использую репликацию виртуального адресного пространства родителя для знаю, где искать. Также обратите внимание, что когда потомок завершается, я подозреваю, что есть неявное отключение, которое должно позволить родителю продолжить, я не проводил дальнейших исследований.

8
ответ дан 3 November 2019 в 02:51
поделиться

Да, возможно ... Даже 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, &regs));
        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?
1
ответ дан 3 November 2019 в 02:51
поделиться
Другие вопросы по тегам:

Похожие вопросы: