1 /*
2 * Copyright (c) 2016-2024 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28
29 #include <assert.h>
30 #include <errno.h>
31 #include <string.h>
32 #include <stdlib.h>
33 #include <stdio.h>
34 #include <unistd.h>
35 #include <uuid/uuid.h>
36 #include <sys/select.h>
37 #include <poll.h>
38 #include <sys/event.h>
39 #include <darwintest.h>
40 #include "skywalk_test_driver.h"
41 #include "skywalk_test_common.h"
42 #include "skywalk_test_utils.h"
43
44 static int
skt_badringtx_common(int argc,char * argv[],int method)45 skt_badringtx_common(int argc, char *argv[], int method)
46 {
47 int error;
48 channel_t channel;
49 uuid_t channel_uuid;
50 fd_set rfdset, wfdset, efdset;
51 struct pollfd fds;
52 int kq;
53 struct kevent kevin, kevout;
54 ring_id_t ringid;
55 channel_ring_t ring;
56 int channelfd;
57 struct timeval timeout;
58 struct timespec ktimeout;
59
60 error = uuid_parse(argv[3], channel_uuid);
61 SKTC_ASSERT_ERR(!error);
62
63 channel = sktu_channel_create_extended(channel_uuid, 0,
64 CHANNEL_DIR_TX_RX, CHANNEL_RING_ID_ANY, NULL,
65 -1, -1, -1, -1, -1, -1, -1, 1, -1, -1);
66 assert(channel);
67
68 channelfd = os_channel_get_fd(channel);
69 assert(channelfd != -1);
70
71 ringid = os_channel_ring_id(channel, CHANNEL_FIRST_TX_RING);
72 ring = os_channel_tx_ring(channel, ringid);
73 assert(ring);
74
75 struct __user_channel_ring *cr = (struct __user_channel_ring *)ring->chrd_ring; // deconst
76
77 cr->ring_head = -1;
78 *(slot_idx_t *)(uintptr_t)&cr->ring_tail = -1;
79
80 switch (method) {
81 case 0:
82 memset(&timeout, 0, sizeof(timeout));
83 FD_ZERO(&rfdset);
84 FD_SET(channelfd, &rfdset);
85 FD_ZERO(&wfdset);
86 FD_SET(channelfd, &wfdset);
87 FD_ZERO(&efdset);
88 FD_SET(channelfd, &efdset);
89 error = select(channelfd + 1, &rfdset, &wfdset, &efdset, &timeout);
90 /* SHOULD NOT BE REACHED */
91
92 /*
93 * Sanity checks to localize failures, in case the crash doesn't
94 * succeed:
95 */
96 SKTC_ASSERT_ERR(error != -1);
97 SKTC_ASSERT_ERR(error == 2);
98 assert(!FD_ISSET(channelfd, &rfdset));
99 assert(FD_ISSET(channelfd, &wfdset)); // XXX is it correct to return writable as well as error?
100 assert(FD_ISSET(channelfd, &efdset));
101 break;
102 case 1:
103 fds.fd = channelfd;
104 fds.events = POLLSTANDARD;
105 fds.revents = 0;
106 error = poll(&fds, 1, 0);
107 /* SHOULD NOT BE REACHED */
108
109 /*
110 * Sanity checks to localize failures, in case the crash doesn't
111 * succeed:
112 */
113 SKTC_ASSERT_ERR(error != -1);
114 SKTC_ASSERT_ERR(error == 1);
115 assert(fds.fd == channelfd);
116 assert(fds.events == POLLSTANDARD);
117 T_LOG("events 0x%x revents 0x%x check 0x%x\n", fds.events, fds.revents, (POLLWRNORM | POLLWRBAND | POLLERR));
118 assert(fds.revents == POLLNVAL);
119 /*
120 * XXX poll() can also fail with POLLERR, if the error condition occurs
121 * while waiting, instead of before - should find some way to test that
122 * scenario
123 */
124 break;
125 case 2:
126 memset(&ktimeout, 0, sizeof(ktimeout));
127 kq = kqueue();
128 assert(kq != -1);
129 EV_SET(&kevin, channelfd, EVFILT_WRITE, EV_ADD | EV_ENABLE, 0, 0, NULL);
130 memset(&kevout, 0, sizeof(kevout));
131 error = kevent(kq, &kevin, 1, &kevout, 1, &ktimeout);
132 /* SHOULD NOT BE REACHED */
133
134 /*
135 * Sanity checks to localize failures, in case the crash doesn't
136 * succeed:
137 */
138 T_LOG("error %d flags 0x%x data 0x%lx\n", error, kevout.flags, kevout.data);
139 SKTC_ASSERT_ERR(error != -1);
140 SKTC_ASSERT_ERR(error == 1);
141 assert(kevout.filter == EVFILT_WRITE);
142 assert(kevout.ident == channelfd);
143 assert(kevout.udata == NULL);
144 assert(kevout.flags & EV_ERROR);
145 assert(kevout.data == EFAULT);
146 close(kq);
147 break;
148 case 3:
149 error = os_channel_sync(channel, CHANNEL_SYNC_TX);
150 /* SHOULD NOT BE REACHED */
151
152 T_LOG("error = %d\n", error);
153 SKTC_ASSERT_ERR(error);
154 SKTC_ASSERT_ERR(errno == EFAULT);
155 break;
156 default:
157 abort();
158 }
159
160 return 1;
161 }
162
163 static int
skt_badringrx_common(int argc,char * argv[],int method)164 skt_badringrx_common(int argc, char *argv[], int method)
165 {
166 int error;
167 channel_t channel;
168 uuid_t channel_uuid;
169 fd_set rfdset, wfdset, efdset;
170 struct pollfd fds;
171 int kq;
172 struct kevent kevin, kevout;
173 ring_id_t ringid;
174 channel_ring_t ring;
175 int channelfd;
176 struct timeval timeout;
177 struct timespec ktimeout;
178
179 error = uuid_parse(argv[3], channel_uuid);
180 SKTC_ASSERT_ERR(!error);
181
182 channel = sktu_channel_create_extended(channel_uuid, 0,
183 CHANNEL_DIR_TX_RX, CHANNEL_RING_ID_ANY, NULL,
184 -1, -1, -1, -1, -1, -1, -1, 1, -1, -1);
185 assert(channel);
186
187 channelfd = os_channel_get_fd(channel);
188 assert(channelfd != -1);
189
190 ringid = os_channel_ring_id(channel, CHANNEL_FIRST_RX_RING);
191 ring = os_channel_rx_ring(channel, ringid);
192 assert(ring);
193
194 struct __user_channel_ring *cr = (struct __user_channel_ring *)ring->chrd_ring; // deconst
195
196 cr->ring_head = -1;
197 *(slot_idx_t *)(uintptr_t)&cr->ring_tail = -1;
198
199 switch (method) {
200 case 0:
201 memset(&timeout, 0, sizeof(timeout));
202 FD_ZERO(&rfdset);
203 FD_SET(channelfd, &rfdset);
204 FD_ZERO(&wfdset);
205 FD_SET(channelfd, &wfdset);
206 FD_ZERO(&efdset);
207 FD_SET(channelfd, &efdset);
208 error = select(channelfd + 1, &rfdset, &wfdset, &efdset, &timeout);
209 /* SHOULD NOT BE REACHED */
210
211 /*
212 * Sanity checks to localize failures, in case the crash doesn't
213 * succeed:
214 */
215 SKTC_ASSERT_ERR(error != -1);
216 SKTC_ASSERT_ERR(error == 2);
217 assert(!FD_ISSET(channelfd, &rfdset));
218 assert(FD_ISSET(channelfd, &wfdset)); // XXX is it correct to return writable as well as error?
219 assert(FD_ISSET(channelfd, &efdset));
220 break;
221 case 1:
222 fds.fd = channelfd;
223 fds.events = POLLSTANDARD;
224 fds.revents = 0;
225 error = poll(&fds, 1, 0);
226 /* SHOULD NOT BE REACHED */
227
228 /*
229 * Sanity checks to localize failures, in case the crash doesn't
230 * succeed:
231 */
232 SKTC_ASSERT_ERR(error != -1);
233 SKTC_ASSERT_ERR(error == 1);
234 assert(fds.fd == channelfd);
235 assert(fds.events == POLLSTANDARD);
236 T_LOG("events 0x%x revents 0x%x\n", fds.events, fds.revents);
237 assert(fds.revents == POLLNVAL);
238 /*
239 * XXX poll() can also fail with POLLERR, if the error condition occurs
240 * while waiting, instead of before - should find some way to test that
241 * scenario
242 */
243 break;
244 case 2:
245 memset(&ktimeout, 0, sizeof(ktimeout));
246 kq = kqueue();
247 assert(kq != -1);
248 EV_SET(&kevin, channelfd, EVFILT_READ, EV_ADD | EV_ENABLE, 0, 0, NULL);
249 memset(&kevout, 0, sizeof(kevout));
250 error = kevent(kq, &kevin, 1, &kevout, 1, &ktimeout);
251 /* SHOULD NOT BE REACHED */
252
253 /*
254 * Sanity checks to localize failures, in case the crash doesn't
255 * succeed:
256 */
257 T_LOG("error %d flags 0x%x data 0x%lx\n", error, kevout.flags, kevout.data);
258 SKTC_ASSERT_ERR(error != -1);
259 SKTC_ASSERT_ERR(error == 1);
260 assert(kevout.filter == EVFILT_READ);
261 assert(kevout.ident == channelfd);
262 assert(kevout.udata == NULL);
263 assert(kevout.flags & EV_ERROR);
264 assert(kevout.data == EFAULT);
265 close(kq);
266 break;
267 case 3:
268 error = os_channel_sync(channel, CHANNEL_SYNC_RX);
269 /* SHOULD NOT BE REACHED */
270
271 /*
272 * Sanity checks to localize failures, in case the crash doesn't
273 * succeed:
274 */
275 SKTC_ASSERT_ERR(error);
276 SKTC_ASSERT_ERR(errno == EFAULT);
277 break;
278 default:
279 abort();
280 }
281
282 return 1;
283 }
284
285
286 static int
skt_badringtl_main(int argc,char * argv[])287 skt_badringtl_main(int argc, char *argv[])
288 {
289 return skt_badringtx_common(argc, argv, 0);
290 }
291
292 struct skywalk_test skt_badringtl = {
293 "badringtl", "calls select with bad tx ring pointers",
294 SK_FEATURE_SKYWALK | SK_FEATURE_NEXUS_USER_PIPE,
295 skt_badringtl_main, SKTC_GENERIC_UPIPE_ARGV,
296 sktc_generic_upipe_null_init, sktc_generic_upipe_fini,
297 SIGABRT << 24, 0,
298 };
299
300 static int
skt_badringtp_main(int argc,char * argv[])301 skt_badringtp_main(int argc, char *argv[])
302 {
303 return skt_badringtx_common(argc, argv, 1);
304 }
305
306 struct skywalk_test skt_badringtp = {
307 "badringtp", "calls poll with bad tx ring pointers",
308 SK_FEATURE_SKYWALK | SK_FEATURE_NEXUS_USER_PIPE,
309 skt_badringtp_main, SKTC_GENERIC_UPIPE_ARGV,
310 sktc_generic_upipe_null_init, sktc_generic_upipe_fini,
311 SIGABRT << 24, 0,
312 };
313
314 static int
skt_badringtk_main(int argc,char * argv[])315 skt_badringtk_main(int argc, char *argv[])
316 {
317 return skt_badringtx_common(argc, argv, 2);
318 }
319
320 struct skywalk_test skt_badringtk = {
321 "badringtk", "calls kqueue with bad tx ring pointers",
322 SK_FEATURE_SKYWALK | SK_FEATURE_NEXUS_USER_PIPE,
323 skt_badringtk_main, SKTC_GENERIC_UPIPE_ARGV,
324 sktc_generic_upipe_null_init, sktc_generic_upipe_fini,
325 SIGABRT << 24, 0,
326 };
327
328 static int
skt_badringts_main(int argc,char * argv[])329 skt_badringts_main(int argc, char *argv[])
330 {
331 return skt_badringtx_common(argc, argv, 3);
332 }
333
334 struct skywalk_test skt_badringts = {
335 "badringts", "calls sync with bad tx ring pointers",
336 SK_FEATURE_SKYWALK | SK_FEATURE_NEXUS_USER_PIPE,
337 skt_badringts_main, SKTC_GENERIC_UPIPE_ARGV,
338 sktc_generic_upipe_null_init, sktc_generic_upipe_fini,
339 SIGABRT << 24, 0,
340 };
341
342 static int
skt_badringrl_main(int argc,char * argv[])343 skt_badringrl_main(int argc, char *argv[])
344 {
345 return skt_badringrx_common(argc, argv, 0);
346 }
347
348 struct skywalk_test skt_badringrl = {
349 "badringrl", "calls select with bad rx ring pointers",
350 SK_FEATURE_SKYWALK | SK_FEATURE_NEXUS_USER_PIPE,
351 skt_badringrl_main, SKTC_GENERIC_UPIPE_ARGV,
352 sktc_generic_upipe_null_init, sktc_generic_upipe_fini,
353 SIGABRT << 24, 0,
354 };
355
356 static int
skt_badringrp_main(int argc,char * argv[])357 skt_badringrp_main(int argc, char *argv[])
358 {
359 return skt_badringrx_common(argc, argv, 1);
360 }
361
362 struct skywalk_test skt_badringrp = {
363 "badringrp", "calls poll with bad rx ring pointers",
364 SK_FEATURE_SKYWALK | SK_FEATURE_NEXUS_USER_PIPE,
365 skt_badringrp_main, SKTC_GENERIC_UPIPE_ARGV,
366 sktc_generic_upipe_null_init, sktc_generic_upipe_fini,
367 SIGABRT << 24, 0,
368 };
369
370 static int
skt_badringrk_main(int argc,char * argv[])371 skt_badringrk_main(int argc, char *argv[])
372 {
373 return skt_badringrx_common(argc, argv, 2);
374 }
375
376 struct skywalk_test skt_badringrk = {
377 "badringrk", "calls kqueue with bad rx ring pointers",
378 SK_FEATURE_SKYWALK | SK_FEATURE_NEXUS_USER_PIPE,
379 skt_badringrk_main, SKTC_GENERIC_UPIPE_ARGV,
380 sktc_generic_upipe_null_init, sktc_generic_upipe_fini,
381 SIGABRT << 24, 0,
382 };
383
384 static int
skt_badringrs_main(int argc,char * argv[])385 skt_badringrs_main(int argc, char *argv[])
386 {
387 return skt_badringrx_common(argc, argv, 3);
388 }
389
390 struct skywalk_test skt_badringrs = {
391 "badringrs", "calls sync with bad rx ring pointers",
392 SK_FEATURE_SKYWALK | SK_FEATURE_NEXUS_USER_PIPE,
393 skt_badringrs_main, SKTC_GENERIC_UPIPE_ARGV,
394 sktc_generic_upipe_null_init, sktc_generic_upipe_fini,
395 SIGABRT << 24, 0,
396 };
397
398
399 /***************************************************************/
400