• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Author: Karl MacMillan <kmacmillan@tresys.com>
3  *
4  * Modified:
5  *   Dan Walsh <dwalsh@redhat.com> - Added security_load_booleans().
6  */
7 
8 #ifndef DISABLE_BOOL
9 
10 #include <assert.h>
11 #include <sys/types.h>
12 #include <sys/stat.h>
13 #include <fcntl.h>
14 #include <stdlib.h>
15 #include <dirent.h>
16 #include <string.h>
17 #include <stdio.h>
18 #include <stdio_ext.h>
19 #include <unistd.h>
20 #include <fnmatch.h>
21 #include <limits.h>
22 #include <ctype.h>
23 #include <errno.h>
24 
25 #include "selinux_internal.h"
26 #include "policy.h"
27 
28 #define SELINUX_BOOL_DIR "/booleans/"
29 
filename_select(const struct dirent * d)30 static int filename_select(const struct dirent *d)
31 {
32 	if (d->d_name[0] == '.'
33 	    && (d->d_name[1] == '\0'
34 		|| (d->d_name[1] == '.' && d->d_name[2] == '\0')))
35 		return 0;
36 	return 1;
37 }
38 
security_get_boolean_names(char *** names,int * len)39 int security_get_boolean_names(char ***names, int *len)
40 {
41 	char path[PATH_MAX];
42 	int i, rc;
43 	struct dirent **namelist;
44 	char **n;
45 
46 	if (!len || names == NULL) {
47 		errno = EINVAL;
48 		return -1;
49 	}
50 	if (!selinux_mnt) {
51 		errno = ENOENT;
52 		return -1;
53 	}
54 
55 	snprintf(path, sizeof path, "%s%s", selinux_mnt, SELINUX_BOOL_DIR);
56 	*len = scandir(path, &namelist, &filename_select, alphasort);
57 	if (*len <= 0) {
58 		errno = ENOENT;
59 		return -1;
60 	}
61 
62 	n = (char **)malloc(sizeof(char *) * *len);
63 	if (!n) {
64 		rc = -1;
65 		goto bad;
66 	}
67 
68 	for (i = 0; i < *len; i++) {
69 		n[i] = strdup(namelist[i]->d_name);
70 		if (!n[i]) {
71 			rc = -1;
72 			goto bad_freen;
73 		}
74 	}
75 	rc = 0;
76 	*names = n;
77       out:
78 	for (i = 0; i < *len; i++) {
79 		free(namelist[i]);
80 	}
81 	free(namelist);
82 	return rc;
83       bad_freen:
84 	if (i > 0) {
85 		while (i >= 1)
86 			free(n[--i]);
87 	}
88 	free(n);
89       bad:
90 	goto out;
91 }
92 
selinux_boolean_sub(const char * name)93 char *selinux_boolean_sub(const char *name)
94 {
95 	char *sub = NULL;
96 	char *line_buf = NULL;
97 	size_t line_len;
98 	FILE *cfg;
99 
100 	if (!name)
101 		return NULL;
102 
103 	cfg = fopen(selinux_booleans_subs_path(), "re");
104 	if (!cfg)
105 		goto out;
106 
107 	while (getline(&line_buf, &line_len, cfg) != -1) {
108 		char *ptr;
109 		char *src = line_buf;
110 		char *dst;
111 		while (*src && isspace(*src))
112 			src++;
113 		if (!*src)
114 			continue;
115 		if (src[0] == '#')
116 			continue;
117 
118 		ptr = src;
119 		while (*ptr && !isspace(*ptr))
120 			ptr++;
121 		*ptr++ = '\0';
122 		if (strcmp(src, name) != 0)
123 			continue;
124 
125 		dst = ptr;
126 		while (*dst && isspace(*dst))
127 			dst++;
128 		if (!*dst)
129 			continue;
130 		ptr = dst;
131 		while (*ptr && !isspace(*ptr))
132 			ptr++;
133 		*ptr = '\0';
134 
135 		sub = strdup(dst);
136 
137 		break;
138 	}
139 	free(line_buf);
140 	fclose(cfg);
141 out:
142 	if (!sub)
143 		sub = strdup(name);
144 	return sub;
145 }
146 
bool_open(const char * name,int flag)147 static int bool_open(const char *name, int flag) {
148 	char *fname = NULL;
149 	char *alt_name = NULL;
150 	int len;
151 	int fd = -1;
152 	int ret;
153 	char *ptr;
154 
155 	if (!name) {
156 		errno = EINVAL;
157 		return -1;
158 	}
159 
160 	/* note the 'sizeof' gets us enough room for the '\0' */
161 	len = strlen(name) + strlen(selinux_mnt) + sizeof(SELINUX_BOOL_DIR);
162 	fname = malloc(sizeof(char) * len);
163 	if (!fname)
164 		return -1;
165 
166 	ret = snprintf(fname, len, "%s%s%s", selinux_mnt, SELINUX_BOOL_DIR, name);
167 	if (ret < 0)
168 		goto out;
169 	assert(ret < len);
170 
171 	fd = open(fname, flag);
172 	if (fd >= 0 || errno != ENOENT)
173 		goto out;
174 
175 	alt_name = selinux_boolean_sub(name);
176 	if (!alt_name)
177 		goto out;
178 
179 	/* note the 'sizeof' gets us enough room for the '\0' */
180 	len = strlen(alt_name) + strlen(selinux_mnt) + sizeof(SELINUX_BOOL_DIR);
181 	ptr = realloc(fname, len);
182 	if (!ptr)
183 		goto out;
184 	fname = ptr;
185 
186 	ret = snprintf(fname, len, "%s%s%s", selinux_mnt, SELINUX_BOOL_DIR, alt_name);
187 	if (ret < 0)
188 		goto out;
189 	assert(ret < len);
190 
191 	fd = open(fname, flag);
192 out:
193 	free(fname);
194 	free(alt_name);
195 
196 	return fd;
197 }
198 
199 #define STRBUF_SIZE 3
get_bool_value(const char * name,char ** buf)200 static int get_bool_value(const char *name, char **buf)
201 {
202 	int fd, len;
203 	int errno_tmp;
204 
205 	if (!selinux_mnt) {
206 		errno = ENOENT;
207 		return -1;
208 	}
209 
210 	*buf = malloc(sizeof(char) * (STRBUF_SIZE + 1));
211 	if (!*buf)
212 		return -1;
213 
214 	(*buf)[STRBUF_SIZE] = 0;
215 
216 	fd = bool_open(name, O_RDONLY | O_CLOEXEC);
217 	if (fd < 0)
218 		goto out_err;
219 
220 	len = read(fd, *buf, STRBUF_SIZE);
221 	errno_tmp = errno;
222 	close(fd);
223 	errno = errno_tmp;
224 	if (len != STRBUF_SIZE)
225 		goto out_err;
226 
227 	return 0;
228 out_err:
229 	free(*buf);
230 	return -1;
231 }
232 
security_get_boolean_pending(const char * name)233 int security_get_boolean_pending(const char *name)
234 {
235 	char *buf;
236 	int val;
237 
238 	if (get_bool_value(name, &buf))
239 		return -1;
240 
241 	if (atoi(&buf[1]))
242 		val = 1;
243 	else
244 		val = 0;
245 	free(buf);
246 	return val;
247 }
248 
security_get_boolean_active(const char * name)249 int security_get_boolean_active(const char *name)
250 {
251 	char *buf;
252 	int val;
253 
254 	if (get_bool_value(name, &buf))
255 		return -1;
256 
257 	buf[1] = '\0';
258 	if (atoi(buf))
259 		val = 1;
260 	else
261 		val = 0;
262 	free(buf);
263 	return val;
264 }
265 
security_set_boolean(const char * name,int value)266 int security_set_boolean(const char *name, int value)
267 {
268 	int fd, ret;
269 	char buf[2];
270 
271 	if (!selinux_mnt) {
272 		errno = ENOENT;
273 		return -1;
274 	}
275 	if (value < 0 || value > 1) {
276 		errno = EINVAL;
277 		return -1;
278 	}
279 
280 	fd = bool_open(name, O_WRONLY | O_CLOEXEC);
281 	if (fd < 0)
282 		return -1;
283 
284 	if (value)
285 		buf[0] = '1';
286 	else
287 		buf[0] = '0';
288 	buf[1] = '\0';
289 
290 	ret = write(fd, buf, 2);
291 	close(fd);
292 
293 	if (ret > 0)
294 		return 0;
295 	else
296 		return -1;
297 }
298 
security_commit_booleans(void)299 int security_commit_booleans(void)
300 {
301 	int fd, ret;
302 	char buf[2];
303 	char path[PATH_MAX];
304 
305 	if (!selinux_mnt) {
306 		errno = ENOENT;
307 		return -1;
308 	}
309 
310 	snprintf(path, sizeof path, "%s/commit_pending_bools", selinux_mnt);
311 	fd = open(path, O_WRONLY | O_CLOEXEC);
312 	if (fd < 0)
313 		return -1;
314 
315 	buf[0] = '1';
316 	buf[1] = '\0';
317 
318 	ret = write(fd, buf, 2);
319 	close(fd);
320 
321 	if (ret > 0)
322 		return 0;
323 	else
324 		return -1;
325 }
326 
rollback(SELboolean * boollist,int end)327 static void rollback(SELboolean * boollist, int end)
328 {
329 	int i;
330 
331 	for (i = 0; i < end; i++)
332 		security_set_boolean(boollist[i].name,
333 				     security_get_boolean_active(boollist[i].
334 								 name));
335 }
336 
security_set_boolean_list(size_t boolcnt,SELboolean * boollist,int permanent)337 int security_set_boolean_list(size_t boolcnt, SELboolean * boollist,
338 			      int permanent)
339 {
340 
341 	size_t i;
342 	for (i = 0; i < boolcnt; i++) {
343 		boollist[i].value = !!boollist[i].value;
344 		if (security_set_boolean(boollist[i].name, boollist[i].value)) {
345 			rollback(boollist, i);
346 			return -1;
347 		}
348 	}
349 
350 	/* OK, let's do the commit */
351 	if (security_commit_booleans()) {
352 		return -1;
353 	}
354 
355 	/* Return error as flag no longer used */
356 	if (permanent)
357 		return -1;
358 
359 	return 0;
360 }
361 
362 /* This function is deprecated */
security_load_booleans(char * path)363 int security_load_booleans(char *path __attribute__((unused)))
364 {
365 	return -1;
366 }
367 #else
368 
369 #include <stdlib.h>
370 #include "selinux_internal.h"
371 
security_set_boolean_list(size_t boolcnt,SELboolean * boollist,int permanent)372 int security_set_boolean_list(size_t boolcnt __attribute__((unused)),
373 	SELboolean * boollist __attribute__((unused)),
374 	int permanent __attribute__((unused)))
375 {
376 	return -1;
377 }
378 
security_load_booleans(char * path)379 int security_load_booleans(char *path __attribute__((unused)))
380 {
381 	return -1;
382 }
383 
security_get_boolean_names(char *** names,int * len)384 int security_get_boolean_names(char ***names __attribute__((unused)),
385 	int *len __attribute__((unused)))
386 {
387 	return -1;
388 }
389 
security_get_boolean_pending(const char * name)390 int security_get_boolean_pending(const char *name __attribute__((unused)))
391 {
392 	return -1;
393 }
394 
security_get_boolean_active(const char * name)395 int security_get_boolean_active(const char *name __attribute__((unused)))
396 {
397 	return -1;
398 }
399 
security_set_boolean(const char * name,int value)400 int security_set_boolean(const char *name __attribute__((unused)),
401 	int value __attribute__((unused)))
402 {
403 	return -1;
404 }
405 
security_commit_booleans(void)406 int security_commit_booleans(void)
407 {
408 	return -1;
409 }
410 
selinux_boolean_sub(const char * name)411 char *selinux_boolean_sub(const char *name __attribute__((unused)))
412 {
413 	return NULL;
414 }
415 #endif
416 
417 hidden_def(security_get_boolean_names)
418 hidden_def(selinux_boolean_sub)
419 hidden_def(security_get_boolean_active)
420 hidden_def(security_set_boolean)
421 hidden_def(security_commit_booleans)
422