2016-07-13 7 views
1

私は、ptraceを使用してバイス用にsyscallsを監視しようとしています。バイナリはpselect()内でスリープし、ptraceなしでは、SIGQUITはpselectから戻ります。 pselectに渡されるブロックされたシグナルのマスクにはSIGQUITが含まれます。Ptraceは、トレースされたプロセスでシグナルがpselect()を中断するのを防ぎます。

ptraceで実行すると、sys_pselect6から終了しますが、glibcのpselectから抜けるわけではありません。 sys_pselect6がユーザーコードから抜けるのを防ぐために何をしていますか?

トレーサー:

#include <stdio.h> 
#include <sys/ptrace.h> 
#include <sys/reg.h> 
#include <err.h> 
#include <wait.h> 
#include <unistd.h> 

int main(int argc, char *argv[]) 
{ 
    int pid = fork(), sys_in = 1, status; 

    if (pid == 0) { 
     if (ptrace(PTRACE_TRACEME, getppid(), NULL, NULL) < 0) 
      err(1, "TRACEME()"); 

     execl("./child", "./child", NULL); 
     err(1, "execl()"); 
    } 

    if (waitpid(pid, &status, 0) != pid) err(1, "wait()"); 

    for (;; sys_in ^= 1) { 
     if (ptrace(PTRACE_SYSCALL, pid, NULL, NULL) < 0) err(1, "SYSCALL"); 

     if (waitpid(pid, &status, 0) != pid) err(1, "wait()"); 

     if (sys_in) { 
      long long sys_no = ptrace(PTRACE_PEEKUSER, pid, 8 * ORIG_RAX, NULL); 
      printf("syscall entry %lld\n", sys_no); 
     } 
     else printf("syscall exit\n"); 
    } 
    return 0; 
} 

子供:

#include <stdio.h> 
#include <sys/select.h> 
#include <signal.h> 
#include <err.h> 

void handle_sigquit(int sig, siginfo_t* info, void *ctx) 
{ 
} 

int main() 
{ 
    sigset_t mask; 
    sigset_t orig_mask; 
    struct sigaction sa = {}; 

    sa.sa_flags = SA_SIGINFO; 
    sa.sa_sigaction = handle_sigquit; 
    sigaction(SIGQUIT, &sa, NULL); 

    sigemptyset(&mask); 
    sigaddset(&mask, SIGQUIT); 

    if (sigprocmask(SIG_BLOCK, &mask, &orig_mask) < 0) err(1, "sigprocmask()"); 

    pselect(0, NULL, NULL, NULL, NULL, &orig_mask); 
    warn("pselect()"); 
    return 0; 
} 

答えて

1
ptrace(PTRACE_SYSCALL, pid, NULL, NULL) 

デバッガが通知を取得するたび、あなたはちょうどその通知は、システムコールについてであると仮定し、それに応じてそれを扱います。そうではありません。

waitを使用して受け取った通知の一部は、あなたの脱税者が受け取ったの信号です。それらが起こると、あなたのPTRACE_SYSCALLコールの最後のNULLは、debugeeプロセスに到着する信号を除去し、効果的にマスクします。

ptraceの結果を処理する場合は、デバッガの起動要因となった信号を確認する必要があります。少なくとも、それがSIGTRAPまたはそれ以外のものかどうかを確認してください。それが他のものであれば、最良の方法は、それをdebugeeプロセスに渡すことです。

これをチェックすると、簡単な方法がわかります。small program

関連する問題