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