Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 | /* * Copyright (c) 2025 Apple Computer, 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 <darwintest.h> #include <mach/mach.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include "../ipc/ipc_utils.h" T_GLOBAL_META( T_META_NAMESPACE("xnu.ipc"), T_META_RADAR_COMPONENT_NAME("xnu"), T_META_RADAR_COMPONENT_VERSION("IPC"), T_META_TIMEOUT(20), T_META_IGNORECRASHES(".*containment_ipc_notification.*"), T_META_RUN_CONCURRENTLY(TRUE)); /* * Test that containment processes with IPC entitlements cannot register for * notifications on various port types. * * A containment process has the com.apple.private.security.container-required * entitlement which restricts certain IPC operations. This test verifies that * attempting to register for mach notifications on various port types fails * with SIGKILL as expected. */ static const mach_msg_id_t notification_types[] = { MACH_NOTIFY_PORT_DESTROYED, MACH_NOTIFY_NO_SENDERS, MACH_NOTIFY_SEND_POSSIBLE, }; static const char* get_notification_name(mach_msg_id_t notification_id) { switch (notification_id) { case MACH_NOTIFY_PORT_DESTROYED: return "PORT_DESTROYED"; case MACH_NOTIFY_NO_SENDERS: return "NO_SENDERS"; case MACH_NOTIFY_SEND_POSSIBLE: return "SEND_POSSIBLE"; default: return "UNKNOWN"; } } /* * Helper function to test notification registration with a specific port type * and notification type combination. */ static void test_notification_registration(ipc_test_port_type_t type, mach_msg_id_t notify_id) { kern_return_t kr; mach_port_t port, notify_port, previous; const port_type_desc_t *desc = ipc_get_port_type_desc(type); /* Create a regular port to register notifications on */ port = ipc_create_receive_port(); T_QUIET; T_ASSERT_NE(port, MACH_PORT_NULL, "Created regular port"); /* Create the port which will receive notifications */ notify_port = ipc_create_port_with_type(type); T_QUIET; T_ASSERT_NE(notify_port, MACH_PORT_NULL, "constructing port type %s", desc->port_type_name); /* * Attempt to register for notifications. * For containment processes with IPC entitlements, * this should result in SIGKILL. */ kr = mach_port_request_notification(mach_task_self(), port, notify_id, 0, notify_port, MACH_MSG_TYPE_MAKE_SEND_ONCE, &previous); T_ASSERT_MACH_SUCCESS(kr, "%s successfully registered for notifications", desc->port_type_name); } T_DECL(containment_ipc_notification_registration, "Containment processes with IPC entitlements cannot register for notifications") { /* * Iterate through all port types and all notification types. * Each combination should result in SIGKILL for containment processes. */ for (ipc_test_port_type_t type = 0; type < TEST_PORT_TYPE_COUNT; type++) { const port_type_desc_t *desc = ipc_get_port_type_desc(type); if (type == TEST_IOT_REPLY_PORT) { /* * skipping this port due to BATS difficulties with reply ports * we rely on TEST_IOT_SPECIAL_REPLY_PORT for reply port coverage */ continue; } for (size_t j = 0; j < sizeof(notification_types) / sizeof(notification_types[0]); j++) { mach_msg_id_t notify_id = notification_types[j]; if (ipc_containment_notification_causes_sigkill(type)) { expect_sigkill(^{ test_notification_registration(type, notify_id); }, "Containment IPC: %s with %s notification:", desc->port_type_name, get_notification_name(notify_id)); } else { assert_normal_exit(^{ test_notification_registration(type, notify_id); }, "Containment IPC: %s with %s notification:", desc->port_type_name, get_notification_name(notify_id)); } } } T_PASS("All port types correctly denied notification registration for containment process"); } |