1 /*        $NetBSD: t_compat_cancel.c,v 1.3 2025/04/25 13:09:44 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.3 2025/04/25 13:09:44 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
cancelpoint_compat100_kevent(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
cancelpoint_compat12_msync(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
cancelpoint_compat50___sigtimedwait(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
cancelpoint_compat50_aio_suspend(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
cancelpoint_compat50_kevent(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
cancelpoint_compat50_mq_timedreceive(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
cancelpoint_compat50_mq_timedsend(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
cancelpoint_compat50_nanosleep(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
cancelpoint_compat50_pollts(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
cancelpoint_compat50_pselect(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
cancelpoint_compat50_select(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
cancelpoint_compat13_sigsuspend(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
cancelpoint_compat50_sigtimedwait(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 
TEST_CANCELPOINT(cancelpoint_compat100_kevent,__nothing)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(-1, "PR lib/59240: POSIX.1-2024:"
253           " cancellation point audit"))
254 TEST_CANCELPOINT(cancelpoint_compat50___sigtimedwait,
255     atf_tc_expect_signal(-1, "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(-1, "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