[英]Systemcall child-parent execution problem (fork execve) Linux
Im new to systemcall.我是系统调用的新手。 Im using execve inside a child so the parent should run as normal and not be ovewritten by execve.
我在孩子内部使用 execve,因此父级应该正常运行并且不会被 execve 覆盖。 The problem is that the child executes and stops the whole thing after execve.
问题是孩子在execve之后执行并停止了整个事情。 My goal here is to count the number of clone executed in the bash command(argument) executed by execve.
我的目标是计算 execve 执行的 bash 命令(参数)中执行的克隆数。
Ive read the man, Im still a bit confused.我读过这个人,我还是有点困惑。 I can only use ptrace, fork, wait/waitpid.
我只能使用 ptrace、fork、wait/waitpid。
argument:争论:
/bin/bash -c "echo 'first test' | wc -c"
int main(int argc, char *argv[]) {
pid_t child_pid = fork();
int status;
int counter = 0;
wait(&status);
if (child_pid == -1) {
exit(1);
} else {
while(status != child_pid){
if (child_pid == 0) {
ptrace(PTRACE_TRACEME, child_pid, 0, 0);
raise(SIGSTOP);
execve(argv[1], &argv[1], NULL);
ptrace(PTRACE_SETOPTIONS, child_pid, 0, PTRACE_O_TRACECLONE);
ptrace(PTRACE_CONT, child_pid, 0L, 0L);
if(status>>8 == (SIGTRAP | (PTRACE_EVENT_CLONE<<8)))
counter++;
}
}
}
printf("# of clone executions: %d", counter);
return 0;
}
execve
will overwrite the child process, so any instruction after execve
will not be executed, unless the call to execve
fails. execve
会覆盖子进程,所以execve
之后的任何指令都不会被执行,除非调用execve
失败。 You should instead run the ptrace
tracing that appears after the execve
in the parent process您应该改为运行父进程中
execve
之后出现的ptrace
跟踪
Edit: here is a commented solution to count the number of clone syscalls:编辑:这是一个计算克隆系统调用数量的注释解决方案:
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/ptrace.h>
#include <sys/syscall.h>
#include <sys/reg.h> // ORIG_RAX
int main(int argc, char *argv[]) {
pid_t child_pid = fork();
int counter = 0;
int entering_syscall = 1;
if(child_pid == -1) {
perror("fork failed");
exit(1);
} else if(child_pid != 0) {
// parent
u_int64_t rax;
int status;
while(1) {
// wait for the next signal by the child
if(wait(&status) != child_pid)
continue;
if(WIFEXITED(status)) {
puts("child exited");
break;
}
// read the USER area, defined in sys/user.h, which contains the registers information
// in linux, rax contains the syscall number
rax = ptrace(PTRACE_PEEKUSER, child_pid, 8 * ORIG_RAX, NULL);
if(rax == SYS_clone /* 56 */) {
// PTRACE_SYSCALL generates a signal both when entering and exiting a syscall
// only count the syscall during enter
if(entering_syscall)
counter++;
entering_syscall = !entering_syscall;
}
//printf("syscall %ld\n", rax);
// continue the child process until the next syscall enter/exit
ptrace(PTRACE_SYSCALL, child_pid, NULL, NULL);
}
} else {
// child
// turns the calling thread into a tracee
ptrace(PTRACE_TRACEME, child_pid, 0, 0);
// signal and wait for the parent. This ensures that PTRACE_SYSCALL
// will not miss any child syscall
raise(SIGSTOP);
execve(argv[1], &argv[1], NULL);
// should be never reached
perror("execve failed");
exit(1);
}
printf("Num clone: %d\n", counter);
}
You can cross-check it against strace strace 2>&1 your_command | grep clone | wc -l
您可以对照 strace 交叉检查
strace 2>&1 your_command | grep clone | wc -l
strace 2>&1 your_command | grep clone | wc -l
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.