当我附加到另一个进程时,我无法跟踪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;
}
答案 0 :(得分:0)
从waitpid返回的
status
始终为零(右移后) 16次)。
您先将status
位移至16位,但先移动status >>= 16
然后printf (…, status >> 16);
移动32次,因此始终打印0
。还有一些不太明显的缺陷:
WIFSIGNALED
。wait
来处理他们。PTRACE_SYSCALL
之前的PTRACE_CONT
没有意义。PTRACE_SETOPTIONS
尚未完成,PTRACE_ATTACH
可能会失败,因此我们必须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;
}