ptrace一个线程与另一个线程

ptrace一个线程与另一个线程

问题描述:

我正在尝试使用ptrace()系统调用来跟踪同一进程的另一个线程.根据手册页,示踪剂和示踪剂都是特定的线程(不是进程),所以我看不出它不起作用的原因.到目前为止,我已经尝试了以下方法:

Experimenting with the ptrace() system call, I am trying to trace another thread of the same process. According to the man page, both the tracer and the tracee are specific threads (not processes), so I don't see a reason why it should not work. So far, I have tried the following:

  • 使用clone() d子项中的PTRACE_TRACEME:调用成功,但是没有执行我想要的操作,可能是因为要跟踪的线程的父级不是调用clone()的线程
  • 使用父线程中的PTRACE_ATTACHPTRACE_SEIZE:即使进程以root身份运行且使用prctl(PR_SET_DUMPABLE, 1)
  • ,这始终会因EPERM而失败.
  • use PTRACE_TRACEME from the clone()d child: the call succeeds, but does not do what I want, probably because the parent of the to-be-traced thread is not the thread that called clone()
  • use PTRACE_ATTACH or PTRACE_SEIZE from the parent thread: this always fails with EPERM, even if the process runs as root and with prctl(PR_SET_DUMPABLE, 1)

在所有情况下,waitpid(-1, &status, __WALL)均失败,并显示ECHILD(与显式传递子pid相同).

In all cases, waitpid(-1, &status, __WALL) fails with ECHILD (same when passing the child pid explicitly).

我应该怎么做才能使其正常工作?

What should I do to make it work?

如果根本不可能,是由于设计问题还是内核中的错误(我正在使用3.8.0版).在前一种情况下,您能指出我文档的正确位置吗?

If it is not possible at all, is it by desing or a bug in the kernel (I am using version 3.8.0). In the former case, could you point me to the right bit of the documentation?

正如@mic_e所指出的,这是有关内核的已知事实-并不是一个bug,但也不是完全正确. 请参阅有关它的内核邮件列表线程.要提供Linus Torvalds的摘录: /p>

As @mic_e pointed out, this is a known fact about the kernel - not quite a bug, but not quite correct either. See the kernel mailing list thread about it. To provide an excerpt from Linus Torvalds:

新"(去年11月)支票不太可能消失.解决了 so 许多问题(安全性和稳定性),并考虑到这一点

That "new" (last November) check isn't likely going away. It solved so many problems (both security and stability), and considering that

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

(a) in a year, only two people have ever even noticed

(b)上面有一种解决方法,它不是非常可怕的入侵

(b) there's a work-around as per above that isn't horribly invasive

我不得不说,为了真正回到过去的行为, 我们必须要有人在乎,回去检查一下 单个特殊情况,死锁和种族.

I have to say that in order to actually go back to the old behaviour, we'd have to have somebody who cares deeply, go back and check every single special case, deadlock, and race.

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

The solution is to actually start the process that is being traced in a subprocess - you'll need to make the ptracing process be the parent of the other.

这里是根据我写的另一个答案进行此操作的概述:

Here's an outline of doing this based on 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
}