• 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 #include <sys/types.h>
9 #include <sys/stat.h>
10 #include <fcntl.h>
11 #include <assert.h>
12 #include <stdlib.h>
13 #include <dirent.h>
14 #include <string.h>
15 #include <stdio.h>
16 #include <unistd.h>
17 #include <fnmatch.h>
18 #include <limits.h>
19 #include <ctype.h>
20 #include <errno.h>
21 
22 #include "selinux_internal.h"
23 #include "policy.h"
24 
25 #define SELINUX_BOOL_DIR "/booleans/"
26 
filename_select(const struct dirent * d)27 static int filename_select(const struct dirent *d)
28 {
29 	if (d->d_name[0] == '.'
30 	    && (d->d_name[1] == '\0'
31 		|| (d->d_name[1] == '.' && d->d_name[2] == '\0')))
32 		return 0;
33 	return 1;
34 }
35 
security_get_boolean_names(char *** names,int * len)36 int security_get_boolean_names(char ***names, int *len)
37 {
38 	char path[PATH_MAX];
39 	int i, rc;
40 	struct dirent **namelist;
41 	char **n;
42 
43 	assert(len);
44 	if (!selinux_mnt) {
45 		errno = ENOENT;
46 		return -1;
47 	}
48 
49 	snprintf(path, sizeof path, "%s%s", selinux_mnt, SELINUX_BOOL_DIR);
50 	*len = scandir(path, &namelist, &filename_select, alphasort);
51 	if (*len <= 0) {
52 		return -1;
53 	}
54 
55 	n = (char **)malloc(sizeof(char *) * *len);
56 	if (!n) {
57 		rc = -1;
58 		goto bad;
59 	}
60 
61 	for (i = 0; i < *len; i++) {
62 	        n[i] = strdup(namelist[i]->d_name);
63 		if (!n[i]) {
64 			rc = -1;
65 			goto bad_freen;
66 		}
67 	}
68 	rc = 0;
69 	*names = n;
70       out:
71 	for (i = 0; i < *len; i++) {
72 		free(namelist[i]);
73 	}
74 	free(namelist);
75 	return rc;
76       bad_freen:
77 	for (--i; i >= 0; --i)
78 		free(n[i]);
79 	free(n);
80       bad:
81 	goto out;
82 }
83 
hidden_def(security_get_boolean_names)84 hidden_def(security_get_boolean_names)
85 #define STRBUF_SIZE 3
86 static int get_bool_value(const char *name, char **buf)
87 {
88 	int fd, len;
89 	char *fname = NULL;
90 
91 	if (!selinux_mnt) {
92 		errno = ENOENT;
93 		return -1;
94 	}
95 
96 	*buf = (char *)malloc(sizeof(char) * (STRBUF_SIZE + 1));
97 	if (!*buf)
98 		goto out;
99 	(*buf)[STRBUF_SIZE] = 0;
100 
101 	len = strlen(name) + strlen(selinux_mnt) + sizeof(SELINUX_BOOL_DIR);
102 	fname = (char *)malloc(sizeof(char) * len);
103 	if (!fname)
104 		goto out;
105 	snprintf(fname, len, "%s%s%s", selinux_mnt, SELINUX_BOOL_DIR, name);
106 
107 	fd = open(fname, O_RDONLY);
108 	if (fd < 0)
109 		goto out;
110 
111 	len = read(fd, *buf, STRBUF_SIZE);
112 	close(fd);
113 	if (len != STRBUF_SIZE)
114 		goto out;
115 
116 	free(fname);
117 	return 0;
118       out:
119 	if (*buf)
120 		free(*buf);
121 	if (fname)
122 		free(fname);
123 	return -1;
124 }
125 
security_get_boolean_pending(const char * name)126 int security_get_boolean_pending(const char *name)
127 {
128 	char *buf;
129 	int val;
130 
131 	if (get_bool_value(name, &buf))
132 		return -1;
133 
134 	if (atoi(&buf[1]))
135 		val = 1;
136 	else
137 		val = 0;
138 	free(buf);
139 	return val;
140 }
141 
security_get_boolean_active(const char * name)142 int security_get_boolean_active(const char *name)
143 {
144 	char *buf;
145 	int val;
146 
147 	if (get_bool_value(name, &buf))
148 		return -1;
149 
150 	buf[1] = '\0';
151 	if (atoi(buf))
152 		val = 1;
153 	else
154 		val = 0;
155 	free(buf);
156 	return val;
157 }
158 
hidden_def(security_get_boolean_active)159 hidden_def(security_get_boolean_active)
160 
161 int security_set_boolean(const char *name, int value)
162 {
163 	int fd, ret, len;
164 	char buf[2], *fname;
165 
166 	if (!selinux_mnt) {
167 		errno = ENOENT;
168 		return -1;
169 	}
170 	if (value < 0 || value > 1) {
171 		errno = EINVAL;
172 		return -1;
173 	}
174 
175 	len = strlen(name) + strlen(selinux_mnt) + sizeof(SELINUX_BOOL_DIR);
176 	fname = (char *)malloc(sizeof(char) * len);
177 	if (!fname)
178 		return -1;
179 	snprintf(fname, len, "%s%s%s", selinux_mnt, SELINUX_BOOL_DIR, name);
180 
181 	fd = open(fname, O_WRONLY);
182 	if (fd < 0) {
183 		ret = -1;
184 		goto out;
185 	}
186 
187 	if (value)
188 		buf[0] = '1';
189 	else
190 		buf[0] = '0';
191 	buf[1] = '\0';
192 
193 	ret = write(fd, buf, 2);
194 	close(fd);
195       out:
196 	free(fname);
197 	if (ret > 0)
198 		return 0;
199 	else
200 		return -1;
201 }
202 
hidden_def(security_set_boolean)203 hidden_def(security_set_boolean)
204 
205 int security_commit_booleans(void)
206 {
207 	int fd, ret;
208 	char buf[2];
209 	char path[PATH_MAX];
210 
211 	if (!selinux_mnt) {
212 		errno = ENOENT;
213 		return -1;
214 	}
215 
216 	snprintf(path, sizeof path, "%s/commit_pending_bools", selinux_mnt);
217 	fd = open(path, O_WRONLY);
218 	if (fd < 0)
219 		return -1;
220 
221 	buf[0] = '1';
222 	buf[1] = '\0';
223 
224 	ret = write(fd, buf, 2);
225 	close(fd);
226 
227 	if (ret > 0)
228 		return 0;
229 	else
230 		return -1;
231 }
232 
hidden_def(security_commit_booleans)233 hidden_def(security_commit_booleans)
234 
235 static char *strtrim(char *dest, char *source, int size)
236 {
237 	int i = 0;
238 	char *ptr = source;
239 	i = 0;
240 	while (isspace(*ptr) && i < size) {
241 		ptr++;
242 		i++;
243 	}
244 	strncpy(dest, ptr, size);
245 	for (i = strlen(dest) - 1; i > 0; i--) {
246 		if (!isspace(dest[i]))
247 			break;
248 	}
249 	dest[i + 1] = '\0';
250 	return dest;
251 }
process_boolean(char * buffer,char * name,int namesize,int * val)252 static int process_boolean(char *buffer, char *name, int namesize, int *val)
253 {
254 	char name1[BUFSIZ];
255 	char *ptr;
256 	char *tok = strtok_r(buffer, "=", &ptr);
257 	if (tok) {
258 		strncpy(name1, tok, BUFSIZ - 1);
259 		strtrim(name, name1, namesize - 1);
260 		if (name[0] == '#')
261 			return 0;
262 		tok = strtok_r(NULL, "\0", &ptr);
263 		if (tok) {
264 			while (isspace(*tok))
265 				tok++;
266 			*val = -1;
267 			if (isdigit(tok[0]))
268 				*val = atoi(tok);
269 			else if (!strncasecmp(tok, "true", sizeof("true") - 1))
270 				*val = 1;
271 			else if (!strncasecmp
272 				 (tok, "false", sizeof("false") - 1))
273 				*val = 0;
274 			if (*val != 0 && *val != 1) {
275 				errno = EINVAL;
276 				return -1;
277 			}
278 
279 		}
280 	}
281 	return 1;
282 }
283 
rollback(SELboolean * boollist,int end)284 static void rollback(SELboolean * boollist, int end)
285 {
286 	int i;
287 
288 	for (i = 0; i < end; i++)
289 		security_set_boolean(boollist[i].name,
290 				     security_get_boolean_active(boollist[i].
291 								 name));
292 }
293 
security_set_boolean_list(size_t boolcnt,SELboolean * boollist,int permanent)294 int security_set_boolean_list(size_t boolcnt, SELboolean * boollist,
295 			      int permanent __attribute__((unused)))
296 {
297 
298 	size_t i;
299 	for (i = 0; i < boolcnt; i++) {
300 		if (security_set_boolean(boollist[i].name, boollist[i].value)) {
301 			rollback(boollist, i);
302 			return -1;
303 		}
304 	}
305 
306 	/* OK, let's do the commit */
307 	if (security_commit_booleans()) {
308 		return -1;
309 	}
310 
311 	return 0;
312 }
313