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
main(void)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