xref: /aosp_15_r20/external/selinux/libselinux/src/stringrep.c (revision 2d543d20722ada2425b5bdab9d0d1d29470e7bba)
1*2d543d20SAndroid Build Coastguard Worker /*
2*2d543d20SAndroid Build Coastguard Worker  * String representation support for classes and permissions.
3*2d543d20SAndroid Build Coastguard Worker  */
4*2d543d20SAndroid Build Coastguard Worker #include <sys/stat.h>
5*2d543d20SAndroid Build Coastguard Worker #include <dirent.h>
6*2d543d20SAndroid Build Coastguard Worker #include <fcntl.h>
7*2d543d20SAndroid Build Coastguard Worker #include <limits.h>
8*2d543d20SAndroid Build Coastguard Worker #include <unistd.h>
9*2d543d20SAndroid Build Coastguard Worker #include <errno.h>
10*2d543d20SAndroid Build Coastguard Worker #include <stddef.h>
11*2d543d20SAndroid Build Coastguard Worker #include <stdio.h>
12*2d543d20SAndroid Build Coastguard Worker #include <stdlib.h>
13*2d543d20SAndroid Build Coastguard Worker #include <string.h>
14*2d543d20SAndroid Build Coastguard Worker #include <stdint.h>
15*2d543d20SAndroid Build Coastguard Worker #include <ctype.h>
16*2d543d20SAndroid Build Coastguard Worker #include "selinux_internal.h"
17*2d543d20SAndroid Build Coastguard Worker #include "policy.h"
18*2d543d20SAndroid Build Coastguard Worker #include "mapping.h"
19*2d543d20SAndroid Build Coastguard Worker 
20*2d543d20SAndroid Build Coastguard Worker #define MAXVECTORS 8*sizeof(access_vector_t)
21*2d543d20SAndroid Build Coastguard Worker 
22*2d543d20SAndroid Build Coastguard Worker struct discover_class_node {
23*2d543d20SAndroid Build Coastguard Worker 	char *name;
24*2d543d20SAndroid Build Coastguard Worker 	security_class_t value;
25*2d543d20SAndroid Build Coastguard Worker 	char **perms;
26*2d543d20SAndroid Build Coastguard Worker 
27*2d543d20SAndroid Build Coastguard Worker 	struct discover_class_node *next;
28*2d543d20SAndroid Build Coastguard Worker };
29*2d543d20SAndroid Build Coastguard Worker 
30*2d543d20SAndroid Build Coastguard Worker static struct discover_class_node *discover_class_cache = NULL;
31*2d543d20SAndroid Build Coastguard Worker 
get_class_cache_entry_name(const char * s)32*2d543d20SAndroid Build Coastguard Worker static struct discover_class_node * get_class_cache_entry_name(const char *s)
33*2d543d20SAndroid Build Coastguard Worker {
34*2d543d20SAndroid Build Coastguard Worker 	struct discover_class_node *node = discover_class_cache;
35*2d543d20SAndroid Build Coastguard Worker 
36*2d543d20SAndroid Build Coastguard Worker 	for (; node != NULL && strcmp(s,node->name) != 0; node = node->next);
37*2d543d20SAndroid Build Coastguard Worker 
38*2d543d20SAndroid Build Coastguard Worker 	return node;
39*2d543d20SAndroid Build Coastguard Worker }
40*2d543d20SAndroid Build Coastguard Worker 
get_class_cache_entry_value(security_class_t c)41*2d543d20SAndroid Build Coastguard Worker static struct discover_class_node * get_class_cache_entry_value(security_class_t c)
42*2d543d20SAndroid Build Coastguard Worker {
43*2d543d20SAndroid Build Coastguard Worker 	struct discover_class_node *node = discover_class_cache;
44*2d543d20SAndroid Build Coastguard Worker 
45*2d543d20SAndroid Build Coastguard Worker 	for (; node != NULL && c != node->value; node = node->next);
46*2d543d20SAndroid Build Coastguard Worker 
47*2d543d20SAndroid Build Coastguard Worker 	return node;
48*2d543d20SAndroid Build Coastguard Worker }
49*2d543d20SAndroid Build Coastguard Worker 
discover_class(const char * s)50*2d543d20SAndroid Build Coastguard Worker static struct discover_class_node * discover_class(const char *s)
51*2d543d20SAndroid Build Coastguard Worker {
52*2d543d20SAndroid Build Coastguard Worker 	int fd, ret;
53*2d543d20SAndroid Build Coastguard Worker 	char path[PATH_MAX];
54*2d543d20SAndroid Build Coastguard Worker 	char buf[20];
55*2d543d20SAndroid Build Coastguard Worker 	DIR *dir;
56*2d543d20SAndroid Build Coastguard Worker 	struct dirent *dentry;
57*2d543d20SAndroid Build Coastguard Worker 	size_t i;
58*2d543d20SAndroid Build Coastguard Worker 
59*2d543d20SAndroid Build Coastguard Worker 	struct discover_class_node *node;
60*2d543d20SAndroid Build Coastguard Worker 
61*2d543d20SAndroid Build Coastguard Worker 	if (!selinux_mnt) {
62*2d543d20SAndroid Build Coastguard Worker 		errno = ENOENT;
63*2d543d20SAndroid Build Coastguard Worker 		return NULL;
64*2d543d20SAndroid Build Coastguard Worker 	}
65*2d543d20SAndroid Build Coastguard Worker 
66*2d543d20SAndroid Build Coastguard Worker 	if (strchr(s, '/') != NULL)
67*2d543d20SAndroid Build Coastguard Worker 		return NULL;
68*2d543d20SAndroid Build Coastguard Worker 
69*2d543d20SAndroid Build Coastguard Worker 	/* allocate a node */
70*2d543d20SAndroid Build Coastguard Worker 	node = malloc(sizeof(struct discover_class_node));
71*2d543d20SAndroid Build Coastguard Worker 	if (node == NULL)
72*2d543d20SAndroid Build Coastguard Worker 		return NULL;
73*2d543d20SAndroid Build Coastguard Worker 
74*2d543d20SAndroid Build Coastguard Worker 	/* allocate array for perms */
75*2d543d20SAndroid Build Coastguard Worker 	node->perms = calloc(MAXVECTORS,sizeof(char*));
76*2d543d20SAndroid Build Coastguard Worker 	if (node->perms == NULL)
77*2d543d20SAndroid Build Coastguard Worker 		goto err1;
78*2d543d20SAndroid Build Coastguard Worker 
79*2d543d20SAndroid Build Coastguard Worker 	/* load up the name */
80*2d543d20SAndroid Build Coastguard Worker 	node->name = strdup(s);
81*2d543d20SAndroid Build Coastguard Worker 	if (node->name == NULL)
82*2d543d20SAndroid Build Coastguard Worker 		goto err2;
83*2d543d20SAndroid Build Coastguard Worker 
84*2d543d20SAndroid Build Coastguard Worker 	/* load up class index */
85*2d543d20SAndroid Build Coastguard Worker 	ret = snprintf(path, sizeof path, "%s/class/%s/index", selinux_mnt,s);
86*2d543d20SAndroid Build Coastguard Worker 	if (ret < 0 || (size_t)ret >= sizeof path)
87*2d543d20SAndroid Build Coastguard Worker 		goto err3;
88*2d543d20SAndroid Build Coastguard Worker 
89*2d543d20SAndroid Build Coastguard Worker 	fd = open(path, O_RDONLY | O_CLOEXEC);
90*2d543d20SAndroid Build Coastguard Worker 	if (fd < 0)
91*2d543d20SAndroid Build Coastguard Worker 		goto err3;
92*2d543d20SAndroid Build Coastguard Worker 
93*2d543d20SAndroid Build Coastguard Worker 	memset(buf, 0, sizeof(buf));
94*2d543d20SAndroid Build Coastguard Worker 	ret = read(fd, buf, sizeof(buf) - 1);
95*2d543d20SAndroid Build Coastguard Worker 	close(fd);
96*2d543d20SAndroid Build Coastguard Worker 	if (ret < 0)
97*2d543d20SAndroid Build Coastguard Worker 		goto err3;
98*2d543d20SAndroid Build Coastguard Worker 
99*2d543d20SAndroid Build Coastguard Worker 	if (sscanf(buf, "%hu", &node->value) != 1)
100*2d543d20SAndroid Build Coastguard Worker 		goto err3;
101*2d543d20SAndroid Build Coastguard Worker 
102*2d543d20SAndroid Build Coastguard Worker 	/* load up permission indices */
103*2d543d20SAndroid Build Coastguard Worker 	ret = snprintf(path, sizeof path, "%s/class/%s/perms",selinux_mnt,s);
104*2d543d20SAndroid Build Coastguard Worker 	if (ret < 0 || (size_t)ret >= sizeof path)
105*2d543d20SAndroid Build Coastguard Worker 		goto err3;
106*2d543d20SAndroid Build Coastguard Worker 
107*2d543d20SAndroid Build Coastguard Worker 	dir = opendir(path);
108*2d543d20SAndroid Build Coastguard Worker 	if (dir == NULL)
109*2d543d20SAndroid Build Coastguard Worker 		goto err3;
110*2d543d20SAndroid Build Coastguard Worker 
111*2d543d20SAndroid Build Coastguard Worker 	dentry = readdir(dir);
112*2d543d20SAndroid Build Coastguard Worker 	while (dentry != NULL) {
113*2d543d20SAndroid Build Coastguard Worker 		unsigned int value;
114*2d543d20SAndroid Build Coastguard Worker 		struct stat m;
115*2d543d20SAndroid Build Coastguard Worker 
116*2d543d20SAndroid Build Coastguard Worker 		ret = snprintf(path, sizeof path, "%s/class/%s/perms/%s", selinux_mnt,s,dentry->d_name);
117*2d543d20SAndroid Build Coastguard Worker 		if (ret < 0 || (size_t)ret >= sizeof path)
118*2d543d20SAndroid Build Coastguard Worker 			goto err4;
119*2d543d20SAndroid Build Coastguard Worker 
120*2d543d20SAndroid Build Coastguard Worker 		fd = open(path, O_RDONLY | O_CLOEXEC);
121*2d543d20SAndroid Build Coastguard Worker 		if (fd < 0)
122*2d543d20SAndroid Build Coastguard Worker 			goto err4;
123*2d543d20SAndroid Build Coastguard Worker 
124*2d543d20SAndroid Build Coastguard Worker 		if (fstat(fd, &m) < 0) {
125*2d543d20SAndroid Build Coastguard Worker 			close(fd);
126*2d543d20SAndroid Build Coastguard Worker 			goto err4;
127*2d543d20SAndroid Build Coastguard Worker 		}
128*2d543d20SAndroid Build Coastguard Worker 
129*2d543d20SAndroid Build Coastguard Worker 		if (m.st_mode & S_IFDIR) {
130*2d543d20SAndroid Build Coastguard Worker 			close(fd);
131*2d543d20SAndroid Build Coastguard Worker 			dentry = readdir(dir);
132*2d543d20SAndroid Build Coastguard Worker 			continue;
133*2d543d20SAndroid Build Coastguard Worker 		}
134*2d543d20SAndroid Build Coastguard Worker 
135*2d543d20SAndroid Build Coastguard Worker 		memset(buf, 0, sizeof(buf));
136*2d543d20SAndroid Build Coastguard Worker 		ret = read(fd, buf, sizeof(buf) - 1);
137*2d543d20SAndroid Build Coastguard Worker 		close(fd);
138*2d543d20SAndroid Build Coastguard Worker 		if (ret < 0)
139*2d543d20SAndroid Build Coastguard Worker 			goto err4;
140*2d543d20SAndroid Build Coastguard Worker 
141*2d543d20SAndroid Build Coastguard Worker 		if (sscanf(buf, "%u", &value) != 1)
142*2d543d20SAndroid Build Coastguard Worker 			goto err4;
143*2d543d20SAndroid Build Coastguard Worker 
144*2d543d20SAndroid Build Coastguard Worker 		if (value == 0 || value > MAXVECTORS)
145*2d543d20SAndroid Build Coastguard Worker 			goto err4;
146*2d543d20SAndroid Build Coastguard Worker 
147*2d543d20SAndroid Build Coastguard Worker 		node->perms[value-1] = strdup(dentry->d_name);
148*2d543d20SAndroid Build Coastguard Worker 		if (node->perms[value-1] == NULL)
149*2d543d20SAndroid Build Coastguard Worker 			goto err4;
150*2d543d20SAndroid Build Coastguard Worker 
151*2d543d20SAndroid Build Coastguard Worker 		dentry = readdir(dir);
152*2d543d20SAndroid Build Coastguard Worker 	}
153*2d543d20SAndroid Build Coastguard Worker 	closedir(dir);
154*2d543d20SAndroid Build Coastguard Worker 
155*2d543d20SAndroid Build Coastguard Worker 	node->next = discover_class_cache;
156*2d543d20SAndroid Build Coastguard Worker 	discover_class_cache = node;
157*2d543d20SAndroid Build Coastguard Worker 
158*2d543d20SAndroid Build Coastguard Worker 	return node;
159*2d543d20SAndroid Build Coastguard Worker 
160*2d543d20SAndroid Build Coastguard Worker err4:
161*2d543d20SAndroid Build Coastguard Worker 	closedir(dir);
162*2d543d20SAndroid Build Coastguard Worker 	for (i = 0; i < MAXVECTORS; i++)
163*2d543d20SAndroid Build Coastguard Worker 		free(node->perms[i]);
164*2d543d20SAndroid Build Coastguard Worker err3:
165*2d543d20SAndroid Build Coastguard Worker 	free(node->name);
166*2d543d20SAndroid Build Coastguard Worker err2:
167*2d543d20SAndroid Build Coastguard Worker 	free(node->perms);
168*2d543d20SAndroid Build Coastguard Worker err1:
169*2d543d20SAndroid Build Coastguard Worker 	free(node);
170*2d543d20SAndroid Build Coastguard Worker 	return NULL;
171*2d543d20SAndroid Build Coastguard Worker }
172*2d543d20SAndroid Build Coastguard Worker 
selinux_flush_class_cache(void)173*2d543d20SAndroid Build Coastguard Worker void selinux_flush_class_cache(void)
174*2d543d20SAndroid Build Coastguard Worker {
175*2d543d20SAndroid Build Coastguard Worker 	struct discover_class_node *cur = discover_class_cache, *prev = NULL;
176*2d543d20SAndroid Build Coastguard Worker 	size_t i;
177*2d543d20SAndroid Build Coastguard Worker 
178*2d543d20SAndroid Build Coastguard Worker 	while (cur != NULL) {
179*2d543d20SAndroid Build Coastguard Worker 		free(cur->name);
180*2d543d20SAndroid Build Coastguard Worker 
181*2d543d20SAndroid Build Coastguard Worker 		for (i = 0; i < MAXVECTORS; i++)
182*2d543d20SAndroid Build Coastguard Worker 			free(cur->perms[i]);
183*2d543d20SAndroid Build Coastguard Worker 
184*2d543d20SAndroid Build Coastguard Worker 		free(cur->perms);
185*2d543d20SAndroid Build Coastguard Worker 
186*2d543d20SAndroid Build Coastguard Worker 		prev = cur;
187*2d543d20SAndroid Build Coastguard Worker 		cur = cur->next;
188*2d543d20SAndroid Build Coastguard Worker 
189*2d543d20SAndroid Build Coastguard Worker 		free(prev);
190*2d543d20SAndroid Build Coastguard Worker 	}
191*2d543d20SAndroid Build Coastguard Worker 
192*2d543d20SAndroid Build Coastguard Worker 	discover_class_cache = NULL;
193*2d543d20SAndroid Build Coastguard Worker }
194*2d543d20SAndroid Build Coastguard Worker 
195*2d543d20SAndroid Build Coastguard Worker 
string_to_security_class(const char * s)196*2d543d20SAndroid Build Coastguard Worker security_class_t string_to_security_class(const char *s)
197*2d543d20SAndroid Build Coastguard Worker {
198*2d543d20SAndroid Build Coastguard Worker 	struct discover_class_node *node;
199*2d543d20SAndroid Build Coastguard Worker 
200*2d543d20SAndroid Build Coastguard Worker 	node = get_class_cache_entry_name(s);
201*2d543d20SAndroid Build Coastguard Worker 	if (node == NULL) {
202*2d543d20SAndroid Build Coastguard Worker 		node = discover_class(s);
203*2d543d20SAndroid Build Coastguard Worker 
204*2d543d20SAndroid Build Coastguard Worker 		if (node == NULL) {
205*2d543d20SAndroid Build Coastguard Worker 			errno = EINVAL;
206*2d543d20SAndroid Build Coastguard Worker 			return 0;
207*2d543d20SAndroid Build Coastguard Worker 		}
208*2d543d20SAndroid Build Coastguard Worker 	}
209*2d543d20SAndroid Build Coastguard Worker 
210*2d543d20SAndroid Build Coastguard Worker 	return map_class(node->value);
211*2d543d20SAndroid Build Coastguard Worker }
212*2d543d20SAndroid Build Coastguard Worker 
mode_to_security_class(mode_t m)213*2d543d20SAndroid Build Coastguard Worker security_class_t mode_to_security_class(mode_t m) {
214*2d543d20SAndroid Build Coastguard Worker 
215*2d543d20SAndroid Build Coastguard Worker 	if (S_ISREG(m))
216*2d543d20SAndroid Build Coastguard Worker 		return string_to_security_class("file");
217*2d543d20SAndroid Build Coastguard Worker 	if (S_ISDIR(m))
218*2d543d20SAndroid Build Coastguard Worker 		return string_to_security_class("dir");
219*2d543d20SAndroid Build Coastguard Worker 	if (S_ISCHR(m))
220*2d543d20SAndroid Build Coastguard Worker 		return string_to_security_class("chr_file");
221*2d543d20SAndroid Build Coastguard Worker 	if (S_ISBLK(m))
222*2d543d20SAndroid Build Coastguard Worker 		return string_to_security_class("blk_file");
223*2d543d20SAndroid Build Coastguard Worker 	if (S_ISFIFO(m))
224*2d543d20SAndroid Build Coastguard Worker 		return string_to_security_class("fifo_file");
225*2d543d20SAndroid Build Coastguard Worker 	if (S_ISLNK(m))
226*2d543d20SAndroid Build Coastguard Worker 		return string_to_security_class("lnk_file");
227*2d543d20SAndroid Build Coastguard Worker 	if (S_ISSOCK(m))
228*2d543d20SAndroid Build Coastguard Worker 		return string_to_security_class("sock_file");
229*2d543d20SAndroid Build Coastguard Worker 
230*2d543d20SAndroid Build Coastguard Worker 	errno = EINVAL;
231*2d543d20SAndroid Build Coastguard Worker 	return 0;
232*2d543d20SAndroid Build Coastguard Worker }
233*2d543d20SAndroid Build Coastguard Worker 
string_to_av_perm(security_class_t tclass,const char * s)234*2d543d20SAndroid Build Coastguard Worker access_vector_t string_to_av_perm(security_class_t tclass, const char *s)
235*2d543d20SAndroid Build Coastguard Worker {
236*2d543d20SAndroid Build Coastguard Worker 	struct discover_class_node *node;
237*2d543d20SAndroid Build Coastguard Worker 	security_class_t kclass = unmap_class(tclass);
238*2d543d20SAndroid Build Coastguard Worker 
239*2d543d20SAndroid Build Coastguard Worker 	node = get_class_cache_entry_value(kclass);
240*2d543d20SAndroid Build Coastguard Worker 	if (node != NULL) {
241*2d543d20SAndroid Build Coastguard Worker 		size_t i;
242*2d543d20SAndroid Build Coastguard Worker 		for (i = 0; i < MAXVECTORS && node->perms[i] != NULL; i++)
243*2d543d20SAndroid Build Coastguard Worker 			if (strcmp(node->perms[i],s) == 0)
244*2d543d20SAndroid Build Coastguard Worker 				return map_perm(tclass, UINT32_C(1)<<i);
245*2d543d20SAndroid Build Coastguard Worker 	}
246*2d543d20SAndroid Build Coastguard Worker 
247*2d543d20SAndroid Build Coastguard Worker 	errno = EINVAL;
248*2d543d20SAndroid Build Coastguard Worker 	return 0;
249*2d543d20SAndroid Build Coastguard Worker }
250*2d543d20SAndroid Build Coastguard Worker 
security_class_to_string(security_class_t tclass)251*2d543d20SAndroid Build Coastguard Worker const char *security_class_to_string(security_class_t tclass)
252*2d543d20SAndroid Build Coastguard Worker {
253*2d543d20SAndroid Build Coastguard Worker 	struct discover_class_node *node;
254*2d543d20SAndroid Build Coastguard Worker 
255*2d543d20SAndroid Build Coastguard Worker 	tclass = unmap_class(tclass);
256*2d543d20SAndroid Build Coastguard Worker 
257*2d543d20SAndroid Build Coastguard Worker 	node = get_class_cache_entry_value(tclass);
258*2d543d20SAndroid Build Coastguard Worker 	if (node == NULL)
259*2d543d20SAndroid Build Coastguard Worker 		return NULL;
260*2d543d20SAndroid Build Coastguard Worker 	else
261*2d543d20SAndroid Build Coastguard Worker 		return node->name;
262*2d543d20SAndroid Build Coastguard Worker }
263*2d543d20SAndroid Build Coastguard Worker 
security_av_perm_to_string(security_class_t tclass,access_vector_t av)264*2d543d20SAndroid Build Coastguard Worker const char *security_av_perm_to_string(security_class_t tclass,
265*2d543d20SAndroid Build Coastguard Worker 				       access_vector_t av)
266*2d543d20SAndroid Build Coastguard Worker {
267*2d543d20SAndroid Build Coastguard Worker 	struct discover_class_node *node;
268*2d543d20SAndroid Build Coastguard Worker 	size_t i;
269*2d543d20SAndroid Build Coastguard Worker 
270*2d543d20SAndroid Build Coastguard Worker 	av = unmap_perm(tclass, av);
271*2d543d20SAndroid Build Coastguard Worker 	tclass = unmap_class(tclass);
272*2d543d20SAndroid Build Coastguard Worker 
273*2d543d20SAndroid Build Coastguard Worker 	node = get_class_cache_entry_value(tclass);
274*2d543d20SAndroid Build Coastguard Worker 	if (av && node)
275*2d543d20SAndroid Build Coastguard Worker 		for (i = 0; i<MAXVECTORS; i++)
276*2d543d20SAndroid Build Coastguard Worker 			if ((UINT32_C(1)<<i) & av)
277*2d543d20SAndroid Build Coastguard Worker 				return node->perms[i];
278*2d543d20SAndroid Build Coastguard Worker 
279*2d543d20SAndroid Build Coastguard Worker 	return NULL;
280*2d543d20SAndroid Build Coastguard Worker }
281*2d543d20SAndroid Build Coastguard Worker 
security_av_string(security_class_t tclass,access_vector_t av,char ** res)282*2d543d20SAndroid Build Coastguard Worker int security_av_string(security_class_t tclass, access_vector_t av, char **res)
283*2d543d20SAndroid Build Coastguard Worker {
284*2d543d20SAndroid Build Coastguard Worker 	unsigned int i;
285*2d543d20SAndroid Build Coastguard Worker 	size_t len = 5;
286*2d543d20SAndroid Build Coastguard Worker 	access_vector_t tmp = av;
287*2d543d20SAndroid Build Coastguard Worker 	int rc = 0;
288*2d543d20SAndroid Build Coastguard Worker 	const char *str;
289*2d543d20SAndroid Build Coastguard Worker 	char *ptr;
290*2d543d20SAndroid Build Coastguard Worker 
291*2d543d20SAndroid Build Coastguard Worker 	/* first pass computes the required length */
292*2d543d20SAndroid Build Coastguard Worker 	for (i = 0; tmp; tmp >>= 1, i++) {
293*2d543d20SAndroid Build Coastguard Worker 		if (tmp & 1) {
294*2d543d20SAndroid Build Coastguard Worker 			str = security_av_perm_to_string(tclass, av & (UINT32_C(1)<<i));
295*2d543d20SAndroid Build Coastguard Worker 			if (str)
296*2d543d20SAndroid Build Coastguard Worker 				len += strlen(str) + 1;
297*2d543d20SAndroid Build Coastguard Worker 		}
298*2d543d20SAndroid Build Coastguard Worker 	}
299*2d543d20SAndroid Build Coastguard Worker 
300*2d543d20SAndroid Build Coastguard Worker 	*res = malloc(len);
301*2d543d20SAndroid Build Coastguard Worker 	if (!*res) {
302*2d543d20SAndroid Build Coastguard Worker 		rc = -1;
303*2d543d20SAndroid Build Coastguard Worker 		goto out;
304*2d543d20SAndroid Build Coastguard Worker 	}
305*2d543d20SAndroid Build Coastguard Worker 
306*2d543d20SAndroid Build Coastguard Worker 	/* second pass constructs the string */
307*2d543d20SAndroid Build Coastguard Worker 	tmp = av;
308*2d543d20SAndroid Build Coastguard Worker 	ptr = *res;
309*2d543d20SAndroid Build Coastguard Worker 
310*2d543d20SAndroid Build Coastguard Worker 	if (!av) {
311*2d543d20SAndroid Build Coastguard Worker 		sprintf(ptr, "null");
312*2d543d20SAndroid Build Coastguard Worker 		goto out;
313*2d543d20SAndroid Build Coastguard Worker 	}
314*2d543d20SAndroid Build Coastguard Worker 
315*2d543d20SAndroid Build Coastguard Worker 	ptr += sprintf(ptr, "{ ");
316*2d543d20SAndroid Build Coastguard Worker 	for (i = 0; tmp; tmp >>= 1, i++) {
317*2d543d20SAndroid Build Coastguard Worker 		if (tmp & 1) {
318*2d543d20SAndroid Build Coastguard Worker 			str = security_av_perm_to_string(tclass, av & (UINT32_C(1)<<i));
319*2d543d20SAndroid Build Coastguard Worker 			if (str)
320*2d543d20SAndroid Build Coastguard Worker 				ptr += sprintf(ptr, "%s ", str);
321*2d543d20SAndroid Build Coastguard Worker 		}
322*2d543d20SAndroid Build Coastguard Worker 	}
323*2d543d20SAndroid Build Coastguard Worker 	sprintf(ptr, "}");
324*2d543d20SAndroid Build Coastguard Worker out:
325*2d543d20SAndroid Build Coastguard Worker 	return rc;
326*2d543d20SAndroid Build Coastguard Worker }
327*2d543d20SAndroid Build Coastguard Worker 
print_access_vector(security_class_t tclass,access_vector_t av)328*2d543d20SAndroid Build Coastguard Worker void print_access_vector(security_class_t tclass, access_vector_t av)
329*2d543d20SAndroid Build Coastguard Worker {
330*2d543d20SAndroid Build Coastguard Worker 	const char *permstr;
331*2d543d20SAndroid Build Coastguard Worker 	access_vector_t bit = 1;
332*2d543d20SAndroid Build Coastguard Worker 
333*2d543d20SAndroid Build Coastguard Worker 	if (av == 0) {
334*2d543d20SAndroid Build Coastguard Worker 		printf(" null");
335*2d543d20SAndroid Build Coastguard Worker 		return;
336*2d543d20SAndroid Build Coastguard Worker 	}
337*2d543d20SAndroid Build Coastguard Worker 
338*2d543d20SAndroid Build Coastguard Worker 	printf(" {");
339*2d543d20SAndroid Build Coastguard Worker 
340*2d543d20SAndroid Build Coastguard Worker 	for (;;) {
341*2d543d20SAndroid Build Coastguard Worker 		if (av & bit) {
342*2d543d20SAndroid Build Coastguard Worker 			permstr = security_av_perm_to_string(tclass, bit);
343*2d543d20SAndroid Build Coastguard Worker 			if (!permstr)
344*2d543d20SAndroid Build Coastguard Worker 				break;
345*2d543d20SAndroid Build Coastguard Worker 			printf(" %s", permstr);
346*2d543d20SAndroid Build Coastguard Worker 			av &= ~bit;
347*2d543d20SAndroid Build Coastguard Worker 			if (!av)
348*2d543d20SAndroid Build Coastguard Worker 				break;
349*2d543d20SAndroid Build Coastguard Worker 		}
350*2d543d20SAndroid Build Coastguard Worker 		bit <<= 1;
351*2d543d20SAndroid Build Coastguard Worker 	}
352*2d543d20SAndroid Build Coastguard Worker 
353*2d543d20SAndroid Build Coastguard Worker 	if (av)
354*2d543d20SAndroid Build Coastguard Worker 		printf(" 0x%x", av);
355*2d543d20SAndroid Build Coastguard Worker 	printf(" }");
356*2d543d20SAndroid Build Coastguard Worker }
357