5 #include <darwintest.h>
7 #include <mach/host_priv.h>
9 #include <mach/mach_types.h>
10 #include <mach/mach_vm.h>
11 #include <mach/processor_set.h>
12 #include <mach/task.h>
13 #include <sys/sysctl.h>
16 T_GLOBAL_META(T_META_NAMESPACE("xnu.ipc"));
19 * Attempt to inspect kernel_task using a task_inspect_t. Interact with the
20 * kernel in the same way top(1) and lsmp(1) do.
24 check_secure_kernel(void)
27 size_t secure_kern_size
= sizeof(secure_kern
);
29 T_ASSERT_POSIX_SUCCESS(sysctlbyname("kern.secure_kernel", &secure_kern
,
30 &secure_kern_size
, NULL
, 0), NULL
);
33 T_SKIP("secure kernel: processor_set_tasks will not return kernel_task");
38 attempt_kernel_inspection(task_t task
)
40 pid_t pid
= (pid_t
)-1;
41 mach_msg_type_number_t i
, count
, thcnt
;
42 struct task_basic_info_64 ti
;
43 thread_act_array_t threads
;
46 T_EXPECT_MACH_SUCCESS(pid_for_task(task
, &pid
), NULL
);
47 T_LOG("Checking pid %d", pid
);
53 T_LOG("found kernel_task, attempting to inspect");
55 count
= TASK_BASIC_INFO_64_COUNT
;
56 T_EXPECT_MACH_SUCCESS(task_info(task
, TASK_BASIC_INFO_64
, (task_info_t
)&ti
,
57 &count
), "task_info(... TASK_BASIC_INFO_64 ...)");
59 T_EXPECT_MACH_SUCCESS(task_threads(task
, &threads
, &thcnt
), "task_threads");
60 T_LOG("Found %d kernel threads.", thcnt
);
61 for (i
= 0; i
< thcnt
; i
++) {
63 thread_basic_info_data_t basic_info
;
64 mach_msg_type_number_t bi_count
= THREAD_BASIC_INFO_COUNT
;
66 kr
= thread_info(threads
[i
], THREAD_BASIC_INFO
,
67 (thread_info_t
)&basic_info
, &bi_count
);
69 * Ignore threads that have gone away.
71 if (kr
== MACH_SEND_INVALID_DEST
) {
72 T_LOG("ignoring thread that has been destroyed");
75 T_EXPECT_MACH_SUCCESS(kr
, "thread_info(... THREAD_BASIC_INFO ...)");
76 (void)mach_port_deallocate(mach_task_self(), threads
[i
]);
78 mach_vm_deallocate(mach_task_self(),
79 (mach_vm_address_t
)(uintptr_t)threads
,
80 thcnt
* sizeof(*threads
));
82 ipc_info_space_basic_t basic_info
;
83 T_EXPECT_MACH_SUCCESS(mach_port_space_basic_info(task
, &basic_info
), "mach_port_space_basic_info");
85 ipc_info_space_t info_space
;
86 ipc_info_name_array_t table
;
87 ipc_info_tree_name_array_t tree
;
88 mach_msg_type_number_t tblcnt
= 0, treecnt
= 0;
89 T_EXPECT_MACH_SUCCESS(mach_port_space_info(task
, &info_space
, &table
,
90 &tblcnt
, &tree
, &treecnt
), "mach_port_space_info");
92 mach_vm_deallocate(mach_task_self(),
93 (mach_vm_address_t
)(uintptr_t)table
,
94 tblcnt
* sizeof(*table
));
97 mach_vm_deallocate(mach_task_self(),
98 (mach_vm_address_t
)(uintptr_t)tree
,
99 treecnt
* sizeof(*tree
));
105 T_DECL(inspect_kernel_task
,
106 "ensure that kernel task can be inspected",
107 T_META_CHECK_LEAKS(false),
110 processor_set_name_array_t psets
;
111 processor_set_t pset
;
113 mach_msg_type_number_t i
, j
, tcnt
, pcnt
= 0;
114 mach_port_t self
= mach_host_self();
116 check_secure_kernel();
118 T_ASSERT_MACH_SUCCESS(host_processor_sets(self
, &psets
, &pcnt
),
121 for (i
= 0; i
< pcnt
; i
++) {
122 T_ASSERT_MACH_SUCCESS(host_processor_set_priv(self
, psets
[i
], &pset
), NULL
);
123 T_LOG("Checking pset %d/%d", i
, pcnt
- 1);
126 T_ASSERT_MACH_SUCCESS(processor_set_tasks(pset
, &tasks
, &tcnt
), NULL
);
128 for (j
= 0; j
< tcnt
; j
++) {
129 attempt_kernel_inspection(tasks
[j
]);
130 mach_port_deallocate(self
, tasks
[j
]);
133 /* free tasks array */
134 mach_vm_deallocate(mach_task_self(),
135 (mach_vm_address_t
)(uintptr_t)tasks
,
136 tcnt
* sizeof(*tasks
));
137 mach_port_deallocate(mach_task_self(), pset
);
138 mach_port_deallocate(mach_task_self(), psets
[i
]);
140 mach_vm_deallocate(mach_task_self(),
141 (mach_vm_address_t
)(uintptr_t)psets
,
142 pcnt
* sizeof(*psets
));
144 T_FAIL("could not find kernel_task in list of tasks returned");