This is xnu-11215.1.10. See this file in:
/*
* Copyright (c) 2016-2024 Apple Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. The rights granted to you under the License
* may not be used to create, or enable the creation or redistribution of,
* unlawful or unlicensed copies of an Apple operating system, or to
* circumvent, violate, or enable the circumvention or violation of, any
* terms of an Apple operating system software license agreement.
*
* Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_END@
*/
#include <assert.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <uuid/uuid.h>
#include <sys/select.h>
#include <sys/mman.h>
#include <mach/vm_map.h>
#include <darwintest.h>
#include "skywalk_test_driver.h"
#include "skywalk_test_common.h"
#include "skywalk_test_utils.h"
static int
skt_writeif_main(int argc, char *argv[])
{
int error;
channel_t channel;
uuid_t channel_uuid;
error = uuid_parse(argv[3], channel_uuid);
SKTC_ASSERT_ERR(!error);
channel = sktu_channel_create_extended(channel_uuid, 0,
CHANNEL_DIR_TX_RX, CHANNEL_RING_ID_ANY, NULL,
-1, -1, -1, -1, -1, -1, -1, 1, -1, -1);
assert(channel);
*(char *)channel->chd_schema->csm_kern_name = 'X';
return 1; // shouldn't be reached
}
struct skywalk_test skt_writeif = {
.skt_testname = "writeif",
.skt_testdesc = "writes to the read only channel if",
.skt_required_features = SK_FEATURE_SKYWALK | SK_FEATURE_NEXUS_USER_PIPE,
.skt_main = skt_writeif_main,
.skt_argv = SKTC_GENERIC_UPIPE_ARGV,
.skt_init = sktc_generic_upipe_null_init,
.skt_fini = sktc_generic_upipe_fini,
.skt_expected_exception_code = 0xa100002,
.skt_expected_exception_code_ignore = 0,
};
static int
skt_writering_main(int argc, char *argv[])
{
int error;
channel_t channel;
uuid_t channel_uuid;
error = uuid_parse(argv[3], channel_uuid);
SKTC_ASSERT_ERR(!error);
channel = sktu_channel_create_extended(channel_uuid, 0,
CHANNEL_DIR_TX_RX, CHANNEL_RING_ID_ANY, NULL,
-1, -1, -1, -1, -1, -1, -1, 1, -1, -1);
assert(channel);
ring_id_t ringid;
channel_ring_t ring;
ringid = os_channel_ring_id(channel, CHANNEL_FIRST_TX_RING);
ring = os_channel_tx_ring(channel, ringid);
assert(ring);
assert((intptr_t)channel->chd_schema +
channel->chd_schema->csm_ring_ofs[0].ring_off ==
(intptr_t)ring->chrd_ring);
/* Write garbage to ring descriptors */
memset((void *)ring->chrd_ring, 0x5a, sizeof(*ring->chrd_ring));
error = os_channel_sync(channel, CHANNEL_SYNC_TX);
/* Expect failure (and a process crash) here */
/*
* Sanity checks to localize failures, in case the crash doesn't
* succeed:
*/
SKTC_ASSERT_ERR(error);
SKTC_ASSERT_ERR(errno == EFAULT);
return 1;
}
struct skywalk_test skt_writering = {
.skt_testname = "writering",
.skt_testdesc = "writes to the writeable ring",
.skt_required_features = SK_FEATURE_SKYWALK | SK_FEATURE_NEXUS_USER_PIPE,
.skt_main = skt_writering_main,
.skt_argv = SKTC_GENERIC_UPIPE_ARGV,
.skt_init = sktc_generic_upipe_null_init,
.skt_fini = sktc_generic_upipe_fini,
.skt_expected_exception_code = SIGABRT << 24,
.skt_expected_exception_code_ignore = 0,
};
static int
skt_readsmap_main(int argc, char *argv[])
{
int error;
channel_t channel;
uuid_t channel_uuid;
uint8_t byte;
error = uuid_parse(argv[3], channel_uuid);
SKTC_ASSERT_ERR(!error);
channel = sktu_channel_create_extended(channel_uuid, 0,
CHANNEL_DIR_TX_RX, CHANNEL_RING_ID_ANY, NULL,
-1, -1, -1, -1, -1, -1, -1, 1, -1, -1);
assert(channel);
//T_LOG("ch_if 0x%p offset 0x%llx pointer 0x%p\n",
// channel->chd_schema, channel->chd_schema->csm_ring_ofs[0].sd_off,
// (char *)channel->chd_schema+channel->chd_schema->csm_ring_ofs[0].sd_off);
// Verify we can read it
memcpy(&byte, (void *)channel->chd_schema + channel->chd_schema->csm_ring_ofs[0].sd_off, 1);
return 0;
}
struct skywalk_test skt_readsmap = {
.skt_testname = "readsmap",
.skt_testdesc = "reads from the read only smap",
.skt_required_features = SK_FEATURE_SKYWALK | SK_FEATURE_NEXUS_USER_PIPE,
.skt_main = skt_readsmap_main,
.skt_argv = SKTC_GENERIC_UPIPE_ARGV,
.skt_init = sktc_generic_upipe_null_init,
.skt_fini = sktc_generic_upipe_fini,
};
static int
skt_writesmap_main(int argc, char *argv[])
{
int error;
channel_t channel;
uuid_t channel_uuid;
uint8_t byte;
error = uuid_parse(argv[3], channel_uuid);
SKTC_ASSERT_ERR(!error);
channel = sktu_channel_create_extended(channel_uuid, 0,
CHANNEL_DIR_TX_RX, CHANNEL_RING_ID_ANY, NULL,
-1, -1, -1, -1, -1, -1, -1, 1, -1, -1);
assert(channel);
//T_LOG("ch_if 0x%p offset 0x%llx pointer 0x%p\n",
// channel->chd_schema, channel->chd_schema->csm_ring_ofs[0].sd_off,
// (char *)channel->chd_schema+channel->chd_schema->csm_ring_ofs[0].sd_off);
// Verify we can read it
memcpy(&byte, (void *)channel->chd_schema + channel->chd_schema->csm_ring_ofs[0].sd_off, 1);
// Now try to write it
memcpy((void *)channel->chd_schema + channel->chd_schema->csm_ring_ofs[0].sd_off, &byte, 1);
return 1; // shouldn't be reached
}
struct skywalk_test skt_writesmap = {
.skt_testname = "writesmap",
.skt_testdesc = "writes to the read only smap",
.skt_required_features = SK_FEATURE_SKYWALK | SK_FEATURE_NEXUS_USER_PIPE,
.skt_main = skt_writesmap_main,
.skt_argv = SKTC_GENERIC_UPIPE_ARGV,
.skt_init = sktc_generic_upipe_null_init,
.skt_fini = sktc_generic_upipe_fini,
.skt_expected_exception_code = 0xa100002,
.skt_expected_exception_code_ignore = 0,
};
/****************************************************************/
/*
* Nexus region verification tests.
*/
struct sktc_nexus_handles ms_fsw_handle;
static uuid_string_t ms_fsw_uuid_string;
#define SKT_VERIFY_NXADV_REGION 1
#define SKT_VERIFY_NXADV_REGION_STR "1"
static void
skt_ms_fsw_init(void)
{
uuid_t flow_id;
int error;
sktc_ifnet_feth0_create();
sktc_create_flowswitch(&ms_fsw_handle, 0);
uuid_unparse(ms_fsw_handle.fsw_nx_uuid, ms_fsw_uuid_string);
/*
* flowswitch doesn't allow opening a channel without a flow bound
* to the port.
*/
uuid_generate(flow_id);
error = sktc_bind_tcp4_flow(ms_fsw_handle.controller,
ms_fsw_handle.fsw_nx_uuid, 0, NEXUS_PORT_FLOW_SWITCH_CLIENT,
flow_id);
/* Don't assert as this is running in the test driver */
if (error) {
T_LOG("func %s sktc_bind_tcp4_flow returned error %d "
"errno %d: %s\n", __func__, error, errno, strerror(errno));
}
}
static void
skt_ms_fsw_fini(void)
{
sktc_cleanup_flowswitch(&ms_fsw_handle);
sktc_ifnet_feth0_destroy();
}
static void
skt_verify_nxadv_region(channel_t channel)
{
struct sk_nexusadv *region;
uint64_t region_size;
channel_attr_t attr;
int error;
attr = os_channel_attr_create();
assert(attr != NULL);
error = os_channel_read_attr(channel, attr);
SKTC_ASSERT_ERR(!error);
/* verify size of the region */
os_channel_attr_get(attr, CHANNEL_ATTR_NEXUS_ADV_SIZE, ®ion_size);
assert(region_size == sizeof(*region));
/* verify version number */
region = os_channel_get_advisory_region(channel);
assert(region != NULL);
assert(region->nxadv_ver == NX_ADVISORY_CURRENT_VERSION);
/* write should fault as the region is mapped read-only */
region->nxadv_ver = 0;
/* shouldn't be reached */
error = 1;
SKTC_ASSERT_ERR(!error);
}
int
skt_nxregion_verify_main(int argc, char *argv[])
{
int error;
int test_id;
uuid_t fsw_uuid;
channel_t channel;
error = uuid_parse(argv[3], fsw_uuid);
SKTC_ASSERT_ERR(error == 0);
test_id = atoi(argv[4]);
T_LOG("opening channel %d on fsw %s\n",
NEXUS_PORT_FLOW_SWITCH_CLIENT, argv[3]);
/* must fail without user packet pool set (flow switch) */
assert(sktu_channel_create_extended(fsw_uuid,
NEXUS_PORT_FLOW_SWITCH_CLIENT, CHANNEL_DIR_TX_RX,
CHANNEL_RING_ID_ANY, NULL, -1, -1, -1, -1, -1, -1, -1, 1, -1, -1) == NULL);
channel = sktu_channel_create_extended(fsw_uuid,
NEXUS_PORT_FLOW_SWITCH_CLIENT, CHANNEL_DIR_TX_RX,
CHANNEL_RING_ID_ANY, NULL, -1, -1, -1, -1, -1, -1, 1, 1, -1, -1);
assert(channel);
switch (test_id) {
case SKT_VERIFY_NXADV_REGION:
skt_verify_nxadv_region(channel);
break;
default:
assert(0);
}
os_channel_destroy(channel);
return 0;
}
struct skywalk_test skt_verifynxadv = {
.skt_testname = "verifynadv",
.skt_testdesc = "verifies nexus advisory region",
.skt_required_features = SK_FEATURE_SKYWALK | SK_FEATURE_NEXUS_NETIF |
SK_FEATURE_NEXUS_FLOWSWITCH | SK_FEATURE_NETNS,
.skt_main = skt_nxregion_verify_main,
.skt_argv = { NULL, NULL, NULL, ms_fsw_uuid_string, SKT_VERIFY_NXADV_REGION_STR},
.skt_init = skt_ms_fsw_init,
.skt_fini = skt_ms_fsw_fini,
.skt_expected_exception_code = 0xa100002,
.skt_expected_exception_code_ignore = 0,
};