xref: /xnu-11417.121.6/tests/skywalk/skt_writemem.c (revision a1e26a70f38d1d7daa7b49b258e2f8538ad81650)
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 <stdlib.h>
32 #include <string.h>
33 #include <stdio.h>
34 #include <uuid/uuid.h>
35 #include <sys/select.h>
36 #include <sys/mman.h>
37 #include <mach/vm_map.h>
38 #include <darwintest.h>
39 #include "skywalk_test_driver.h"
40 #include "skywalk_test_common.h"
41 #include "skywalk_test_utils.h"
42 
43 static int
skt_writeif_main(int argc,char * argv[])44 skt_writeif_main(int argc, char *argv[])
45 {
46 	int error;
47 	channel_t channel;
48 	uuid_t channel_uuid;
49 	error = uuid_parse(argv[3], channel_uuid);
50 	SKTC_ASSERT_ERR(!error);
51 
52 	channel = sktu_channel_create_extended(channel_uuid, 0,
53 	    CHANNEL_DIR_TX_RX, CHANNEL_RING_ID_ANY, NULL,
54 	    -1, -1, -1, -1, -1, -1, -1, 1, -1, -1);
55 	assert(channel);
56 
57 	*(char *)channel->chd_schema->csm_kern_name = 'X';
58 
59 	return 1; // shouldn't be reached
60 }
61 
62 struct skywalk_test skt_writeif = {
63 	.skt_testname = "writeif",
64 	.skt_testdesc = "writes to the read only channel if",
65 	.skt_required_features = SK_FEATURE_SKYWALK | SK_FEATURE_NEXUS_USER_PIPE,
66 	.skt_main = skt_writeif_main,
67 	.skt_argv = SKTC_GENERIC_UPIPE_ARGV,
68 	.skt_init = sktc_generic_upipe_null_init,
69 	.skt_fini = sktc_generic_upipe_fini,
70 	.skt_expected_exception_code = 0xa100002,
71 	.skt_expected_exception_code_ignore = 0,
72 };
73 
74 static int
skt_writering_main(int argc,char * argv[])75 skt_writering_main(int argc, char *argv[])
76 {
77 	int error;
78 	channel_t channel;
79 	uuid_t channel_uuid;
80 	error = uuid_parse(argv[3], channel_uuid);
81 	SKTC_ASSERT_ERR(!error);
82 
83 	channel = sktu_channel_create_extended(channel_uuid, 0,
84 	    CHANNEL_DIR_TX_RX, CHANNEL_RING_ID_ANY, NULL,
85 	    -1, -1, -1, -1, -1, -1, -1, 1, -1, -1);
86 	assert(channel);
87 
88 	ring_id_t ringid;
89 	channel_ring_t ring;
90 	ringid = os_channel_ring_id(channel, CHANNEL_FIRST_TX_RING);
91 	ring = os_channel_tx_ring(channel, ringid);
92 	assert(ring);
93 
94 	assert((intptr_t)channel->chd_schema +
95 	    channel->chd_schema->csm_ring_ofs[0].ring_off ==
96 	    (intptr_t)ring->chrd_ring);
97 
98 	/* Write garbage to ring descriptors */
99 	memset((void *)ring->chrd_ring, 0x5a, sizeof(*ring->chrd_ring));
100 
101 	error = os_channel_sync(channel, CHANNEL_SYNC_TX);
102 	/* Expect failure (and a process crash) here */
103 
104 	/*
105 	 * Sanity checks to localize failures, in case the crash doesn't
106 	 * succeed:
107 	 */
108 	SKTC_ASSERT_ERR(error);
109 	SKTC_ASSERT_ERR(errno == EFAULT);
110 
111 	return 1;
112 }
113 
114 struct skywalk_test skt_writering = {
115 	.skt_testname = "writering",
116 	.skt_testdesc = "writes to the writeable ring",
117 	.skt_required_features = SK_FEATURE_SKYWALK | SK_FEATURE_NEXUS_USER_PIPE,
118 	.skt_main = skt_writering_main,
119 	.skt_argv = SKTC_GENERIC_UPIPE_ARGV,
120 	.skt_init = sktc_generic_upipe_null_init,
121 	.skt_fini = sktc_generic_upipe_fini,
122 	.skt_expected_exception_code = SIGABRT << 24,
123 	        .skt_expected_exception_code_ignore = 0,
124 };
125 
126 static int
skt_readsmap_main(int argc,char * argv[])127 skt_readsmap_main(int argc, char *argv[])
128 {
129 	int error;
130 	channel_t channel;
131 	uuid_t channel_uuid;
132 	uint8_t byte;
133 
134 	error = uuid_parse(argv[3], channel_uuid);
135 	SKTC_ASSERT_ERR(!error);
136 
137 	channel = sktu_channel_create_extended(channel_uuid, 0,
138 	    CHANNEL_DIR_TX_RX, CHANNEL_RING_ID_ANY, NULL,
139 	    -1, -1, -1, -1, -1, -1, -1, 1, -1, -1);
140 	assert(channel);
141 
142 	//T_LOG("ch_if 0x%p offset 0x%llx pointer 0x%p\n",
143 	//	channel->chd_schema, channel->chd_schema->csm_ring_ofs[0].sd_off,
144 	//	(char *)channel->chd_schema+channel->chd_schema->csm_ring_ofs[0].sd_off);
145 
146 	// Verify we can read it
147 	memcpy(&byte, (void *)channel->chd_schema + channel->chd_schema->csm_ring_ofs[0].sd_off, 1);
148 
149 	return 0;
150 }
151 
152 struct skywalk_test skt_readsmap = {
153 	.skt_testname = "readsmap",
154 	.skt_testdesc = "reads from the read only smap",
155 	.skt_required_features = SK_FEATURE_SKYWALK | SK_FEATURE_NEXUS_USER_PIPE,
156 	.skt_main = skt_readsmap_main,
157 	.skt_argv = SKTC_GENERIC_UPIPE_ARGV,
158 	.skt_init = sktc_generic_upipe_null_init,
159 	.skt_fini = sktc_generic_upipe_fini,
160 };
161 
162 static int
skt_writesmap_main(int argc,char * argv[])163 skt_writesmap_main(int argc, char *argv[])
164 {
165 	int error;
166 	channel_t channel;
167 	uuid_t channel_uuid;
168 	uint8_t byte;
169 
170 	error = uuid_parse(argv[3], channel_uuid);
171 	SKTC_ASSERT_ERR(!error);
172 
173 	channel = sktu_channel_create_extended(channel_uuid, 0,
174 	    CHANNEL_DIR_TX_RX, CHANNEL_RING_ID_ANY, NULL,
175 	    -1, -1, -1, -1, -1, -1, -1, 1, -1, -1);
176 	assert(channel);
177 
178 	//T_LOG("ch_if 0x%p offset 0x%llx pointer 0x%p\n",
179 	//	channel->chd_schema, channel->chd_schema->csm_ring_ofs[0].sd_off,
180 	//	(char *)channel->chd_schema+channel->chd_schema->csm_ring_ofs[0].sd_off);
181 
182 	// Verify we can read it
183 	memcpy(&byte, (void *)channel->chd_schema + channel->chd_schema->csm_ring_ofs[0].sd_off, 1);
184 
185 	// Now try to write it
186 	memcpy((void *)channel->chd_schema + channel->chd_schema->csm_ring_ofs[0].sd_off, &byte, 1);
187 
188 	return 1; // shouldn't be reached
189 }
190 
191 struct skywalk_test skt_writesmap = {
192 	.skt_testname = "writesmap",
193 	.skt_testdesc = "writes to the read only smap",
194 	.skt_required_features = SK_FEATURE_SKYWALK | SK_FEATURE_NEXUS_USER_PIPE,
195 	.skt_main = skt_writesmap_main,
196 	.skt_argv = SKTC_GENERIC_UPIPE_ARGV,
197 	.skt_init = sktc_generic_upipe_null_init,
198 	.skt_fini = sktc_generic_upipe_fini,
199 	.skt_expected_exception_code = 0xa100002,
200 	.skt_expected_exception_code_ignore = 0,
201 };
202 
203 /****************************************************************/
204 
205 /*
206  * Nexus region verification tests.
207  */
208 
209 struct sktc_nexus_handles ms_fsw_handle;
210 static uuid_string_t ms_fsw_uuid_string;
211 #define SKT_VERIFY_NXADV_REGION         1
212 #define SKT_VERIFY_NXADV_REGION_STR     "1"
213 
214 static void
skt_ms_fsw_init(void)215 skt_ms_fsw_init(void)
216 {
217 	uuid_t flow_id;
218 	int error;
219 
220 	sktc_ifnet_feth0_create();
221 	sktc_create_flowswitch(&ms_fsw_handle, 0);
222 	uuid_unparse(ms_fsw_handle.fsw_nx_uuid, ms_fsw_uuid_string);
223 	/*
224 	 * flowswitch doesn't allow opening a channel without a flow bound
225 	 * to the port.
226 	 */
227 	uuid_generate(flow_id);
228 	error = sktc_bind_tcp4_flow(ms_fsw_handle.controller,
229 	    ms_fsw_handle.fsw_nx_uuid, 0, NEXUS_PORT_FLOW_SWITCH_CLIENT,
230 	    flow_id);
231 
232 	/* Don't assert as this is running in the test driver */
233 	if (error) {
234 		T_LOG("func %s sktc_bind_tcp4_flow returned error %d "
235 		    "errno %d: %s\n", __func__, error, errno, strerror(errno));
236 	}
237 }
238 
239 static void
skt_ms_fsw_fini(void)240 skt_ms_fsw_fini(void)
241 {
242 	sktc_cleanup_flowswitch(&ms_fsw_handle);
243 	sktc_ifnet_feth0_destroy();
244 }
245 
246 static void
skt_verify_nxadv_region(channel_t channel)247 skt_verify_nxadv_region(channel_t channel)
248 {
249 	struct sk_nexusadv *region;
250 	uint64_t region_size;
251 	channel_attr_t attr;
252 	int error;
253 
254 	attr = os_channel_attr_create();
255 	assert(attr != NULL);
256 	error = os_channel_read_attr(channel, attr);
257 	SKTC_ASSERT_ERR(!error);
258 
259 	/* verify size of the region */
260 	os_channel_attr_get(attr, CHANNEL_ATTR_NEXUS_ADV_SIZE, &region_size);
261 	assert(region_size == sizeof(*region));
262 
263 	/* verify version number */
264 	region = os_channel_get_advisory_region(channel);
265 	assert(region != NULL);
266 	assert(region->nxadv_ver == NX_ADVISORY_CURRENT_VERSION);
267 
268 	/* write should fault as the region is mapped read-only */
269 	region->nxadv_ver = 0;
270 
271 	/* shouldn't be reached */
272 	error = 1;
273 	SKTC_ASSERT_ERR(!error);
274 }
275 
276 int
skt_nxregion_verify_main(int argc,char * argv[])277 skt_nxregion_verify_main(int argc, char *argv[])
278 {
279 	int error;
280 	int test_id;
281 	uuid_t fsw_uuid;
282 	channel_t channel;
283 
284 	error = uuid_parse(argv[3], fsw_uuid);
285 	SKTC_ASSERT_ERR(error == 0);
286 	test_id = atoi(argv[4]);
287 
288 	T_LOG("opening channel %d on fsw %s\n",
289 	    NEXUS_PORT_FLOW_SWITCH_CLIENT, argv[3]);
290 
291 	/* must fail without user packet pool set (flow switch) */
292 	assert(sktu_channel_create_extended(fsw_uuid,
293 	    NEXUS_PORT_FLOW_SWITCH_CLIENT, CHANNEL_DIR_TX_RX,
294 	    CHANNEL_RING_ID_ANY, NULL, -1, -1, -1, -1, -1, -1, -1, 1, -1, -1) == NULL);
295 
296 	channel = sktu_channel_create_extended(fsw_uuid,
297 	    NEXUS_PORT_FLOW_SWITCH_CLIENT, CHANNEL_DIR_TX_RX,
298 	    CHANNEL_RING_ID_ANY, NULL, -1, -1, -1, -1, -1, -1, 1, 1, -1, -1);
299 	assert(channel);
300 
301 	switch (test_id) {
302 	case SKT_VERIFY_NXADV_REGION:
303 		skt_verify_nxadv_region(channel);
304 		break;
305 
306 	default:
307 		assert(0);
308 	}
309 
310 	os_channel_destroy(channel);
311 	return 0;
312 }
313 
314 struct skywalk_test skt_verifynxadv = {
315 	.skt_testname = "verifynadv",
316 	.skt_testdesc = "verifies nexus advisory region",
317 	.skt_required_features = SK_FEATURE_SKYWALK | SK_FEATURE_NEXUS_NETIF |
318     SK_FEATURE_NEXUS_FLOWSWITCH | SK_FEATURE_NETNS,
319 	.skt_main = skt_nxregion_verify_main,
320 	.skt_argv = { NULL, NULL, NULL, ms_fsw_uuid_string, SKT_VERIFY_NXADV_REGION_STR},
321 	.skt_init = skt_ms_fsw_init,
322 	.skt_fini = skt_ms_fsw_fini,
323 	.skt_expected_exception_code = 0xa100002,
324 	.skt_expected_exception_code_ignore = 0,
325 };
326