1 #ifdef HAVE_CONFIG_H 2 # include "config.h" 3 #endif 4 #include <dlfcn.h> 5 #include <fcntl.h> 6 #include <unistd.h> 7 #include <sys/mman.h> 8 #include <sys/wait.h> 9 #include <sys/sendfile.h> 10 11 int main(void) 12 { 13 const unsigned long pagesize = sysconf(_SC_PAGESIZE); 14 15 #ifdef __s390__ 16 /* 17 * The si_addr field is unreliable: 18 * https://marc.info/?l=linux-s390&m=142515870124248&w=2 19 */ 20 return 77; 21 #endif 22 23 /* write instruction pointer length to the log */ 24 if (write(-1, NULL, 2 * sizeof(void *)) >= 0) 25 return 77; 26 27 /* just a noticeable line in the log */ 28 if (munmap(&main, 0) >= 0) 29 return 77; 30 31 int pid = fork(); 32 if (pid < 0) 33 return 77; 34 35 if (!pid) { 36 const unsigned long mask = ~(pagesize - 1); 37 unsigned long addr = (unsigned long) &main & mask; 38 unsigned long size = pagesize << 1; 39 40 #ifdef HAVE_DLADDR 41 Dl_info info; 42 if (dladdr(&main, &info)) { 43 const unsigned long base = 44 (unsigned long) info.dli_fbase & mask; 45 if (base < addr) { 46 size += addr - base; 47 addr = base; 48 } 49 } else 50 #endif 51 { 52 addr -= size; 53 size <<= 1; 54 } 55 56 /* SIGSEGV is expected */ 57 (void) munmap((void *) addr, size); 58 (void) munmap((void *) addr, size); 59 return 77; 60 } 61 62 int status; 63 if (wait(&status) != pid || 64 !WIFSIGNALED(status) || 65 WTERMSIG(status) != SIGSEGV) 66 return 77; 67 68 /* dump process map for debug purposes */ 69 close(0); 70 if (!open("/proc/self/maps", O_RDONLY)) 71 (void) sendfile(1, 0, NULL, pagesize); 72 73 return 0; 74 } 75