【问题标题】:ptrace options not working at allptrace 选项根本不起作用
【发布时间】:2013-12-14 04:24:47
【问题描述】:

当我附加到另一个进程时,我无法跟踪 fork / exec 事件,从 waitpid 返回的 status 始终为零(右移 16 次后)。

我已成功附加到 bash shell,但无论我运行什么命令,状态始终为零,因此我没有捕获任何 fork 或 exec 事件:

#define PALL PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORK | PTRACE_O_TRACECLONE \
    | PTRACE_O_TRACEEXEC | PTRACE_O_TRACEVFORKDONE | PTRACE_O_TRACEEXIT

int main(int argc, char **argv)
{ 
    pid_t child = 0;
    int status = 0;

    if (argc != 2) { ... }
    child = atoi (argv[1]);
    if (ptrace (PTRACE_ATTACH, child, 0, 0) < 0) { ... }

    ptrace(PTRACE_SETOPTIONS, child, NULL, PALL);
    ptrace(PTRACE_SYSCALL, child, NULL, NULL);
    ptrace(PTRACE_CONT, child, NULL, NULL);

    while(1) {
        waitpid(child, &status, 0);
        if(WIFEXITED(status))
            break;

        status >>= 16;
        if (status != 0)
            printf ("Status: %d\n", status >> 16);

        ptrace(PTRACE_SYSCALL, child, NULL, NULL);
    }

    ptrace(PTRACE_DETACH, child, NULL, NULL);
    return 0;
}

【问题讨论】:

    标签: c linux ptrace


    【解决方案1】:

    从 waitpid 返回的 status 始终为零(右移后 16 次)。

    您通过先执行 status &gt;&gt;= 16 然后执行 printf (…, status &gt;&gt; 16);status 位移动了 32 次而不是 16 次,因此始终打印 0。还有一些不太明显的缺陷:

    • 为了完整起见,我们应该处理WIFSIGNALED的案例。
    • 我们应该向孩子传递信号;它可能需要它们才能正常运行。
    • 由于我们还追踪孩子的孩子,因此我们也必须 wait 获取并处理它们。
    • 紧接在PTRACE_CONT 之前的PTRACE_SYSCALL 没有意义。
    • 如果PTRACE_ATTACH 尚未完成,PTRACE_SETOPTIONS 可能会失败,因此我们必须wait

    考虑到这一切,程序可能看起来像

    #include <stdio.h>
    #include <sys/wait.h>
    #include <sys/ptrace.h>
    #define PALL PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORK | PTRACE_O_TRACECLONE \
               | PTRACE_O_TRACEEXEC | PTRACE_O_TRACEVFORKDONE | PTRACE_O_TRACEEXIT
    int main(int argc, char **argv)
    { 
        pid_t child, pid;
        int status;
        if (argc != 2) { return 2; }
        child = atoi(argv[1]);
        if (ptrace(PTRACE_ATTACH, child, 0, 0) < 0) { return 1; }
        wait(NULL); // PTRACE_SETOPTIONS may work only after this
        ptrace(PTRACE_SETOPTIONS, child, NULL, PALL);
        ptrace(PTRACE_CONT, child, NULL, NULL);
        while (pid = wait(&status), pid > 0)
        {
            if (WIFEXITED(status) || WIFSIGNALED(status))
            {
                if (pid == child) break;
                printf("grandchild %d exited\n", pid);
                continue;
            }
            if (status>>16)
                printf("[%d] Status: %x\n", pid, status);
            int signal = WSTOPSIG(status);
            if (signal == SIGTRAP)
            {   // system call or ptrace event
                signal = 0;
                if (status>>16)
                    printf("ptrace event: %d\n", status>>16);
            }
            ptrace(PTRACE_CONT, pid, 0, signal);
        }
        ptrace(PTRACE_DETACH, child, NULL, NULL);
        return 0;
    }
    

    【讨论】:

      猜你喜欢
      • 2022-06-14
      • 1970-01-01
      • 1970-01-01
      • 2023-04-08
      • 2011-06-25
      • 1970-01-01
      • 2016-10-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多