2016-07-13 16 views
1

Ich versuche, syscalls für eine Binärdatei mit ptrace zu überwachen. Das binary schläft in pselect() und ohne ptrace bewirkt ein SIGQUIT, dass es von pselect zurückgegeben wird. Die Maske der blockierten Signale, die an pselect übergeben werden, enthält SIGQUIT.Ptrace verhindert, dass Signal pselect() im verfolgten Prozess unterbricht

Wenn es mit ptrace ausgeführt wird, wird es von sys_pselect6, aber nicht vollständig aus glibcs ​​pselect beendet. Was mache ich, die verhindert, dass sys_pselect6 zu Benutzercode austritt?

Tracer:

#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; 
} 

Kind:

#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; 
} 

Antwort

1
ptrace(PTRACE_SYSCALL, pid, NULL, NULL) 

Wenn Ihr Debugger eine Benachrichtigung erhält, Sie davon ausgehen, dass nur die Benachrichtigung über eine Systemaufruf ist, und entsprechend behandeln. Das ist nicht der Fall.

Einige der Benachrichtigungen, die Sie mit wait erhalten, sind für Signale, die Ihr Debugee erhalten hat. Wenn diese passieren, beseitigt der letzte NULL-Wert in Ihrem PTRACE_SYSCALL-Aufruf das Signal des Debugee-Prozesses.

Bei der Verarbeitung von ptrace Ergebnissen müssen Sie das Signal überprüfen, das Ihren Debugger zum Aufwachen veranlasst hat. Überprüfen Sie zumindest, ob es sich um eine SIGTRAP oder etwas anderes handelt. Wenn es etwas anderes ist, ist es am besten, es an den Debugee-Prozess weiterzugeben.

Schauen Sie sich small program an, um einen einfachen Weg zu sehen.