]>
Commit | Line | Data |
---|---|---|
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 | ||
57 | uint32_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 | ||
100 | uint32_t | |
101 | get_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 | */ | |
113 | extern int __proc_info(int32_t callnum, int32_t pid, uint32_t flavor, uint64_t arg, user_addr_t buffer, int32_t buffersize); | |
114 | struct 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 | }; | |
122 | typedef struct proc_config_s * proc_config_t; | |
123 | ||
124 | typedef void (^child_action_handler_t)(proc_config_t proc_config, int child_id); | |
125 | ||
126 | enum 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 | ||
149 | static int tmp_fd = -1; | |
150 | ||
151 | static 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 | ||
196 | static 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 | ||
330 | static void | |
331 | free_proc_config(proc_config_t proc_config) | |
332 | { | |
333 | free(proc_config); | |
334 | } | |
335 | ||
336 | static void | |
337 | send_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 | ||
350 | static void | |
351 | kill_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 | ||
367 | static proc_config_t | |
368 | spawn_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 | ||
432 | static void | |
433 | proc_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 | ||
645 | static void | |
646 | free_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 | ||
659 | T_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 | ||
727 | T_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 | ||
750 | T_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 | ||
771 | T_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 | ||
791 | T_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 | ||
811 | T_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 | ||
842 | T_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 | ||
863 | T_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 | ||
896 | T_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 | ||
926 | T_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 | ||
971 | T_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 | ||
1029 | T_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 | ||
1107 | T_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 | ||
1116 | T_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 | ||
1155 | T_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 | ||
1184 | T_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 | ||
1216 | T_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 | ||
1239 | T_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 | ||
1290 | T_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 | ||
1378 | T_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 | ||
1471 | T_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 | ||
1554 | T_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 | ||
1590 | T_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 | ||
1639 | T_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 | ||
1656 | T_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 | ||
1708 | T_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 | ||
1736 | T_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 | } | |
1763 | T_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 | ||
1785 | T_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 | 1820 | static uint64_t uptrs[NUPTRS] = {0x1122334455667788ULL, 0x99aabbccddeeff00ULL, 0xaabbaaddccaaffeeULL, 0xcc000011ccaa7755ULL}; |
5ba3f43e | 1821 | |
a39ff7e2 | 1822 | static const char * uptr_names[NUPTRS]; |
5ba3f43e A |
1823 | |
1824 | static void | |
a39ff7e2 | 1825 | print_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 | 1860 | T_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 | ||
1946 | static void | |
1947 | setup_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 | ||
1955 | static kqueue_id_t * | |
a39ff7e2 | 1956 | list_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 | ||
1963 | retry: | |
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 | 1991 | T_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 | 2015 | T_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 | 2030 | T_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 | 2048 | T_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, ®, ®size, 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 | } |