c - ptrace PTRACE_EVENT_FORK 挂起
问题描述
嗨,我正在尝试创建一个程序 fork 并在 child 中执行 /bin/sh 并跟踪 /bin/sh 内的所有系统调用,每次你在 sh shell 中编写命令时,sh 二进制文件将 fork() 并产生一个新进程,我知道我应该使用PTRACE_O_TRACEFORK,无论如何,每当我得到PTRACE_EVENT_FORK时,我都能够获取新的进程 PID,但我无法让它继续执行.. 这是我的代码,非常感谢!
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <assert.h>
#include <sys/ptrace.h>
#include <sys/wait.h>
#define elog(...) fprintf(stderr, __VA_ARGS__)
#define FILE_EXISTS(f) (access(f, F_OK ) != -1)
#define SAFECHECK(r,e,f) (r!=e?fatal(f):0)
#define IS_EVENT(s,e) (s >> 8 == (SIGTRAP| e << 8))
void fatal(char * f) {
perror(f);
abort();
}
void set_self_trace() {
SAFECHECK(ptrace(PTRACE_TRACEME, 0, 0, 0), 0, "ptrace(PTRACE_TRACEME)");
raise(SIGSTOP);
}
void parent_set_child_options(int pid, int options) {
// PTRACE_O_TRACEEXEC
int status;
waitpid(pid, &status, 0);
assert(WIFSTOPPED(status));
SAFECHECK(ptrace(PTRACE_SETOPTIONS, pid, 0, options), 0, "ptrace(PTRACE_SETOPTIONS)");
SAFECHECK(ptrace(PTRACE_CONT, pid, 0, 0), 0, "ptrace(PTRACE_CONT)");
}
long get_ptrace_eventmsg(int pid) {
long result;
SAFECHECK(ptrace(PTRACE_GETEVENTMSG, pid, 0, &result), 0, "ptrace(PTRACE_GETEVENTMSG)");
return result;
}
int main(int argc, char **argv) {
if(argc > 1) {
if(FILE_EXISTS(argv[1])) {
int pid = fork();
if(pid == 0) {
set_self_trace();
char * envp[] = {NULL};
execve(argv[1], &argv[1], envp);
}else{
parent_set_child_options(pid, PTRACE_O_TRACEFORK);
int s;
int wait_pid;
elog("Child pid: %d\n", pid);
while(1) {
wait_pid = waitpid(pid, &s, __WALL);
if(wait_pid == -1) {
fatal("waitpid(-1, __WALL)");
}
if(WIFSTOPPED(s) && WSTOPSIG(s) == SIGTRAP) {
// We got an event!
int event = (s >> 8);
switch (event) {
case (SIGTRAP | PTRACE_EVENT_EXEC << 8):
elog("Got event PTRACE_EVENT_EXEC\n", event);
SAFECHECK(ptrace(PTRACE_CONT, wait_pid, 0, 0), 0, "ptrace(PTRACE_CONT)");
break;
case (SIGTRAP | PTRACE_EVENT_FORK << 8):
elog("Got event PTRACE_EVENT_FORK\n", event);
long new_child = get_ptrace_eventmsg(wait_pid);
elog("Forked to proc: %d\n", new_child);
// THOSE WON'T WORK HERE new_Child HANG I SUPPOSE
SAFECHECK(ptrace(PTRACE_CONT, new_child, 0, 0), 0, "ptrace(PTRACE_CONT) (new_child)");
SAFECHECK(ptrace(PTRACE_CONT, wait_pid, 0, 0), 0, "ptrace(PTRACE_CONT)");
// END
break;
default:
elog("Uknown event %d\n", event);
SAFECHECK(ptrace(PTRACE_CONT, wait_pid, 0, 0), 0, "ptrace(PTRACE_CONT)");
}
}else if(WIFEXITED(s)) {
elog("Process %d exited with status code: %d\n", wait_pid, WEXITSTATUS(s));
break;
}else if(WIFSIGNALED(s)) {
elog("Process %d exited received signal: %d\n", wait_pid, WTERMSIG(s));
break;
}
}
}
}else{
elog("File %s does not exists!\n", argv[1]);
}
}else{
elog("%s\n","Missing arguments.");
elog("Usage: %s <program> <arguments>\n", argv[0]);
}
}
这是执行输出:
dan@host:~/Scrivania/tracer$ ./tracer /bin/sh
Child pid: 11688
Got event PTRACE_EVENT_EXEC
$ id
Got event PTRACE_EVENT_FORK
Forked to proc: 11689
*** HERE HANG /usr/bin/id IS NEVER EXECUTED**
解决方案
推荐阅读
- group-by - DAX:先区分然后聚合两次
- javascript - 我怎样才能画出完美的多重线螺旋与循环和点?
- hyperledger-fabric - 在 Hyperledger fabirc 中从 kafka 迁移到 RAFT 时出错
- java - 具有动态大小的 Java 整数数组
- slack - 输入 :) 作为 slack 上的文本
- r - 如何引用多个数据框列来计算 R 中的加权平均值的新列
- python - 以父子格式将excel数据导入django数据库
- apache-spark - 为什么这个简单的 Spark 应用程序会创造这么多工作?
- typescript - 通过 ClearScript 将 System.Data.DataTable 暴露到 JS 中后,我如何为 TypeScript 表达它的对象?
- angular - 离子选择/离子标签未正确显示,属性在 Ionic 4 中浮动