1 /* -*- mode: C; c-basic-offset: 3; -*- */ 2 3 #include <assert.h> 4 #include <elf.h> 5 #include <stdio.h> 6 #include <stdlib.h> 7 #include <string.h> 8 #include <unistd.h> 9 10 #include <sys/ptrace.h> 11 #include <sys/types.h> 12 #include <sys/uio.h> 13 #include <sys/user.h> 14 #include <sys/wait.h> 15 16 static int 17 err_out(const char *msg) 18 { 19 perror(msg); 20 return 1; 21 } 22 23 static int 24 non_empty(const char *buf, size_t len) 25 { 26 size_t i; 27 int c = 0; 28 volatile const char *p = buf; 29 30 for (i = 0; i != len; i++) 31 c |= p[i]; 32 return c; 33 } 34 35 static int 36 do_child(void) 37 { 38 if (ptrace(PTRACE_TRACEME, 0, NULL, NULL) == -1) 39 return err_out("ptrace traceme"); 40 raise(SIGUSR1); 41 return 0; 42 } 43 44 int 45 main(void) 46 { 47 char buf[1024]; 48 struct iovec iov; 49 pid_t cpid, pid; 50 int status; 51 52 cpid = fork(); 53 if (cpid == -1) 54 return err_out("fork"); 55 if (cpid == 0) 56 return do_child(); 57 58 pid = wait(&status); 59 if (pid == -1) 60 return err_out("wait"); 61 62 /* Intentionally provide an uninitialized buffer to ptrace. */ 63 iov.iov_len = sizeof(buf); 64 iov.iov_base = buf; 65 if (ptrace(0x4204, cpid, NT_PRSTATUS, &iov) == -1) 66 return err_out("ptrace getregset"); 67 68 assert(iov.iov_base == buf); 69 assert(iov.iov_len > 0 && iov.iov_len < sizeof(buf)); 70 71 /* We're assuming here that NT_PRSTATUS never contains 72 all-zeros. */ 73 assert(non_empty(buf, iov.iov_len)); 74 puts("OK"); 75 return 0; 76 } 77