]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - tests/sys/vm/page_fault_signal.c
Remove $FreeBSD$: one-line .c pattern
[FreeBSD/FreeBSD.git] / tests / sys / vm / page_fault_signal.c
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause
3  *
4  * Copyright (c) 2019 Jilles Tjoelker
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  */
27
28 #include <sys/mman.h>
29
30 #include <atf-c.h>
31 #include <fcntl.h>
32 #include <setjmp.h>
33 #include <signal.h>
34 #include <stdio.h>
35
36 static sigjmp_buf sig_env;
37 static volatile int last_sig, last_code;
38
39 static void
40 sighandler(int sig, siginfo_t *info, void *context __unused)
41 {
42
43         last_sig = sig;
44         last_code = info->si_code;
45         siglongjmp(sig_env, 1);
46 }
47
48 static void
49 setup_signals(void)
50 {
51         struct sigaction sa;
52         int r;
53
54         sa.sa_sigaction = sighandler;
55         sa.sa_flags = SA_RESTART | SA_RESETHAND | SA_SIGINFO;
56         r = sigfillset(&sa.sa_mask);
57         ATF_REQUIRE(r != -1);
58         r = sigaction(SIGILL, &sa, NULL);
59         ATF_REQUIRE(r != -1);
60         r = sigaction(SIGBUS, &sa, NULL);
61         ATF_REQUIRE(r != -1);
62         r = sigaction(SIGSEGV, &sa, NULL);
63         ATF_REQUIRE(r != -1);
64 }
65
66 ATF_TC_WITHOUT_HEAD(page_fault_signal__segv_maperr_1);
67 ATF_TC_BODY(page_fault_signal__segv_maperr_1, tc)
68 {
69         int *p;
70         int r;
71         int sz;
72
73         sz = getpagesize();
74         p = mmap(NULL, sz, PROT_READ, MAP_ANON, -1, 0);
75         ATF_REQUIRE(p != MAP_FAILED);
76         r = munmap(p, sz);
77         ATF_REQUIRE(r != -1);
78         if (sigsetjmp(sig_env, 1) == 0) {
79                 setup_signals();
80                 *(volatile int *)p = 1;
81         }
82         ATF_CHECK_EQ(SIGSEGV, last_sig);
83         ATF_CHECK_EQ(SEGV_MAPERR, last_code);
84 }
85
86 ATF_TC_WITHOUT_HEAD(page_fault_signal__segv_accerr_1);
87 ATF_TC_BODY(page_fault_signal__segv_accerr_1, tc)
88 {
89         int *p;
90         int sz;
91
92         sz = getpagesize();
93         p = mmap(NULL, sz, PROT_READ, MAP_ANON, -1, 0);
94         ATF_REQUIRE(p != MAP_FAILED);
95         if (sigsetjmp(sig_env, 1) == 0) {
96                 setup_signals();
97                 *(volatile int *)p = 1;
98         }
99         (void)munmap(p, sz);
100         ATF_CHECK_EQ(SIGSEGV, last_sig);
101         ATF_CHECK_EQ(SEGV_ACCERR, last_code);
102 }
103
104 ATF_TC_WITHOUT_HEAD(page_fault_signal__segv_accerr_2);
105 ATF_TC_BODY(page_fault_signal__segv_accerr_2, tc)
106 {
107         int *p;
108         int sz;
109
110         sz = getpagesize();
111         p = mmap(NULL, sz, PROT_NONE, MAP_ANON, -1, 0);
112         ATF_REQUIRE(p != MAP_FAILED);
113         if (sigsetjmp(sig_env, 1) == 0) {
114                 setup_signals();
115                 (void)*(volatile int *)p;
116         }
117         (void)munmap(p, sz);
118         ATF_CHECK_EQ(SIGSEGV, last_sig);
119         ATF_CHECK_EQ(SEGV_ACCERR, last_code);
120 }
121
122 ATF_TC_WITHOUT_HEAD(page_fault_signal__bus_objerr_1);
123 ATF_TC_BODY(page_fault_signal__bus_objerr_1, tc)
124 {
125         int *p;
126         int fd;
127         int sz;
128
129         sz = getpagesize();
130         fd = shm_open(SHM_ANON, O_RDWR | O_CREAT, 0600);
131         ATF_REQUIRE(fd != -1);
132         p = mmap(NULL, sz, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
133         ATF_REQUIRE(p != MAP_FAILED);
134         if (sigsetjmp(sig_env, 1) == 0) {
135                 setup_signals();
136                 *(volatile int *)p = 1;
137         }
138         (void)munmap(p, sz);
139         (void)close(fd);
140         ATF_CHECK_EQ(SIGBUS, last_sig);
141         ATF_CHECK_EQ(BUS_OBJERR, last_code);
142 }
143
144 ATF_TC_WITHOUT_HEAD(page_fault_signal__bus_objerr_2);
145 ATF_TC_BODY(page_fault_signal__bus_objerr_2, tc)
146 {
147         int *p;
148         int fd;
149         int r;
150         int sz;
151
152         sz = getpagesize();
153         fd = shm_open(SHM_ANON, O_RDWR | O_CREAT, 0600);
154         ATF_REQUIRE(fd != -1);
155         r = ftruncate(fd, sz);
156         ATF_REQUIRE(r != -1);
157         p = mmap(NULL, sz * 2, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
158         ATF_REQUIRE(p != MAP_FAILED);
159         if (sigsetjmp(sig_env, 1) == 0) {
160                 setup_signals();
161                 ((volatile int *)p)[sz / sizeof(int)] = 1;
162         }
163         (void)munmap(p, sz * 2);
164         (void)close(fd);
165         ATF_CHECK_EQ(SIGBUS, last_sig);
166         ATF_CHECK_EQ(BUS_OBJERR, last_code);
167 }
168
169 ATF_TP_ADD_TCS(tp)
170 {
171
172         ATF_TP_ADD_TC(tp, page_fault_signal__segv_maperr_1);
173         ATF_TP_ADD_TC(tp, page_fault_signal__segv_accerr_1);
174         ATF_TP_ADD_TC(tp, page_fault_signal__segv_accerr_2);
175         ATF_TP_ADD_TC(tp, page_fault_signal__bus_objerr_1);
176         ATF_TP_ADD_TC(tp, page_fault_signal__bus_objerr_2);
177
178         return (atf_no_error());
179 }