1 #include <darwintest.h>
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <stdbool.h>
5 #include <errno.h>
6 #include <libproc.h>
7 #include <bsm/libbsm.h>
8 
9 #undef USE_AUDIT_TOKEN_FOR_PID
10 
11 #ifdef USE_AUDIT_TOKEN_FOR_PID
12 static bool
audit_token_for_pid(pid_t pid,audit_token_t * token)13 audit_token_for_pid(pid_t pid, audit_token_t *token)
14 {
15 	kern_return_t err;
16 	task_t task;
17 	mach_msg_type_number_t info_size = TASK_AUDIT_TOKEN_COUNT;
18 
19 	err = task_for_pid(mach_task_self(), pid, &task);
20 	if (err != KERN_SUCCESS) {
21 		printf("task_for_pid returned %d\n", err);
22 		return false;
23 	}
24 
25 	err = task_info(task, TASK_AUDIT_TOKEN, (integer_t *)token, &info_size);
26 	if (err != KERN_SUCCESS) {
27 		printf("task_info returned %d\n", err);
28 		return false;
29 	}
30 
31 	return true;
32 }
33 
34 #else
35 
36 static int
idversion_for_pid(pid_t pid)37 idversion_for_pid(pid_t pid)
38 {
39 	struct proc_uniqidentifierinfo uniqidinfo = {0};
40 
41 	int ret = proc_pidinfo(pid, PROC_PIDUNIQIDENTIFIERINFO, 0, &uniqidinfo, sizeof(uniqidinfo));
42 	if (ret <= 0) {
43 		perror("proc_pidinfo(PROC_PIDUNIQIDENTIFIERINFO)");
44 		T_ASSERT_FAIL("proc_pidinfo(%d, PROC_PIDUNIQIDENTIFIERINFO) failed unexpectedly with errno %d", pid, errno);
45 	}
46 
47 #ifdef NOTDEF
48 	printf("%s>pid = %d, p_uniqueid = %lld\n", __FUNCTION__, pid, uniqidinfo.p_uniqueid);
49 	printf("%s>pid = %d, p_idversion = %d\n", __FUNCTION__, pid, uniqidinfo.p_idversion);
50 #endif
51 
52 	return uniqidinfo.p_idversion;
53 }
54 #endif
55 
56 static void
show_pidpaths(void)57 show_pidpaths(void)
58 {
59 	char buffer[PROC_PIDPATHINFO_MAXSIZE] = {};
60 	int count = 0;
61 
62 	for (pid_t pid = 1; ((pid < 1000) && (count <= 25)); pid++) {
63 		int ret = proc_pidpath(pid, buffer, sizeof(buffer));
64 		if (ret <= 0) {
65 			if (errno == ESRCH) {
66 				continue;
67 			}
68 			T_ASSERT_FAIL("proc_pidpath(%d) failed unexpectedly with errno %d", pid, errno);
69 		}
70 		count++;
71 
72 		memset(buffer, 0, sizeof(buffer));
73 
74 		audit_token_t token = INVALID_AUDIT_TOKEN_VALUE;
75 #ifdef USE_AUDIT_TOKEN_FOR_PID
76 		if (!audit_token_for_pid(pid, &token)) {
77 			T_ASSERT_FAIL("audit_token_for_pid(%d) failed", pid);
78 			continue;
79 		}
80 #else
81 		token.val[5] = (unsigned int)pid;
82 		token.val[7] = (unsigned int)idversion_for_pid(pid);
83 #endif
84 		ret = proc_pidpath_audittoken(&token, buffer, sizeof(buffer));
85 		if (ret <= 0) {
86 			if (errno == ESRCH) {
87 				continue;
88 			}
89 			T_ASSERT_FAIL("proc_pidpath_audittoken(%d) failed unexpectedly with errno %d", pid, errno);
90 		}
91 		T_PASS("%5d %s\n", pid, buffer);
92 
93 		token.val[7]--; /* Change to idversion so the next call fails */
94 		ret = proc_pidpath_audittoken(&token, buffer, sizeof(buffer));
95 		T_ASSERT_LE(ret, 0, "proc_pidpath_audittoken() failed as expected due to incorrect idversion");
96 		T_ASSERT_EQ(errno, ESRCH, "errno is ESRCH as expected");
97 	}
98 }
99 
100 T_DECL(proc_pidpath_audittoken, "Test proc_pidpath_audittoken()", T_META_ASROOT(false))
101 {
102 	show_pidpaths();
103 	T_PASS("Successfully tested prod_pidpath_audittoken()");
104 	T_END;
105 }
106