xref: /xnu-11215/tests/exception_tests.c (revision 8d741a5d)
1 #include <darwintest.h>
2 #include <pthread/private.h>
3 #include <sys/sysctl.h>
4 #include <mach/task.h>
5 #include "exc_helpers.h"
6 
7 #define EXCEPTION_IDENTITY_PROTECTED 4
8 
9 T_GLOBAL_META(
10 	T_META_NAMESPACE("xnu.ipc"),
11 	T_META_RADAR_COMPONENT_NAME("xnu"),
12 	T_META_RADAR_COMPONENT_VERSION("IPC"),
13 	T_META_RUN_CONCURRENTLY(true));
14 
15 static size_t
exc_immovable_handler(mach_port_t task,mach_port_t thread,__unused exception_type_t type,__unused mach_exception_data_t codes)16 exc_immovable_handler(
17 	mach_port_t task,
18 	mach_port_t thread,
19 	__unused exception_type_t type,
20 	__unused mach_exception_data_t codes)
21 {
22 	T_EXPECT_EQ(task, mach_task_self(), "Received immovable task port");
23 	T_EXPECT_EQ(thread, pthread_mach_thread_np(pthread_main_thread_np()),
24 	    "Received immovable thread port");
25 	T_END;
26 }
27 
28 static size_t
exc_handler_identity_protected(task_id_token_t token,uint64_t thread_id,exception_type_t type,__unused exception_data_t codes)29 exc_handler_identity_protected(
30 	task_id_token_t token,
31 	uint64_t thread_id,
32 	exception_type_t type,
33 	__unused exception_data_t codes)
34 {
35 	mach_port_t port1, port2;
36 	kern_return_t kr;
37 
38 	T_LOG("Got protected exception!");
39 
40 	port1 = mach_task_self();
41 	kr = task_identity_token_get_task_port(token, TASK_FLAVOR_CONTROL, &port2); /* Immovable control port for self */
42 	T_ASSERT_MACH_SUCCESS(kr, "task_identity_token_get_task_port() - CONTROL");
43 	T_EXPECT_EQ(port1, port2, "Control port matches!");
44 
45 	T_END;
46 }
47 
48 T_DECL(exc_immovable, "Test that exceptions receive immovable ports",
49     T_META_TAG_VM_PREFERRED)
50 {
51 	mach_port_t exc_port = create_exception_port(EXC_MASK_BAD_ACCESS);
52 	uint32_t opts = 0;
53 	size_t size = sizeof(&opts);
54 	mach_port_t mp;
55 	kern_return_t kr;
56 
57 	T_LOG("Check if task_exc_guard exception has been enabled\n");
58 	int ret = sysctlbyname("kern.ipc_control_port_options", &opts, &size, NULL, 0);
59 	T_EXPECT_POSIX_SUCCESS(ret, "sysctlbyname(kern.ipc_control_port_options)");
60 
61 	if ((opts & 0x30) == 0) {
62 		T_SKIP("immovable rights aren't enabled");
63 	}
64 
65 	kr = task_get_special_port(mach_task_self(), TASK_KERNEL_PORT, &mp);
66 	T_EXPECT_MACH_SUCCESS(kr, "task_get_special_port");
67 	T_EXPECT_NE(mp, mach_task_self(), "should receive movable port");
68 
69 	/*
70 	 * do not deallocate the port we received on purpose to check
71 	 * that the exception will not coalesce with the movable port
72 	 * we have in our space now
73 	 */
74 
75 	run_exception_handler(exc_port, exc_immovable_handler);
76 	*(void *volatile*)0 = 0;
77 }
78 
79 T_DECL(exc_raise_identity_protected, "Test identity-protected exception delivery behavior",
80     T_META_TAG_VM_NOT_PREFERRED)
81 {
82 	mach_port_t exc_port = create_exception_port_behavior64(EXC_MASK_BAD_ACCESS, EXCEPTION_IDENTITY_PROTECTED);
83 
84 	run_exception_handler_behavior64(exc_port, NULL, exc_handler_identity_protected, EXCEPTION_IDENTITY_PROTECTED, true);
85 	*(void *volatile*)0 = 0;
86 }
87