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