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