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 void rollback(SELboolean * boollist, int end)
236 {
237 int i;
238
239 for (i = 0; i < end; i++)
240 security_set_boolean(boollist[i].name,
241 security_get_boolean_active(boollist[i].
242 name));
243 }
244
security_set_boolean_list(size_t boolcnt,SELboolean * const boollist,int permanent)245 int security_set_boolean_list(size_t boolcnt, SELboolean * const boollist,
246 int permanent __attribute__((unused)))
247 {
248
249 size_t i;
250 for (i = 0; i < boolcnt; i++) {
251 if (security_set_boolean(boollist[i].name, boollist[i].value)) {
252 rollback(boollist, i);
253 return -1;
254 }
255 }
256
257 /* OK, let's do the commit */
258 if (security_commit_booleans()) {
259 return -1;
260 }
261
262 return 0;
263 }
264