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