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