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