1 #include <darwintest.h> 2 #include <mach/mach.h> 3 #include <mach/mach_types.h> 4 #include <mach/task.h> 5 #include <mach/thread_act.h> 6 #include <mach_debug/ipc_info.h> 7 8 T_GLOBAL_META( 9 T_META_NAMESPACE("xnu.ipc"), 10 T_META_RADAR_COMPONENT_NAME("xnu"), 11 T_META_RADAR_COMPONENT_VERSION("IPC"), 12 T_META_RUN_CONCURRENTLY(true)); 13 14 T_DECL(exception_ports_info, "Test {task, thread}_get_exception_ports_info") 15 { 16 kern_return_t kr; 17 mach_port_t exc_port1, exc_port2, exc_port3; 18 19 mach_msg_type_number_t count = EXC_TYPES_COUNT; 20 exception_mask_t masks[EXC_TYPES_COUNT]; 21 ipc_info_port_t ports_info[EXC_TYPES_COUNT]; 22 exception_behavior_t behaviors[EXC_TYPES_COUNT]; 23 thread_state_flavor_t flavors[EXC_TYPES_COUNT]; 24 25 mach_msg_type_number_t count2 = EXC_TYPES_COUNT; 26 exception_mask_t masks2[EXC_TYPES_COUNT]; 27 mach_port_t ports[EXC_TYPES_COUNT]; 28 exception_behavior_t behaviors2[EXC_TYPES_COUNT]; 29 thread_state_flavor_t flavors2[EXC_TYPES_COUNT]; 30 31 unsigned int exc_port1_kotype = 0, exc_port1_kaddr = 0; 32 unsigned int exc_port2_kotype = 0, exc_port2_kaddr = 0; 33 unsigned int kotype = 0, kobject = 0, exc_port3_kotype = 0, exc_port3_kaddr = 0; 34 boolean_t found_exc_port1 = false; 35 boolean_t found_exc_port2 = false; 36 boolean_t found_exc_port3 = false; 37 38 ipc_info_space_t info_space; 39 ipc_info_name_array_t table; 40 ipc_info_tree_name_array_t tree; 41 mach_msg_type_number_t tblcnt = 0, treecnt = 0; 42 43 /* Create the mach port the exception messages will be sent to. */ 44 kr = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &exc_port1); 45 T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "Allocated mach exception port"); 46 kr = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &exc_port2); 47 T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "Allocated mach exception port"); 48 kr = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &exc_port3); 49 T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "Allocated mach exception port"); 50 51 /* 52 * Insert a send right into the exception port that the kernel will use to 53 * send the exception thread the exception messages. 54 */ 55 kr = mach_port_insert_right(mach_task_self(), exc_port1, exc_port1, MACH_MSG_TYPE_MAKE_SEND); 56 T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "Inserted a SEND right into the exception port"); 57 kr = mach_port_insert_right(mach_task_self(), exc_port2, exc_port2, MACH_MSG_TYPE_MAKE_SEND); 58 T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "Inserted a SEND right into the exception port"); 59 kr = mach_port_insert_right(mach_task_self(), exc_port3, exc_port3, MACH_MSG_TYPE_MAKE_SEND); 60 T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "Inserted a SEND right into the exception port"); 61 62 T_LOG("exc_port1: 0x%x", exc_port1); 63 T_LOG("exc_port2: 0x%x", exc_port2); 64 T_LOG("exc_port3: 0x%x", exc_port3); 65 66 /* Tell the kernel what port to send exceptions to. */ 67 kr = task_set_exception_ports( 68 mach_task_self(), 69 EXC_MASK_GUARD, 70 exc_port1, 71 (exception_behavior_t)(EXCEPTION_STATE_IDENTITY | MACH_EXCEPTION_CODES), 72 THREAD_STATE_NONE); 73 T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "Set the exception port to my custom handler"); 74 75 kr = task_set_exception_ports( 76 mach_task_self(), 77 EXC_MASK_RPC_ALERT, /* why can't be EXC_CRASH or EXC_MASK_CORPSE_NOTIFY ? */ 78 exc_port2, 79 (exception_behavior_t)(EXCEPTION_STATE_IDENTITY | MACH_EXCEPTION_CODES), 80 THREAD_STATE_NONE); 81 T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "Set the exception port to my custom handler"); 82 83 kr = task_set_exception_ports( 84 mach_task_self(), 85 EXC_MASK_RESOURCE | EXC_MASK_BREAKPOINT | EXC_MASK_SYSCALL, 86 exc_port3, 87 (exception_behavior_t)(EXCEPTION_STATE_IDENTITY | MACH_EXCEPTION_CODES), 88 THREAD_STATE_NONE); 89 T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "Set the exception port to my custom handler"); 90 91 /* now, get exception ports info */ 92 kr = thread_get_exception_ports(mach_thread_self(), EXC_MASK_ALL, masks2, &count2, ports, behaviors2, flavors2); 93 T_EXPECT_MACH_SUCCESS(kr, "thread_get_exception_ports(): 0x%x", kr); 94 T_EXPECT_EQ(count2, 0, "should have 0 exception ports"); 95 96 kr = thread_get_exception_ports_info(mach_thread_self(), EXC_MASK_ALL, masks, &count, ports_info, behaviors, flavors); 97 T_EXPECT_MACH_SUCCESS(kr, "thread_get_exception_ports_info(): 0x%x", kr); 98 T_EXPECT_EQ(count, 0, "should have 0 exception ports"); 99 100 count = EXC_TYPES_COUNT; 101 count2 = EXC_TYPES_COUNT; 102 103 kr = task_get_exception_ports_info(mach_task_self(), EXC_MASK_ALL, masks, &count, ports_info, behaviors, flavors); 104 T_EXPECT_MACH_SUCCESS(kr, "task_get_exception_ports_info(): 0x%x", kr); 105 T_EXPECT_EQ(count, 4, "should have 4 masks"); /* Returns 3 if one exc_port registers for EXC_CRASH */ 106 107 /* get exception ports */ 108 kr = task_get_exception_ports(mach_task_self(), EXC_MASK_ALL, masks2, &count2, ports, behaviors2, flavors2); 109 T_EXPECT_MACH_SUCCESS(kr, "task_get_exception_ports(): 0x%x", kr); 110 111 for (int i = 0; i < count2; i++) { 112 T_LOG("exception port name: 0x%x", ports[i]); 113 } 114 T_EXPECT_EQ(count, count2, "should return same mask count"); 115 116 kr = memcmp(masks, masks2, count * sizeof(exception_mask_t)); 117 T_EXPECT_EQ(kr, 0, "masks should be the same"); 118 119 kr = memcmp(behaviors, behaviors2, count * sizeof(exception_behavior_t)); 120 T_EXPECT_EQ(kr, 0, "behaviors should be the same"); 121 122 kr = memcmp(flavors, flavors, count * sizeof(thread_state_flavor_t)); 123 T_EXPECT_EQ(kr, 0, "flavors should be the same"); 124 125 kr = mach_port_kernel_object(mach_task_self(), mach_task_self(), &kotype, &kobject); 126 T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "mach_port_kernel_object(): 0x%x", kr); 127 T_LOG("task_self kobject: 0x%x", kobject); 128 129 T_QUIET; T_EXPECT_MACH_SUCCESS(mach_port_space_info(mach_task_self(), &info_space, &table, 130 &tblcnt, &tree, &treecnt), "mach_port_space_info(): 0x%x", kr); 131 132 for (int i = 0; i < tblcnt; i++) { 133 if (table[i].iin_name == exc_port1) { 134 exc_port1_kaddr = table[i].iin_object; 135 } 136 if (table[i].iin_name == exc_port2) { 137 exc_port2_kaddr = table[i].iin_object; 138 } 139 if (table[i].iin_name == exc_port3) { 140 exc_port3_kaddr = table[i].iin_object; 141 } 142 } 143 144 T_LOG("exc_port_1_kaddr: 0x%x", exc_port1_kaddr); 145 T_LOG("exc_port_2_kaddr: 0x%x", exc_port2_kaddr); 146 T_LOG("exc_port_3_kaddr: 0x%x", exc_port3_kaddr); 147 148 for (int i = 0; i < count; i++) { 149 T_LOG("ports_info[%d].iip_port_object: 0x%x", i, ports_info[i].iip_port_object); 150 151 if (ports_info[i].iip_port_object == exc_port1_kaddr) { 152 T_EXPECT_NE(ports_info[i].iip_port_object, 0, 153 "on debug/kernel, port object should be non-zero: 0x%x", ports_info[i].iip_port_object); 154 T_EXPECT_EQ(ports_info[i].iip_receiver_object, kobject, 155 "receiver object should match task self kobject: 0x%x", ports_info[i].iip_receiver_object); 156 T_EXPECT_EQ(masks[i], EXC_MASK_GUARD, "check if mask for exc_port1 is correct"); 157 found_exc_port1 = true; 158 } 159 if (ports_info[i].iip_port_object == exc_port2_kaddr) { 160 T_EXPECT_NE(ports_info[i].iip_port_object, 0, 161 "on debug/kernel, port object should be non-zero: 0x%x", ports_info[i].iip_port_object); 162 T_EXPECT_EQ(ports_info[i].iip_receiver_object, kobject, 163 "receiver object should match task self kobject: 0x%x", ports_info[i].iip_receiver_object); 164 T_EXPECT_EQ(masks[i], EXC_MASK_RPC_ALERT, "check if mask for exc_port2 is correct"); 165 found_exc_port2 = true; 166 } 167 if (ports_info[i].iip_port_object == exc_port3_kaddr) { 168 T_EXPECT_NE(ports_info[i].iip_port_object, 0, 169 "on debug/kernel, port object should be non-zero: 0x%x", ports_info[i].iip_port_object); 170 T_EXPECT_EQ(ports_info[i].iip_receiver_object, kobject, 171 "receiver object should match task self kobject: 0x%x", ports_info[i].iip_receiver_object); 172 T_EXPECT_EQ(masks[i], EXC_MASK_RESOURCE | EXC_MASK_BREAKPOINT | EXC_MASK_SYSCALL, "check if mask for exc_port3 is correct"); 173 found_exc_port3 = true; 174 } 175 } 176 177 T_EXPECT_TRUE(found_exc_port1, "should find exc_port1"); 178 T_EXPECT_TRUE(found_exc_port2, "should find exc_port2"); 179 T_EXPECT_TRUE(found_exc_port3, "should find exc_port3"); 180 } 181