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