ptrace来自另一个的一个线程

时间:2014-06-11 07:44:31

标签: multithreading ptrace

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

  • 使用来自PTRACE_TRACEME d子节点的clone():调用成功,但不执行我想要的操作,可能是因为要跟踪的线程的父节点不是调用{的线程{1}}
  • 使用来自父线程的clone()PTRACE_ATTACH:即使进程以root身份运行并使用PTRACE_SEIZE
  • ,这始终会失败并显示EPERM

在所有情况下,prctl(PR_SET_DUMPABLE, 1)都会失败并显示waitpid(-1, &status, __WALL)(明确传递子pid时相同)。

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

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

1 个答案:

答案 0 :(得分:4)

正如@mic_e所指出的,这是关于内核的已知事实 - 不是一个错误,但也不是很正确。 See the kernel mailing list thread about it.提供Linus Torvalds的摘录:

  

那" new" (去年11月)检查可能不会消失。它解决了   所以许多问题(安全性和稳定性),并考虑到

     

(a)在一年中,只有两个人甚至注意到

     

(b)如上所述的解决方案不是非常具有侵略性

     

我不得不说,为了真正回归旧的行为,   我们必须有一个关心深深的人,回去检查每一个   单一特例,死锁和种族。

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

以下是基于another answer that I wrote执行此操作的大纲:

// 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
}