1 #define PRIVATE
2 #include <System/sys/kdebug.h>
3 #include <darwintest.h>
4 #include <darwintest_utils.h>
5 #include <dispatch/dispatch.h>
6 #include <fcntl.h>
7 #include <inttypes.h>
8 #include <libproc.h>
9 #include <libgen.h>
10 #include <limits.h>
11 #include <mach/mach.h>
12 #include <mach/policy.h>
13 #include <mach/vm_param.h>
14 #include <os/assumes.h>
15 #include <os/overflow.h>
16 #include <pthread.h>
17 #include <pthread/qos_private.h>
18 #include <signal.h>
19 #include <stdint.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <sys/event.h>
24 #include <sys/mman.h>
25 #include <sys/proc_info.h>
26 #include <sys/stat.h>
27 #include <sys/sysctl.h>
28 #include <sys/fileport.h>
29 #include <sys/vnode.h>
30 #include <sys/fileport.h>
31 #include <unistd.h>
32 #undef PRIVATE
33
34 #include "recount/recount_test_utils.h"
35
36 T_GLOBAL_META(T_META_RUN_CONCURRENTLY(true));
37
38 #define ACT_CHANGE_UID 1
39 #define ACT_CHANGE_RUID 2
40 #define ACT_EXIT 127
41
42 #define ACT_PHASE2 2
43 #define ACT_PHASE3 3
44 #define ACT_PHASE4 4
45 #define ACT_PHASE5 5
46
47 #define PIPE_IN 0
48 #define PIPE_OUT 1
49
50 #define CONF_THREAD_NAME "test_child_thread"
51 #define CONF_CMD_NAME getprogname()
52 #define CONF_PROC_COUNT 20
53 #define CONF_BLK_SIZE 4096
54 #define CONF_UID_VAL 999U
55 #define CONF_RUID_VAL 998U
56 #define CONF_GID_VAL 997U
57 #define CONF_NICE_VAL 5
58 #define CONF_NUM_THREADS 2
59
60 #define BASEPRI_DEFAULT 31
61 #define MAXPRI_USER 63
62
63 #define CONF_OPN_FILE_COUNT 3
64 #define CONF_TMP_FILE_PFX "/tmp/xnu.tests.proc_info."
65 static int
CONF_TMP_FILE_OPEN(char path[PATH_MAX])66 CONF_TMP_FILE_OPEN(char path[PATH_MAX])
67 {
68 static char stmp_path[PATH_MAX] = {};
69 char *nm;
70 if (path) {
71 nm = path;
72 } else {
73 nm = stmp_path;
74 }
75 strlcpy(nm, CONF_TMP_FILE_PFX "XXXXXXXXXX", PATH_MAX);
76 int fd = mkstemp(nm);
77 T_QUIET;
78 T_ASSERT_POSIX_SUCCESS(fd, "mkstemp(" CONF_TMP_FILE_PFX "XXXXXXXXXX)");
79 return fd;
80 }
81
82 // Forward declarations for currently 'private' functions implemented by libproc.
83 int proc_list_uptrs(int pid, uint64_t *buf, uint32_t bufsz);
84 int proc_list_dynkqueueids(int pid, kqueue_id_t *buf, uint32_t bufsz);
85 int proc_piddynkqueueinfo(int pid, int flavor, kqueue_id_t kq_id, void *buffer, int buffersize);
86
87 uint32_t get_tty_dev(void);
88
89 #define WAIT_FOR_CHILDREN(pipefd, action, child_count) \
90 do { \
91 long ret; \
92 if (child_count == 1) { \
93 int child_ret_action = 999; \
94 while (child_ret_action != action) { \
95 ret = read(pipefd, &child_ret_action, sizeof(child_ret_action)); \
96 } \
97 } else { \
98 int child_ready_count = child_count * (int)sizeof(action); \
99 \
100 action = 0; \
101 while (child_ready_count) { \
102 ret = read(pipefd, &action, (int)sizeof(action)); \
103 if (ret != -1) { \
104 child_ready_count -= ret; \
105 } else { \
106 T_FAIL("ERROR: Could not read from pipe() : %d", errno); \
107 } \
108 if (action) { \
109 T_FAIL("ERROR: Child action failed with error %d", action); \
110 } \
111 } \
112 } \
113 } while (0)
114
115 #define PROC_INFO_CALL(struct_name, pid, flavor, proc_arg) \
116 do { \
117 struct struct_name * struct_var = malloc(sizeof(struct struct_name)); \
118 T_QUIET; \
119 T_ASSERT_NOTNULL(struct_var, "malloc() for " #flavor); \
120 retval = __proc_info(PROC_INFO_CALL_PIDINFO, pid, flavor, (uint64_t)proc_arg, (user_addr_t)struct_var, \
121 (uint32_t)sizeof(struct struct_name)); \
122 \
123 T_QUIET; \
124 T_EXPECT_POSIX_SUCCESS(retval, "__proc_info call for " #flavor); \
125 T_ASSERT_EQ_INT(retval, (int)sizeof(struct struct_name), "__proc_info call for " #flavor); \
126 ret_structs[i] = (void *)struct_var; \
127 i++; \
128 } while (0)
129
130 uint32_t
get_tty_dev()131 get_tty_dev()
132 {
133 struct stat buf;
134 stat(ttyname(1), &buf);
135 return (uint32_t)buf.st_rdev;
136 }
137
138 /*
139 * Defined in libsyscall/wrappers/libproc/libproc.c
140 * For API test only. For normal use, please use the libproc API instead.
141 * DO NOT COPY
142 */
143 extern int __proc_info(int32_t callnum, int32_t pid, uint32_t flavor, uint64_t arg, user_addr_t buffer, int32_t buffersize);
144 struct proc_config_s {
145 int parent_pipe[2];
146 int child_count;
147 pid_t proc_grp_id;
148 int child_pipe[CONF_PROC_COUNT][2];
149 int child_pids[CONF_PROC_COUNT];
150 void * cow_map; /* memory for cow test */
151 };
152 typedef struct proc_config_s * proc_config_t;
153
154 typedef void (^child_action_handler_t)(proc_config_t proc_config, int child_id);
155
156 enum proc_info_opt {
157 P_UNIQIDINFO = 0x01,
158 C_UNIQIDINFO = 0x02,
159 PBSD_OLD = 0x04,
160 PBSD = 0x08,
161 PBSD_SHORT = 0x10,
162 PBSD_UNIQID = 0x20,
163 P_TASK_INFO = 0x40,
164 P_TASK_INFO_NEW = 0x80,
165 PALL = 0x100,
166 THREAD_ADDR = 0x200,
167 PTHINFO_OLD = 0x400,
168 PTHINFO = 0x800,
169 PTHINFO_64 = 0x1000,
170 PINFO_PATH = 0x2000,
171 PAI = 0x4000,
172 PREGINFO = 0x8000,
173 PREGINFO_PATH = 0x10000,
174 PREGINFO_PATH_2 = 0x20000,
175 PREGINFO_PATH_3 = 0x40000,
176 PVNINFO = 0x80000
177 };
178
179 static int tmp_fd = -1;
180
181 static child_action_handler_t proc_info_listpids_handler = ^void (proc_config_t proc_config, int child_id) {
182 close(proc_config->parent_pipe[PIPE_IN]);
183 close(proc_config->child_pipe[child_id][PIPE_OUT]);
184 long retval = 0;
185 int child_action = 0;
186 retval = write(proc_config->parent_pipe[PIPE_OUT], &child_action, sizeof(child_action));
187 if (retval != -1) {
188 while (child_action != ACT_EXIT) {
189 retval = read(proc_config->child_pipe[child_id][PIPE_IN], &child_action, sizeof(child_action));
190 if (retval == 0 || (retval == -1 && errno == EAGAIN)) {
191 continue;
192 }
193 if (retval != -1) {
194 switch (child_action) {
195 case ACT_CHANGE_UID:
196 /*
197 * Change uid
198 */
199 retval = setuid(CONF_UID_VAL);
200 break;
201 case ACT_CHANGE_RUID:
202 /*
203 * Change ruid
204 */
205 retval = setreuid(CONF_RUID_VAL, (uid_t)-1);
206 break;
207 case ACT_EXIT:
208 /*
209 * Exit
210 */
211 break;
212 }
213 }
214 if (child_action != ACT_EXIT) {
215 retval = write(proc_config->parent_pipe[PIPE_OUT], &retval, sizeof(retval));
216 if (retval == -1) {
217 break;
218 }
219 }
220 }
221 }
222 close(proc_config->parent_pipe[PIPE_OUT]);
223 close(proc_config->child_pipe[child_id][PIPE_IN]);
224 exit(0);
225 };
226
227 static child_action_handler_t proc_info_call_pidinfo_handler = ^void (proc_config_t proc_config, int child_id) {
228 close(proc_config->parent_pipe[PIPE_IN]);
229 close(proc_config->child_pipe[child_id][PIPE_OUT]);
230 int action = 0;
231 long retval = 0;
232 int i;
233 void * tmp_map = NULL;
234 dispatch_queue_t q = NULL;
235 dispatch_semaphore_t sem = NULL;
236 /*
237 * PHASE 1: Child ready and waits for parent to send next action
238 */
239 T_LOG("Child ready to accept action from parent");
240 retval = write(proc_config->parent_pipe[PIPE_OUT], &action, sizeof(action));
241 if (retval != -1) {
242 while (action != ACT_EXIT) {
243 retval = read(proc_config->child_pipe[child_id][PIPE_IN], &action, sizeof(action));
244
245 if (retval != -1) {
246 retval = 0;
247 switch (action) {
248 case ACT_PHASE2: {
249 /*
250 * Change uid, euid, guid, rgid, nice value
251 * Also change the svuid and svgid
252 */
253 T_LOG("Child changing uid, euid, rguid, svuid, svgid and nice value");
254 retval = nice(CONF_NICE_VAL);
255 if (retval == -1) {
256 T_LOG("(child) ERROR: nice() failed");
257 break;
258 }
259 retval = setgid(CONF_GID_VAL);
260 if (retval == -1) {
261 T_LOG("(child) ERROR: setgid() failed");
262 break;
263 }
264 retval = setreuid((uid_t)-1, CONF_RUID_VAL);
265 if (retval == -1) {
266 T_LOG("(child) ERROR: setreuid() failed");
267 break;
268 }
269 break;
270 }
271 case ACT_PHASE3: {
272 /*
273 * Allocate a page of memory
274 * Copy on write shared memory
275 *
276 * WARNING
277 * Don't add calls to T_LOG here as they can end up generating unwanted
278 * calls to mach_msg_send(). If curtask->messages_sent gets incremented
279 * at this point it will interfere with testing pti_messages_sent.
280 */
281 retval = 0;
282 tmp_map = mmap(0, PAGE_SIZE, PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0);
283 if (tmp_map == MAP_FAILED) {
284 T_LOG("(child) ERROR: mmap() failed");
285 retval = 1;
286 break;
287 }
288 /*
289 * Get the page allocated
290 */
291 int * map_ptr = (int *)tmp_map;
292 for (i = 0; i < (int)(PAGE_SIZE / sizeof(int)); i++) {
293 *map_ptr++ = i;
294 }
295 /*
296 * Cause copy on write to the page
297 */
298 *((int *)(proc_config->cow_map)) = 20;
299
300 break;
301 }
302 case ACT_PHASE4: {
303 T_LOG("Child spending CPU cycles and changing thread name");
304 retval = 0;
305 int number = 1000;
306 unsigned long long factorial = 1;
307 int j;
308 for (j = 1; j <= number; j++) {
309 factorial *= (unsigned long long)j;
310 }
311 sysctlbyname("kern.threadname", NULL, 0, CONF_THREAD_NAME, strlen(CONF_THREAD_NAME));
312 break;
313 }
314 case ACT_PHASE5: {
315 /*
316 * Dispatch for Workq test
317 */
318 T_LOG("Child creating a dispatch queue, and dispatching blocks on it");
319 q = dispatch_queue_create("com.apple.test_proc_info.workqtest",
320 DISPATCH_QUEUE_CONCURRENT); // dispatch_get_global_queue(0, 0);
321 sem = dispatch_semaphore_create(0);
322
323 for (i = 0; i < CONF_NUM_THREADS; i++) {
324 dispatch_async(q, ^{
325 /*
326 * Block the thread, do nothing
327 */
328 dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
329 });
330 }
331 break;
332 }
333 case ACT_EXIT: {
334 /*
335 * Exit
336 */
337 if (sem) {
338 for (i = 0; i < CONF_NUM_THREADS; i++) {
339 dispatch_semaphore_signal(sem);
340 }
341 }
342
343 if (tmp_map) {
344 munmap(tmp_map, PAGE_SIZE);
345 }
346
347 if (proc_config->cow_map) {
348 munmap(proc_config->cow_map, PAGE_SIZE);
349 }
350
351 break;
352 }
353 }
354 }
355 if (action != ACT_EXIT) {
356 retval = write(proc_config->parent_pipe[PIPE_OUT], &action, sizeof(action));
357 if (retval == -1) {
358 break;
359 }
360 }
361 }
362 close(proc_config->parent_pipe[PIPE_OUT]);
363 close(proc_config->child_pipe[child_id][PIPE_IN]);
364 exit(0);
365 }
366 };
367
368 static void
free_proc_config(proc_config_t proc_config)369 free_proc_config(proc_config_t proc_config)
370 {
371 free(proc_config);
372 }
373
374 static void
send_action_to_child_processes(proc_config_t proc_config,int action)375 send_action_to_child_processes(proc_config_t proc_config, int action)
376 {
377 long err;
378 for (int i = 0; i < proc_config->child_count; i++) {
379 err = write(proc_config->child_pipe[i][PIPE_OUT], &action, sizeof(action));
380 T_QUIET;
381 T_ASSERT_POSIX_SUCCESS(err, "write() to child in send_action");
382 }
383 if (action != ACT_EXIT) {
384 WAIT_FOR_CHILDREN(proc_config->parent_pipe[PIPE_IN], action, proc_config->child_count);
385 }
386 }
387
388 static void
kill_child_processes(proc_config_t proc_config)389 kill_child_processes(proc_config_t proc_config)
390 {
391 int ret = 0;
392 T_LOG("Killing child processes");
393 send_action_to_child_processes(proc_config, ACT_EXIT);
394 for (int child_id = 0; child_id < proc_config->child_count; child_id++) {
395 close(proc_config->child_pipe[child_id][PIPE_OUT]);
396 dt_waitpid(proc_config->child_pids[child_id], NULL, NULL, 5);
397 T_QUIET;
398 T_ASSERT_POSIX_SUCCESS(ret, "killed child %d", child_id);
399 }
400 close(proc_config->parent_pipe[PIPE_IN]);
401 munmap(proc_config->cow_map, PAGE_SIZE);
402 T_LOG("Killed child processes");
403 }
404
405 static proc_config_t
spawn_child_processes(int child_count,child_action_handler_t child_handler)406 spawn_child_processes(int child_count, child_action_handler_t child_handler)
407 {
408 /*
409 * Spawn procs for Tests 1.2 and 1.3
410 */
411 T_LOG("Spawning child processes...");
412 proc_config_t proc_config = malloc(sizeof(*proc_config));
413 int action = 0;
414 int err;
415
416 setpgid(0, 0);
417 proc_config->proc_grp_id = getpgid(0);
418
419 proc_config->child_count = child_count;
420
421 err = pipe(proc_config->parent_pipe);
422 T_QUIET;
423 T_ASSERT_POSIX_SUCCESS(err, "pipe() call");
424
425 /*
426 * Needed for ACT_PHASE3 tests
427 */
428 proc_config->cow_map = mmap(0, PAGE_SIZE, PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0);
429 T_QUIET;
430 T_ASSERT_NE_PTR(proc_config->cow_map, MAP_FAILED, "cow_map mmap()");
431 *((int *)(proc_config->cow_map)) = 10;
432
433 pid_t child_pid;
434 int i;
435 int child_id;
436 for (i = 0; i < child_count; i++) {
437 err = pipe(proc_config->child_pipe[i]);
438 T_QUIET;
439 T_ASSERT_POSIX_SUCCESS(err, "pipe() call");
440
441 child_pid = fork();
442 child_id = i;
443 T_QUIET;
444 T_ASSERT_POSIX_SUCCESS(child_pid, "fork() in parent process for child %d", child_id);
445
446 if (child_pid == 0) {
447 child_handler(proc_config, child_id);
448 } else {
449 proc_config->child_pids[child_id] = child_pid;
450 }
451 close(proc_config->child_pipe[child_id][PIPE_IN]);
452 }
453 /*
454 * Wait for the children processes to spawn
455 */
456 close(proc_config->parent_pipe[PIPE_OUT]);
457 WAIT_FOR_CHILDREN(proc_config->parent_pipe[PIPE_IN], action, child_count);
458
459 return proc_config;
460 }
461
462 /*
463 * All PROC_INFO_CALL_PIDINFO __proc_info calls fire from this function.
464 * T_DECLs require different combinations of structs and different actions
465 * must occur in the child to get the data. Instead of performing the setup
466 * in each T_DECL, this function accepts a bitmap and performs the necessary setup
467 * and cleanup work
468 */
469
470 static void
proc_info_caller(int proc_info_opts,void ** ret_structs,int * ret_child_pid)471 proc_info_caller(int proc_info_opts, void ** ret_structs, int * ret_child_pid)
472 {
473 int retval, i = 0;
474 uint64_t * thread_addr = NULL;
475 void * map_tmp = NULL;
476 static char tmp_path[PATH_MAX] = {};
477
478 proc_config_t proc_config = spawn_child_processes(1, proc_info_call_pidinfo_handler);
479 int child_pid = proc_config->child_pids[0];
480 /*
481 * These tests only require one child.
482 * Some DECLs need to know the child pid, so we pass that back if applicable
483 */
484 if (ret_child_pid != NULL) {
485 *ret_child_pid = child_pid;
486 }
487
488 if (proc_info_opts & P_UNIQIDINFO) {
489 PROC_INFO_CALL(proc_uniqidentifierinfo, getpid(), PROC_PIDUNIQIDENTIFIERINFO, 0);
490 }
491 if (proc_info_opts & C_UNIQIDINFO) {
492 PROC_INFO_CALL(proc_uniqidentifierinfo, child_pid, PROC_PIDUNIQIDENTIFIERINFO, 0);
493 }
494 if (proc_info_opts & PBSD_OLD) {
495 PROC_INFO_CALL(proc_bsdinfo, child_pid, PROC_PIDTBSDINFO, 0);
496 }
497
498 /*
499 * Child Phase 2 Fires if opts require it
500 * Small nap after call to give child time to receive and execute the action
501 */
502
503 if (proc_info_opts >= PBSD) {
504 send_action_to_child_processes(proc_config, ACT_PHASE2);
505 }
506
507 if (proc_info_opts & PBSD) {
508 PROC_INFO_CALL(proc_bsdinfo, child_pid, PROC_PIDTBSDINFO, 0);
509 }
510
511 if (proc_info_opts & PBSD_SHORT) {
512 PROC_INFO_CALL(proc_bsdshortinfo, child_pid, PROC_PIDT_SHORTBSDINFO, 0);
513 }
514
515 if (proc_info_opts & PBSD_UNIQID) {
516 PROC_INFO_CALL(proc_bsdinfowithuniqid, child_pid, PROC_PIDT_BSDINFOWITHUNIQID, 0);
517 }
518 if (proc_info_opts & P_TASK_INFO) {
519 PROC_INFO_CALL(proc_taskinfo, child_pid, PROC_PIDTASKINFO, 0);
520 }
521
522 /*
523 * Child Phase 3 Fires
524 */
525 if (proc_info_opts >= P_TASK_INFO_NEW) {
526 send_action_to_child_processes(proc_config, ACT_PHASE3);
527 }
528
529 if (proc_info_opts & P_TASK_INFO_NEW) {
530 PROC_INFO_CALL(proc_taskinfo, child_pid, PROC_PIDTASKINFO, 0);
531 }
532
533 if (proc_info_opts & PALL) {
534 PROC_INFO_CALL(proc_taskallinfo, child_pid, PROC_PIDTASKALLINFO, 0);
535 }
536 /*
537 * This case breaks the pattern in that its proc_info call requires PALL,
538 * its value is required in some other proc_info calls
539 * and we never put the retval into our ret_structs
540 */
541 if (proc_info_opts & THREAD_ADDR || proc_info_opts & PTHINFO_OLD || proc_info_opts & PTHINFO || proc_info_opts & PINFO_PATH) {
542 struct proc_taskallinfo * pall = malloc(sizeof(struct proc_taskallinfo));
543 T_QUIET;
544 T_ASSERT_NOTNULL(pall, "malloc() for PROC_TASKALLINFO");
545
546 retval = __proc_info(PROC_INFO_CALL_PIDINFO, child_pid, PROC_PIDTASKALLINFO, (uint32_t)0, (user_addr_t)pall,
547 (uint32_t)sizeof(struct proc_taskallinfo));
548 T_QUIET;
549 T_ASSERT_EQ_INT(retval, (int)sizeof(struct proc_taskallinfo), "__proc_info call for PROC_PIDTASKALLINFO in THREAD_ADDR");
550
551 thread_addr = malloc(sizeof(uint64_t) * (unsigned long)(pall->ptinfo.pti_threadnum + 1));
552 memset(thread_addr, 0, sizeof(uint64_t) * (unsigned long)(pall->ptinfo.pti_threadnum + 1));
553 T_QUIET;
554 T_ASSERT_NOTNULL(thread_addr, "malloc() for PROC_PIDLISTTHREADS");
555
556 retval = __proc_info(PROC_INFO_CALL_PIDINFO, child_pid, PROC_PIDLISTTHREADS, (uint32_t)0, (user_addr_t)thread_addr,
557 (int32_t)(sizeof(uint64_t) * (unsigned long)(pall->ptinfo.pti_threadnum + 1)));
558 T_LOG("(int)((unsigned long)retval / PROC_PIDLISTTHREADS_SIZE: %d",
559 (int)((unsigned long)retval / PROC_PIDLISTTHREADS_SIZE));
560 T_ASSERT_GE_INT((int)((unsigned long)retval / PROC_PIDLISTTHREADS_SIZE), pall->ptinfo.pti_threadnum,
561 "__proc_info call for PROC_PIDLISTTHREADS");
562
563 free(pall);
564 }
565 if (proc_info_opts & PTHINFO_OLD) {
566 PROC_INFO_CALL(proc_threadinfo, child_pid, PROC_PIDTHREADINFO, thread_addr[0]);
567 }
568
569 /*
570 * Child Phase 4 Fires
571 */
572 if (proc_info_opts >= PTHINFO) {
573 send_action_to_child_processes(proc_config, ACT_PHASE4);
574 }
575
576 if (proc_info_opts & PTHINFO) {
577 PROC_INFO_CALL(proc_threadinfo, child_pid, PROC_PIDTHREADINFO, thread_addr[0]);
578 }
579 if (proc_info_opts & PTHINFO_64) {
580 mach_port_name_t child_task = MACH_PORT_NULL;
581 thread_array_t child_threads = NULL;
582 mach_msg_type_number_t child_thread_count;
583 thread_identifier_info_data_t child_thread_threadinfo;
584 mach_msg_type_number_t thread_info_count = THREAD_IDENTIFIER_INFO_COUNT;
585 struct proc_threadinfo * pthinfo_64 = malloc(sizeof(struct proc_threadinfo));
586 T_QUIET;
587 T_ASSERT_NOTNULL(pthinfo_64, "malloc() for PROC_THREADINFO");
588
589 retval = task_for_pid(mach_task_self(), child_pid, &child_task);
590 T_ASSERT_EQ_INT(retval, 0, "task_for_pid for PROC_PIDTHREADID64INFO");
591
592 retval = task_threads(child_task, &child_threads, &child_thread_count);
593 T_ASSERT_MACH_SUCCESS(retval, "task_threads() call for PROC_PIDTHREADID64INFO");
594
595 retval = thread_info(child_threads[0], THREAD_IDENTIFIER_INFO, (thread_info_t)&child_thread_threadinfo, &thread_info_count);
596 T_ASSERT_MACH_SUCCESS(retval, "thread_info call for PROC_PIDTHREADID64INFO");
597
598 retval = __proc_info(PROC_INFO_CALL_PIDINFO, child_pid, PROC_PIDTHREADID64INFO, (uint64_t)child_thread_threadinfo.thread_id,
599 (user_addr_t)pthinfo_64, (uint32_t)sizeof(struct proc_threadinfo));
600 T_ASSERT_EQ_INT(retval, (int)sizeof(struct proc_threadinfo), "__proc_info call for PROC_PIDTHREADID64INFO");
601
602 ret_structs[i] = (void *)pthinfo_64;
603 i++;
604
605 mach_port_deallocate(mach_task_self(), child_task);
606 mach_port_deallocate(mach_task_self(), child_threads[0]);
607 child_threads[0] = MACH_PORT_NULL;
608 child_task = MACH_PORT_NULL;
609 }
610 if (proc_info_opts & PINFO_PATH) {
611 PROC_INFO_CALL(proc_threadwithpathinfo, child_pid, PROC_PIDTHREADPATHINFO, thread_addr[0]);
612 }
613
614 if (proc_info_opts & PAI) {
615 PROC_INFO_CALL(proc_archinfo, getpid(), PROC_PIDARCHINFO, 0);
616 }
617
618 vm_map_size_t map_tmp_sz = 0;
619 if ((proc_info_opts & PREGINFO) | (proc_info_opts & PREGINFO_PATH) | (proc_info_opts & PREGINFO_PATH_2) |
620 (proc_info_opts & PREGINFO_PATH_3)) {
621 tmp_fd = CONF_TMP_FILE_OPEN(tmp_path);
622
623 /*
624 * subsequent checks assume that this data does *not* stay
625 * resident in the buffer cache, so set F_NOCACHE for direct
626 * to storage writing. NOTE: this works if the writes are
627 * page-aligned and > 2 pages in length.
628 */
629 retval = fcntl(tmp_fd, F_NOCACHE, 1);
630 T_QUIET;
631 T_ASSERT_POSIX_SUCCESS(retval, "fcntl(%d, F_NOCACHE) failed", tmp_fd);
632
633 int npages_to_write = 10;
634 map_tmp_sz = (vm_map_size_t)npages_to_write * (vm_map_size_t)PAGE_SIZE;
635
636 /*
637 * To make sure we don't go through the cached write paths in
638 * the VM, we allocate a PAGE-aligned buffer that is > 2
639 * pages, and perform a write of the entire buffer (not in
640 * small page-aligned chunks).
641 */
642 char *buf = valloc((size_t)map_tmp_sz);
643 T_QUIET;
644 T_ASSERT_NOTNULL(buf, "valloc(%d) failed", (int)map_tmp_sz);
645
646 memset(buf, 0x5, map_tmp_sz);
647 ssize_t bw = write(tmp_fd, buf, (size_t)map_tmp_sz);
648 T_QUIET;
649 T_ASSERT_GT_INT((int)bw, 0, "write(%d, buf, %d) failed", tmp_fd, (int)map_tmp_sz);
650
651 free(buf);
652
653 map_tmp_sz -= PAGE_SIZE;
654 map_tmp = mmap(0, (size_t)map_tmp_sz, PROT_WRITE, MAP_PRIVATE, tmp_fd, (off_t)PAGE_SIZE);
655 T_ASSERT_NE_PTR(map_tmp, MAP_FAILED, "mmap() for PROC_PIDREGIONINFO");
656
657 T_LOG("file: %s is opened as fd %d and mapped at %llx with size %lu", tmp_path, tmp_fd, (uint64_t)map_tmp,
658 (unsigned long)PAGE_SIZE);
659
660 /*
661 * unlink() the file to be nice, but do it _after_ we've
662 * already flushed and mapped the file. This will ensure that
663 * we don't end up writing to the buffer cache because the
664 * file is unlinked.
665 */
666 if (!(proc_info_opts & PREGINFO_PATH_3)) {
667 retval = unlink(tmp_path);
668 T_QUIET;
669 T_ASSERT_POSIX_SUCCESS(retval, "unlink(%s) failed", tmp_path);
670 }
671 }
672
673 if (proc_info_opts & PREGINFO) {
674 PROC_INFO_CALL(proc_regioninfo, getpid(), PROC_PIDREGIONINFO, map_tmp);
675 ret_structs[i] = map_tmp;
676 i++;
677 ret_structs[i] = (void *)(uintptr_t)map_tmp_sz;
678 i++;
679 }
680 if (proc_info_opts & PREGINFO_PATH) {
681 PROC_INFO_CALL(proc_regionwithpathinfo, getpid(), PROC_PIDREGIONPATHINFO, map_tmp);
682 ret_structs[i] = map_tmp;
683 i++;
684 ret_structs[i] = (void *)(uintptr_t)map_tmp_sz;
685 i++;
686 }
687 if (proc_info_opts & PREGINFO_PATH_2) {
688 PROC_INFO_CALL(proc_regionwithpathinfo, getpid(), PROC_PIDREGIONPATHINFO2, map_tmp);
689 ret_structs[i] = map_tmp;
690 i++;
691 ret_structs[i] = (void *)(uintptr_t)map_tmp_sz;
692 i++;
693 }
694
695 if (proc_info_opts & PREGINFO_PATH_3) {
696 struct proc_regionwithpathinfo * preginfo_path = malloc(sizeof(struct proc_regionwithpathinfo));
697
698 retval = __proc_info(PROC_INFO_CALL_PIDINFO, getpid(), PROC_PIDREGIONPATHINFO2, (uint64_t)map_tmp,
699 (user_addr_t)preginfo_path, (uint32_t)sizeof(struct proc_regionwithpathinfo));
700
701 T_ASSERT_EQ_INT(retval, (int)sizeof(struct proc_regionwithpathinfo), "__proc_info call for PROC_PIDREGIONPATHINFO2");
702
703 T_LOG("preginfo_path.prp_vip.vip_vi.vi_fsid.val 0: %d", preginfo_path->prp_vip.vip_vi.vi_fsid.val[0]);
704 T_LOG("preginfo_path.prp_vip.vip_vi.vi_fsid.val 1: %d", preginfo_path->prp_vip.vip_vi.vi_fsid.val[1]);
705 ret_structs[3] = (void *)(uintptr_t)preginfo_path->prp_vip.vip_vi.vi_fsid.val[0];
706 ret_structs[4] = (void *)(uintptr_t)preginfo_path->prp_vip.vip_vi.vi_fsid.val[1];
707
708 retval = __proc_info(PROC_INFO_CALL_PIDINFO, getpid(), PROC_PIDREGIONPATHINFO3,
709 (uint64_t)preginfo_path->prp_vip.vip_vi.vi_fsid.val[0] +
710 ((uint64_t)preginfo_path->prp_vip.vip_vi.vi_fsid.val[1] << 32),
711 (user_addr_t)preginfo_path,
712 (uint32_t)sizeof(struct proc_regionwithpathinfo));
713 T_ASSERT_EQ_INT(retval, (int)sizeof(struct proc_regionwithpathinfo), "__proc_info call for PROC_PIDREGIONPATHWITHINFO3");
714 ret_structs[0] = (void *)preginfo_path;
715 ret_structs[1] = (void *)map_tmp;
716 ret_structs[2] = (void *)(uintptr_t)map_tmp_sz;
717
718 retval = unlink(tmp_path);
719 T_QUIET;
720 T_ASSERT_POSIX_SUCCESS(retval, "unlink(%s) failed", preginfo_path->prp_vip.vip_path);
721 }
722
723 if (proc_info_opts & PVNINFO) {
724 PROC_INFO_CALL(proc_vnodepathinfo, getpid(), PROC_PIDVNODEPATHINFO, 0);
725 }
726
727 kill_child_processes(proc_config);
728 free_proc_config(proc_config);
729 free(thread_addr);
730 thread_addr = NULL;
731 close(tmp_fd);
732 tmp_fd = -1;
733 }
734
735 static void
free_proc_info(void ** proc_info,int num)736 free_proc_info(void ** proc_info, int num)
737 {
738 for (int i = 0; i < num; i++) {
739 free(proc_info[i]);
740 }
741
742 return;
743 }
744
745 /*
746 * Start DECLs
747 */
748
749 T_DECL(proc_info_listpids_all_pids,
750 "proc_info API test to verify PROC_INFO_CALL_LISTPIDS",
751 T_META_ASROOT(true), T_META_TAG_VM_PREFERRED)
752 {
753 /*
754 * Get the value of nprocs with no buffer sent in
755 */
756 int num_procs;
757 num_procs = __proc_info(PROC_INFO_CALL_LISTPIDS, PROC_ALL_PIDS, (uint32_t)getpid(), (uint32_t)0, (user_addr_t)0, (uint32_t)0);
758 T_ASSERT_GE_INT(num_procs, 1, "verify valid value for nprocs: %d", num_procs);
759
760 proc_config_t proc_config = spawn_child_processes(CONF_PROC_COUNT, proc_info_listpids_handler);
761
762 num_procs = __proc_info(PROC_INFO_CALL_LISTPIDS, PROC_ALL_PIDS, (uint32_t)getpid(), (uint32_t)0, (user_addr_t)0, (uint32_t)0);
763
764 int proc_count = num_procs / (int)sizeof(pid_t);
765 int proc_count_all = num_procs / (int)sizeof(pid_t);
766 if (proc_count > (CONF_PROC_COUNT + 1)) {
767 proc_count = CONF_PROC_COUNT + 1;
768 }
769 pid_t * proc_ids = malloc(sizeof(pid_t) * (unsigned long)proc_count);
770 num_procs = __proc_info(PROC_INFO_CALL_LISTPIDS, PROC_ALL_PIDS, (uint32_t)getpid(), (uint32_t)0, (user_addr_t)proc_ids,
771 (int32_t)(proc_count * (int)sizeof(pid_t)));
772 num_procs = num_procs / (int)sizeof(pid_t);
773 T_ASSERT_GE_INT(num_procs, proc_count, "Valid number of pids obtained for PROC_ALL_PIDS.");
774
775 free(proc_ids);
776
777 /*
778 * Grab list of all procs and make sure our spawned children are in the list.
779 */
780
781 proc_ids = malloc(sizeof(pid_t) * (unsigned long)proc_count_all);
782 num_procs = __proc_info(PROC_INFO_CALL_LISTPIDS, PROC_ALL_PIDS, (uint32_t)getpid(), (uint32_t)0, (user_addr_t)proc_ids,
783 (int32_t)(proc_count_all * (int)sizeof(pid_t)));
784 num_procs = num_procs / (int)sizeof(pid_t);
785
786 int pid_match = 1;
787
788 for (int i = 0; i < (CONF_PROC_COUNT - 1); i++) {
789 for (int j = 0; j < num_procs; j++) {
790 if (proc_ids[j] == proc_config->child_pids[i]) {
791 break;
792 } else if (j == (num_procs - 1)) {
793 pid_match = 0;
794 break;
795 }
796 }
797
798 if (!pid_match) {
799 break;
800 }
801 }
802
803 T_ASSERT_EQ(pid_match, 1, "PROC_INFO_CALL_LISTPIDS contains our spawned children's pids");
804
805 free(proc_ids);
806
807 kill_child_processes(proc_config);
808 free_proc_config(proc_config);
809
810 errno = 0;
811 num_procs = __proc_info(PROC_INFO_CALL_LISTPIDS, PROC_ALL_PIDS, (uint32_t)getpid(), (uint32_t)0, (user_addr_t)proc_ids,
812 (uint32_t)(sizeof(pid_t) - 1));
813 T_EXPECT_POSIX_ERROR(errno, ENOMEM, "Valid proc_info behavior when bufsize < sizeof(pid_t).");
814 }
815
816 T_DECL(proc_info_listpids_pgrp_only,
817 "proc_info API test to verify PROC_INFO_CALL_LISTPIDS",
818 T_META_ASROOT(true), T_META_TAG_VM_PREFERRED)
819 {
820 proc_config_t proc_config = spawn_child_processes(CONF_PROC_COUNT, proc_info_listpids_handler);
821 T_LOG("Test to verify PROC_PGRP_ONLY returns correct value");
822 /*
823 * The number of obtained pids depends on size of buffer.
824 * count = childCount + 1(parent)
825 * So, we set it to one more than expected to capture any error.
826 */
827 int proc_count = CONF_PROC_COUNT + 2;
828 pid_t * proc_ids = malloc(sizeof(*proc_ids) * (unsigned long)proc_count);
829 int num_procs = __proc_info(PROC_INFO_CALL_LISTPIDS, PROC_PGRP_ONLY, (uint32_t)proc_config->proc_grp_id, (uint32_t)0,
830 (user_addr_t)proc_ids, (int32_t)(proc_count * (int)sizeof(*proc_ids)));
831 num_procs = num_procs / (int)sizeof(pid_t);
832 T_ASSERT_EQ_INT(num_procs, CONF_PROC_COUNT + 1, "Valid number of pids obtained for PROC_PGRP_ONLY.");
833 kill_child_processes(proc_config);
834 free_proc_config(proc_config);
835 free(proc_ids);
836 }
837
838 T_DECL(proc_info_listpids_ppid_only,
839 "proc_info API test to verify PROC_INFO_CALL_LISTPIDS",
840 T_META_ASROOT(true), T_META_TAG_VM_PREFERRED)
841 {
842 proc_config_t proc_config = spawn_child_processes(CONF_PROC_COUNT, proc_info_listpids_handler);
843 T_LOG("Test to verify PROC_PPID_ONLY returns correct value");
844 /*
845 * Pass in the same (bigger) buffer but expect only the pids where ppid is pid of current proc.
846 */
847 int proc_count = CONF_PROC_COUNT + 2;
848 pid_t * proc_ids = malloc(sizeof(*proc_ids) * (unsigned long)proc_count);
849 int num_procs = __proc_info(PROC_INFO_CALL_LISTPIDS, PROC_PPID_ONLY, (uint32_t)getpid(), (uint32_t)0, (user_addr_t)proc_ids,
850 (int32_t)(proc_count * (int)sizeof(*proc_ids)));
851 num_procs = num_procs / (int)sizeof(pid_t);
852 T_ASSERT_EQ_INT(num_procs, CONF_PROC_COUNT, "Valid number of pids obtained for PROC_PPID_ONLY.");
853 kill_child_processes(proc_config);
854 free_proc_config(proc_config);
855 free(proc_ids);
856 }
857
858 T_DECL(proc_info_listpids_uid_only,
859 "proc_info API test to verify PROC_INFO_CALL_LISTPIDS",
860 T_META_ASROOT(true),
861 T_META_TAG_VM_PREFERRED,
862 T_META_ENABLED(false) /* rdar://134505671 */)
863 {
864 proc_config_t proc_config = spawn_child_processes(CONF_PROC_COUNT, proc_info_listpids_handler);
865 T_LOG("Test to verify PROC_UID_ONLY returns correct value");
866 int proc_count = CONF_PROC_COUNT + 2;
867 pid_t * proc_ids = malloc(sizeof(*proc_ids) * (unsigned long)proc_count);
868 send_action_to_child_processes(proc_config, ACT_CHANGE_UID);
869 usleep(10000);
870 int num_procs = __proc_info(PROC_INFO_CALL_LISTPIDS, PROC_UID_ONLY, CONF_UID_VAL, (uint32_t)0, (user_addr_t)proc_ids,
871 (int32_t)(proc_count * (int)sizeof(*proc_ids)));
872 T_ASSERT_GE_ULONG((unsigned long)num_procs / sizeof(pid_t), (unsigned long)CONF_PROC_COUNT,
873 "Valid number of pids obtained for PROC_UID_ONLY.");
874 kill_child_processes(proc_config);
875 free_proc_config(proc_config);
876 free(proc_ids);
877 }
878
879 T_DECL(proc_info_listpids_ruid_only,
880 "proc_info API test to verify PROC_INFO_CALL_LISTPIDS",
881 T_META_ASROOT(true),
882 T_META_TAG_VM_PREFERRED,
883 T_META_ENABLED(false) /* rdar://134505671 */)
884 {
885 proc_config_t proc_config = spawn_child_processes(CONF_PROC_COUNT, proc_info_listpids_handler);
886 T_LOG("Test to verify PROC_RUID_ONLY returns correct value");
887 int proc_count = CONF_PROC_COUNT + 2;
888 pid_t * proc_ids = malloc(sizeof(*proc_ids) * (unsigned long)proc_count);
889 send_action_to_child_processes(proc_config, ACT_CHANGE_RUID);
890 usleep(10000);
891 int num_procs = __proc_info(PROC_INFO_CALL_LISTPIDS, PROC_RUID_ONLY, CONF_RUID_VAL, (uint32_t)0, (user_addr_t)proc_ids,
892 (int32_t)(proc_count * (int)sizeof(*proc_ids)));
893 T_ASSERT_GE_ULONG((unsigned long)num_procs / sizeof(pid_t), (unsigned long)CONF_PROC_COUNT,
894 "Valid number of pids obtained for PROC_RUID_ONLY.");
895 kill_child_processes(proc_config);
896 free_proc_config(proc_config);
897 free(proc_ids);
898 }
899
900 T_DECL(proc_info_listpids_tty_only,
901 "proc_info API test to verify PROC_INFO_CALL_LISTPIDS",
902 T_META_ASROOT(true), T_META_TAG_VM_PREFERRED)
903 {
904 int ret = isatty(STDOUT_FILENO);
905 if (ret != 1) {
906 T_SKIP("Not connected to tty...skipping test");
907 }
908
909 proc_config_t proc_config = spawn_child_processes(CONF_PROC_COUNT, proc_info_listpids_handler);
910
911 T_LOG("Test to verify PROC_TTY_ONLY returns correct value");
912 int proc_count = CONF_PROC_COUNT + 2;
913 pid_t * proc_ids = malloc(sizeof(*proc_ids) * (unsigned long)proc_count);
914 int num_procs = __proc_info(PROC_INFO_CALL_LISTPIDS, PROC_TTY_ONLY, get_tty_dev(), (uint32_t)0, (user_addr_t)proc_ids,
915 (int32_t)(proc_count * (int)sizeof(*proc_ids)));
916 num_procs = num_procs / (int)sizeof(pid_t);
917 T_ASSERT_GE_INT(num_procs, 0, "Valid number of pids returned by PROC_TTY_ONLY.");
918 kill_child_processes(proc_config);
919 free_proc_config(proc_config);
920 free(proc_ids);
921 }
922
923 /*
924 * Most of the following PROC_INFO_CALL_PIDINFO tests rely on a helper function (proc_info_caller) to make the necessary proc_info
925 * calls on their behalf
926 * In a previous iteration, these tests were all in one giant T_DECL and the helper function handles inter-DECL dependencies such as
927 * a proc_info call relying on the results of a previous proc_info call or an assumed state that a child should be in.
928 */
929
930 T_DECL(proc_info_pidinfo_proc_piduniqidentifierinfo,
931 "Test to identify PROC_PIDUNIQIDENTIFIERINFO returns correct unique identifiers for process",
932 T_META_ASROOT(true), T_META_TAG_VM_PREFERRED)
933 {
934 void * proc_info[2];
935 proc_info_caller(P_UNIQIDINFO | C_UNIQIDINFO, proc_info, NULL);
936 struct proc_uniqidentifierinfo * p_uniqidinfo = (struct proc_uniqidentifierinfo *)proc_info[0];
937 struct proc_uniqidentifierinfo * c_uniqidinfo = (struct proc_uniqidentifierinfo *)proc_info[1];
938
939 T_EXPECT_NE_ULLONG(c_uniqidinfo->p_uniqueid, p_uniqidinfo->p_uniqueid, "p_uniqueid not unique for the process");
940
941 for (size_t i = 0; i < 16; i++) {
942 T_EXPECT_EQ_UCHAR(c_uniqidinfo->p_uuid[i], p_uniqidinfo->p_uuid[i], "p_uuid should be the same unique id");
943 }
944 T_EXPECT_EQ_ULLONG(c_uniqidinfo->p_puniqueid, p_uniqidinfo->p_uniqueid,
945 "p_puniqueid of child should be same as p_uniqueid for parent");
946
947 // The child's p_orig_ppidversion should be set to the p_idversion of the parent.
948 T_EXPECT_EQ_INT(c_uniqidinfo->p_orig_ppidversion, p_uniqidinfo->p_idversion,
949 "child->p_pidversion == parent->p_idversion");
950
951 free_proc_info(proc_info, 2);
952 }
953
954 T_DECL(ensure_ppidversion_is_not_updated,
955 "A process's parent's idversion field should not be updated when the parent re-execs",
956 T_META_ASROOT(true), T_META_TAG_VM_PREFERRED)
957 {
958 // Given a process (the test runner) which forks to create a child
959 pid_t original_pid = getpid();
960 if (!fork()) {
961 // And the child process waits for the parent to re-exec...
962 // (To get rid of this, we could exec something controlled that signals a semaphore.)
963 sleep(1);
964
965 // When the child inspects the parent's current idversion
966 struct proc_uniqidentifierinfo parent_info;
967 int ret = proc_pidinfo(original_pid, PROC_PIDUNIQIDENTIFIERINFO, 0, &parent_info, sizeof(parent_info));
968 T_ASSERT_EQ((unsigned long)ret, sizeof(parent_info), "PROC_PIDUNIQIDENTIFIERINFO - parent");
969
970 // And compares it to the child's stored idversion
971 struct proc_uniqidentifierinfo child_info;
972 ret = proc_pidinfo(getpid(), PROC_PIDUNIQIDENTIFIERINFO, 0, &child_info, sizeof(child_info));
973 T_ASSERT_EQ((unsigned long)ret, sizeof(child_info), "PROC_PIDUNIQIDENTIFIERINFO - child");
974
975 // Then the child can see that the parent's idversion has changed from what was stored.
976 T_EXPECT_NE_INT(child_info.p_orig_ppidversion, parent_info.p_idversion,
977 "child->p_orig_ppidversion != parent->p_idversion after parent exec");
978 } else {
979 // And we (the parent process) re-exec into something else
980 const char* exec_cmd[] = { "sleep", "2", NULL };
981 execvp(exec_cmd[0], exec_cmd);
982 T_FAIL("execvp() failed");
983 }
984 }
985
986 T_DECL(ensure_ppidversion_is_not_updated_after_exec,
987 "A child's parent pidversion field should not be updated when the child re-execs",
988 T_META_ASROOT(true), T_META_TAG_VM_PREFERRED)
989 {
990 // Given a child
991 pid_t child_pid = fork();
992 if (!child_pid) {
993 // Give the parent a moment to record our initial p_orig_ppidversion
994 sleep(1);
995
996 // When the child execs into something else
997 const char* exec_cmd[] = { "sleep", "2", NULL };
998 execvp(exec_cmd[0], exec_cmd);
999 T_FAIL("execvp() failed");
1000 } else {
1001 // And we save the child's original p_orig_ppidversion
1002 struct proc_uniqidentifierinfo child_parent_info;
1003 int ret = proc_pidinfo(child_pid, PROC_PIDUNIQIDENTIFIERINFO, 0, &child_parent_info, sizeof(child_parent_info));
1004 T_ASSERT_EQ((unsigned long)ret, sizeof(child_parent_info), "PROC_PIDUNIQIDENTIFIERINFO - child");
1005 int first_ppidversion = child_parent_info.p_orig_ppidversion;
1006
1007 // And we give the child a moment to re-exec into something else
1008 sleep(2);
1009
1010 // And we inspect the child's p_orig_ppidversion again
1011 ret = proc_pidinfo(child_pid, PROC_PIDUNIQIDENTIFIERINFO, 0, &child_parent_info, sizeof(child_parent_info));
1012 T_ASSERT_EQ((unsigned long)ret, sizeof(child_parent_info), "PROC_PIDUNIQIDENTIFIERINFO - child");
1013 int second_ppidversion = child_parent_info.p_orig_ppidversion;
1014
1015 // Then the child's p_orig_ppidversion has not changed due to exec()
1016 T_ASSERT_EQ(first_ppidversion, second_ppidversion, "p_orig_ppidversion should not change after exec()");
1017 }
1018 }
1019
1020 T_DECL(proc_info_pidinfo_proc_pidtbsdinfo,
1021 "Test to verify PROC_PIDTBSDINFO returns valid information about the process",
1022 T_META_ASROOT(true),
1023 T_META_TAG_VM_PREFERRED,
1024 T_META_ENABLED(false) /* rdar://134505671 */)
1025 {
1026 void * proc_info[2];
1027 int child_pid = 0;
1028 proc_info_caller(PBSD_OLD | PBSD, proc_info, &child_pid);
1029 struct proc_bsdinfo * pbsd_old = (struct proc_bsdinfo *)proc_info[0];
1030 struct proc_bsdinfo * pbsd = (struct proc_bsdinfo *)proc_info[1];
1031
1032 T_EXPECT_EQ_UINT((unsigned int)SRUN, pbsd->pbi_status, "PROC_PIDTBSDINFO shows Correct status");
1033 T_EXPECT_EQ_UINT(0U, pbsd->pbi_xstatus, "PROC_PIDTBSDINFO show Correct xstatus (exit status)");
1034 T_EXPECT_EQ_UINT(pbsd->pbi_pid, (unsigned int)child_pid, "PROC_PIDTBSDINFO returns valid pid");
1035 T_EXPECT_EQ_UINT(pbsd->pbi_ppid, (unsigned int)getpid(), "PROC_PIDTBSDINFO returns valid ppid");
1036 T_EXPECT_EQ_UINT(pbsd->pbi_uid, CONF_RUID_VAL, "PROC_PIDTBSDINFO returns valid uid");
1037 T_EXPECT_EQ_UINT(pbsd->pbi_gid, CONF_GID_VAL, "PROC_PIDTBSDINFO returns valid gid");
1038 T_EXPECT_EQ_UINT(pbsd->pbi_ruid, 0U, "PROC_PIDTBSDINFO returns valid ruid");
1039 T_EXPECT_EQ_UINT(pbsd->pbi_rgid, CONF_GID_VAL, "PROC_PIDTBSDINFO returns valid rgid");
1040 T_EXPECT_EQ_UINT(pbsd->pbi_svuid, CONF_RUID_VAL, "PROC_PIDTBSDINFO returns valid svuid");
1041 T_EXPECT_EQ_UINT(pbsd->pbi_svgid, CONF_GID_VAL, "PROC_PIDTBSDINFO returns valid svgid");
1042 T_EXPECT_EQ_UINT(pbsd->pbi_nice, CONF_NICE_VAL, "PROC_PIDTBSDINFO returns valid nice value");
1043 T_EXPECT_EQ_STR(pbsd->pbi_comm, CONF_CMD_NAME, "PROC_PIDTBSDINFO returns valid p_comm name");
1044 T_EXPECT_EQ_STR(pbsd->pbi_name, CONF_CMD_NAME, "PROC_PIDTBSDINFO returns valid p_name name");
1045 T_EXPECT_EQ_UINT(pbsd->pbi_flags, (pbsd_old->pbi_flags | PROC_FLAG_PSUGID), "PROC_PIDTBSDINFO returns valid flags");
1046 T_EXPECT_EQ_UINT(pbsd->pbi_nfiles, pbsd_old->pbi_nfiles, "PROC_PIDTBSDINFO returned valid pbi_nfiles");
1047 T_EXPECT_EQ_UINT(pbsd->pbi_pgid, (uint32_t)getpgid(getpid()), "PROC_PIDTBSDINFO returned valid pbi_pgid");
1048 T_EXPECT_EQ_UINT(pbsd->pbi_pjobc, pbsd->pbi_pjobc, "PROC_PIDTBSDINFO returned valid pbi_pjobc");
1049 T_EXPECT_NE_UINT(pbsd->e_tdev, 0U, "PROC_PIDTBSDINFO returned valid e_tdev");
1050
1051 free_proc_info(proc_info, 2);
1052 }
1053
1054 T_DECL(proc_info_pidt_shortbsdinfo,
1055 "Test to verify PROC_PIDT_SHORTBSDINFO returns valid information about the process",
1056 T_META_ASROOT(true), T_META_TAG_VM_PREFERRED)
1057 {
1058 void * proc_info[2];
1059 int child_pid = 0;
1060 proc_info_caller(PBSD | PBSD_SHORT, proc_info, &child_pid);
1061 struct proc_bsdinfo * pbsd = (struct proc_bsdinfo *)proc_info[0];
1062 struct proc_bsdshortinfo * pbsd_short = (struct proc_bsdshortinfo *)proc_info[1];
1063
1064 T_EXPECT_EQ_UINT(pbsd_short->pbsi_pid, (unsigned int)child_pid, "PROC_PIDT_SHORTBSDINFO returns valid pid");
1065 T_EXPECT_EQ_UINT(pbsd_short->pbsi_ppid, (unsigned int)getpid(), "PROC_PIDT_SHORTBSDINFO returns valid ppid");
1066 T_EXPECT_EQ_UINT(pbsd_short->pbsi_pgid, (uint32_t)getpgid(getpid()), "PROC_PIDT_SHORTBSDINFO returned valid pbi_pgid");
1067 T_EXPECT_EQ_UINT((unsigned int)SRUN, pbsd_short->pbsi_status, "PROC_PIDT_SHORTBSDINFO shows Correct status");
1068 T_EXPECT_EQ_STR(pbsd_short->pbsi_comm, CONF_CMD_NAME, "PROC_PIDT_SHORTBSDINFO returns valid p_comm name");
1069 /*
1070 * The short variant returns all flags except session flags, hence ignoring them here.
1071 */
1072 T_EXPECT_EQ_UINT(pbsd_short->pbsi_flags, (pbsd->pbi_flags & (unsigned int)(~PROC_FLAG_CTTY)),
1073 "PROC_PIDT_SHORTBSDINFO returns valid flags");
1074 T_EXPECT_EQ_UINT(pbsd_short->pbsi_uid, CONF_RUID_VAL, "PROC_PIDT_SHORTBSDINFO returns valid uid");
1075 T_EXPECT_EQ_UINT(pbsd_short->pbsi_gid, CONF_GID_VAL, "PROC_PIDT_SHORTBSDINFO returns valid gid");
1076 T_EXPECT_EQ_UINT(pbsd_short->pbsi_ruid, 0U, "PROC_PIDT_SHORTBSDINFO returns valid ruid");
1077 T_EXPECT_EQ_UINT(pbsd_short->pbsi_svuid, CONF_RUID_VAL, "PROC_PIDT_SHORTBSDINFO returns valid svuid");
1078 T_EXPECT_EQ_UINT(pbsd_short->pbsi_svgid, CONF_GID_VAL, "PROC_PIDT_SHORTBSDINFO returns valid svgid");
1079
1080 free_proc_info(proc_info, 2);
1081 }
1082
1083 T_DECL(proc_info_pidt_bsdinfowithuniqid,
1084 "Test to verify PROC_PIDT_BSDINFOWITHUNIQID returns valid information about the process",
1085 T_META_ASROOT(true),
1086 T_META_TAG_VM_PREFERRED,
1087 T_META_ENABLED(false) /* rdar://134505671 */)
1088 {
1089 void * proc_info[4];
1090 int child_pid = 0;
1091 proc_info_caller(P_UNIQIDINFO | PBSD_OLD | PBSD | PBSD_UNIQID, proc_info, &child_pid);
1092 struct proc_uniqidentifierinfo * p_uniqidinfo = (struct proc_uniqidentifierinfo *)proc_info[0];
1093 struct proc_bsdinfo * pbsd_old = (struct proc_bsdinfo *)proc_info[1];
1094 struct proc_bsdinfo * pbsd = (struct proc_bsdinfo *)proc_info[2];
1095 struct proc_bsdinfowithuniqid * pbsd_uniqid = (struct proc_bsdinfowithuniqid *)proc_info[3];
1096
1097 T_EXPECT_EQ_UINT((unsigned int)SRUN, pbsd->pbi_status, "PROC_PIDT_BSDINFOWITHUNIQID shows Correct status");
1098 T_EXPECT_EQ_UINT(0U, pbsd->pbi_xstatus, "PROC_PIDT_BSDINFOWITHUNIQID show Correct xstatus");
1099 T_EXPECT_EQ_UINT(pbsd_uniqid->pbsd.pbi_pid, (unsigned int)child_pid, "PROC_PIDT_BSDINFOWITHUNIQID returns valid pid");
1100 T_EXPECT_EQ_UINT(pbsd_uniqid->pbsd.pbi_ppid, (unsigned int)getpid(), "PROC_PIDT_BSDINFOWITHUNIQID returns valid ppid");
1101 T_EXPECT_EQ_UINT(pbsd_uniqid->pbsd.pbi_uid, CONF_RUID_VAL, "PROC_PIDT_BSDINFOWITHUNIQID returns valid uid");
1102 T_EXPECT_EQ_UINT(pbsd_uniqid->pbsd.pbi_gid, CONF_GID_VAL, "PROC_PIDT_BSDINFOWITHUNIQID returns valid gid");
1103 T_EXPECT_EQ_UINT(pbsd_uniqid->pbsd.pbi_ruid, 0U, "PROC_PIDT_BSDINFOWITHUNIQID returns valid ruid");
1104 T_EXPECT_EQ_UINT(pbsd_uniqid->pbsd.pbi_rgid, CONF_GID_VAL, "PROC_PIDT_BSDINFOWITHUNIQID returns valid rgid");
1105 T_EXPECT_EQ_UINT(pbsd_uniqid->pbsd.pbi_svuid, CONF_RUID_VAL, "PROC_PIDT_BSDINFOWITHUNIQID returns valid svuid");
1106 T_EXPECT_EQ_UINT(pbsd_uniqid->pbsd.pbi_svgid, CONF_GID_VAL, "PROC_PIDT_BSDINFOWITHUNIQID returns valid svgid");
1107 T_EXPECT_EQ_UINT(pbsd_uniqid->pbsd.pbi_nice, CONF_NICE_VAL, "PROC_PIDT_BSDINFOWITHUNIQID returns valid nice value");
1108 T_EXPECT_EQ_STR(pbsd_uniqid->pbsd.pbi_comm, CONF_CMD_NAME, "PROC_PIDT_BSDINFOWITHUNIQID returns valid p_comm name");
1109 T_EXPECT_EQ_STR(pbsd_uniqid->pbsd.pbi_name, CONF_CMD_NAME, "PROC_PIDT_BSDINFOWITHUNIQID returns valid p_name name");
1110 T_EXPECT_EQ_UINT(pbsd_uniqid->pbsd.pbi_flags, (pbsd_old->pbi_flags | PROC_FLAG_PSUGID),
1111 "PROC_PIDT_BSDINFOWITHUNIQID returns valid flags");
1112 T_EXPECT_EQ_UINT(pbsd_uniqid->pbsd.pbi_nfiles, pbsd_old->pbi_nfiles, "PROC_PIDT_BSDINFOWITHUNIQID returned valid pbi_nfiles");
1113 T_EXPECT_EQ_UINT(pbsd_uniqid->pbsd.pbi_pgid, (uint32_t)getpgid(getpid()),
1114 "PROC_PIDT_BSDINFOWITHUNIQID returned valid pbi_pgid");
1115 T_EXPECT_EQ_UINT(pbsd_uniqid->pbsd.pbi_pjobc, pbsd->pbi_pjobc, "PROC_PIDT_BSDINFOWITHUNIQID returned valid pbi_pjobc");
1116 T_EXPECT_NE_UINT(pbsd_uniqid->pbsd.e_tdev, 0U, "PROC_PIDT_BSDINFOWITHUNIQID returned valid e_tdev");
1117 T_EXPECT_NE_ULLONG(pbsd_uniqid->p_uniqidentifier.p_uniqueid, p_uniqidinfo->p_uniqueid,
1118 "PROC_PIDT_BSDINFOWITHUNIQID returned valid p_uniqueid");
1119 for (int i = 0; i < 16; i++) {
1120 T_EXPECT_EQ_UCHAR(pbsd_uniqid->p_uniqidentifier.p_uuid[i], p_uniqidinfo->p_uuid[i],
1121 "PROC_PIDT_BSDINFOWITHUNIQID reported valid p_uniqueid");
1122 }
1123 T_EXPECT_EQ_ULLONG(pbsd_uniqid->p_uniqidentifier.p_puniqueid, p_uniqidinfo->p_uniqueid,
1124 "p_puniqueid of child should be same as p_uniqueid for parent");
1125
1126 free_proc_info(proc_info, 4);
1127 }
1128
1129 static void
_expect_increasing_taskinfo_times(const char * name,struct proc_taskinfo * early,struct proc_taskinfo * late)1130 _expect_increasing_taskinfo_times(const char *name, struct proc_taskinfo *early,
1131 struct proc_taskinfo *late)
1132 {
1133 if (has_user_system_times()) {
1134 T_EXPECT_GT(late->pti_total_system, early->pti_total_system,
1135 "%s returned increasing pti_total_system time", name);
1136 T_EXPECT_GT(late->pti_threads_system, early->pti_threads_system,
1137 "%s returned increasing pti_threads_system time", name);
1138 }
1139
1140 T_EXPECT_GT(late->pti_threads_user, early->pti_threads_user,
1141 "%s returned increasing pti_threads_user time", name);
1142 T_EXPECT_GT(late->pti_total_user, early->pti_total_user,
1143 "%s returned increasing pti_total_user time", name);
1144 }
1145
1146 T_DECL(proc_info_proc_pidtask_info,
1147 "Test to verify PROC_PIDTASKINFO returns valid information about the process",
1148 T_META_ASROOT(true), T_META_TAG_VM_PREFERRED)
1149 {
1150 void * proc_info[2];
1151 proc_info_caller(P_TASK_INFO | P_TASK_INFO_NEW, proc_info, NULL);
1152 struct proc_taskinfo * p_task_info = (struct proc_taskinfo *)proc_info[0];
1153 struct proc_taskinfo * p_task_info_new = (struct proc_taskinfo *)proc_info[1];
1154
1155 T_EXPECT_GE_ULLONG((p_task_info_new->pti_virtual_size - p_task_info->pti_virtual_size), (unsigned long long)PAGE_SIZE,
1156 "PROC_PIDTASKINFO returned valid value for pti_virtual_size");
1157 T_EXPECT_GE_ULLONG((p_task_info_new->pti_resident_size - p_task_info->pti_resident_size), (unsigned long long)PAGE_SIZE,
1158 "PROC_PIDTASKINFO returned valid value for pti_resident_size");
1159 T_EXPECT_EQ_INT(p_task_info_new->pti_policy, POLICY_TIMESHARE, "PROC_PIDTASKINFO returned valid value for pti_policy");
1160 _expect_increasing_taskinfo_times("PROC_PIDTASKINFO", p_task_info, p_task_info_new);
1161 T_EXPECT_GE_INT((p_task_info_new->pti_faults - p_task_info->pti_faults), 1,
1162 "PROC_PIDTASKINFO returned valid value for pti_faults");
1163 T_EXPECT_GE_INT((p_task_info_new->pti_cow_faults - p_task_info->pti_cow_faults), 1,
1164 "PROC_PIDTASKINFO returned valid value for pti_cow_faults");
1165 T_EXPECT_GE_INT((p_task_info_new->pti_syscalls_mach - p_task_info->pti_syscalls_mach), 0,
1166 "PROC_PIDTASKINFO returned valid value for pti_syscalls_mach");
1167 T_EXPECT_GE_INT((p_task_info_new->pti_syscalls_unix - p_task_info->pti_syscalls_unix), 2,
1168 "PROC_PIDTASKINFO returned valid value for pti_syscalls_unix");
1169 T_EXPECT_EQ_INT((p_task_info_new->pti_messages_sent - p_task_info->pti_messages_sent), 0,
1170 "PROC_PIDTASKINFO returned valid value for pti_messages_sent");
1171 T_EXPECT_EQ_INT((p_task_info_new->pti_messages_received - p_task_info->pti_messages_received), 0,
1172 "PROC_PIDTASKINFO returned valid value for pti_messages_received");
1173 T_EXPECT_EQ_INT(p_task_info_new->pti_priority, p_task_info->pti_priority,
1174 "PROC_PIDTASKINFO returned valid value for pti_priority");
1175 T_EXPECT_GE_INT(p_task_info_new->pti_threadnum, 1, "PROC_PIDTASKINFO returned valid value for pti_threadnum");
1176
1177 if (p_task_info_new->pti_threadnum > 1) {
1178 T_LOG("WARN: PROC_PIDTASKINFO returned threadnum greater than 1");
1179 }
1180 T_EXPECT_GE_INT(p_task_info_new->pti_numrunning, 0, "PROC_PIDTASKINFO returned valid value for pti_numrunning");
1181 T_EXPECT_GE_INT(p_task_info_new->pti_pageins, 0, "PROC_PIDTASKINFO returned valid value for pti_pageins");
1182
1183 if (p_task_info_new->pti_pageins > 0) {
1184 T_LOG("WARN: PROC_PIDTASKINFO returned pageins greater than 0");
1185 }
1186
1187 T_EXPECT_GE_INT(p_task_info_new->pti_csw, p_task_info->pti_csw, "PROC_PIDTASKINFO returned valid value for pti_csw");
1188
1189 free_proc_info(proc_info, 2);
1190 }
1191
1192 T_DECL(proc_info_proc_pidtaskallinfo,
1193 "Test to verify PROC_PIDTASKALLINFO returns valid information about the process",
1194 T_META_ASROOT(true),
1195 T_META_TAG_VM_PREFERRED,
1196 T_META_ENABLED(false) /* rdar://134505671 */)
1197 {
1198 void * proc_info[4];
1199 int child_pid = 0;
1200 proc_info_caller(PBSD | PBSD_OLD | P_TASK_INFO | PALL, proc_info, &child_pid);
1201 struct proc_bsdinfo * pbsd = (struct proc_bsdinfo *)proc_info[0];
1202 struct proc_bsdinfo * pbsd_old = (struct proc_bsdinfo *)proc_info[1];
1203 struct proc_taskinfo * p_task_info = (struct proc_taskinfo *)proc_info[2];
1204 struct proc_taskallinfo * pall = (struct proc_taskallinfo *)proc_info[3];
1205
1206 T_EXPECT_EQ_UINT((unsigned int)SRUN, pbsd->pbi_status, "PROC_PIDTASKALLINFO shows Correct status");
1207 T_EXPECT_EQ_UINT(0U, pbsd->pbi_xstatus, "PROC_PIDTASKALLINFO show Correct xstatus");
1208 T_EXPECT_EQ_UINT(pall->pbsd.pbi_pid, (unsigned int)child_pid, "PROC_PIDTASKALLINFO returns valid pid");
1209 T_EXPECT_EQ_UINT(pall->pbsd.pbi_ppid, (unsigned int)getpid(), "PROC_PIDTASKALLINFO returns valid ppid");
1210 T_EXPECT_EQ_UINT(pall->pbsd.pbi_uid, CONF_RUID_VAL, "PROC_PIDTASKALLINFO returns valid uid");
1211 T_EXPECT_EQ_UINT(pall->pbsd.pbi_gid, CONF_GID_VAL, "PROC_PIDTASKALLINFO returns valid gid");
1212 T_EXPECT_EQ_UINT(pall->pbsd.pbi_ruid, 0U, "PROC_PIDTASKALLINFO returns valid ruid");
1213 T_EXPECT_EQ_UINT(pall->pbsd.pbi_rgid, CONF_GID_VAL, "PROC_PIDTASKALLINFO returns valid rgid");
1214 T_EXPECT_EQ_UINT(pall->pbsd.pbi_svuid, CONF_RUID_VAL, "PROC_PIDTASKALLINFO returns valid svuid");
1215 T_EXPECT_EQ_UINT(pall->pbsd.pbi_svgid, CONF_GID_VAL, "PROC_PIDTASKALLINFO returns valid svgid");
1216 T_EXPECT_EQ_INT(pall->pbsd.pbi_nice, CONF_NICE_VAL, "PROC_PIDTASKALLINFO returns valid nice value");
1217 T_EXPECT_EQ_STR(pall->pbsd.pbi_comm, CONF_CMD_NAME, "PROC_PIDTASKALLINFO returns valid p_comm name");
1218 T_EXPECT_EQ_STR(pall->pbsd.pbi_name, CONF_CMD_NAME, "PROC_PIDTASKALLINFO returns valid p_name name");
1219 T_EXPECT_EQ_UINT(pall->pbsd.pbi_flags, (pbsd_old->pbi_flags | PROC_FLAG_PSUGID), "PROC_PIDTASKALLINFO returns valid flags");
1220 T_EXPECT_EQ_UINT(pall->pbsd.pbi_nfiles, pbsd_old->pbi_nfiles, "PROC_PIDTASKALLINFO returned valid pbi_nfiles");
1221 T_EXPECT_EQ_UINT(pall->pbsd.pbi_pgid, (uint32_t)getpgid(getpid()), "PROC_PIDTASKALLINFO returned valid pbi_pgid");
1222 T_EXPECT_EQ_UINT(pall->pbsd.pbi_pjobc, pbsd->pbi_pjobc, "PROC_PIDTASKALLINFO returned valid pbi_pjobc");
1223 T_EXPECT_NE_UINT(pall->pbsd.e_tdev, 0U, "PROC_PIDTASKALLINFO returned valid e_tdev");
1224
1225 T_EXPECT_GE_ULLONG((pall->ptinfo.pti_virtual_size - p_task_info->pti_virtual_size), (unsigned long long)PAGE_SIZE,
1226 "PROC_PIDTASKALLINFO returned valid value for pti_virtual_size");
1227 T_EXPECT_GE_ULLONG((pall->ptinfo.pti_resident_size - p_task_info->pti_resident_size), (unsigned long long)PAGE_SIZE,
1228 "PROC_PIDTASKALLINFO returned valid value for pti_resident_size");
1229 T_EXPECT_EQ_INT(pall->ptinfo.pti_policy, POLICY_TIMESHARE, "PROC_PIDTASKALLINFO returned valid value for pti_policy");
1230 _expect_increasing_taskinfo_times("PROC_PIDTASKALLLINFO", p_task_info, &pall->ptinfo);
1231 T_EXPECT_GE_INT((pall->ptinfo.pti_faults - p_task_info->pti_faults), 1,
1232 "PROC_PIDTASKALLINFO returned valid value for pti_faults");
1233 T_EXPECT_GE_INT((pall->ptinfo.pti_cow_faults - p_task_info->pti_cow_faults), 1,
1234 "PROC_PIDTASKALLINFO returned valid value for pti_cow_faults");
1235 T_EXPECT_GE_INT((pall->ptinfo.pti_syscalls_mach - p_task_info->pti_syscalls_mach), 0,
1236 "PROC_PIDTASKALLINFO returned valid value for pti_syscalls_mach");
1237 T_EXPECT_GE_INT((pall->ptinfo.pti_syscalls_unix - p_task_info->pti_syscalls_unix), 2,
1238 "PROC_PIDTASKALLINFO returned valid value for pti_syscalls_unix");
1239 T_EXPECT_EQ_INT((pall->ptinfo.pti_messages_sent - p_task_info->pti_messages_sent), 0,
1240 "PROC_PIDTASKALLINFO returned valid value for pti_messages_sent");
1241 T_EXPECT_EQ_INT((pall->ptinfo.pti_messages_received - p_task_info->pti_messages_received), 0,
1242 "PROC_PIDTASKALLINFO returned valid value for pti_messages_received");
1243 T_EXPECT_EQ_INT(pall->ptinfo.pti_priority, p_task_info->pti_priority,
1244 "PROC_PIDTASKALLINFO returned valid value for pti_priority");
1245 T_EXPECT_GE_INT(pall->ptinfo.pti_threadnum, 1, "PROC_PIDTASKALLINFO returned valid value for pti_threadnum");
1246 if (pall->ptinfo.pti_threadnum > 1) {
1247 T_LOG("WARN: PROC_PIDTASKALLINFO returned threadnum greater than 1");
1248 }
1249 T_EXPECT_GE_INT(pall->ptinfo.pti_numrunning, 0, "PROC_PIDTASKALLINFO returned valid value for pti_numrunning");
1250 T_EXPECT_GE_INT(pall->ptinfo.pti_pageins, 0, "PROC_PIDTASKALLINFO returned valid value for pti_pageins");
1251 if (pall->ptinfo.pti_pageins > 0) {
1252 T_LOG("WARN: PROC_PIDTASKALLINFO returned pageins greater than 0");
1253 }
1254 T_EXPECT_GE_INT(pall->ptinfo.pti_csw, p_task_info->pti_csw, "PROC_PIDTASKALLINFO returned valid value for pti_csw");
1255
1256 free_proc_info(proc_info, 4);
1257 }
1258
1259 T_DECL(proc_info_proc_pidlistthreads,
1260 "Test to verify PROC_PIDLISTTHREADS returns valid information about process",
1261 T_META_ASROOT(true), T_META_TAG_VM_PREFERRED)
1262 {
1263 void * proc_info[1];
1264 proc_info_caller(THREAD_ADDR, proc_info, NULL);
1265 }
1266
1267 T_DECL(proc_info_proc_pidthreadinfo,
1268 "Test to verify PROC_PIDTHREADINFO returns valid information about the process",
1269 T_META_ASROOT(true),
1270 T_META_TAG_VM_PREFERRED,
1271 T_META_ENABLED(false) /* rdar://134505671 */)
1272 {
1273 void * proc_info[2];
1274 int child_pid = 0;
1275 proc_info_caller(PTHINFO_OLD | PTHINFO, proc_info, &child_pid);
1276 struct proc_threadinfo * pthinfo_old = (struct proc_threadinfo *)proc_info[0];
1277 struct proc_threadinfo * pthinfo = (struct proc_threadinfo *)proc_info[1];
1278
1279 T_EXPECT_GT_ULLONG((pthinfo->pth_user_time - pthinfo_old->pth_user_time), 0ULL,
1280 "PROC_PIDTHREADINFO returns valid value for pth_user_time");
1281 T_EXPECT_GE_ULLONG((pthinfo->pth_system_time - pthinfo_old->pth_system_time), 0ULL,
1282 "PROC_PIDTHREADINFO returns valid value for pth_system_time");
1283 /*
1284 * This is the scaled cpu usage percentage, since we are not
1285 * doing a really long CPU bound task, it is (nearly) zero
1286 */
1287 T_EXPECT_GE_INT(pthinfo->pth_cpu_usage, 0, "PROC_PIDTHREADINFO returns valid value for pth_cpu_usage");
1288 T_EXPECT_EQ_INT(pthinfo->pth_policy, POLICY_TIMESHARE, "PROC_PIDTHREADINFO returns valid value for pth_policy");
1289 if (!(pthinfo->pth_run_state == TH_STATE_WAITING) && !(pthinfo->pth_run_state == TH_STATE_RUNNING)) {
1290 T_EXPECT_EQ_INT(pthinfo->pth_run_state, -1, "PROC_PIDTHREADINFO returns valid value for pth_run_state");
1291 }
1292 /*
1293 * This value is hardcoded to 0 in the source, hence it will always
1294 * unconditionally return 0
1295 */
1296 T_EXPECT_EQ_INT(pthinfo->pth_sleep_time, 0, "PROC_PIDTHREADINFO returns valid value for pth_sleep_time");
1297 T_EXPECT_LE_INT(pthinfo->pth_curpri, (BASEPRI_DEFAULT - CONF_NICE_VAL),
1298 "PROC_PIDTHREADINFO returns valid value for pth_curpri");
1299 T_EXPECT_EQ_INT(pthinfo->pth_priority, (BASEPRI_DEFAULT - CONF_NICE_VAL),
1300 "PROC_PIDTHREADINFO returns valid value for pth_priority");
1301 T_EXPECT_EQ_INT(pthinfo->pth_maxpriority, MAXPRI_USER, "PROC_PIDTHREADINFO returns valid value for pth_maxpriority");
1302 T_EXPECT_EQ_STR(pthinfo->pth_name, CONF_THREAD_NAME, "PROC_PIDTHREADINFO returns valid value for pth_name");
1303
1304 free_proc_info(proc_info, 2);
1305 }
1306
1307 T_DECL(proc_info_proc_threadid64info,
1308 "Test to verify PROC_PIDTHREADID64INFO returns valid information about the process",
1309 T_META_ASROOT(true), T_META_TAG_VM_PREFERRED)
1310 {
1311 void * proc_info[2];
1312 proc_info_caller(PTHINFO | PTHINFO_64, proc_info, NULL);
1313 struct proc_threadinfo pthinfo = *((struct proc_threadinfo *)proc_info[0]);
1314 struct proc_threadinfo pthinfo_64 = *((struct proc_threadinfo *)proc_info[1]);
1315 T_EXPECT_GE_ULLONG(pthinfo_64.pth_user_time, pthinfo.pth_user_time,
1316 "PROC_PIDTHREADID64INFO returns valid value for pth_user_time");
1317 T_EXPECT_GE_ULLONG(pthinfo_64.pth_system_time, pthinfo.pth_system_time,
1318 "PROC_PIDTHREADID64INFO returns valid value for pth_system_time");
1319 T_EXPECT_GE_INT(pthinfo_64.pth_cpu_usage, pthinfo.pth_cpu_usage,
1320 "PROC_PIDTHREADID64INFO returns valid value for pth_cpu_usage");
1321 T_EXPECT_EQ_INT(pthinfo_64.pth_policy, POLICY_TIMESHARE, "PROC_PIDTHREADID64INFO returns valid value for pth_policy");
1322 if (!(pthinfo_64.pth_run_state == TH_STATE_WAITING) && !(pthinfo_64.pth_run_state == TH_STATE_RUNNING)) {
1323 T_EXPECT_EQ_INT(pthinfo_64.pth_run_state, -1, "PROC_PIDTHREADID64INFO returns valid value for pth_run_state");
1324 }
1325 T_EXPECT_EQ_INT(pthinfo_64.pth_sleep_time, 0, "PROC_PIDTHREADID64INFO returns valid value for pth_sleep_time");
1326 T_EXPECT_EQ_INT(pthinfo_64.pth_curpri, pthinfo.pth_curpri, "PROC_PIDTHREADID64INFO returns valid value for pth_curpri");
1327 T_EXPECT_EQ_INT(pthinfo_64.pth_priority, pthinfo.pth_priority, "PROC_PIDTHREADID64INFO returns valid value for pth_priority");
1328 T_EXPECT_EQ_INT(pthinfo_64.pth_maxpriority, pthinfo.pth_maxpriority,
1329 "PROC_PIDTHREADID64INFO returns valid value for pth_maxpriority");
1330 T_EXPECT_EQ_STR(pthinfo_64.pth_name, CONF_THREAD_NAME, "PROC_PIDTHREADID64INFO returns valid value for pth_name");
1331
1332 free_proc_info(proc_info, 2);
1333 }
1334
1335 T_DECL(proc_info_proc_pidthreadpathinfo,
1336 "Test to verify PROC_PIDTHREADPATHINFO returns valid information about the process",
1337 T_META_ASROOT(true), T_META_TAG_VM_PREFERRED)
1338 {
1339 void * proc_info[2];
1340 proc_info_caller(PTHINFO | PINFO_PATH, proc_info, NULL);
1341 struct proc_threadinfo pthinfo = *((struct proc_threadinfo *)proc_info[0]);
1342 struct proc_threadwithpathinfo pinfo_path = *((struct proc_threadwithpathinfo *)proc_info[1]);
1343
1344 T_EXPECT_GE_ULLONG(pinfo_path.pt.pth_user_time, pthinfo.pth_user_time,
1345 "PROC_PIDTHREADPATHINFO returns valid value for pth_user_time");
1346 T_EXPECT_GE_ULLONG(pinfo_path.pt.pth_system_time, pthinfo.pth_system_time,
1347 "PROC_PIDTHREADPATHINFO returns valid value for pth_system_time");
1348 T_EXPECT_GE_INT(pinfo_path.pt.pth_cpu_usage, pthinfo.pth_cpu_usage,
1349 "PROC_PIDTHREADPATHINFO returns valid value for pth_cpu_usage");
1350 T_EXPECT_EQ_INT(pinfo_path.pt.pth_policy, POLICY_TIMESHARE, "PROC_PIDTHREADPATHINFO returns valid value for pth_policy");
1351 if (!(pinfo_path.pt.pth_run_state == TH_STATE_WAITING) && !(pinfo_path.pt.pth_run_state == TH_STATE_RUNNING)) {
1352 T_EXPECT_EQ_INT(pinfo_path.pt.pth_run_state, -1, "PROC_PIDTHREADPATHINFO returns valid value for pth_run_state");
1353 }
1354 T_EXPECT_EQ_INT(pinfo_path.pt.pth_sleep_time, 0, "PROC_PIDTHREADPATHINFO returns valid value for pth_sleep_time");
1355 T_EXPECT_EQ_INT(pinfo_path.pt.pth_curpri, pthinfo.pth_curpri, "PROC_PIDTHREADPATHINFO returns valid value for pth_curpri");
1356 T_EXPECT_EQ_INT(pinfo_path.pt.pth_priority, pthinfo.pth_priority,
1357 "PROC_PIDTHREADPATHINFO returns valid value for pth_priority");
1358 T_EXPECT_EQ_INT(pinfo_path.pt.pth_maxpriority, pthinfo.pth_maxpriority,
1359 "PROC_PIDTHREADPATHINFO returns valid value for pth_maxpriority");
1360 T_EXPECT_EQ_STR(pinfo_path.pt.pth_name, CONF_THREAD_NAME, "PROC_PIDTHREADPATHINFO returns valid value for pth_name");
1361 T_EXPECT_EQ_INT(pinfo_path.pvip.vip_vi.vi_type, VNON, "PROC_PIDTHREADPATHINFO valid vnode information");
1362
1363 free_proc_info(proc_info, 2);
1364 }
1365
1366 T_DECL(proc_info_proc_pidarchinfo,
1367 "Test to verify PROC_PIDARCHINFO returns valid information about the process",
1368 T_META_ASROOT(true), T_META_TAG_VM_PREFERRED)
1369 {
1370 void * proc_info[1];
1371 proc_info_caller(PAI, proc_info, NULL);
1372 struct proc_archinfo pai = *((struct proc_archinfo *)proc_info[0]);
1373
1374 #if defined(__arm64__)
1375 if (!((pai.p_cputype & CPU_TYPE_ARM) == CPU_TYPE_ARM) && !((pai.p_cputype & CPU_TYPE_ARM64) == CPU_TYPE_ARM64)) {
1376 T_EXPECT_EQ_INT(pai.p_cputype, CPU_TYPE_ARM, "PROC_PIDARCHINFO returned valid value for p_cputype");
1377 }
1378 T_EXPECT_EQ_INT((pai.p_cpusubtype & CPU_SUBTYPE_ARM_ALL), CPU_SUBTYPE_ARM_ALL,
1379 "PROC_PIDARCHINFO returned valid value for p_cpusubtype");
1380 #else
1381 if (!((pai.p_cputype & CPU_TYPE_X86) == CPU_TYPE_X86) && !((pai.p_cputype & CPU_TYPE_X86_64) == CPU_TYPE_X86_64)) {
1382 T_EXPECT_EQ_INT(pai.p_cputype, CPU_TYPE_X86, "PROC_PIDARCHINFO returned valid value for p_cputype");
1383 }
1384 #endif
1385 free_proc_info(proc_info, 1);
1386 }
1387
1388 T_DECL(proc_info_proc_pidregioninfo,
1389 "Test to verify PROC_PIDREGIONINFO returns valid information about the process",
1390 T_META_ASROOT(true), T_META_TAG_VM_PREFERRED)
1391 {
1392 void * proc_info[3];
1393 proc_info_caller(PREGINFO, proc_info, NULL);
1394
1395 struct proc_regioninfo preginfo = *((struct proc_regioninfo *)proc_info[0]);
1396 /*
1397 * map_tmp isn't a struct like the rest of our ret_structs, but we sneak it back because we need it
1398 */
1399 void *map_tmp = proc_info[1];
1400 vm_map_size_t map_tmp_sz = (vm_map_size_t)(uintptr_t)proc_info[2];
1401
1402 T_EXPECT_EQ_ULLONG(preginfo.pri_offset, (unsigned long long)PAGE_SIZE, "PROC_PIDREGIONINFO returns valid value for pri_offset");
1403 T_EXPECT_EQ_UINT((preginfo.pri_protection ^ (VM_PROT_READ | VM_PROT_WRITE)), 0U,
1404 "PROC_PIDREGIONINFO returns valid value for pri_protection, expected read/write only");
1405 T_EXPECT_EQ_UINT((preginfo.pri_max_protection & (VM_PROT_READ | VM_PROT_WRITE)), (unsigned int)(VM_PROT_READ | VM_PROT_WRITE),
1406 "PROC_PIDREGIONINFO returns valid value for pri_max_protection");
1407 T_EXPECT_EQ_UINT((preginfo.pri_inheritance ^ VM_INHERIT_COPY), 0U,
1408 "PROC_PIDREGIONINFO returns valid value for pri_inheritance");
1409 T_EXPECT_EQ_UINT((preginfo.pri_behavior ^ VM_BEHAVIOR_DEFAULT), 0U, "PROC_PIDREGIONINFO returns valid value for pri_behavior");
1410 T_EXPECT_EQ_UINT(preginfo.pri_user_wired_count, 0U, "PROC_PIDREGIONINFO returns valid value for pri_user_wired_count");
1411 T_EXPECT_EQ_UINT(preginfo.pri_user_tag, 0U, "PROC_PIDREGIONINFO returns valid value for pri_user_tag");
1412 T_EXPECT_NE_UINT((preginfo.pri_flags ^ (PROC_REGION_SUBMAP | PROC_REGION_SHARED)), 0U,
1413 "PROC_PIDREGIONINFO returns valid value for pri_flags");
1414 T_EXPECT_EQ_UINT(preginfo.pri_pages_resident, 0U, "PROC_PIDREGIONINFO returns valid value for pri_pages_resident");
1415 T_EXPECT_EQ_UINT(preginfo.pri_pages_shared_now_private, 0U,
1416 "PROC_PIDREGIONINFO returns valid value for pri_pages_shared_now_private");
1417 T_EXPECT_EQ_UINT(preginfo.pri_pages_swapped_out, 0U, "PROC_PIDREGIONINFO returns valid value for pri_pages_swapped_out");
1418 T_EXPECT_EQ_UINT(preginfo.pri_pages_dirtied, 0U, "PROC_PIDREGIONINFO returns valid value for pri_pages_dirtied");
1419 T_EXPECT_EQ_UINT(preginfo.pri_ref_count, 2U, "PROC_PIDREGIONINFO returns valid value for pri_ref_count");
1420 T_EXPECT_EQ_UINT(preginfo.pri_shadow_depth, 1U, "PROC_PIDREGIONINFO returns valid value for pri_shadow_depth");
1421 T_EXPECT_EQ_UINT(preginfo.pri_share_mode, (unsigned int)SM_COW, "PROC_PIDREGIONINFO returns valid value for pri_share_mode");
1422 T_EXPECT_EQ_UINT(preginfo.pri_private_pages_resident, 0U,
1423 "PROC_PIDREGIONINFO returns valid value for pri_private_pages_resident");
1424 T_EXPECT_GE_UINT(preginfo.pri_shared_pages_resident, 0U,
1425 "PROC_PIDREGIONINFO returns valid value for pri_shared_pages_resident");
1426 T_EXPECT_EQ_ULLONG(preginfo.pri_address, (uint64_t)map_tmp, "PROC_PIDREGIONINFO returns valid value for pri_addr");
1427 T_EXPECT_NE_UINT(preginfo.pri_obj_id, 0U, "PROC_PIDREGIONINFO returns valid value for pri_obj_id");
1428 T_EXPECT_EQ_ULLONG(preginfo.pri_size, (unsigned long long)map_tmp_sz, "PROC_PIDREGIONINFO returns valid value for pri_size");
1429 T_EXPECT_EQ_UINT(preginfo.pri_depth, 0U, "PROC_PIDREGIONINFO returns valid value for pri_depth");
1430
1431 int ret = 0;
1432 ret = munmap(map_tmp, (size_t)map_tmp_sz);
1433 T_QUIET;
1434 T_EXPECT_POSIX_SUCCESS(ret, "munmap of map_tmp");
1435 free_proc_info(proc_info, 1);
1436 }
1437
1438 T_DECL(proc_info_proc_pidregionpathinfo,
1439 "Test to verify PROC_PIDREGIONPATHINFO returns valid information about the process",
1440 T_META_ASROOT(true), T_META_TAG_VM_PREFERRED)
1441 {
1442 void * proc_info[3];
1443 proc_info_caller(PREGINFO_PATH, proc_info, NULL);
1444
1445 struct proc_regionwithpathinfo preginfo_path = *((struct proc_regionwithpathinfo *)proc_info[0]);
1446 /*
1447 * map_tmp isn't a struct like the rest of our ret_structs, but we sneak it back because we need it
1448 */
1449 void *map_tmp = proc_info[1];
1450 vm_map_size_t map_tmp_sz = (vm_map_size_t)(uintptr_t)proc_info[2];
1451
1452 T_EXPECT_EQ_ULLONG(preginfo_path.prp_prinfo.pri_offset, (uint64_t)PAGE_SIZE,
1453 "PROC_PIDREGIONPATHINFO returns valid value for pri_offset");
1454 T_EXPECT_EQ_UINT((preginfo_path.prp_prinfo.pri_protection ^ (VM_PROT_READ | VM_PROT_WRITE)), 0U,
1455 "PROC_PIDREGIONPATHINFO returns valid value for pri_protection, expected read/write only");
1456 T_EXPECT_EQ_UINT((preginfo_path.prp_prinfo.pri_max_protection & (VM_PROT_READ | VM_PROT_WRITE)),
1457 (unsigned int)(VM_PROT_READ | VM_PROT_WRITE),
1458 "PROC_PIDREGIONPATHINFO returns valid value for pri_max_protection");
1459 T_EXPECT_EQ_UINT((preginfo_path.prp_prinfo.pri_inheritance ^ VM_INHERIT_COPY), 0U,
1460 "PROC_PIDREGIONPATHINFO returns valid value for pri_inheritance");
1461 T_EXPECT_EQ_UINT((preginfo_path.prp_prinfo.pri_behavior ^ VM_BEHAVIOR_DEFAULT), 0U,
1462 "PROC_PIDREGIONPATHINFO returns valid value for pri_behavior");
1463 T_EXPECT_EQ_UINT(preginfo_path.prp_prinfo.pri_user_wired_count, 0U,
1464 "PROC_PIDREGIONPATHINFO returns valid value for pri_user_wired_count");
1465 T_EXPECT_EQ_UINT(preginfo_path.prp_prinfo.pri_user_tag, 0U, "PROC_PIDREGIONPATHINFO returns valid value for pri_user_tag");
1466 T_EXPECT_NE_UINT((preginfo_path.prp_prinfo.pri_flags ^ (PROC_REGION_SUBMAP | PROC_REGION_SHARED)), 0U,
1467 "PROC_PIDREGIONPATHINFO returns valid value for pri_flags");
1468 T_EXPECT_EQ_UINT(preginfo_path.prp_prinfo.pri_pages_resident, 0U,
1469 "PROC_PIDREGIONPATHINFO returns valid value for pri_pages_resident");
1470 T_EXPECT_EQ_UINT(preginfo_path.prp_prinfo.pri_pages_shared_now_private, 0U,
1471 "PROC_PIDREGIONPATHINFO returns valid value for pri_pages_shared_now_private");
1472 T_EXPECT_EQ_UINT(preginfo_path.prp_prinfo.pri_pages_swapped_out, 0U,
1473 "PROC_PIDREGIONPATHINFO returns valid value for pri_pages_swapped_out");
1474 T_EXPECT_EQ_UINT(preginfo_path.prp_prinfo.pri_pages_dirtied, 0U,
1475 "PROC_PIDREGIONPATHINFO returns valid value for pri_pages_dirtied");
1476 T_EXPECT_EQ_UINT(preginfo_path.prp_prinfo.pri_ref_count, 2U, "PROC_PIDREGIONPATHINFO returns valid value for pri_ref_count");
1477 T_EXPECT_EQ_UINT(preginfo_path.prp_prinfo.pri_shadow_depth, 1U,
1478 "PROC_PIDREGIONPATHINFO returns valid value for pri_shadow_depth");
1479 T_EXPECT_EQ_UINT(preginfo_path.prp_prinfo.pri_share_mode, (unsigned int)SM_COW,
1480 "PROC_PIDREGIONPATHINFO returns valid value for pri_share_mode");
1481 T_EXPECT_EQ_UINT(preginfo_path.prp_prinfo.pri_private_pages_resident, 0U,
1482 "PROC_PIDREGIONPATHINFO returns valid value for pri_private_pages_resident");
1483 T_EXPECT_GE_UINT(preginfo_path.prp_prinfo.pri_shared_pages_resident, 0U,
1484 "PROC_PIDREGIONPATHINFO returns valid value for pri_shared_pages_resident");
1485 T_EXPECT_EQ_ULLONG(preginfo_path.prp_prinfo.pri_address, (uint64_t)map_tmp,
1486 "PROC_PIDREGIONPATHINFO returns valid value for pri_addr");
1487 T_EXPECT_NE_UINT(preginfo_path.prp_prinfo.pri_obj_id, 0U, "PROC_PIDREGIONPATHINFO returns valid value for pri_obj_id");
1488 T_EXPECT_EQ_ULLONG(preginfo_path.prp_prinfo.pri_size, (uint64_t)map_tmp_sz,
1489 "PROC_PIDREGIONPATHINFO returns valid value for pri_size");
1490 T_EXPECT_EQ_UINT(preginfo_path.prp_prinfo.pri_depth, 0U, "PROC_PIDREGIONPATHINFO returns valid value for pri_depth");
1491 T_EXPECT_EQ_INT(preginfo_path.prp_vip.vip_vi.vi_type, VREG, "PROC_PIDREGIONPATHINFO returns valid value for vi_type");
1492 T_EXPECT_EQ_INT(preginfo_path.prp_vip.vip_vi.vi_pad, 0, "PROC_PIDREGIONPATHINFO returns valid value for vi_pad");
1493 T_EXPECT_NE_INT(preginfo_path.prp_vip.vip_vi.vi_fsid.val[0], 0,
1494 "PROC_PIDREGIONPATHINFO returns valid value for vi_fsid.val[0]");
1495 T_EXPECT_NE_INT(preginfo_path.prp_vip.vip_vi.vi_fsid.val[1], 0,
1496 "PROC_PIDREGIONPATHINFO returns valid value for vi_fsid.val[1]");
1497 T_EXPECT_NE_PTR((void *)(strcasestr(preginfo_path.prp_vip.vip_path, CONF_TMP_FILE_PFX)), NULL,
1498 "PROC_PIDREGIONPATHINFO returns valid value for vi_path");
1499 /*
1500 * Basic sanity checks for vnode stat returned by the API
1501 */
1502 T_EXPECT_NE_UINT(preginfo_path.prp_vip.vip_vi.vi_stat.vst_dev, 0U, "PROC_PIDREGIONPATHINFO returns valid value for vst_dev");
1503 T_EXPECT_EQ_INT(((preginfo_path.prp_vip.vip_vi.vi_stat.vst_mode & S_IFMT) ^ S_IFREG), 0,
1504 "PROC_PIDREGIONPATHINFO returns valid value for vst_mode");
1505 T_EXPECT_EQ_USHORT(preginfo_path.prp_vip.vip_vi.vi_stat.vst_nlink, (unsigned short)0, /* the file was unlink()'d! */
1506 "PROC_PIDREGIONPATHINFO returns valid value for vst_nlink");
1507 T_EXPECT_NE_ULLONG(preginfo_path.prp_vip.vip_vi.vi_stat.vst_ino, 0ULL,
1508 "PROC_PIDREGIONPATHINFO returns valid value for vst_ino");
1509 T_EXPECT_EQ_UINT(preginfo_path.prp_vip.vip_vi.vi_stat.vst_uid, 0U, "PROC_PIDREGIONPATHINFO returns valid value for vst_uid");
1510 T_EXPECT_EQ_UINT(preginfo_path.prp_vip.vip_vi.vi_stat.vst_gid, 0U, "PROC_PIDREGIONPATHINFO returns valid value for vst_gid");
1511 T_EXPECT_GE_LLONG(preginfo_path.prp_vip.vip_vi.vi_stat.vst_size, (off_t)CONF_BLK_SIZE,
1512 "PROC_PIDREGIONPATHINFO returns valid value for vst_size");
1513 T_EXPECT_GE_LLONG(preginfo_path.prp_vip.vip_vi.vi_stat.vst_blocks, 1LL,
1514 "PROC_PIDREGIONPATHINFO returns valid value for vst_blocks");
1515 T_EXPECT_GE_INT(preginfo_path.prp_vip.vip_vi.vi_stat.vst_blksize, CONF_BLK_SIZE,
1516 "PROC_PIDREGIONPATHINFO returns valid value for vst_blksize");
1517
1518 int ret = 0;
1519 ret = munmap(map_tmp, (size_t)map_tmp_sz);
1520 T_QUIET;
1521 T_EXPECT_POSIX_SUCCESS(ret, "munmap of map_tmp");
1522 free_proc_info(proc_info, 1);
1523 }
1524
1525 T_DECL(proc_info_proc_pidregionpathinfo2,
1526 "Test to verify PROC_PIDREGIONPATHINFO2 returns valid information about the process",
1527 T_META_ASROOT(true), T_META_TAG_VM_PREFERRED)
1528 {
1529 void * proc_info[3];
1530 proc_info_caller(PREGINFO_PATH_2, proc_info, NULL);
1531
1532 struct proc_regionwithpathinfo preginfo_path = *((struct proc_regionwithpathinfo *)proc_info[0]);
1533 /*
1534 * map_tmp isn't a struct like the rest of our ret_structs, but we sneak it back because we need it
1535 */
1536 void *map_tmp = proc_info[1];
1537 vm_map_size_t map_tmp_sz = (vm_map_size_t)(uintptr_t)proc_info[2];
1538
1539 T_EXPECT_EQ_ULLONG(preginfo_path.prp_prinfo.pri_offset, (uint64_t)PAGE_SIZE,
1540 "PROC_PIDREGIONPATHINFO2 returns valid value for pri_offset");
1541 T_EXPECT_EQ_UINT((preginfo_path.prp_prinfo.pri_protection ^ (VM_PROT_READ | VM_PROT_WRITE)), 0U,
1542 "PROC_PIDREGIONPATHINFO2 returns valid value for pri_protection, expected read/write only");
1543 T_EXPECT_EQ_UINT((preginfo_path.prp_prinfo.pri_max_protection & (VM_PROT_READ | VM_PROT_WRITE)),
1544 (unsigned int)(VM_PROT_READ | VM_PROT_WRITE),
1545 "PROC_PIDREGIONPATHINFO2 returns valid value for pri_max_protection");
1546 T_EXPECT_EQ_UINT((preginfo_path.prp_prinfo.pri_inheritance ^ VM_INHERIT_COPY), 0U,
1547 "PROC_PIDREGIONPATHINFO2 returns valid value for pri_inheritance");
1548 T_EXPECT_EQ_UINT((preginfo_path.prp_prinfo.pri_behavior ^ VM_BEHAVIOR_DEFAULT), 0U,
1549 "PROC_PIDREGIONPATHINFO2 returns valid value for pri_behavior");
1550 T_EXPECT_EQ_UINT(preginfo_path.prp_prinfo.pri_user_wired_count, 0U,
1551 "PROC_PIDREGIONPATHINFO2 returns valid value for pri_user_wired_count");
1552 T_EXPECT_EQ_UINT(preginfo_path.prp_prinfo.pri_user_tag, 0U, "PROC_PIDREGIONPATHINFO2 returns valid value for pri_user_tag");
1553 T_EXPECT_NE_UINT((preginfo_path.prp_prinfo.pri_flags ^ (PROC_REGION_SUBMAP | PROC_REGION_SHARED)), 0U,
1554 "PROC_PIDREGIONPATHINFO2 returns valid value for pri_flags");
1555 /*
1556 * Following values are hard-coded to be zero in source
1557 */
1558 T_EXPECT_EQ_UINT(preginfo_path.prp_prinfo.pri_pages_resident, 0U,
1559 "PROC_PIDREGIONPATHINFO2 returns valid value for pri_pages_resident");
1560 T_EXPECT_EQ_UINT(preginfo_path.prp_prinfo.pri_pages_shared_now_private, 0U,
1561 "PROC_PIDREGIONPATHINFO2 returns valid value for pri_pages_shared_now_private");
1562 T_EXPECT_EQ_UINT(preginfo_path.prp_prinfo.pri_pages_swapped_out, 0U,
1563 "PROC_PIDREGIONPATHINFO2 returns valid value for pri_pages_swapped_out");
1564 T_EXPECT_EQ_UINT(preginfo_path.prp_prinfo.pri_pages_dirtied, 0U,
1565 "PROC_PIDREGIONPATHINFO2 returns valid value for pri_pages_dirtied");
1566 T_EXPECT_EQ_UINT(preginfo_path.prp_prinfo.pri_ref_count, 0U, "PROC_PIDREGIONPATHINFO2 returns valid value for pri_ref_count");
1567 T_EXPECT_EQ_UINT(preginfo_path.prp_prinfo.pri_shadow_depth, 0U,
1568 "PROC_PIDREGIONPATHINFO2 returns valid value for pri_shadow_depth");
1569 T_EXPECT_EQ_UINT(preginfo_path.prp_prinfo.pri_share_mode, 0U, "PROC_PIDREGIONPATHINFO2 returns valid value for pri_share_mode");
1570 T_EXPECT_EQ_UINT(preginfo_path.prp_prinfo.pri_private_pages_resident, 0U,
1571 "PROC_PIDREGIONPATHINFO2 returns valid value for pri_private_pages_resident");
1572 T_EXPECT_EQ_UINT(preginfo_path.prp_prinfo.pri_shared_pages_resident, 0U,
1573 "PROC_PIDREGIONPATHINFO2 returns valid value for pri_shared_pages_resident");
1574 T_EXPECT_EQ_ULLONG(preginfo_path.prp_prinfo.pri_address, (uint64_t)map_tmp,
1575 "PROC_PIDREGIONPATHINFO2 returns valid value for pri_addr");
1576 T_EXPECT_EQ_UINT(preginfo_path.prp_prinfo.pri_obj_id, 0U, "PROC_PIDREGIONPATHINFO2 returns valid value for pri_obj_id");
1577 T_EXPECT_EQ_ULLONG(preginfo_path.prp_prinfo.pri_size, (unsigned long long)map_tmp_sz,
1578 "PROC_PIDREGIONPATHINFO2 returns valid value for pri_size");
1579 T_EXPECT_EQ_UINT(preginfo_path.prp_prinfo.pri_depth, 0U, "PROC_PIDREGIONPATHINFO2 returns valid value for pri_depth");
1580
1581 T_EXPECT_EQ_INT(preginfo_path.prp_vip.vip_vi.vi_type, VREG, "PROC_PIDREGIONPATHINFO2 returns valid value for vi_type");
1582 T_EXPECT_EQ_INT(preginfo_path.prp_vip.vip_vi.vi_pad, 0, "PROC_PIDREGIONPATHINFO2 returns valid value for vi_pad");
1583 T_EXPECT_NE_INT(preginfo_path.prp_vip.vip_vi.vi_fsid.val[0], 0,
1584 "PROC_PIDREGIONPATHINFO2 returns valid value for vi_fsid.val[0]:%d",
1585 preginfo_path.prp_vip.vip_vi.vi_fsid.val[0]);
1586 T_EXPECT_NE_INT(preginfo_path.prp_vip.vip_vi.vi_fsid.val[1], 0,
1587 "PROC_PIDREGIONPATHINFO2 returns valid value for vi_fsid.val[1]:%d",
1588 preginfo_path.prp_vip.vip_vi.vi_fsid.val[1]);
1589 T_EXPECT_NE_PTR((void *)(strcasestr(preginfo_path.prp_vip.vip_path, CONF_TMP_FILE_PFX)), NULL,
1590 "PROC_PIDREGIONPATHINFO2 returns valid value for vi_path");
1591 /*
1592 * Basic sanity checks for vnode stat returned by the API
1593 */
1594 T_EXPECT_NE_UINT(preginfo_path.prp_vip.vip_vi.vi_stat.vst_dev, 0U, "PROC_PIDREGIONPATHINFO2 returns valid value for vst_dev");
1595 T_EXPECT_EQ_UINT(((preginfo_path.prp_vip.vip_vi.vi_stat.vst_mode & S_IFMT) ^ S_IFREG), 0,
1596 "PROC_PIDREGIONPATHINFO2 returns valid value for vst_mode");
1597 T_EXPECT_EQ_USHORT(preginfo_path.prp_vip.vip_vi.vi_stat.vst_nlink, (unsigned short)0, /* the file was unlink()'d! */
1598 "PROC_PIDREGIONPATHINFO2 returns valid value for vst_nlink");
1599 T_EXPECT_NE_ULLONG(preginfo_path.prp_vip.vip_vi.vi_stat.vst_ino, 0ULL,
1600 "PROC_PIDREGIONPATHINFO2 returns valid value for vst_ino");
1601 T_EXPECT_EQ_UINT(preginfo_path.prp_vip.vip_vi.vi_stat.vst_uid, 0U, "PROC_PIDREGIONPATHINFO2 returns valid value for vst_uid");
1602 T_EXPECT_EQ_UINT(preginfo_path.prp_vip.vip_vi.vi_stat.vst_gid, 0U, "PROC_PIDREGIONPATHINFO2 returns valid value for vst_gid");
1603 T_EXPECT_GE_LLONG(preginfo_path.prp_vip.vip_vi.vi_stat.vst_size, (off_t)CONF_BLK_SIZE,
1604 "PROC_PIDREGIONPATHINFO2 returns valid value for vst_size");
1605 T_EXPECT_GE_LLONG(preginfo_path.prp_vip.vip_vi.vi_stat.vst_blocks, 1LL,
1606 "PROC_PIDREGIONPATHINFO2 returns valid value for vst_blocks");
1607 T_EXPECT_GE_UINT(preginfo_path.prp_vip.vip_vi.vi_stat.vst_blksize, CONF_BLK_SIZE,
1608 "PROC_PIDREGIONPATHINFO2 returns valid value for vst_blksize");
1609
1610 int ret = 0;
1611 ret = munmap(map_tmp, (size_t)map_tmp_sz);
1612 T_QUIET;
1613 T_EXPECT_POSIX_SUCCESS(ret, "munmap of map_tmp");
1614 free_proc_info(proc_info, 1);
1615 }
1616
1617 T_DECL(proc_info_proc_pidregionpathinfo3,
1618 "Test to verify PROC_PIDREGIONPATHINFO3 returns valid information about the process",
1619 T_META_ASROOT(true), T_META_TAG_VM_PREFERRED)
1620 {
1621 void * proc_info[5];
1622 proc_info_caller(PREGINFO_PATH_3, proc_info, NULL);
1623
1624 struct proc_regionwithpathinfo preginfo_path = *((struct proc_regionwithpathinfo *)proc_info[0]);
1625 void *map_tmp = proc_info[1];
1626 vm_map_size_t map_tmp_sz = (vm_map_size_t)(uintptr_t)proc_info[2];
1627
1628 /* The *info3 version of this call returns any open file that lives on the same file system */
1629 T_EXPECT_EQ_INT(preginfo_path.prp_vip.vip_vi.vi_fsid.val[0], (int)(uintptr_t)proc_info[3],
1630 "PROC_PIDREGIONPATHINFO3 returns valid value for vi_fsid.val[0]");
1631 T_EXPECT_EQ_INT(preginfo_path.prp_vip.vip_vi.vi_fsid.val[1], (int)(uintptr_t)proc_info[4],
1632 "PROC_PIDREGIONPATHINFO3 returns valid value for vi_fsid.val[1]");
1633
1634 int ret = 0;
1635 ret = munmap(map_tmp, (size_t)map_tmp_sz);
1636 T_QUIET;
1637 T_EXPECT_POSIX_SUCCESS(ret, "munmap of map_tmp");
1638 free_proc_info(proc_info, 1);
1639 }
1640
1641 T_DECL(proc_info_proc_pidvnodepathinfo,
1642 "Test to verify PROC_PIDVNODEPATHINFO returns valid information about the process",
1643 T_META_ASROOT(true), T_META_TAG_VM_PREFERRED)
1644 {
1645 void * proc_info[1];
1646 proc_info_caller(PVNINFO, proc_info, NULL);
1647 struct proc_vnodepathinfo pvninfo = *((struct proc_vnodepathinfo *)proc_info[0]);
1648
1649 T_EXPECT_EQ_INT(pvninfo.pvi_cdir.vip_vi.vi_type, VDIR, "PROC_PIDVNODEPATHINFO returns valid value for vi_type");
1650 T_EXPECT_EQ_INT(pvninfo.pvi_cdir.vip_vi.vi_pad, 0, "PROC_PIDVNODEPATHINFO returns valid value for vi_pad");
1651 T_EXPECT_NE_INT(pvninfo.pvi_cdir.vip_vi.vi_fsid.val[0], 0, "PROC_PIDVNODEPATHINFO returns valid value for vi_fsid.val[0]");
1652 T_EXPECT_NE_INT(pvninfo.pvi_cdir.vip_vi.vi_fsid.val[1], 0, "PROC_PIDVNODEPATHINFO returns valid value for vi_fsid.val[1]");
1653 /*
1654 * Basic sanity checks for vnode stat returned by the API
1655 */
1656 T_EXPECT_NE_UINT(pvninfo.pvi_cdir.vip_vi.vi_stat.vst_dev, 0U, "PROC_PIDVNODEPATHINFO returns valid value for vst_dev");
1657 T_EXPECT_EQ_INT(((pvninfo.pvi_cdir.vip_vi.vi_stat.vst_mode & S_IFMT) ^ S_IFDIR), 0,
1658 "PROC_PIDVNODEPATHINFO returns valid value for vst_mode");
1659 T_EXPECT_GE_USHORT(pvninfo.pvi_cdir.vip_vi.vi_stat.vst_nlink, (unsigned short)2,
1660 "PROC_PIDVNODEPATHINFO returns valid value for vst_nlink");
1661 T_EXPECT_NE_ULLONG(pvninfo.pvi_cdir.vip_vi.vi_stat.vst_ino, 0ULL, "PROC_PIDVNODEPATHINFO returns valid value for vst_ino");
1662 T_EXPECT_GE_UINT(pvninfo.pvi_cdir.vip_vi.vi_stat.vst_uid, 0U, "PROC_PIDVNODEPATHINFO returns valid value for vst_uid");
1663 T_EXPECT_GE_UINT(pvninfo.pvi_cdir.vip_vi.vi_stat.vst_gid, 0U, "PROC_PIDVNODEPATHINFO returns valid value for vst_gid");
1664 T_EXPECT_GT_LLONG(pvninfo.pvi_cdir.vip_vi.vi_stat.vst_size, 0LL, "PROC_PIDVNODEPATHINFO returns valid value for vst_size");
1665 T_EXPECT_GE_LLONG(pvninfo.pvi_cdir.vip_vi.vi_stat.vst_blocks, 0LL, "PROC_PIDVNODEPATHINFO returns valid value for vst_blocks");
1666 T_EXPECT_GE_UINT(pvninfo.pvi_cdir.vip_vi.vi_stat.vst_blksize, CONF_BLK_SIZE,
1667 "PROC_PIDVNODEPATHINFO returns valid value for vst_blksize");
1668
1669 free_proc_info(proc_info, 1);
1670 }
1671 /*
1672 * The remaining tests break from the pattern of the other PROC_INFO_CALL_PIDINFO tests.
1673 * We call proc_info directly as it's more efficient
1674 */
1675
1676 T_DECL(proc_info_pidinfo_proc_pidlistfds,
1677 "proc_info API tests to verify PROC_INFO_CALL_PIDINFO/PROC_PIDLISTFDS",
1678 T_META_ASROOT(true), T_META_TAG_VM_PREFERRED)
1679 {
1680 int retval;
1681 int orig_nfiles = 0;
1682 struct proc_fdinfo * fd_info = NULL;
1683
1684 T_LOG("Test to verify PROC_PIDLISTFDS returns sane number of open files");
1685 retval = __proc_info(PROC_INFO_CALL_PIDINFO, getpid(), PROC_PIDLISTFDS, (uint32_t)0, (user_addr_t)0, (uint32_t)0);
1686 orig_nfiles = retval / (int)sizeof(struct proc_fdinfo);
1687 T_EXPECT_GE_INT(orig_nfiles, CONF_OPN_FILE_COUNT, "The number of open files is lower than expected.");
1688
1689 /*
1690 * Allocate a buffer of expected size + 1 to ensure that
1691 * the API still returns expected size
1692 * i.e. 3 + 1 = 4 open fds
1693 */
1694 T_LOG("Test to verify PROC_PIDLISTFDS returns valid fd information");
1695 fd_info = malloc(sizeof(*fd_info) * 5);
1696 tmp_fd = CONF_TMP_FILE_OPEN(NULL);
1697 T_LOG("tmp_fd val:%d", tmp_fd);
1698 T_QUIET;
1699 T_EXPECT_POSIX_SUCCESS(tmp_fd, "open() for PROC_PIDLISTFDS");
1700
1701 retval = __proc_info(PROC_INFO_CALL_PIDINFO, getpid(), PROC_PIDLISTFDS, (uint32_t)0, (user_addr_t)fd_info,
1702 (uint32_t)(sizeof(*fd_info) * 5));
1703 retval = retval / (int)sizeof(struct proc_fdinfo);
1704
1705 close(tmp_fd);
1706
1707 for (int i = 0; i < retval; i++) {
1708 /*
1709 * Check only for the fd that we control.
1710 */
1711 if (tmp_fd != fd_info[i].proc_fd) {
1712 continue;
1713 }
1714 T_EXPECT_EQ_UINT(fd_info[i].proc_fdtype, (unsigned int)PROX_FDTYPE_VNODE, "Correct proc_fdtype for returned fd");
1715 }
1716
1717 T_EXPECT_GE_INT(retval, 4, "Correct number of fds was returned.");
1718
1719 tmp_fd = -1;
1720 free(fd_info);
1721 fd_info = NULL;
1722 }
1723
1724 T_DECL(proc_info_proc_pidpathinfo,
1725 "Test to verify PROC_PIDPATHINFO returns valid information about the process",
1726 T_META_ASROOT(true), T_META_TAG_VM_PREFERRED)
1727 {
1728 char * pid_path = NULL;
1729 pid_path = malloc(sizeof(char) * PROC_PIDPATHINFO_MAXSIZE);
1730 T_EXPECT_NOTNULL(pid_path, "malloc for PROC_PIDPATHINFO");
1731 int retval = __proc_info(PROC_INFO_CALL_PIDINFO, getpid(), PROC_PIDPATHINFO, (uint64_t)0, (user_addr_t)pid_path,
1732 (uint32_t)PROC_PIDPATHINFO_MAXSIZE);
1733 T_EXPECT_EQ_INT(retval, 0, "__proc_info call for PROC_PIDPATHINFO");
1734
1735 T_EXPECT_NE_PTR((void *)(strcasestr(pid_path, CONF_CMD_NAME)), NULL, "PROC_PIDPATHINFOreturns valid value for pid_path");
1736 free(pid_path);
1737 pid_path = NULL;
1738 }
1739
1740 T_DECL(proc_info_proc_pidlistfileports,
1741 "Test to verify PROC_PIDLISTFILEPORTS returns valid information about the process",
1742 T_META_ASROOT(true), T_META_TAG_VM_PREFERRED)
1743 {
1744 struct proc_fileportinfo * fileport_info = NULL;
1745 mach_port_t tmp_file_port = MACH_PORT_NULL;
1746 proc_config_t proc_config = spawn_child_processes(1, proc_info_call_pidinfo_handler);
1747 int child_pid = proc_config->child_pids[0];
1748
1749 /*
1750 * Create a file port
1751 */
1752 tmp_fd = CONF_TMP_FILE_OPEN(NULL);
1753 int retval = fileport_makeport(tmp_fd, &tmp_file_port);
1754 T_EXPECT_POSIX_SUCCESS(retval, "fileport_makeport() for PROC_PIDLISTFILEPORTS");
1755
1756 /*
1757 * Like the other APIs, this returns the actual count + 20. Hence we expect it to be atleast 1 (that we created)
1758 */
1759 retval = __proc_info(PROC_INFO_CALL_PIDINFO, getpid(), PROC_PIDLISTFILEPORTS, (uint64_t)0, (user_addr_t)0, (uint32_t)0);
1760 T_EXPECT_GE_INT(retval / (int)sizeof(fileport_info), 1,
1761 "__proc_info call for PROC_PIDLISTFILEPORTS to get total ports in parent");
1762
1763 /*
1764 * Child doesn't have any fileports, should return zero
1765 */
1766 retval = __proc_info(PROC_INFO_CALL_PIDINFO, child_pid, PROC_PIDLISTFILEPORTS, (uint64_t)0, (user_addr_t)0, (uint32_t)0);
1767 T_EXPECT_EQ_INT(retval / (int)sizeof(fileport_info), 0,
1768 "__proc_info call for PROC_PIDLISTFILEPORTS to get total ports in child");
1769
1770 fileport_info = malloc(sizeof(*fileport_info) * (size_t)retval);
1771 retval = __proc_info(PROC_INFO_CALL_PIDINFO, getpid(), PROC_PIDLISTFILEPORTS, (uint64_t)0, (user_addr_t)fileport_info,
1772 (uint32_t)sizeof(*fileport_info));
1773 T_EXPECT_EQ_INT(retval, (int)sizeof(*fileport_info), "__proc_info call for PROC_PIDLISTFILEPORTS");
1774
1775 T_EXPECT_NE_UINT(fileport_info->proc_fileport, (uint32_t)0, "PROC_PIDLISTFILEPORTS returns valid value for proc_fileport");
1776 T_EXPECT_EQ_UINT(fileport_info->proc_fdtype, (uint32_t)PROX_FDTYPE_VNODE,
1777 "PROC_PIDLISTFILEPORTS returns valid value for proc_fdtype");
1778
1779 /*
1780 * Cleanup for the fileport
1781 */
1782 mach_port_deallocate(mach_task_self(), tmp_file_port);
1783 tmp_file_port = MACH_PORT_NULL;
1784 free(fileport_info);
1785 fileport_info = NULL;
1786 close(tmp_fd);
1787 tmp_fd = -1;
1788 free_proc_config(proc_config);
1789 }
1790
1791 T_DECL(proc_info_proc_pidcoalitioninfo,
1792 "Test to verify PROC_PIDCOALITIONINFO returns valid information about the process",
1793 T_META_ASROOT(true), T_META_TAG_VM_PREFERRED)
1794 {
1795 proc_config_t proc_config = spawn_child_processes(1, proc_info_call_pidinfo_handler);
1796 int child_pid = proc_config->child_pids[0];
1797
1798 struct proc_pidcoalitioninfo pci_parent;
1799 struct proc_pidcoalitioninfo pci_child;
1800 int retval = __proc_info(PROC_INFO_CALL_PIDINFO, getpid(), PROC_PIDCOALITIONINFO, (uint64_t)0, (user_addr_t)&pci_parent,
1801 (uint32_t)sizeof(pci_parent));
1802 T_EXPECT_EQ_INT(retval, (int)sizeof(pci_parent), "__proc_info call for PROC_PIDCOALITIONINFO (parent)");
1803 retval = __proc_info(PROC_INFO_CALL_PIDINFO, child_pid, PROC_PIDCOALITIONINFO, (uint64_t)0, (user_addr_t)&pci_child,
1804 (uint32_t)sizeof(pci_child));
1805 T_EXPECT_EQ_INT(retval, (int)sizeof(pci_child), "__proc_info call for PROC_PIDCOALITIONINFO (child)");
1806
1807 /*
1808 * Coalition IDs should match for child and parent
1809 */
1810 for (int i = 0; i < COALITION_NUM_TYPES; i++) {
1811 T_EXPECT_EQ_ULLONG(pci_parent.coalition_id[i], pci_child.coalition_id[i],
1812 "PROC_PIDCOALITIONINFO returns valid value for coalition_id");
1813 }
1814
1815 free_proc_config(proc_config);
1816 }
1817
1818 T_DECL(proc_info_proc_pidworkqueueinfo,
1819 "Test to verify PROC_PIDWORKQUEUEINFO returns valid information about the process",
1820 T_META_ASROOT(true), T_META_TAG_VM_PREFERRED)
1821 {
1822 proc_config_t proc_config = spawn_child_processes(1, proc_info_call_pidinfo_handler);
1823 int child_pid = proc_config->child_pids[0];
1824 send_action_to_child_processes(proc_config, ACT_PHASE5);
1825
1826 struct proc_workqueueinfo pwqinfo;
1827 usleep(10000);
1828 int retval = __proc_info(PROC_INFO_CALL_PIDINFO, child_pid, PROC_PIDWORKQUEUEINFO, (uint64_t)0, (user_addr_t)&pwqinfo,
1829 (uint32_t)sizeof(pwqinfo));
1830 T_EXPECT_EQ_INT(retval, (int)sizeof(pwqinfo), "__proc_info call for PROC_PIDWORKQUEUEINFO");
1831
1832 int ncpu = 0;
1833 size_t ncpu_size = sizeof(ncpu);
1834 retval = sysctlbyname("hw.ncpu", (void *)&ncpu, &ncpu_size, NULL, 0);
1835 T_EXPECT_EQ_INT(retval, 0, "sysctl() for PROC_PIDWORKQUEUEINFO");
1836 T_EXPECT_GE_UINT(pwqinfo.pwq_nthreads, (uint32_t)1, "PROC_PIDWORKQUEUEINFO returns valid value for pwq_nthreads");
1837 T_EXPECT_GE_UINT(pwqinfo.pwq_blockedthreads + pwqinfo.pwq_runthreads, (uint32_t)1,
1838 "PROC_PIDWORKQUEUEINFO returns valid value for pwqinfo.pwq_runthreads/pwq_blockedthreads");
1839 T_EXPECT_EQ_UINT(pwqinfo.pwq_state, (uint32_t)0, "PROC_PIDWORKQUEUEINFO returns valid value for pwq_state");
1840
1841 kill_child_processes(proc_config);
1842 free_proc_config(proc_config);
1843 }
1844 T_DECL(proc_info_proc_pidnoteexit,
1845 "Test to verify PROC_PIDNOTEEXIT returns valid information about the process",
1846 T_META_ASROOT(true), T_META_TAG_VM_PREFERRED)
1847 {
1848 /*
1849 * Ask the child to close pipe and quit, cleanup pipes for parent
1850 */
1851 proc_config_t proc_config = spawn_child_processes(1, proc_info_call_pidinfo_handler);
1852 int child_pid = proc_config->child_pids[0];
1853 send_action_to_child_processes(proc_config, ACT_EXIT);
1854
1855 uint32_t exit_data = 0;
1856 int retval = __proc_info(PROC_INFO_CALL_PIDINFO, child_pid, PROC_PIDNOTEEXIT, (uint64_t)(NOTE_EXITSTATUS | NOTE_EXIT_DETAIL),
1857 (user_addr_t)&exit_data, (uint32_t)sizeof(exit_data));
1858 T_EXPECT_EQ_INT(retval, (int)sizeof(exit_data), "__proc_info call for PROC_PIDNOTEEXIT");
1859
1860 T_EXPECT_EQ_UINT(exit_data, 0U, "PROC_PIDNOTEEXIT returned valid value for exit_data");
1861
1862 free_proc_config(proc_config);
1863 }
1864
1865 T_DECL(proc_info_negative_tests,
1866 "Test to validate PROC_INFO_CALL_PIDINFO for invalid arguments",
1867 T_META_ASROOT(true), T_META_TAG_VM_PREFERRED)
1868 {
1869 proc_config_t proc_config = spawn_child_processes(1, proc_info_call_pidinfo_handler);
1870 int child_pid = proc_config->child_pids[0];
1871 uint32_t exit_data = 0;
1872
1873 int retval =
1874 __proc_info(PROC_INFO_CALL_PIDINFO, child_pid, PROC_PIDNOTEEXIT, (uint64_t)0, (user_addr_t)&exit_data, (uint32_t)0);
1875 T_EXPECT_EQ_INT(errno, ENOMEM, "PROC_INFO_CALL_PIDINFO call should fail with ENOMEM if buffersize is zero");
1876 retval = __proc_info(PROC_INFO_CALL_PIDINFO, child_pid, PROC_PIDPATHINFO, (uint64_t)0, (user_addr_t)&exit_data,
1877 (uint32_t)PROC_PIDPATHINFO_MAXSIZE + 1);
1878 T_EXPECT_EQ_INT(errno, EOVERFLOW,
1879 "PROC_INFO_CALL_PIDINFO call should fail with EOVERFLOW if buffersize is larger than PROC_PIDPATHINFO_MAXSIZE");
1880 retval = __proc_info(PROC_INFO_CALL_PIDINFO, -1, PROC_PIDNOTEEXIT, (uint64_t)0, (user_addr_t)&exit_data,
1881 (uint32_t)sizeof(exit_data));
1882 T_EXPECT_EQ_INT(errno, ESRCH, "PROC_INFO_CALL_PIDINFO call should fail with ESRCH for invalid process id");
1883 retval = __proc_info(PROC_INFO_CALL_PIDINFO, child_pid, -1U, (uint64_t)0, (user_addr_t)&exit_data, (uint32_t)sizeof(exit_data));
1884 T_EXPECT_EQ_INT(errno, EINVAL, "PROC_INFO_CALL_PIDINFO call should fail with EINVAL for invalid flavor");
1885 retval = __proc_info(PROC_INFO_CALL_PIDINFO, 0, PROC_PIDWORKQUEUEINFO, (uint64_t)0, (user_addr_t)0, (uint32_t)0);
1886 T_EXPECT_EQ_INT(errno, EINVAL,
1887 "PROC_INFO_CALL_PIDINFO call should fail with EINVAL if flavor is PROC_PIDWORKQUEUEINFO and pid=0");
1888
1889 free_proc_config(proc_config);
1890 }
1891
1892 /*
1893 * END PROC_INFO_CALL_PIDINFO DECLs
1894 */
1895
1896 #pragma mark proc_list_uptrs
1897
1898 #define NUPTRS 4
1899 static uint64_t uptrs[NUPTRS] = {0x1122334455667788ULL, 0x99aabbccddeeff00ULL, 0xaabbaaddccaaffeeULL, 0xcc000011ccaa7755ULL};
1900
1901 static const char * uptr_names[NUPTRS];
1902
1903 static void
print_uptrs(int argc,char * const * argv)1904 print_uptrs(int argc, char * const * argv)
1905 {
1906 for (int i = 0; i < argc; i++) {
1907 char * end;
1908 unsigned long pid = strtoul(argv[i], &end, 0);
1909 if (pid > INT_MAX) {
1910 printf("error: pid '%lu' would overflow an integer\n", pid);
1911 }
1912 if (end == argv[i]) {
1913 printf("error: could not parse '%s' as a pid\n", argv[i]);
1914 continue;
1915 }
1916 int uptrs_count = proc_list_uptrs((int)pid, NULL, 0);
1917 if (uptrs_count == 0) {
1918 printf("no uptrs for process %d\n", (int)pid);
1919 return;
1920 }
1921
1922 /* extra space */
1923 unsigned int uptrs_len = (unsigned int)uptrs_count + 32;
1924
1925 uint64_t * uptrs_alloc = malloc(sizeof(uint64_t) * uptrs_len);
1926 os_assert(uptrs_alloc != NULL);
1927
1928 uptrs_count = proc_list_uptrs((int)pid, uptrs_alloc, (uint32_t)(sizeof(uint64_t) * uptrs_len));
1929 printf("process %d has %d uptrs:\n", (int)pid, uptrs_count);
1930 if (uptrs_count > (int)uptrs_len) {
1931 uptrs_count = (int)uptrs_len;
1932 }
1933 for (int j = 0; j < uptrs_count; j++) {
1934 printf("%#17" PRIx64 "\n", uptrs_alloc[j]);
1935 }
1936 }
1937 }
1938
1939 T_DECL(proc_list_uptrs, "the kernel should return any up-pointers it knows about", T_META_TAG_VM_PREFERRED)
1940 {
1941 if (argc > 0) {
1942 print_uptrs(argc, argv);
1943 T_SKIP("command line invocation of tool, not test");
1944 }
1945
1946 unsigned int cur_uptr = 0;
1947
1948 int kq = kqueue();
1949 T_QUIET;
1950 T_ASSERT_POSIX_SUCCESS(kq, "kqueue");
1951
1952 /*
1953 * Should find uptrs on file-type knotes and generic knotes (two
1954 * different search locations, internally).
1955 */
1956 struct kevent64_s events[2];
1957 memset(events, 0, sizeof(events));
1958
1959 uptr_names[cur_uptr] = "kqueue file-backed knote";
1960 events[0].filter = EVFILT_WRITE;
1961 events[0].ident = STDOUT_FILENO;
1962 events[0].flags = EV_ADD;
1963 events[0].udata = uptrs[cur_uptr++];
1964
1965 uptr_names[cur_uptr] = "kqueue non-file-backed knote";
1966 events[1].filter = EVFILT_USER;
1967 events[1].ident = 1;
1968 events[1].flags = EV_ADD;
1969 events[1].udata = uptrs[cur_uptr++];
1970
1971 int kev_err = kevent64(kq, events, sizeof(events) / sizeof(events[0]), NULL, 0, KEVENT_FLAG_IMMEDIATE, NULL);
1972 T_ASSERT_POSIX_SUCCESS(kev_err, "register events with kevent64");
1973
1974 /*
1975 * Should find uptrs both on a kevent_id kqueue and in a workloop
1976 * kqueue's knote's udata field.
1977 */
1978 uptr_names[cur_uptr] = "dynamic kqueue non-file-backed knote";
1979 struct kevent_qos_s events_id[] = {{
1980 .filter = EVFILT_USER,
1981 .ident = 1,
1982 .flags = EV_ADD,
1983 .qos = (int)_pthread_qos_class_encode(QOS_CLASS_DEFAULT, 0, 0),
1984 .udata = uptrs[cur_uptr++]
1985 }};
1986
1987 uptr_names[cur_uptr] = "dynamic kqueue ID";
1988 kev_err = kevent_id(uptrs[cur_uptr++], events_id, 1, NULL, 0, NULL, NULL, KEVENT_FLAG_WORKLOOP | KEVENT_FLAG_IMMEDIATE);
1989 T_ASSERT_POSIX_SUCCESS(kev_err, "register event with kevent_id");
1990
1991 errno = 0;
1992 int uptrs_count = proc_list_uptrs(getpid(), NULL, 0);
1993 T_QUIET;
1994 T_ASSERT_POSIX_SUCCESS(uptrs_count, "proc_list_uptrs");
1995 T_QUIET;
1996 T_EXPECT_EQ(uptrs_count, NUPTRS, "should see correct number of up-pointers");
1997
1998 uint64_t uptrs_obs[NUPTRS] = {0};
1999 uptrs_count = proc_list_uptrs(getpid(), uptrs_obs, sizeof(uptrs_obs));
2000 T_QUIET;
2001 T_ASSERT_POSIX_SUCCESS(uptrs_count, "proc_list_uptrs");
2002
2003 for (int i = 0; i < uptrs_count; i++) {
2004 int found = -1;
2005 for (int j = 0; j < NUPTRS; j++) {
2006 if (uptrs_obs[i] == uptrs[j]) {
2007 found = j;
2008 goto next;
2009 }
2010 }
2011 T_FAIL("unexpected up-pointer found: %#" PRIx64, uptrs_obs[i]);
2012 next: ;
2013 if (found != -1) {
2014 T_PASS("found up-pointer for %s", uptr_names[found]);
2015 }
2016 }
2017
2018 uint64_t up_overflow[2] = {0};
2019 uptrs_count = proc_list_uptrs(getpid(), up_overflow, sizeof(uint64_t) + 1);
2020 T_ASSERT_EQ(up_overflow[1], (uint64_t)0, "overflow check");
2021 }
2022
2023 #pragma mark dynamic kqueue info
2024
2025 #define EXPECTED_ID UINT64_C(0x1122334455667788)
2026 #define EXPECTED_UDATA UINT64_C(0x99aabbccddeeff00)
2027 #ifndef KQ_WORKLOOP
2028 #define KQ_WORKLOOP 0x80
2029 #endif
2030
2031 static void
setup_kevent_id(kqueue_id_t id)2032 setup_kevent_id(kqueue_id_t id)
2033 {
2034 struct kevent_qos_s events_id[] = {{
2035 .filter = EVFILT_USER,
2036 .ident = 1,
2037 .flags = EV_ADD,
2038 .qos = (int)_pthread_qos_class_encode(QOS_CLASS_DEFAULT, 0, 0),
2039 .udata = EXPECTED_UDATA
2040 }};
2041
2042 int err = kevent_id(id, events_id, 1, NULL, 0, NULL, NULL, KEVENT_FLAG_WORKLOOP | KEVENT_FLAG_IMMEDIATE);
2043 T_ASSERT_POSIX_SUCCESS(err, "register event with kevent_id");
2044 }
2045
2046 static kqueue_id_t *
list_kqids(pid_t pid,int * nkqids_out)2047 list_kqids(pid_t pid, int * nkqids_out)
2048 {
2049 int kqids_len = 256;
2050 int nkqids;
2051 kqueue_id_t * kqids = NULL;
2052 uint32_t kqids_size;
2053
2054 retry:
2055 if (os_mul_overflow(sizeof(kqueue_id_t), kqids_len, &kqids_size)) {
2056 T_QUIET;
2057 T_ASSERT_GT(kqids_len, PROC_PIDDYNKQUEUES_MAX, NULL);
2058 kqids_len = PROC_PIDDYNKQUEUES_MAX;
2059 goto retry;
2060 }
2061 if (!kqids) {
2062 kqids = malloc(kqids_size);
2063 T_QUIET;
2064 T_ASSERT_NOTNULL(kqids, "malloc(%" PRIu32 ")", kqids_size);
2065 }
2066
2067 nkqids = proc_list_dynkqueueids(pid, kqids, kqids_size);
2068 if (nkqids > kqids_len && kqids_len < PROC_PIDDYNKQUEUES_MAX) {
2069 kqids_len *= 2;
2070 if (kqids_len > PROC_PIDDYNKQUEUES_MAX) {
2071 kqids_len = PROC_PIDDYNKQUEUES_MAX;
2072 }
2073 free(kqids);
2074 kqids = NULL;
2075 goto retry;
2076 }
2077
2078 *nkqids_out = nkqids;
2079 return kqids;
2080 }
2081
2082 T_DECL(list_dynamic_kqueues, "the kernel should list IDs of dynamic kqueues", T_META_ALL_VALID_ARCHS(true), T_META_TAG_VM_PREFERRED)
2083 {
2084 int nkqids;
2085 bool found = false;
2086
2087 setup_kevent_id(EXPECTED_ID);
2088 kqueue_id_t * kqids = list_kqids(getpid(), &nkqids);
2089 T_ASSERT_GE(nkqids, 1, "at least one dynamic kqueue is listed");
2090 for (int i = 0; i < nkqids; i++) {
2091 if (kqids[i] == EXPECTED_ID) {
2092 found = true;
2093 T_PASS("found expected dynamic kqueue ID");
2094 } else {
2095 T_LOG("found another dynamic kqueue with ID %#" PRIx64, kqids[i]);
2096 }
2097 }
2098
2099 if (!found) {
2100 T_FAIL("could not find dynamic ID of kqueue created");
2101 }
2102
2103 free(kqids);
2104 }
2105
2106 T_DECL(dynamic_kqueue_basic_info, "the kernel should report valid basic dynamic kqueue info", T_META_ALL_VALID_ARCHS(true), T_META_TAG_VM_PREFERRED)
2107 {
2108 struct kqueue_info kqinfo;
2109 int ret;
2110
2111 setup_kevent_id(EXPECTED_ID);
2112 ret = proc_piddynkqueueinfo(getpid(), PROC_PIDDYNKQUEUE_INFO, EXPECTED_ID, &kqinfo, sizeof(kqinfo));
2113 T_ASSERT_POSIX_SUCCESS(ret, "proc_piddynkqueueinfo(... PROC_PIDDYNKQUEUE_INFO ...)");
2114 T_QUIET;
2115 T_ASSERT_GE(ret, (int)sizeof(kqinfo), "PROC_PIDDYNKQUEUE_INFO should return the right size");
2116
2117 T_EXPECT_NE(kqinfo.kq_state & KQ_WORKLOOP, 0U, "kqueue info should be for a workloop kqueue");
2118 T_EXPECT_EQ(kqinfo.kq_stat.vst_ino, EXPECTED_ID, "inode field should be the kqueue's ID");
2119 }
2120
2121 T_DECL(dynamic_kqueue_extended_info, "the kernel should report valid extended dynamic kqueue info", T_META_ALL_VALID_ARCHS(true), T_META_TAG_VM_PREFERRED)
2122 {
2123 struct kevent_extinfo kqextinfo[1];
2124 int ret;
2125
2126 setup_kevent_id(EXPECTED_ID);
2127 ret = proc_piddynkqueueinfo(getpid(), PROC_PIDDYNKQUEUE_EXTINFO, EXPECTED_ID, kqextinfo, sizeof(kqextinfo));
2128 T_ASSERT_POSIX_SUCCESS(ret, "proc_piddynkqueueinfo(... PROC_PIDDYNKQUEUE_EXTINFO ...)");
2129 T_QUIET;
2130 T_ASSERT_EQ(ret, 1, "PROC_PIDDYNKQUEUE_EXTINFO should return a single knote");
2131
2132 T_EXPECT_EQ(kqextinfo[0].kqext_kev.ident, 1ULL, "kevent identifier matches what was configured");
2133 T_EXPECT_EQ(kqextinfo[0].kqext_kev.filter, (short)EVFILT_USER, "kevent filter matches what was configured");
2134 T_EXPECT_EQ(kqextinfo[0].kqext_kev.udata, EXPECTED_UDATA, "kevent udata matches what was configured");
2135 }
2136
2137 #pragma mark proc_listpids
2138
2139 T_DECL(list_kdebug_pids, "the kernel should report processes that are filtered by kdebug",
2140 T_META_ASROOT(YES), T_META_RUN_CONCURRENTLY(false), T_META_TAG_VM_PREFERRED)
2141 {
2142 int mib[4] = {CTL_KERN, KERN_KDEBUG};
2143 int npids;
2144 int pids[1];
2145 int ret;
2146 kd_regtype reg;
2147 size_t regsize = sizeof(reg);
2148
2149 mib[2] = KERN_KDREMOVE;
2150 ret = sysctl(mib, 3, NULL, NULL, NULL, 0);
2151 T_QUIET;
2152 T_ASSERT_POSIX_SUCCESS(ret, "KERN_KDREMOVE sysctl");
2153
2154 mib[2] = KERN_KDSETBUF;
2155 mib[3] = 100000;
2156 ret = sysctl(mib, 4, NULL, NULL, NULL, 0);
2157 T_QUIET;
2158 T_ASSERT_POSIX_SUCCESS(ret, "KERN_KDSETBUF sysctl");
2159
2160 mib[2] = KERN_KDSETUP;
2161 ret = sysctl(mib, 3, NULL, NULL, NULL, 0);
2162 T_QUIET;
2163 T_ASSERT_POSIX_SUCCESS(ret, "KERN_KDSETUP sysctl");
2164
2165 npids = proc_listpids(PROC_KDBG_ONLY, 0, pids, sizeof(pids));
2166 T_EXPECT_EQ(npids, 0, "no processes should be filtered initially");
2167
2168 reg.type = KDBG_TYPENONE;
2169 reg.value1 = (unsigned int)getpid();
2170 reg.value2 = 1; /* set the pid in the filter */
2171 mib[2] = KERN_KDPIDTR;
2172 ret = sysctl(mib, 3, ®, ®size, NULL, 0);
2173 T_ASSERT_POSIX_SUCCESS(ret, "KERN_KDPIDTR sysctl to set a pid in the filter");
2174
2175 npids = proc_listpids(PROC_KDBG_ONLY, 0, pids, sizeof(pids));
2176 npids /= 4;
2177 T_EXPECT_EQ(npids, 1, "a process should be filtered");
2178 T_EXPECT_EQ(pids[0], getpid(), "process filtered should be the one that was set");
2179
2180 mib[2] = KERN_KDREMOVE;
2181 ret = sysctl(mib, 3, NULL, NULL, NULL, 0);
2182 T_QUIET;
2183 T_ASSERT_POSIX_SUCCESS(ret, "KERN_KDREMOVE sysctl");
2184 }
2185
2186 #pragma mark misc
2187
2188 static int prf_fd;
2189 static char prf_path[PATH_MAX];
2190 static void
prf_end(void)2191 prf_end(void)
2192 {
2193 close(prf_fd);
2194 unlink(prf_path);
2195 }
2196
2197 T_DECL(proc_regionfilename, "proc_regionfilename() should work", T_META_TAG_VM_PREFERRED)
2198 {
2199 static char expected[] = "'very rigorous maritime engineering standards' && the front fell off";
2200 static char real[sizeof(expected)];
2201 int rc;
2202 void *addr;
2203
2204 prf_fd = CONF_TMP_FILE_OPEN(prf_path);
2205 T_ATEND(prf_end);
2206
2207 rc = (int) write(prf_fd, expected, sizeof(expected));
2208 T_ASSERT_POSIX_SUCCESS(rc, "write to tmpfile");
2209
2210 addr = mmap(0, 0x1000, PROT_READ, MAP_PRIVATE, prf_fd, 0);
2211 T_WITH_ERRNO;
2212 T_ASSERT_NE_PTR(addr, MAP_FAILED, "mmap of tmpfile");
2213
2214 T_WITH_ERRNO;
2215 T_ASSERT_GT(proc_regionfilename(getpid(), (uint64_t) addr, real, MAXPATHLEN), 0, "proc_regionfilename");
2216 T_EXPECT_EQ_STR(basename(prf_path), basename(real), "filename");
2217 }
2218
2219 T_DECL(proc_regionpath, "PROC_PIDREGIONPATH should return addr, length and path", T_META_TAG_VM_PREFERRED)
2220 {
2221 int rc;
2222 struct proc_regionpath path;
2223 static char some_text[] = "'very rigorous maritime engineering standards' && the front fell off";
2224 unsigned long rounded_length = (sizeof(some_text) & (unsigned long) ~(PAGE_SIZE - 1)) + PAGE_SIZE;
2225 void *addr;
2226
2227 prf_fd = CONF_TMP_FILE_OPEN(prf_path);
2228 T_ATEND(prf_end);
2229
2230 rc = (int) write(prf_fd, some_text, sizeof(some_text));
2231 T_ASSERT_POSIX_SUCCESS(rc, "write to tmpfile");
2232
2233 addr = mmap(0, PAGE_SIZE, PROT_READ, MAP_PRIVATE, prf_fd, 0);
2234 T_WITH_ERRNO;
2235 T_ASSERT_NE_PTR(addr, MAP_FAILED, "mmap of tmpfile");
2236
2237 rc = proc_pidinfo(getpid(), PROC_PIDREGIONPATH, (uint64_t)addr, &path, sizeof(struct proc_regionpath));
2238 T_ASSERT_POSIX_SUCCESS(rc, "proc_pidinfo");
2239
2240 T_ASSERT_EQ((unsigned long) path.prpo_regionlength, rounded_length, "regionlength must match");
2241 T_ASSERT_EQ_PTR((void *) path.prpo_addr, addr, "addr must match");
2242
2243 rc = proc_pidinfo(getpid(), PROC_PIDREGIONPATH, (uint64_t)((char *) addr + 20), &path, sizeof(struct proc_regionpath));
2244 T_ASSERT_POSIX_SUCCESS(rc, "proc_pidinfo 20 bytes past the base address");
2245
2246 T_ASSERT_EQ((unsigned long) path.prpo_regionlength, rounded_length, "regionlength must match, even when 20 bytes past the base address");
2247 T_ASSERT_EQ_PTR((void *) path.prpo_addr, addr, "addr must match, even when 20 bytes past the base address");
2248 }
2249
2250 #ifndef ARRAY_SIZE
2251 #define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
2252 #endif
2253 T_DECL(proc_pidinfo_kernel_task_fail, "calling proc_pidinfo for certain flavors on the kernel task should fail",
2254 T_META_ASROOT(YES), T_META_TAG_VM_PREFERRED)
2255 {
2256 int flavors[] = {PROC_PIDREGIONPATH, PROC_PIDREGIONINFO, PROC_PIDREGIONPATHINFO, PROC_PIDREGIONPATHINFO2, PROC_PIDREGIONPATHINFO3};
2257 for (int f = 0; f < ARRAY_SIZE(flavors); f++) {
2258 int rc = proc_pidinfo(0, flavors[f], 0, 0, 0);
2259 T_ASSERT_EQ(rc, 0, "proc_pidinfo returned %d for flavor %d", rc, flavors[f]);
2260 T_EXPECT_EQ_INT(errno, EPERM, "proc_pidinfo errno expected=%d actual=%d", EPERM, errno);
2261 }
2262 }
2263