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