#include #include #include #include #include #include #include #include #include #include #include char childstack[ 8*1024]; int my_getpid() { long res; __asm__ volatile (" int $0x80\n\t" : "=a" (res) : "0" (__NR_getpid)); return res; } int child_fn( void * unused) { pid_t me = my_getpid(); printf("Child: my PID via 'int $0x80' is %d\n", me); ptrace(PTRACE_TRACEME, 0, 0, 0); kill( me, SIGSTOP); printf("Child: my PID via 'getpid()' is %d\n", getpid()); return 0; } int main( int argc, char ** argv) { int ret, status, suppress=0; pid_t child; printf("Parent: my PID is %d\n", getpid()); printf("Parent: my PID is %d\n", getpid()); if ( argc < 2 || strcmp( argv[1], "clone") ) return 0; child = clone( child_fn, childstack+8*1024-4, SIGCHLD, NULL); if ( child < 0 ) { perror("clone"); exit(1); } printf("Parent: childs PID is %d\n", child); do { ret = waitpid(child, &status, WUNTRACED); if(ret < 0) { perror("waitpid()"); exit(1); } } while(WIFSTOPPED(status) && (WSTOPSIG(status) == SIGVTALRM)); if(!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGSTOP)) { printf("Parent: waitpid(): expected SIGSTOP, got status = %d\n", status); return 1; } while (1) { if ( ptrace( PTRACE_SYSCALL, child, (void *)0, 0) < 0 ) { perror("ptrace( PTRACE_SYSCALL, child, 0, 0)"); exit(1); } ret = waitpid( child, &status, 0); if ( ret != child ) { perror("waitpid"); return 1; } if ( WIFSTOPPED(status) && WSTOPSIG(status) == SIGTRAP ) { errno = 0; ret = ptrace( PTRACE_PEEKUSER, child, (void *)(ORIG_EAX*4), NULL); if ( errno ) { perror("ptrace( PTRACE_PEEKUSER, child, ORIG_EAX, NULL)"); return 1; } if ( ret == __NR_getpid ) { if ( (suppress ^= 1) ) printf("Parent: Child does a getpid() syscall!\n"); } } else { printf("Parent: Child's status is %x: exiting\n", status); return (status != 0); } } }