ptrace来自另一个的一个线程

Grz*_*man 12 multithreading ptrace

尝试ptrace()系统调用,我试图跟踪同一进程的另一个线程.根据手册页,跟踪器和tracee都是特定的线程(不是进程),所以我没有看到它不应该工作的原因.到目前为止,我尝试过以下方法:

  • 使用PTRACE_TRACEMEclone()d子:调用成功,但不会做我想做的,可能是因为要被跟踪线程的父母是不是叫线程clone()
  • 使用PTRACE_ATTACHPTRACE_SEIZE来自父线程:EPERM即使进程以root用户身份运行,也始终失败prctl(PR_SET_DUMPABLE, 1)

在所有情况下,waitpid(-1, &status, __WALL)失败ECHILD(在明确传递子pid时相同).

我该怎么做才能让它发挥作用?

如果它根本不可能,是通过设计或内核中的错误(我使用的是3.8.0版本).在前一种情况下,你能指出我的文档的正确位置吗?

Cel*_*ggs 4

正如 @mic_e 指出的,这是关于内核的已知事实 - 不完全是错误,但也不完全正确。请参阅有关它的内核邮件列表线程。提供 Linus Torvalds 的摘录:

那张“新”(去年 11 月)支票不太可能消失。它解决了 很多问题(安全性和稳定性),并且考虑到

(a) 一年内,只有两个人注意到

(b) 有一个如上所述的解决方法,该解决方法并不是非常具有侵入性

我不得不说,为了真正回到原来的行为,我们必须有一个深切关心的人,回去检查每一个特殊情况、僵局和竞争。

解决方案是实际启动在子进程中跟踪的进程 - 您需要使 ptracing 进程成为另一个进程的父进程。

以下是根据我写的另一个答案执行此操作的概述:

// this number is arbitrary - find a better one.
#define STACK_SIZE (1024 * 1024)

int main_thread(void *ptr) {
    // do work for main thread
}

int main(int argc, char *argv[]) {
    void *vstack = malloc(STACK_SIZE);
    pid_t v;
    if (clone(main_thread, vstack + STACK_SIZE, CLONE_PARENT_SETTID | CLONE_FILES | CLONE_FS | CLONE_IO, NULL, &v) == -1) { // you'll want to check these flags
        perror("failed to spawn child task");
        return 3;
    }
    long ptv = ptrace(PTRACE_SEIZE, v, NULL, NULL);
    if (ptv == -1) {
        perror("failed monitor sieze");
        return 1;
    }
    // do actual ptrace work
}
Run Code Online (Sandbox Code Playgroud)