1*19c3b8c2SApple OSS Distributions #ifdef T_NAMESPACE
2*19c3b8c2SApple OSS Distributions #undef T_NAMESPACE
3*19c3b8c2SApple OSS Distributions #endif
4*19c3b8c2SApple OSS Distributions
5*19c3b8c2SApple OSS Distributions #include <darwintest.h>
6*19c3b8c2SApple OSS Distributions
7*19c3b8c2SApple OSS Distributions #include <mach/host_priv.h>
8*19c3b8c2SApple OSS Distributions #include <mach/mach.h>
9*19c3b8c2SApple OSS Distributions #include <mach/mach_types.h>
10*19c3b8c2SApple OSS Distributions #include <mach/mach_vm.h>
11*19c3b8c2SApple OSS Distributions #include <mach/processor_set.h>
12*19c3b8c2SApple OSS Distributions #include <mach/task.h>
13*19c3b8c2SApple OSS Distributions #include <sys/sysctl.h>
14*19c3b8c2SApple OSS Distributions #include <mach_debug/ipc_info.h>
15*19c3b8c2SApple OSS Distributions #include <unistd.h>
16*19c3b8c2SApple OSS Distributions
17*19c3b8c2SApple OSS Distributions T_GLOBAL_META(T_META_NAMESPACE("xnu.ipc"),
18*19c3b8c2SApple OSS Distributions T_META_RADAR_COMPONENT_NAME("xnu"),
19*19c3b8c2SApple OSS Distributions T_META_RADAR_COMPONENT_VERSION("IPC"),
20*19c3b8c2SApple OSS Distributions T_META_RUN_CONCURRENTLY(true));
21*19c3b8c2SApple OSS Distributions
22*19c3b8c2SApple OSS Distributions /*
23*19c3b8c2SApple OSS Distributions * Attempt to inspect kernel_task using a task_inspect_t. Interact with the
24*19c3b8c2SApple OSS Distributions * kernel in the same way top(1) and lsmp(1) do.
25*19c3b8c2SApple OSS Distributions */
26*19c3b8c2SApple OSS Distributions
27*19c3b8c2SApple OSS Distributions static int found_kernel_task = 0;
28*19c3b8c2SApple OSS Distributions
29*19c3b8c2SApple OSS Distributions static void
check_secure_kernel(void)30*19c3b8c2SApple OSS Distributions check_secure_kernel(void)
31*19c3b8c2SApple OSS Distributions {
32*19c3b8c2SApple OSS Distributions int secure_kern = 0;
33*19c3b8c2SApple OSS Distributions size_t secure_kern_size = sizeof(secure_kern);
34*19c3b8c2SApple OSS Distributions
35*19c3b8c2SApple OSS Distributions T_ASSERT_POSIX_SUCCESS(sysctlbyname("kern.secure_kernel", &secure_kern,
36*19c3b8c2SApple OSS Distributions &secure_kern_size, NULL, 0), NULL);
37*19c3b8c2SApple OSS Distributions
38*19c3b8c2SApple OSS Distributions if (secure_kern) {
39*19c3b8c2SApple OSS Distributions T_SKIP("secure kernel: processor_set_tasks will not return kernel_task");
40*19c3b8c2SApple OSS Distributions }
41*19c3b8c2SApple OSS Distributions }
42*19c3b8c2SApple OSS Distributions
43*19c3b8c2SApple OSS Distributions static void
attempt_kernel_inspection(task_t task)44*19c3b8c2SApple OSS Distributions attempt_kernel_inspection(task_t task)
45*19c3b8c2SApple OSS Distributions {
46*19c3b8c2SApple OSS Distributions pid_t pid = (pid_t)-1;
47*19c3b8c2SApple OSS Distributions mach_msg_type_number_t i, count, thcnt;
48*19c3b8c2SApple OSS Distributions struct task_basic_info_64 ti;
49*19c3b8c2SApple OSS Distributions thread_act_array_t threads;
50*19c3b8c2SApple OSS Distributions
51*19c3b8c2SApple OSS Distributions if (pid_for_task(task, &pid)) {
52*19c3b8c2SApple OSS Distributions return;
53*19c3b8c2SApple OSS Distributions }
54*19c3b8c2SApple OSS Distributions
55*19c3b8c2SApple OSS Distributions T_QUIET; T_LOG("Checking pid %d", pid);
56*19c3b8c2SApple OSS Distributions
57*19c3b8c2SApple OSS Distributions if (pid != 0) {
58*19c3b8c2SApple OSS Distributions return;
59*19c3b8c2SApple OSS Distributions }
60*19c3b8c2SApple OSS Distributions
61*19c3b8c2SApple OSS Distributions T_LOG("found kernel_task, attempting to inspect");
62*19c3b8c2SApple OSS Distributions found_kernel_task++;
63*19c3b8c2SApple OSS Distributions
64*19c3b8c2SApple OSS Distributions count = TASK_BASIC_INFO_64_COUNT;
65*19c3b8c2SApple OSS Distributions T_EXPECT_MACH_SUCCESS(task_info(task, TASK_BASIC_INFO_64, (task_info_t)&ti,
66*19c3b8c2SApple OSS Distributions &count), "task_info(... TASK_BASIC_INFO_64 ...)");
67*19c3b8c2SApple OSS Distributions
68*19c3b8c2SApple OSS Distributions T_EXPECT_MACH_SUCCESS(task_threads(task, &threads, &thcnt), "task_threads");
69*19c3b8c2SApple OSS Distributions T_LOG("Found %d kernel threads.", thcnt);
70*19c3b8c2SApple OSS Distributions for (i = 0; i < thcnt; i++) {
71*19c3b8c2SApple OSS Distributions kern_return_t kr;
72*19c3b8c2SApple OSS Distributions thread_basic_info_data_t basic_info;
73*19c3b8c2SApple OSS Distributions mach_msg_type_number_t bi_count = THREAD_BASIC_INFO_COUNT;
74*19c3b8c2SApple OSS Distributions
75*19c3b8c2SApple OSS Distributions kr = thread_info(threads[i], THREAD_BASIC_INFO,
76*19c3b8c2SApple OSS Distributions (thread_info_t)&basic_info, &bi_count);
77*19c3b8c2SApple OSS Distributions /*
78*19c3b8c2SApple OSS Distributions * Ignore threads that have gone away.
79*19c3b8c2SApple OSS Distributions */
80*19c3b8c2SApple OSS Distributions if (kr == MACH_SEND_INVALID_DEST) {
81*19c3b8c2SApple OSS Distributions T_LOG("ignoring thread that has been destroyed");
82*19c3b8c2SApple OSS Distributions continue;
83*19c3b8c2SApple OSS Distributions }
84*19c3b8c2SApple OSS Distributions T_QUIET; T_EXPECT_MACH_SUCCESS(kr, "thread_info(... THREAD_BASIC_INFO ...)");
85*19c3b8c2SApple OSS Distributions
86*19c3b8c2SApple OSS Distributions /* Now try out READ (skip eval) interfaces on kernel thread */
87*19c3b8c2SApple OSS Distributions mach_msg_type_number_t msk_count = EXC_TYPES_COUNT;
88*19c3b8c2SApple OSS Distributions exception_mask_t masks[EXC_TYPES_COUNT];
89*19c3b8c2SApple OSS Distributions ipc_info_port_t ports_info[EXC_TYPES_COUNT];
90*19c3b8c2SApple OSS Distributions exception_behavior_t behaviors[EXC_TYPES_COUNT];
91*19c3b8c2SApple OSS Distributions thread_state_flavor_t flavors[EXC_TYPES_COUNT];
92*19c3b8c2SApple OSS Distributions kr = thread_get_exception_ports_info(threads[i], EXC_MASK_ALL, masks, &msk_count, ports_info, behaviors, flavors);
93*19c3b8c2SApple OSS Distributions T_QUIET; T_EXPECT_MACH_SUCCESS(kr, "thread_get_exception_ports_info() on kernel thread: 0x%x", kr);
94*19c3b8c2SApple OSS Distributions
95*19c3b8c2SApple OSS Distributions /* READ (with eval) interfaces should fail */
96*19c3b8c2SApple OSS Distributions mach_port_t voucher;
97*19c3b8c2SApple OSS Distributions kr = thread_get_mach_voucher(threads[i], 0, &voucher);
98*19c3b8c2SApple OSS Distributions T_QUIET; T_EXPECT_EQ(kr, KERN_INVALID_ARGUMENT, "thread_get_mach_voucher() should fail with KERN_INVALID_ARGUMENT");
99*19c3b8c2SApple OSS Distributions
100*19c3b8c2SApple OSS Distributions (void)mach_port_deallocate(mach_task_self(), threads[i]);
101*19c3b8c2SApple OSS Distributions }
102*19c3b8c2SApple OSS Distributions mach_vm_deallocate(mach_task_self(),
103*19c3b8c2SApple OSS Distributions (mach_vm_address_t)(uintptr_t)threads,
104*19c3b8c2SApple OSS Distributions thcnt * sizeof(*threads));
105*19c3b8c2SApple OSS Distributions
106*19c3b8c2SApple OSS Distributions ipc_info_space_basic_t basic_info;
107*19c3b8c2SApple OSS Distributions T_EXPECT_MACH_SUCCESS(mach_port_space_basic_info(task, &basic_info), "mach_port_space_basic_info");
108*19c3b8c2SApple OSS Distributions
109*19c3b8c2SApple OSS Distributions ipc_info_space_t info_space;
110*19c3b8c2SApple OSS Distributions ipc_info_name_array_t table;
111*19c3b8c2SApple OSS Distributions ipc_info_tree_name_array_t tree;
112*19c3b8c2SApple OSS Distributions mach_msg_type_number_t tblcnt = 0, treecnt = 0;
113*19c3b8c2SApple OSS Distributions T_EXPECT_MACH_SUCCESS(mach_port_space_info(task, &info_space, &table,
114*19c3b8c2SApple OSS Distributions &tblcnt, &tree, &treecnt), "mach_port_space_info");
115*19c3b8c2SApple OSS Distributions if (tblcnt > 0) {
116*19c3b8c2SApple OSS Distributions mach_vm_deallocate(mach_task_self(),
117*19c3b8c2SApple OSS Distributions (mach_vm_address_t)(uintptr_t)table,
118*19c3b8c2SApple OSS Distributions tblcnt * sizeof(*table));
119*19c3b8c2SApple OSS Distributions }
120*19c3b8c2SApple OSS Distributions if (treecnt > 0) {
121*19c3b8c2SApple OSS Distributions mach_vm_deallocate(mach_task_self(),
122*19c3b8c2SApple OSS Distributions (mach_vm_address_t)(uintptr_t)tree,
123*19c3b8c2SApple OSS Distributions treecnt * sizeof(*tree));
124*19c3b8c2SApple OSS Distributions }
125*19c3b8c2SApple OSS Distributions
126*19c3b8c2SApple OSS Distributions /* Now try out READ (skip eval) interfaces on kernel task */
127*19c3b8c2SApple OSS Distributions mach_msg_type_number_t msk_count = EXC_TYPES_COUNT;
128*19c3b8c2SApple OSS Distributions exception_mask_t masks[EXC_TYPES_COUNT];
129*19c3b8c2SApple OSS Distributions ipc_info_port_t ports_info[EXC_TYPES_COUNT];
130*19c3b8c2SApple OSS Distributions exception_behavior_t behaviors[EXC_TYPES_COUNT];
131*19c3b8c2SApple OSS Distributions thread_state_flavor_t flavors[EXC_TYPES_COUNT];
132*19c3b8c2SApple OSS Distributions kern_return_t kr = task_get_exception_ports_info(task, EXC_MASK_ALL, masks, &msk_count, ports_info, behaviors, flavors);
133*19c3b8c2SApple OSS Distributions T_EXPECT_MACH_SUCCESS(kr, "task_get_exception_ports_info() on kernel_task: 0x%x", kr);
134*19c3b8c2SApple OSS Distributions
135*19c3b8c2SApple OSS Distributions /* READ (with eval) interfaces should fail */
136*19c3b8c2SApple OSS Distributions vm_offset_t data;
137*19c3b8c2SApple OSS Distributions mach_msg_type_number_t cnt;
138*19c3b8c2SApple OSS Distributions mach_vm_address_t addr = 0x10000000; /* can be whatever, the call should fail before getting to VM */
139*19c3b8c2SApple OSS Distributions
140*19c3b8c2SApple OSS Distributions kr = mach_vm_read(task, (mach_vm_address_t)addr, 8, &data, &cnt);
141*19c3b8c2SApple OSS Distributions T_EXPECT_EQ(kr, KERN_INVALID_ARGUMENT, "mach_vm_read() should fail with KERN_INVALID_ARGUMENT");
142*19c3b8c2SApple OSS Distributions
143*19c3b8c2SApple OSS Distributions mach_port_t voucher;
144*19c3b8c2SApple OSS Distributions kr = task_get_mach_voucher(task, 0, &voucher);
145*19c3b8c2SApple OSS Distributions T_EXPECT_EQ(kr, KERN_INVALID_TASK, "task_get_mach_voucher() should fail with KERN_INVALID_TASK");
146*19c3b8c2SApple OSS Distributions
147*19c3b8c2SApple OSS Distributions /* Control interfaces should absolutely fail */
148*19c3b8c2SApple OSS Distributions kr = task_set_mach_voucher(task, mach_task_self()); /* voucher arg is unused, can be whatever port */
149*19c3b8c2SApple OSS Distributions T_EXPECT_EQ(kr, KERN_INVALID_TASK, "task_set_mach_voucher() should fail with KERN_INVALID_TASK");
150*19c3b8c2SApple OSS Distributions }
151*19c3b8c2SApple OSS Distributions
152*19c3b8c2SApple OSS Distributions T_DECL(inspect_kernel_task,
153*19c3b8c2SApple OSS Distributions "ensure that kernel task can be inspected",
154*19c3b8c2SApple OSS Distributions T_META_CHECK_LEAKS(false),
155*19c3b8c2SApple OSS Distributions T_META_ASROOT(true))
156*19c3b8c2SApple OSS Distributions {
157*19c3b8c2SApple OSS Distributions processor_set_name_array_t psets;
158*19c3b8c2SApple OSS Distributions processor_set_t pset;
159*19c3b8c2SApple OSS Distributions task_array_t tasks;
160*19c3b8c2SApple OSS Distributions mach_msg_type_number_t i, j, tcnt, pcnt = 0;
161*19c3b8c2SApple OSS Distributions mach_port_t self = mach_host_self();
162*19c3b8c2SApple OSS Distributions
163*19c3b8c2SApple OSS Distributions check_secure_kernel();
164*19c3b8c2SApple OSS Distributions
165*19c3b8c2SApple OSS Distributions T_ASSERT_MACH_SUCCESS(host_processor_sets(self, &psets, &pcnt),
166*19c3b8c2SApple OSS Distributions NULL);
167*19c3b8c2SApple OSS Distributions
168*19c3b8c2SApple OSS Distributions for (i = 0; i < pcnt; i++) {
169*19c3b8c2SApple OSS Distributions T_ASSERT_MACH_SUCCESS(host_processor_set_priv(self, psets[i], &pset), NULL);
170*19c3b8c2SApple OSS Distributions T_LOG("Checking pset %d/%d", i, pcnt - 1);
171*19c3b8c2SApple OSS Distributions
172*19c3b8c2SApple OSS Distributions tcnt = 0;
173*19c3b8c2SApple OSS Distributions T_LOG("Attempting kernel inspection with control port...");
174*19c3b8c2SApple OSS Distributions T_ASSERT_MACH_SUCCESS(processor_set_tasks(pset, &tasks, &tcnt), NULL);
175*19c3b8c2SApple OSS Distributions
176*19c3b8c2SApple OSS Distributions for (j = 0; j < tcnt; j++) {
177*19c3b8c2SApple OSS Distributions attempt_kernel_inspection(tasks[j]);
178*19c3b8c2SApple OSS Distributions mach_port_deallocate(self, tasks[j]);
179*19c3b8c2SApple OSS Distributions }
180*19c3b8c2SApple OSS Distributions
181*19c3b8c2SApple OSS Distributions /* free tasks array */
182*19c3b8c2SApple OSS Distributions mach_vm_deallocate(mach_task_self(),
183*19c3b8c2SApple OSS Distributions (mach_vm_address_t)(uintptr_t)tasks,
184*19c3b8c2SApple OSS Distributions tcnt * sizeof(*tasks));
185*19c3b8c2SApple OSS Distributions
186*19c3b8c2SApple OSS Distributions T_LOG("Attempting kernel inspection with read port...");
187*19c3b8c2SApple OSS Distributions T_ASSERT_MACH_SUCCESS(processor_set_tasks_with_flavor(pset, TASK_FLAVOR_READ, &tasks, &tcnt), NULL);
188*19c3b8c2SApple OSS Distributions
189*19c3b8c2SApple OSS Distributions for (j = 0; j < tcnt; j++) {
190*19c3b8c2SApple OSS Distributions attempt_kernel_inspection(tasks[j]);
191*19c3b8c2SApple OSS Distributions mach_port_deallocate(self, tasks[j]);
192*19c3b8c2SApple OSS Distributions }
193*19c3b8c2SApple OSS Distributions
194*19c3b8c2SApple OSS Distributions mach_vm_deallocate(mach_task_self(),
195*19c3b8c2SApple OSS Distributions (mach_vm_address_t)(uintptr_t)tasks,
196*19c3b8c2SApple OSS Distributions tcnt * sizeof(*tasks));
197*19c3b8c2SApple OSS Distributions
198*19c3b8c2SApple OSS Distributions mach_port_deallocate(mach_task_self(), pset);
199*19c3b8c2SApple OSS Distributions mach_port_deallocate(mach_task_self(), psets[i]);
200*19c3b8c2SApple OSS Distributions }
201*19c3b8c2SApple OSS Distributions mach_vm_deallocate(mach_task_self(),
202*19c3b8c2SApple OSS Distributions (mach_vm_address_t)(uintptr_t)psets,
203*19c3b8c2SApple OSS Distributions pcnt * sizeof(*psets));
204*19c3b8c2SApple OSS Distributions
205*19c3b8c2SApple OSS Distributions if (found_kernel_task != 2) {
206*19c3b8c2SApple OSS Distributions /* One for kernel control port test, one for kernel read port test. */
207*19c3b8c2SApple OSS Distributions T_FAIL("could not find kernel_task in list of tasks returned");
208*19c3b8c2SApple OSS Distributions }
209*19c3b8c2SApple OSS Distributions }
210