xref: /xnu-11215.41.3/tests/skywalk/skt_badring.c (revision 33de042d024d46de5ff4e89f2471de6608e37fa4)
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