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