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"),
17 T_META_RUN_CONCURRENTLY(true));
20 * Attempt to inspect kernel_task using a task_inspect_t. Interact with the
21 * kernel in the same way top(1) and lsmp(1) do.
25 check_secure_kernel(void)
28 size_t secure_kern_size
= sizeof(secure_kern
);
30 T_ASSERT_POSIX_SUCCESS(sysctlbyname("kern.secure_kernel", &secure_kern
,
31 &secure_kern_size
, NULL
, 0), NULL
);
34 T_SKIP("secure kernel: processor_set_tasks will not return kernel_task");
39 attempt_kernel_inspection(task_t task
)
41 pid_t pid
= (pid_t
)-1;
42 mach_msg_type_number_t i
, count
, thcnt
;
43 struct task_basic_info_64 ti
;
44 thread_act_array_t threads
;
47 T_EXPECT_MACH_SUCCESS(pid_for_task(task
, &pid
), NULL
);
48 T_LOG("Checking pid %d", pid
);
54 T_LOG("found kernel_task, attempting to inspect");
56 count
= TASK_BASIC_INFO_64_COUNT
;
57 T_EXPECT_MACH_SUCCESS(task_info(task
, TASK_BASIC_INFO_64
, (task_info_t
)&ti
,
58 &count
), "task_info(... TASK_BASIC_INFO_64 ...)");
60 T_EXPECT_MACH_SUCCESS(task_threads(task
, &threads
, &thcnt
), "task_threads");
61 T_LOG("Found %d kernel threads.", thcnt
);
62 for (i
= 0; i
< thcnt
; i
++) {
64 thread_basic_info_data_t basic_info
;
65 mach_msg_type_number_t bi_count
= THREAD_BASIC_INFO_COUNT
;
67 kr
= thread_info(threads
[i
], THREAD_BASIC_INFO
,
68 (thread_info_t
)&basic_info
, &bi_count
);
70 * Ignore threads that have gone away.
72 if (kr
== MACH_SEND_INVALID_DEST
) {
73 T_LOG("ignoring thread that has been destroyed");
76 T_EXPECT_MACH_SUCCESS(kr
, "thread_info(... THREAD_BASIC_INFO ...)");
77 (void)mach_port_deallocate(mach_task_self(), threads
[i
]);
79 mach_vm_deallocate(mach_task_self(),
80 (mach_vm_address_t
)(uintptr_t)threads
,
81 thcnt
* sizeof(*threads
));
83 ipc_info_space_basic_t basic_info
;
84 T_EXPECT_MACH_SUCCESS(mach_port_space_basic_info(task
, &basic_info
), "mach_port_space_basic_info");
86 ipc_info_space_t info_space
;
87 ipc_info_name_array_t table
;
88 ipc_info_tree_name_array_t tree
;
89 mach_msg_type_number_t tblcnt
= 0, treecnt
= 0;
90 T_EXPECT_MACH_SUCCESS(mach_port_space_info(task
, &info_space
, &table
,
91 &tblcnt
, &tree
, &treecnt
), "mach_port_space_info");
93 mach_vm_deallocate(mach_task_self(),
94 (mach_vm_address_t
)(uintptr_t)table
,
95 tblcnt
* sizeof(*table
));
98 mach_vm_deallocate(mach_task_self(),
99 (mach_vm_address_t
)(uintptr_t)tree
,
100 treecnt
* sizeof(*tree
));
106 T_DECL(inspect_kernel_task
,
107 "ensure that kernel task can be inspected",
108 T_META_CHECK_LEAKS(false),
111 processor_set_name_array_t psets
;
112 processor_set_t pset
;
114 mach_msg_type_number_t i
, j
, tcnt
, pcnt
= 0;
115 mach_port_t self
= mach_host_self();
117 check_secure_kernel();
119 T_ASSERT_MACH_SUCCESS(host_processor_sets(self
, &psets
, &pcnt
),
122 for (i
= 0; i
< pcnt
; i
++) {
123 T_ASSERT_MACH_SUCCESS(host_processor_set_priv(self
, psets
[i
], &pset
), NULL
);
124 T_LOG("Checking pset %d/%d", i
, pcnt
- 1);
127 T_ASSERT_MACH_SUCCESS(processor_set_tasks(pset
, &tasks
, &tcnt
), NULL
);
129 for (j
= 0; j
< tcnt
; j
++) {
130 attempt_kernel_inspection(tasks
[j
]);
131 mach_port_deallocate(self
, tasks
[j
]);
134 /* free tasks array */
135 mach_vm_deallocate(mach_task_self(),
136 (mach_vm_address_t
)(uintptr_t)tasks
,
137 tcnt
* sizeof(*tasks
));
138 mach_port_deallocate(mach_task_self(), pset
);
139 mach_port_deallocate(mach_task_self(), psets
[i
]);
141 mach_vm_deallocate(mach_task_self(),
142 (mach_vm_address_t
)(uintptr_t)psets
,
143 pcnt
* sizeof(*psets
));
145 T_FAIL("could not find kernel_task in list of tasks returned");