DF-0911 / ptrace_control.c
/* Control: same scenario via ptrace(2) PT_ATTACH/PT_DETACH. * ptrace PT_ATTACH always saves p_oppid (sys_process.c:314), so * detach should restore the child to its original parent (the tracer * itself, since the tracer forked the child) and waitpid should work. */ #include <sys/types.h> #include <sys/wait.h> #include <sys/ptrace.h> #include <signal.h> #include <err.h> #include <errno.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> int main(void) { pid_t child, wp; int st; int p[2]; char b[64]; ssize_t r; if (pipe(p)<0) err(1,"pipe"); child=fork(); if (child<0) err(1,"fork"); if (child==0){ close(p[0]); for(;;){pid_t pp=getppid();snprintf(b,sizeof b,"child ppid=%d\n",pp); (void)write(p[1],b,strlen(b));sleep(1);} _exit(0); } close(p[1]); r=read(p[0],b,sizeof b-1); if(r>0){b[r]=0;fprintf(stderr,"before ptrace attach: %s",b);} if (ptrace(PT_ATTACH, child, 0, 0) < 0) err(1,"ptrace ATTACH"); waitpid(child, &st, 0); /* child stops with SIGSTOP */ if (ptrace(PT_DETACH, child, 0, 0) < 0) err(1,"ptrace DETACH"); usleep(300000); r=read(p[0],b,sizeof b-1); if(r>0){b[r]=0;fprintf(stderr,"after ptrace detach: %s",b); if (strncmp(b,"child ppid=0",12)==0) printf("ptrace RESULT: child ppid=0 (unexpected!)\n"); else printf("ptrace RESULT: child ppid is non-zero (ptrace path is correct)\n"); } errno=0; wp=waitpid(child,&st,WNOHANG); printf("ptrace waitpid(%d)=%d errno=%d (%s)\n",(int)child,(int)wp,errno,errno==ECHILD?"ECHILD":strerror(errno)); (void)kill(child,SIGKILL); (void)waitpid(child,&st,0); return 0; } |