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