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, ®ion_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