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 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 | #ifndef IPC_UTILS_H #define IPC_UTILS_H #include <mach/mach.h> #include <mach/message.h> #include <mach/mach_error.h> #include <stdio.h> #include <stdlib.h> #include <stdbool.h> #include <stdarg.h> #include <sys/code_signing.h> /* * Common IPC utilities for XNU tests * * This header provides standardized message structures and utilities * for common IPC patterns used across multiple test files. */ #ifdef __cplusplus extern "C" { #endif #if __arm64e__ #define TARGET_CPU_ARM64E true #else #define TARGET_CPU_ARM64E false #endif #define countof(arr) (sizeof(arr) / sizeof((arr)[0])) /* Message structure for sending a single port */ typedef struct { mach_msg_header_t header; mach_msg_body_t body; mach_msg_port_descriptor_t port; } ipc_single_port_msg_t; /* Message structure for sending multiple ports in an array */ typedef struct { mach_msg_header_t header; mach_msg_body_t body; mach_msg_ool_ports_descriptor_t ports_descriptor; } ipc_port_array_msg_t; /* Generic message structure with trailer for receiving */ typedef struct { mach_msg_header_t header; mach_msg_body_t body; union { /* Single port descriptor */ struct { mach_msg_port_descriptor_t port; } single; /* Port array descriptor */ struct { mach_msg_ool_ports_descriptor_t ports_descriptor; } array; } data; mach_msg_max_trailer_t trailer; } ipc_receive_msg_t; /* * Port Management Functions */ /* Create a new receive port with send right */ mach_port_t ipc_create_receive_port(void); /* Create a receive port with specific options */ mach_port_t ipc_create_receive_port_with_options(uint32_t mpo_flags); /* Safely deallocate a port */ void ipc_deallocate_port(mach_port_t port); /* Insert a send right to a receive right */ kern_return_t ipc_insert_send_right(mach_port_t receive_port); /* * Single Port Messaging Functions */ /* Send a single port to destination */ kern_return_t ipc_send_port(mach_port_t destination, mach_port_t port, mach_msg_type_name_t disposition); /* Receive a single port from destination */ kern_return_t ipc_receive_port(mach_port_t destination, mach_port_t *port); /* * Port Array Messaging Functions */ /* Send an array of ports to destination */ kern_return_t ipc_send_port_array(mach_port_t destination, mach_port_t *ports, mach_msg_type_number_t count, mach_msg_type_name_t disposition); /* Receive an array of ports from destination */ kern_return_t ipc_receive_port_array(mach_port_t destination, mach_port_t **ports, mach_msg_type_number_t *count); /* * Generic Messaging Functions */ /* Send a pre-constructed message */ kern_return_t ipc_send_message(mach_msg_header_t *msg); /* Receive a message into a pre-allocated buffer */ kern_return_t ipc_receive_message(mach_port_t destination, ipc_receive_msg_t *msg, mach_msg_size_t max_size); /* * Security and Code Signing Utilities */ /* Check if IPC hardening is disabled (CS_CONFIG_GET_OUT_OF_MY_WAY) */ bool ipc_hardening_disabled(void); /* Check if SIP is disabled (CSR_ALLOW_UNRESTRICTED_FS) */ bool ipc_sip_disabled(void); /* XPC domain types - in xpc/launch_private.h */ #define XPC_DOMAIN_SYSTEM 1 #define XPC_DOMAIN_PORT 7 /* * Port Type Testing Infrastructure */ /* Enum to identify port types during testing */ typedef enum { TEST_IOT_PORT = 0, TEST_IOT_REPLY_PORT, TEST_IOT_CONNECTION_PORT, TEST_IOT_EXCEPTION_PORT, TEST_IOT_WEAK_REPLY_PORT, TEST_IOT_CONNECTION_PORT_WITH_PORT_ARRAY, TEST_IOT_NOTIFICATION_PORT, TEST_IOT_TIMER_PORT, TEST_IOT_SPECIAL_REPLY_PORT, TEST_IOT_SERVICE_PORT, TEST_IOT_WEAK_SERVICE_PORT, TEST_IOT_BOOTSTRAP_PORT, TEST_PORT_TYPE_COUNT } ipc_test_port_type_t; /* Port type descriptor for testing different port types */ typedef struct { mach_port_t (*port_ctor)(void); char *port_type_name; } port_type_desc_t; /* Get the array of all port type descriptors */ const port_type_desc_t *ipc_get_all_port_types(void); /* Get the count of port types in the array */ size_t ipc_get_port_type_count(void); /* Get a specific port type descriptor by enum */ const port_type_desc_t *ipc_get_port_type_desc(ipc_test_port_type_t type); /* Create a port of the specified type with null assertion */ mach_port_t ipc_create_port_with_type(ipc_test_port_type_t type); /* * Port Policy Helpers */ /* * Encode if a port type can receive notifications based on * pol_can_receive_notifications in ipc_policy.c */ bool ipc_port_type_can_receive_notifications(ipc_test_port_type_t type); /* * Determine if a reply port type will cause SIGKILL when used as * an exception port. Returns true if SIGKILL is expected, false if * the port is weak (due to hardening being disabled) and will succeed. */ bool ipc_reply_port_causes_sigkill_as_exception_port(ipc_test_port_type_t type); /* * Determine if a port type will cause SIGKILL for containment processes * when attempting to register for notifications. Containment processes have * restricted IPC capabilities, so all notification registration attempts * should result in SIGKILL. */ bool ipc_containment_notification_causes_sigkill(ipc_test_port_type_t type); /* * Fork and Expect SIGKILL Testing */ /* Fork and expect a block to be killed with SIGKILL */ void expect_sigkill(void (^fn)(void), const char *format_description, ...); /* Fork and expect a block to be killed with a specific EXC_GUARD code */ void ipc_expect_exc_guard(unsigned int expected_guard_code, void (^fn)(void), const char *format_description, ...); /* Fork and expect a block to exit normally (status 0, no signal) */ void assert_normal_exit(void (^fn)(void), const char *format_description, ...); #ifdef __cplusplus } #endif #endif /* IPC_UTILS_H */ |