子进程是否可以使用ptrace
系统调用来跟踪其父进程?
Os是linux 2.6
感谢。
upd1:
我想从“本身”跟踪process1。这是不可能的,所以我做fork并尝试从子进程执行ptrace(process1_pid, PTRACE_ATTACH)
。但我不能,有一个奇怪的错误,比如内核禁止孩子跟踪他们的父进程
UPD2:安全策略可以禁止此类跟踪。这样做的政策是什么?内核中的检查代码在哪里?
UPD3:在我的嵌入式Linux上,PEEKDATA没有错误,但GETREGS没有错误:
child: getregs parent: -1
errno is 1, strerror is Operation not permitted
errno = EPERM
答案 0 :(得分:7)
这个问题真让我感兴趣。所以我写了一些代码来试试。
首先请记住,在跟踪流程时,跟踪流程会成为大多数目的的父级,除了名称(即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;
}
请注意,我正在利用父虚拟地址空间的复制来了解要查找的位置。还要注意,当孩子终止时,我怀疑有一个隐含的分离,必须允许父母继续,我没有进一步调查。
答案 1 :(得分:1)
是的,有可能...... 甚至GETREGS都有效。 检查x86 (基于Matt Joiner代码,谢谢他)
#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, ®s));
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?