1 #include <darwintest.h>
3 #include <mach/host_priv.h>
5 #include <mach/mach_types.h>
6 #include <mach/mach_vm.h>
7 #include <mach/processor_set.h>
9 #include <sys/sysctl.h>
12 T_GLOBAL_META(T_META_NAMESPACE("xnu.ipc"));
15 * Attempt to inspect kernel_task using a task_inspect_t. Interact with the
16 * kernel in the same way top(1) and lsmp(1) do.
20 check_secure_kernel(void)
23 size_t secure_kern_size
= sizeof(secure_kern
);
25 T_ASSERT_POSIX_SUCCESS(sysctlbyname("kern.secure_kernel", &secure_kern
,
26 &secure_kern_size
, NULL
, 0), NULL
);
29 T_SKIP("secure kernel: processor_set_tasks will not return kernel_task");
34 attempt_kernel_inspection(task_t task
)
36 pid_t pid
= (pid_t
)-1;
37 mach_msg_type_number_t i
, count
, thcnt
;
38 struct task_basic_info_64 ti
;
39 thread_act_array_t threads
;
42 T_EXPECT_MACH_SUCCESS(pid_for_task(task
, &pid
), NULL
);
43 T_LOG("Checking pid %d", pid
);
49 T_LOG("found kernel_task, attempting to inspect");
51 count
= TASK_BASIC_INFO_64_COUNT
;
52 T_EXPECT_MACH_SUCCESS(task_info(task
, TASK_BASIC_INFO_64
, (task_info_t
)&ti
,
53 &count
), "task_info(... TASK_BASIC_INFO_64 ...)");
55 T_EXPECT_MACH_SUCCESS(task_threads(task
, &threads
, &thcnt
), "task_threads");
56 T_LOG("Found %d kernel threads.", thcnt
);
57 for (i
= 0; i
< thcnt
; i
++) {
58 thread_basic_info_data_t basic_info
;
59 mach_msg_type_number_t bi_count
= THREAD_BASIC_INFO_COUNT
;
60 T_EXPECT_MACH_SUCCESS(thread_info(threads
[i
], THREAD_BASIC_INFO
,
61 (thread_info_t
)&basic_info
, &bi_count
),
62 "thread_info(... THREAD_BASIC_INFO ...)");
63 (void)mach_port_deallocate(mach_task_self(), threads
[i
]);
65 mach_vm_deallocate(mach_task_self(),
66 (mach_vm_address_t
)(uintptr_t)threads
,
67 thcnt
* sizeof(*threads
));
69 ipc_info_space_basic_t basic_info
;
70 T_EXPECT_MACH_SUCCESS(mach_port_space_basic_info(task
, &basic_info
), "mach_port_space_basic_info");
72 ipc_info_space_t info_space
;
73 ipc_info_name_array_t table
;
74 ipc_info_tree_name_array_t tree
;
75 mach_msg_type_number_t tblcnt
= 0, treecnt
= 0;
76 T_EXPECT_MACH_SUCCESS(mach_port_space_info(task
, &info_space
, &table
,
77 &tblcnt
, &tree
, &treecnt
), "mach_port_space_info");
79 mach_vm_deallocate(mach_task_self(),
80 (mach_vm_address_t
)(uintptr_t)table
,
81 tblcnt
* sizeof(*table
));
84 mach_vm_deallocate(mach_task_self(),
85 (mach_vm_address_t
)(uintptr_t)tree
,
86 treecnt
* sizeof(*tree
));
92 T_DECL(inspect_kernel_task
,
93 "ensure that kernel task can be inspected",
94 T_META_CHECK_LEAKS(false),
97 processor_set_name_array_t psets
;
100 mach_msg_type_number_t i
, j
, tcnt
, pcnt
= 0;
101 mach_port_t self
= mach_host_self();
103 check_secure_kernel();
105 T_ASSERT_MACH_SUCCESS(host_processor_sets(self
, &psets
, &pcnt
),
108 for (i
= 0; i
< pcnt
; i
++) {
109 T_ASSERT_MACH_SUCCESS(host_processor_set_priv(self
, psets
[i
], &pset
), NULL
);
110 T_LOG("Checking pset %d/%d", i
, pcnt
- 1);
113 T_ASSERT_MACH_SUCCESS(processor_set_tasks(pset
, &tasks
, &tcnt
), NULL
);
115 for (j
= 0; j
< tcnt
; j
++) {
116 attempt_kernel_inspection(tasks
[j
]);
117 mach_port_deallocate(self
, tasks
[j
]);
120 /* free tasks array */
121 mach_vm_deallocate(mach_task_self(),
122 (mach_vm_address_t
)(uintptr_t)tasks
,
123 tcnt
* sizeof(*tasks
));
124 mach_port_deallocate(mach_task_self(), pset
);
125 mach_port_deallocate(mach_task_self(), psets
[i
]);
127 mach_vm_deallocate(mach_task_self(),
128 (mach_vm_address_t
)(uintptr_t)psets
,
129 pcnt
* sizeof(*psets
));
131 T_FAIL("could not find kernel_task in list of tasks returned");