私はシステムコールを傍受するためにptraceを使用しています。 execveへの16回の呼び出しを傍受していることを除いて、すべてうまく動作しているようです(プリシステムコール8回、システムコール8回)。Ptraceがexecveのための多くのトラップをキャッチ
私はそれがない例を見ましたが、フラグPTRACE_O_TRACESYSGOOD
を使用しようとしています。
その他answers to ptrace problemsは、プレ/ポスト+1信号が1つしか表示されないことを示していますが、PTRACE_O_TRACESYSGOOD
は使用していません。
Intercepted rt_sigprocmask[14]
Syscall returned with value 0
Intercepted execve[59]
Syscall returned with value -2
Intercepted execve[59]
Syscall returned with value -2
Intercepted execve[59]
Syscall returned with value -2
Intercepted execve[59]
Syscall returned with value -2
Intercepted execve[59]
Syscall returned with value -2
Intercepted execve[59]
Syscall returned with value -2
Intercepted execve[59]
Syscall returned with value -2
Intercepted execve[59]
Syscall returned with value 0
Tracer: Received signal: 5
Intercepted brk[12]
...
出力の残りの部分は何strace
出力と一致します。
私の出力は次のようになります。
すべての「インターセプトされた」および「返されるSyscall」は、waitid()
コールに対応します。私はexecve
、またはPTRACE_O_TRACESYSGOOD
をmisunderstingよ恐れる
#include <sys/types.h>
#include <stdint.h>
#include <sys/types.h>
#include <sys/user.h>
#include <sys/vfs.h>
#include <sys/ptrace.h>
#include <sys/reg.h> /* For constants ORIG_EAX, etc */
#include <string.h>
#include <sys/wait.h>
#include <sys/syscall.h> /* For SYS_write, etc */
#include <unistd.h>
#include <stdio.h>
int main(){
pid_t pid = fork();
// Child.
if(pid == 0){
ptrace(PTRACE_TRACEME, 0, NULL, NULL);
// Wait for parent to be ready.
raise(SIGSTOP);
execlp("pwd", "pwd", NULL);
return 0;
}
// Tracer.
else{
struct user_regs_struct regs;
bool isPre = true;
int status;
// Wait for child to stop itself.
waitpid(pid, &status, 0);
ptrace(PTRACE_SETOPTIONS, pid, NULL, PTRACE_O_TRACESYSGOOD);
while(true){
ptrace(PTRACE_SYSCALL, pid, 0, 0);
pid = waitpid(pid, &status, 0);
// Check if tracee has exited.
if (WIFEXITED(status)){
return 0;
}
// This is a stop caused by a system call exit-pre/exit-post.
if(WIFSTOPPED(status) && WSTOPSIG(status) == (SIGTRAP |0x80)){
ptrace(PTRACE_GETREGS, pid, NULL, ®s);
if(isPre){
printf("Intercepted syscall: %llu\n", regs.orig_rax);
isPre = ! isPre;
}else{
printf("Done with system call!\n");
isPre = ! isPre;
}
}else{
printf("Tracer: Received signal: %d\n", WSTOPSIG(status));
}
}
}
return 0;
}
:これを再現するミニマリストのコード例。 私はLubuntu 16.04でカーネルバージョン4.10.0-37-genericを使っています。
編集:システムコールの戻り値が修正されました。
パーフェクトこれは私が探していただけのものです:ここでは
は何が起こっているかを示しmuslからのソースの一部です! 'strace'のようなツールはexecveへの一回の呼び出ししか表示しないので、私はエラーがあると思っていました。 – gatoWololo