1 /*
2 * Copyright (c) 2015-2020 Dmitry V. Levin <ldv@strace.io>
3 * Copyright (c) 2015-2021 The strace developers.
4 * All rights reserved.
5 *
6 * SPDX-License-Identifier: GPL-2.0-or-later
7 */
8
9 #include "tests.h"
10 #include "scno.h"
11 #include <assert.h>
12 #include <dlfcn.h>
13 #include <fcntl.h>
14 #include <unistd.h>
15 #include <sys/mman.h>
16 #include <sys/wait.h>
17 #include <sys/sendfile.h>
18 #include <sys/prctl.h>
19
20 int main(void)
21 {
22 const unsigned long pagesize = get_page_size();
23
24 #ifdef __s390__
25 /*
26 * The si_addr field is unreliable:
27 * https://marc.info/?l=linux-s390&m=142515870124248&w=2
28 */
29 error_msg_and_skip("s390: si_addr is unreliable");
30 #endif
31
32 /* write instruction pointer length to the log */
33 assert(syscall(__NR_write, -1, (void *) 8UL, 2 * sizeof(void *)) < 0);
34
35 /* just a noticeable line in the log */
36 assert(munmap(&main, 0) < 0);
37
38 int pid = fork();
39 if (pid < 0)
40 perror_msg_and_fail("fork");
41
42 if (!pid) {
43 const unsigned long mask = ~(pagesize - 1);
44 unsigned long addr = (unsigned long) &main & mask;
45 unsigned long size = pagesize << 1;
46
47 #ifdef HAVE_DLADDR
48 Dl_info info;
49 if (dladdr(&main, &info)) {
50 const unsigned long base =
51 (unsigned long) info.dli_fbase & mask;
52 if (base < addr) {
53 size += addr - base;
54 addr = base;
55 }
56 } else
57 #endif
58 {
59 addr -= size;
60 size <<= 1;
61 }
62
63 /* Avoid creating core dumps */
64 (void) prctl(PR_SET_DUMPABLE, 0, 0, 0, 0);
65
66 /* SIGSEGV is expected */
67 (void) munmap((void *) addr, size);
68 (void) munmap((void *) addr, size);
69 error_msg_and_skip("SIGSEGV did not happen");
70 }
71
72 int status;
73 assert(wait(&status) == pid);
74 assert(WIFSIGNALED(status));
75 assert(WTERMSIG(status) == SIGSEGV);
76
77 /* dump process map for debug purposes */
78 close(0);
79 if (!open("/proc/self/maps", O_RDONLY))
80 (void) sendfile(1, 0, NULL, pagesize);
81
82 return 0;
83 }