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