t_compat_cancel.c revision 1.2 1 /* $NetBSD: t_compat_cancel.c,v 1.2 2025/04/11 02:07:17 riastradh Exp $ */
2
3 /*
4 * Copyright (c) 2025 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 #define __LIBC12_SOURCE__ /* expose compat declarations */
30
31 #include <sys/cdefs.h>
32 __RCSID("$NetBSD: t_compat_cancel.c,v 1.2 2025/04/11 02:07:17 riastradh Exp $");
33
34 #include <sys/event.h>
35 #include <sys/mman.h>
36
37 #include <aio.h>
38 #include <atf-c.h>
39 #include <mqueue.h>
40 #include <pthread.h>
41 #include <signal.h>
42
43 #include <compat/sys/event.h>
44 #include <compat/sys/mman.h>
45 #include <compat/sys/poll.h>
46 #include <compat/sys/select.h>
47
48 #include <compat/include/aio.h>
49 #include <compat/include/mqueue.h>
50 #include <compat/include/signal.h>
51 #include <compat/include/time.h>
52
53 #include "cancelpoint.h"
54 #include "h_macros.h"
55
56 pthread_barrier_t bar;
57 bool cleanup_done;
58
59 static void
60 cancelpoint_compat100_kevent(void)
61 {
62 int kq;
63 struct kevent100 ev;
64
65 memset(&ev, 0, sizeof(ev));
66 ev.ident = SIGUSR1;
67 ev.filter = EVFILT_SIGNAL;
68 ev.flags = EV_ADD|EV_ENABLE;
69 ev.fflags = 0;
70 ev.data = 0;
71 ev.udata = 0;
72
73 RL(kq = kqueue());
74 RL(__kevent50(kq, &ev, 1, NULL, 1, &(const struct timespec){0,0}));
75 cancelpointready();
76 RL(__kevent50(kq, NULL, 0, &ev, 1, NULL));
77 }
78
79 static void
80 cancelpoint_compat12_msync(void)
81 {
82 const unsigned long pagesize = sysconf(_SC_PAGESIZE);
83 int fd;
84 void *map;
85
86 RL(fd = open("file", O_RDWR|O_CREAT, 0666));
87 RL(ftruncate(fd, pagesize));
88 REQUIRE_LIBC(map = mmap(NULL, pagesize, PROT_READ|PROT_WRITE,
89 MAP_SHARED, fd, 0),
90 MAP_FAILED);
91 cancelpointready();
92 RL(msync(map, pagesize));
93 }
94
95 static void
96 cancelpoint_compat50___sigtimedwait(void)
97 {
98 sigset_t mask, omask;
99 siginfo_t info;
100 struct timespec50 t = {.tv_sec = 2, .tv_nsec = 0};
101
102 RL(__sigfillset14(&mask));
103 RL(__sigprocmask14(SIG_BLOCK, &mask, &omask));
104 cancelpointready();
105 RL(__sigtimedwait(&omask, &info, &t));
106 }
107
108 static void
109 cancelpoint_compat50_aio_suspend(void)
110 {
111 int fd[2];
112 char buf[32];
113 struct aiocb aio = {
114 .aio_offset = 0,
115 .aio_buf = buf,
116 .aio_nbytes = sizeof(buf),
117 .aio_fildes = -1,
118 };
119 const struct aiocb *const aiolist[] = { &aio };
120
121 RL(pipe(fd));
122 aio.aio_fildes = fd[0];
123 RL(aio_read(&aio));
124 cancelpointready();
125 RL(aio_suspend(aiolist, __arraycount(aiolist), NULL));
126 }
127
128 static void
129 cancelpoint_compat50_kevent(void)
130 {
131 int kq;
132 struct kevent100 ev;
133
134 memset(&ev, 0, sizeof(ev));
135 ev.ident = SIGUSR1;
136 ev.filter = EVFILT_SIGNAL;
137 ev.flags = EV_ADD|EV_ENABLE;
138 ev.fflags = 0;
139 ev.data = 0;
140 ev.udata = 0;
141
142 RL(kq = kqueue());
143 RL(kevent(kq, &ev, 1, NULL, 1, &(const struct timespec50){0,0}));
144 cancelpointready();
145 RL(kevent(kq, NULL, 0, &ev, 1, NULL));
146 }
147
148 static void
149 cancelpoint_compat50_mq_timedreceive(void)
150 {
151 mqd_t mq;
152 char buf[32];
153 struct timespec50 t = {.tv_sec = 2, .tv_nsec = 0};
154
155 RL(mq = mq_open("mq", O_RDWR|O_CREAT, 0666, NULL));
156 cancelpointready();
157 RL(mq_timedreceive(mq, buf, sizeof(buf), NULL, &t));
158 }
159
160 static void
161 cancelpoint_compat50_mq_timedsend(void)
162 {
163 mqd_t mq;
164 char buf[32] = {0};
165 struct timespec50 t = {.tv_sec = 2, .tv_nsec = 0};
166
167 RL(mq = mq_open("mq", O_RDWR|O_CREAT, 0666, NULL));
168 cancelpointready();
169 RL(mq_timedsend(mq, buf, sizeof(buf), 0, &t));
170 }
171
172 static void
173 cancelpoint_compat50_nanosleep(void)
174 {
175 struct timespec50 t = {.tv_sec = 2, .tv_nsec = 0};
176
177 cancelpointready();
178 RL(nanosleep(&t, NULL));
179 }
180
181 static void
182 cancelpoint_compat50_pollts(void)
183 {
184 int fd[2];
185 struct pollfd pfd;
186 struct timespec50 t = {.tv_sec = 2, .tv_nsec = 0};
187
188 RL(pipe(fd));
189 pfd.fd = fd[0];
190 pfd.events = POLLIN;
191 cancelpointready();
192 RL(pollts(&pfd, 1, &t, NULL));
193 }
194
195 static void
196 cancelpoint_compat50_pselect(void)
197 {
198 int fd[2];
199 fd_set readfd;
200 struct timespec50 t = {.tv_sec = 2, .tv_nsec = 0};
201
202 FD_ZERO(&readfd);
203
204 RL(pipe(fd));
205 FD_SET(fd[0], &readfd);
206 cancelpointready();
207 RL(pselect(fd[0] + 1, &readfd, NULL, NULL, &t, NULL));
208 }
209
210 static void
211 cancelpoint_compat50_select(void)
212 {
213 int fd[2];
214 fd_set readfd;
215 struct timeval50 t = {.tv_sec = 1, .tv_usec = 0};
216
217 FD_ZERO(&readfd);
218
219 RL(pipe(fd));
220 FD_SET(fd[0], &readfd);
221 cancelpointready();
222 RL(select(fd[0] + 1, &readfd, NULL, NULL, &t));
223 }
224
225 static void
226 cancelpoint_compat13_sigsuspend(void)
227 {
228 sigset13_t mask, omask;
229
230 RL(sigfillset(&mask));
231 RL(sigprocmask(SIG_BLOCK, &mask, &omask));
232 cancelpointready();
233 RL(sigsuspend(&omask));
234 }
235
236 static void
237 cancelpoint_compat50_sigtimedwait(void)
238 {
239 sigset_t mask, omask;
240 siginfo_t info;
241 struct timespec50 t = {.tv_sec = 2, .tv_nsec = 0};
242
243 RL(__sigfillset14(&mask));
244 RL(__sigprocmask14(SIG_BLOCK, &mask, &omask));
245 cancelpointready();
246 RL(sigtimedwait(&omask, &info, &t));
247 }
248
249 TEST_CANCELPOINT(cancelpoint_compat100_kevent, __nothing)
250 TEST_CANCELPOINT(cancelpoint_compat12_msync, __nothing)
251 TEST_CANCELPOINT(cancelpoint_compat13_sigsuspend,
252 atf_tc_expect_signal(SIGALRM, "PR lib/59240: POSIX.1-2024:"
253 " cancellation point audit"))
254 TEST_CANCELPOINT(cancelpoint_compat50___sigtimedwait,
255 atf_tc_expect_signal(SIGALRM, "PR lib/59240: POSIX.1-2024:"
256 " cancellation point audit"))
257 TEST_CANCELPOINT(cancelpoint_compat50_aio_suspend, __nothing)
258 TEST_CANCELPOINT(cancelpoint_compat50_kevent, __nothing)
259 TEST_CANCELPOINT(cancelpoint_compat50_mq_timedreceive, __nothing)
260 TEST_CANCELPOINT(cancelpoint_compat50_mq_timedsend, __nothing)
261 TEST_CANCELPOINT(cancelpoint_compat50_nanosleep, __nothing)
262 TEST_CANCELPOINT(cancelpoint_compat50_pollts, __nothing)
263 TEST_CANCELPOINT(cancelpoint_compat50_pselect, __nothing)
264 TEST_CANCELPOINT(cancelpoint_compat50_select, __nothing)
265 TEST_CANCELPOINT(cancelpoint_compat50_sigtimedwait,
266 atf_tc_expect_signal(SIGALRM, "PR lib/59240: POSIX.1-2024:"
267 " cancellation point audit"))
268
269 ATF_TP_ADD_TCS(tp)
270 {
271
272 ADD_TEST_CANCELPOINT(cancelpoint_compat100_kevent);
273 ADD_TEST_CANCELPOINT(cancelpoint_compat12_msync);
274 ADD_TEST_CANCELPOINT(cancelpoint_compat13_sigsuspend);
275 ADD_TEST_CANCELPOINT(cancelpoint_compat50___sigtimedwait);
276 ADD_TEST_CANCELPOINT(cancelpoint_compat50_aio_suspend);
277 ADD_TEST_CANCELPOINT(cancelpoint_compat50_kevent);
278 ADD_TEST_CANCELPOINT(cancelpoint_compat50_mq_timedreceive);
279 ADD_TEST_CANCELPOINT(cancelpoint_compat50_mq_timedsend);
280 ADD_TEST_CANCELPOINT(cancelpoint_compat50_nanosleep);
281 ADD_TEST_CANCELPOINT(cancelpoint_compat50_pollts);
282 ADD_TEST_CANCELPOINT(cancelpoint_compat50_pselect);
283 ADD_TEST_CANCELPOINT(cancelpoint_compat50_select);
284 ADD_TEST_CANCELPOINT(cancelpoint_compat50_sigtimedwait);
285
286 return atf_no_error();
287 }
288