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