#include #include #include #include #include #include #include #include #include #include //#include #include #define PTRACE_EVENT_FORK 1 #define PTRACE_EVENT_VFORK 2 #define PTRACE_EVENT_CLONE 3 #define PTRACE_EVENT_EXEC 4 #define PTRACE_EVENT_VFORK_DONE 5 #define PTRACE_EVENT_EXIT 6 #define PTRACE_SETOPTIONS 0x4200 #define PTRACE_GETEVENTMSG 0x4201 #define PTRACE_O_TRACESYSGOOD 0x00000001 #define PTRACE_O_TRACEFORK 0x00000002 #define PTRACE_O_TRACEVFORK 0x00000004 #define PTRACE_O_TRACECLONE 0x00000008 #define PTRACE_O_TRACEEXEC 0x00000010 #define PTRACE_O_TRACEVFORKDONE 0x00000020 #define PTRACE_O_TRACEEXIT 0x00000040 #define PALL PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORK | PTRACE_O_TRACECLONE \ | PTRACE_O_TRACEEXEC | PTRACE_O_TRACEVFORKDONE | PTRACE_O_TRACEEXIT void fetch_clone_flags(pid_t pid, unsigned long* clone_flags) { struct pt_all_user_regs ptregs; unsigned long bsp, cfm, sof, sol; unsigned long addr; long ret; ret = ptrace(PTRACE_GETREGS, pid, 0, (unsigned long)&ptregs); bsp = ptrace (PTRACE_PEEKUSER, pid, PT_AR_BSP, 0); cfm = ptrace (PTRACE_PEEKUSER, pid, PT_CFM, 0); sof = (cfm >> 0) & 0x7f; sol = (cfm >> 7) & 0x7f; bsp = (unsigned long) ia64_rse_skip_regs((void *) bsp, -sof + sol); addr= (unsigned long) ia64_rse_skip_regs((void *) bsp, 0); ret = ptrace (PTRACE_PEEKTEXT, pid, addr, (unsigned long) clone_flags); *clone_flags = ret; } /* Wrapper function for waitpid which handles EINTR. */ static int my_waitpid (int pid, int *status, int flags) { int ret; int old_status = status ? *status : 0; do { ret = waitpid (pid, status, flags); } while (ret == -1 && errno == EINTR); if (ret == 0 && status != 0) *status = old_status; return ret; } int main() { unsigned long pid, npid ; int status, event,ret, child_status; char *stack ; unsigned long clone_flags; pid = fork(); if(pid == 0) { ptrace(PTRACE_TRACEME,0,NULL,NULL) ; kill (getpid (), SIGSTOP); if (vfork() == 0){ execve("/bin/true",NULL,NULL) ; } exit(0) ; } ret = my_waitpid(pid, &status, 0); if (!WIFSTOPPED(status)) { perror("waitpid failed unexpected tstatus \n"); return -1; } if (ptrace(PTRACE_SETOPTIONS,pid,NULL,PALL) < 0) { perror("PTRACE_SETOPTIONS not supported\n"); return -1; } if (ptrace(PTRACE_CONT,pid,0,0) < 0) { perror("PTRACE_CONT \n"); return -1; } if ( my_waitpid(pid,&status,0) < 0) { perror("wait4 failed"); return -1; } event = (status >> 16) & 0xffff ; if (event == PTRACE_EVENT_FORK || event == PTRACE_EVENT_VFORK || event == PTRACE_EVENT_CLONE) { if (ptrace(PTRACE_GETEVENTMSG,pid,NULL,&npid) < 0) { perror("PTRACE_GETEVENTMSG\n"); return -1; } sleep(1); fetch_clone_flags(pid, &clone_flags); if (clone_flags == (CLONE_VFORK | CLONE_VM | SIGCHLD)) printf("PTRACE_PEEKUSER succeed\n"); else printf("PTRACE_PEEKUSER failed\n"); if (my_waitpid(npid,&child_status,0) < 0) { perror("waitpid \n"); return -1; } ptrace (PTRACE_KILL, npid, 0, 0); ptrace (PTRACE_KILL, pid, 0, 0); //ptrace(PTRACE_CONT, npid, 0, WSTOPSIG(child_status)); //ptrace(PTRACE_CONT, pid, 0, WSTOPSIG(status)); my_waitpid(-1,&status,0); } return 0 ; }