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