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");