2010-02-07 21 views
9

È possibile che il processo figlio utilizzi la chiamata di sistema ptrace per rintracciare il padre?ptrace'ing del processo padre

Os è linux 2.6

Grazie.

upd1: Desidero rintracciare process1 da "itself". È impossibile, quindi faccio fork e provo a fare ptrace(process1_pid, PTRACE_ATTACH) da processo figlio. Ma non posso, c'è uno strano errore, come il kernel proibisce al bambino di rintracciare i loro processi genitore

UPD2: tale tracciabilità può essere proibita dalle politiche di sicurezza. Quali politiche fanno questo? Dov'è il codice di controllo nel kernel?

UPD3: sul mio Linux embedded non ho nessun errore con PEEKDATA, ma non con GETREGS:

child: getregs parent: -1 
errno is 1, strerror is Operation not permitted 

errno = EPERM

+0

Qual è l'errore ('errno') dopo lo strano errore che state vedendo? – jschmier

+0

osgx, la mia risposta è la seguente sotto testare correttamente la traccia di un processo genitore mentre stai provando? –

+1

Dato che stai biforcando comunque, perché non fai il contrario, cioè rintraccia il bambino dal genitore? – shodanex

risposta

6

Questa domanda mi ha davvero interessato. Così ho scritto del codice per provarlo.

Innanzitutto, tenere presente che quando si traccia un processo, il processo di tracciamento diventa padre per la maggior parte degli scopi, tranne nel nome (ad esempio getppid()). In primo luogo, un frammento della sezione PTRACE_ATTACH del manuale è utile:

PTRACE_ATTACH 
      Attaches to the process specified in pid, making it a traced 
      "child" of the calling process; the behavior of the child is as 
      if it had done a PTRACE_TRACEME. The calling process actually 
      becomes the parent of the child process for most purposes (e.g., 
      it will receive notification of child events and appears in 
      ps(1) output as the child's parent), but a getppid(2) by the 
      child will still return the PID of the original parent. The 
      child is sent a SIGSTOP, but will not necessarily have stopped 
      by the completion of this call; use wait(2) to wait for the 
      child to stop. (addr and data are ignored.) 

Ora qui è il codice che ho scritto per testare e verificare che sia possibile in effetti ptrace() un genitore (si può costruire questo dal dumping in un file chiamato blah.c e l'esecuzione make blah:

#include <assert.h> 
#include <stdio.h> 
#include <unistd.h> 
#include <sys/ptrace.h> 

int main() 
{ 
    pid_t pid = fork(); 
    assert(pid != -1); 
    int status; 
    long readme = 0; 
    if (pid) 
    { 
     readme = 42; 
     printf("parent: child pid is %d\n", pid); 
     assert(pid == wait(&status)); 
     printf("parent: child terminated?\n"); 
     assert(0 == status); 
    } 
    else 
    { 
     pid_t tracee = getppid(); 
     printf("child: parent pid is %d\n", tracee); 
     sleep(1); // give parent time to set readme 
     assert(0 == ptrace(PTRACE_ATTACH, tracee)); 
     assert(tracee == waitpid(tracee, &status, 0)); 
     printf("child: parent should be stopped\n"); 
     printf("child: peeking at parent: %ld\n", ptrace(PTRACE_PEEKDATA, tracee, &readme)); 
    } 
    return 0; 
} 

Nota che sto sfruttando la replica di spazio di indirizzamento virtuale del genitore per sapere dove cercare si noti inoltre che quando il bambino termina poi, ho il sospetto c'è un distacco implicito che. deve consentire al genitore di continuare, non ho investigato e oltre.

+0

Questo codice funziona sul tuo computer? – osgx

+1

sì, certamente sì. forse stai eseguendo una distribuzione che viene fornita con alcune policy di sicurezza di processo predefinite, penso che la Fedora lo faccia per esempio. Ha funzionato per te? dovresti vedere la sbirciata del bambino e stampare il valore dal genitore. –

+0

Questo codice sembra funzionare ... Su linux/x86 e sul mio linux (embedded) – osgx

1

Sì, è possibile ... Anche GETREGS funziona. Controllato su x86 (basato sul codice Matt Joiner, lo ringrazia)

#include <assert.h> 
#include <stdio.h> 
#include <unistd.h> 
#include <sys/ptrace.h> 
#include <sys/types.h> 
#include <sys/user.h> 

int main() 
{ 
    pid_t pid = fork(); 
// assert(pid != -1); 
    int status; 
    long readme = 0; 
    struct user_regs_struct regs; 
    if (pid) 
    { 
     readme = 42; 
     printf("parent: child pid is %d\n", pid); 
     assert(pid == wait(&status)); 
     printf("parent: child terminated?\n"); 
     assert(0 == status); 
    } 
    else 
    { 
     pid_t tracee = getppid(); 
     printf("child: parent pid is %d\n", tracee); 
     sleep(1); // give parent time to set readme 
     assert(0 == ptrace(PTRACE_ATTACH, tracee)); 
     assert(tracee == waitpid(tracee, &status, 0)); 
     printf("child: parent should be stopped\n"); 
     printf("child: peeking at parent: %ld\n", ptrace(PTRACE_PEEKDATA, tracee, &readme, NULL)); 
     printf("Regs was %p, %p, %p, %p; &status is %p \n", regs.eax, regs.ebx, regs.ecx, regs.edx, &status); 
     printf("child: getregs parent: %ld\n", ptrace(PTRACE_GETREGS, tracee, NULL, &regs)); 
     printf("Regs is %p, %p, %p, %p; &status is %p \n", regs.eax, regs.ebx, regs.ecx, regs.edx, &status); 
    } 
    return 0; 
} 

risultato:

child: parent pid is 1188 
parent: child pid is 1189 
child: parent should be stopped 
child: peeking at parent: 42 
Regs was (nil), (nil), (nil), (nil); &status is 0xbfffea50 
child: getregs parent: 0 
Regs is 0xfffffe00, 0xffffffff, 0xbfffea50, (nil); &status is 0xbfffea50 
parent: child terminated? 
+1

copia spudorata del mio codice?: P –

+0

Sì, ma è stato aggiunto GETREGS. con esso. – osgx

+0

osgx, prova a creare un'altra domanda per il problema getregs –

Problemi correlati