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