1 #include <unistd.h>
2 #include <sys/types.h>
3 #include <sys/stat.h>
4 #include <sys/mman.h>
5 #include <sys/mount.h>
6 #include <sys/utsname.h>
7 #include <fcntl.h>
8 #include <stdlib.h>
9 #include <stdio.h>
10 #include <ctype.h>
11 #include <string.h>
12 #include <errno.h>
13 #include "selinux_internal.h"
14 #include <sepol/sepol.h>
15 #include <sepol/policydb.h>
16 #include <dlfcn.h>
17 #include "policy.h"
18 #include <limits.h>
19
security_load_policy(void * data,size_t len)20 int security_load_policy(void *data, size_t len)
21 {
22 char path[PATH_MAX];
23 int fd, ret;
24
25 if (!selinux_mnt) {
26 errno = ENOENT;
27 return -1;
28 }
29
30 snprintf(path, sizeof path, "%s/load", selinux_mnt);
31 fd = open(path, O_RDWR);
32 if (fd < 0)
33 return -1;
34
35 ret = write(fd, data, len);
36 close(fd);
37 if (ret < 0)
38 return -1;
39 return 0;
40 }
41
42 hidden_def(security_load_policy)
43
44 int load_setlocaldefs hidden = 1;
45
46 #undef max
47 #define max(a, b) (((a) > (b)) ? (a) : (b))
48
selinux_mkload_policy(int preservebools)49 int selinux_mkload_policy(int preservebools)
50 {
51 int kernvers = security_policyvers();
52 int maxvers = kernvers, minvers = DEFAULT_POLICY_VERSION, vers;
53 int setlocaldefs = load_setlocaldefs;
54 char path[PATH_MAX];
55 struct stat sb;
56 struct utsname uts;
57 size_t size;
58 void *map, *data;
59 int fd, rc = -1, prot;
60 sepol_policydb_t *policydb;
61 sepol_policy_file_t *pf;
62 int usesepol = 0;
63 int (*vers_max)(void) = NULL;
64 int (*vers_min)(void) = NULL;
65 int (*policy_file_create)(sepol_policy_file_t **) = NULL;
66 void (*policy_file_free)(sepol_policy_file_t *) = NULL;
67 void (*policy_file_set_mem)(sepol_policy_file_t *, char*, size_t) = NULL;
68 int (*policydb_create)(sepol_policydb_t **) = NULL;
69 void (*policydb_free)(sepol_policydb_t *) = NULL;
70 int (*policydb_read)(sepol_policydb_t *, sepol_policy_file_t *) = NULL;
71 int (*policydb_set_vers)(sepol_policydb_t *, unsigned int) = NULL;
72 int (*policydb_to_image)(sepol_handle_t *, sepol_policydb_t *, void **, size_t *) = NULL;
73 int (*genbools_array)(void *data, size_t len, char **names, int *values, int nel) = NULL;
74 int (*genusers)(void *data, size_t len, const char *usersdir, void **newdata, size_t * newlen) = NULL;
75 int (*genbools)(void *data, size_t len, char *boolpath) = NULL;
76
77 #ifdef SHARED
78 char *errormsg = NULL;
79 void *libsepolh = NULL;
80 libsepolh = dlopen("libsepol.so.1", RTLD_NOW);
81 if (libsepolh) {
82 usesepol = 1;
83 dlerror();
84 #define DLERR() if ((errormsg = dlerror())) goto dlclose;
85 vers_max = dlsym(libsepolh, "sepol_policy_kern_vers_max");
86 DLERR();
87 vers_min = dlsym(libsepolh, "sepol_policy_kern_vers_min");
88 DLERR();
89
90 policy_file_create = dlsym(libsepolh, "sepol_policy_file_create");
91 DLERR();
92 policy_file_free = dlsym(libsepolh, "sepol_policy_file_free");
93 DLERR();
94 policy_file_set_mem = dlsym(libsepolh, "sepol_policy_file_set_mem");
95 DLERR();
96 policydb_create = dlsym(libsepolh, "sepol_policydb_create");
97 DLERR();
98 policydb_free = dlsym(libsepolh, "sepol_policydb_free");
99 DLERR();
100 policydb_read = dlsym(libsepolh, "sepol_policydb_read");
101 DLERR();
102 policydb_set_vers = dlsym(libsepolh, "sepol_policydb_set_vers");
103 DLERR();
104 policydb_to_image = dlsym(libsepolh, "sepol_policydb_to_image");
105 DLERR();
106 genbools_array = dlsym(libsepolh, "sepol_genbools_array");
107 DLERR();
108 genusers = dlsym(libsepolh, "sepol_genusers");
109 DLERR();
110 genbools = dlsym(libsepolh, "sepol_genbools");
111 DLERR();
112
113 #undef DLERR
114 }
115 #else
116 usesepol = 1;
117 vers_max = sepol_policy_kern_vers_max;
118 vers_min = sepol_policy_kern_vers_min;
119 policy_file_create = sepol_policy_file_create;
120 policy_file_free = sepol_policy_file_free;
121 policy_file_set_mem = sepol_policy_file_set_mem;
122 policydb_create = sepol_policydb_create;
123 policydb_free = sepol_policydb_free;
124 policydb_read = sepol_policydb_read;
125 policydb_set_vers = sepol_policydb_set_vers;
126 policydb_to_image = sepol_policydb_to_image;
127 genbools_array = sepol_genbools_array;
128 genusers = sepol_genusers;
129 genbools = sepol_genbools;
130
131 #endif
132
133 /*
134 * Check whether we need to support local boolean and user definitions.
135 */
136 if (setlocaldefs) {
137 if (access(selinux_booleans_path(), F_OK) == 0)
138 goto checkbool;
139 snprintf(path, sizeof path, "%s.local", selinux_booleans_path());
140 if (access(path, F_OK) == 0)
141 goto checkbool;
142 snprintf(path, sizeof path, "%s/local.users", selinux_users_path());
143 if (access(path, F_OK) == 0)
144 goto checkbool;
145 /* No local definition files, so disable setlocaldefs. */
146 setlocaldefs = 0;
147 }
148
149 checkbool:
150 /*
151 * As of Linux 2.6.22, the kernel preserves boolean
152 * values across a reload, so we do not need to
153 * preserve them in userspace.
154 */
155 if (preservebools && uname(&uts) == 0 && strverscmp(uts.release, "2.6.22") >= 0)
156 preservebools = 0;
157
158 if (usesepol) {
159 maxvers = vers_max();
160 minvers = vers_min();
161 if (!setlocaldefs && !preservebools)
162 maxvers = max(kernvers, maxvers);
163 }
164
165 vers = maxvers;
166 search:
167 snprintf(path, sizeof(path), "%s.%d",
168 selinux_binary_policy_path(), vers);
169 fd = open(path, O_RDONLY);
170 while (fd < 0 && errno == ENOENT
171 && --vers >= minvers) {
172 /* Check prior versions to see if old policy is available */
173 snprintf(path, sizeof(path), "%s.%d",
174 selinux_binary_policy_path(), vers);
175 fd = open(path, O_RDONLY);
176 }
177 if (fd < 0) {
178 fprintf(stderr,
179 "SELinux: Could not open policy file <= %s.%d: %s\n",
180 selinux_binary_policy_path(), maxvers, strerror(errno));
181 goto dlclose;
182 }
183
184 if (fstat(fd, &sb) < 0) {
185 fprintf(stderr,
186 "SELinux: Could not stat policy file %s: %s\n",
187 path, strerror(errno));
188 goto close;
189 }
190
191 prot = PROT_READ;
192 if (setlocaldefs || preservebools)
193 prot |= PROT_WRITE;
194
195 size = sb.st_size;
196 data = map = mmap(NULL, size, prot, MAP_PRIVATE, fd, 0);
197 if (map == MAP_FAILED) {
198 fprintf(stderr,
199 "SELinux: Could not map policy file %s: %s\n",
200 path, strerror(errno));
201 goto close;
202 }
203
204 if (vers > kernvers && usesepol) {
205 /* Need to downgrade to kernel-supported version. */
206 if (policy_file_create(&pf))
207 goto unmap;
208 if (policydb_create(&policydb)) {
209 policy_file_free(pf);
210 goto unmap;
211 }
212 policy_file_set_mem(pf, data, size);
213 if (policydb_read(policydb, pf)) {
214 policy_file_free(pf);
215 policydb_free(policydb);
216 goto unmap;
217 }
218 if (policydb_set_vers(policydb, kernvers) ||
219 policydb_to_image(NULL, policydb, &data, &size)) {
220 /* Downgrade failed, keep searching. */
221 fprintf(stderr,
222 "SELinux: Could not downgrade policy file %s, searching for an older version.\n",
223 path);
224 policy_file_free(pf);
225 policydb_free(policydb);
226 munmap(map, sb.st_size);
227 close(fd);
228 vers--;
229 goto search;
230 }
231 policy_file_free(pf);
232 policydb_free(policydb);
233 }
234
235 if (usesepol) {
236 if (setlocaldefs) {
237 void *olddata = data;
238 size_t oldsize = size;
239 rc = genusers(olddata, oldsize, selinux_users_path(),
240 &data, &size);
241 if (rc < 0) {
242 /* Fall back to the prior image if genusers failed. */
243 data = olddata;
244 size = oldsize;
245 rc = 0;
246 } else {
247 if (olddata != map)
248 free(olddata);
249 }
250 }
251
252 #ifndef DISABLE_BOOL
253 if (preservebools) {
254 int *values, len, i;
255 char **names;
256 rc = security_get_boolean_names(&names, &len);
257 if (!rc) {
258 values = malloc(sizeof(int) * len);
259 if (!values)
260 goto unmap;
261 for (i = 0; i < len; i++)
262 values[i] =
263 security_get_boolean_active(names[i]);
264 (void)genbools_array(data, size, names, values,
265 len);
266 free(values);
267 for (i = 0; i < len; i++)
268 free(names[i]);
269 free(names);
270 }
271 } else if (setlocaldefs) {
272 (void)genbools(data, size,
273 (char *)selinux_booleans_path());
274 }
275 #endif
276 }
277
278
279 rc = security_load_policy(data, size);
280
281 if (rc)
282 fprintf(stderr,
283 "SELinux: Could not load policy file %s: %s\n",
284 path, strerror(errno));
285
286 unmap:
287 if (data != map)
288 free(data);
289 munmap(map, sb.st_size);
290 close:
291 close(fd);
292 dlclose:
293 #ifdef SHARED
294 if (errormsg)
295 fprintf(stderr, "libselinux: %s\n", errormsg);
296 if (libsepolh)
297 dlclose(libsepolh);
298 #endif
299 return rc;
300 }
301
hidden_def(selinux_mkload_policy)302 hidden_def(selinux_mkload_policy)
303
304 /*
305 * Mount point for selinuxfs.
306 * This definition is private to the function below.
307 * Everything else uses the location determined during
308 * libselinux startup via /proc/mounts (see init_selinuxmnt).
309 * We only need the hardcoded definition for the initial mount
310 * required for the initial policy load.
311 */
312 int selinux_init_load_policy(int *enforce)
313 {
314 int rc = 0, orig_enforce = 0, seconfig = -2, secmdline = -1;
315 FILE *cfg;
316 char *buf;
317
318 /*
319 * Reread the selinux configuration in case it has changed.
320 * Example: Caller has chroot'd and is now loading policy from
321 * chroot'd environment.
322 */
323 selinux_reset_config();
324
325 /*
326 * Get desired mode (disabled, permissive, enforcing) from
327 * /etc/selinux/config.
328 */
329 selinux_getenforcemode(&seconfig);
330
331 /* Check for an override of the mode via the kernel command line. */
332 rc = mount("proc", "/proc", "proc", 0, 0);
333 cfg = fopen("/proc/cmdline", "r");
334 if (cfg) {
335 char *tmp;
336 buf = malloc(selinux_page_size);
337 if (!buf) {
338 fclose(cfg);
339 return -1;
340 }
341 if (fgets(buf, selinux_page_size, cfg) &&
342 (tmp = strstr(buf, "enforcing="))) {
343 if (tmp == buf || isspace(*(tmp - 1))) {
344 secmdline =
345 atoi(tmp + sizeof("enforcing=") - 1);
346 }
347 }
348 fclose(cfg);
349 free(buf);
350 }
351 #ifndef MNT_DETACH
352 #define MNT_DETACH 2
353 #endif
354 if (rc == 0)
355 umount2("/proc", MNT_DETACH);
356
357 /*
358 * Determine the final desired mode.
359 * Command line argument takes precedence, then config file.
360 */
361 if (secmdline >= 0)
362 *enforce = secmdline;
363 else if (seconfig >= 0)
364 *enforce = seconfig;
365 else
366 *enforce = 0; /* unspecified or disabled */
367
368 /*
369 * Check for the existence of SELinux via selinuxfs, and
370 * mount it if present for use in the calls below.
371 */
372 const char *mntpoint = NULL;
373 /* First make sure /sys is mounted */
374 if (mount("sysfs", "/sys", "sysfs", 0, 0) == 0 || errno == EBUSY) {
375 if (mount(SELINUXFS, SELINUXMNT, SELINUXFS, 0, 0) == 0 || errno == EBUSY) {
376 mntpoint = SELINUXMNT;
377 } else {
378 /* check old mountpoint */
379 if (mount(SELINUXFS, OLDSELINUXMNT, SELINUXFS, 0, 0) == 0 || errno == EBUSY) {
380 mntpoint = OLDSELINUXMNT;
381 }
382 }
383 } else {
384 /* check old mountpoint */
385 if (mount(SELINUXFS, OLDSELINUXMNT, SELINUXFS, 0, 0) == 0 || errno == EBUSY) {
386 mntpoint = OLDSELINUXMNT;
387 }
388 }
389
390 if (! mntpoint ) {
391 if (errno == ENODEV || !selinuxfs_exists()) {
392 /*
393 * SELinux was disabled in the kernel, either
394 * omitted entirely or disabled at boot via selinux=0.
395 * This takes precedence over any config or
396 * commandline enforcing setting.
397 */
398 *enforce = 0;
399 } else {
400 /* Only emit this error if selinux was not disabled */
401 fprintf(stderr, "Mount failed for selinuxfs on %s: %s\n", SELINUXMNT, strerror(errno));
402 }
403
404 goto noload;
405 }
406 set_selinuxmnt(mntpoint);
407
408 /*
409 * Note: The following code depends on having selinuxfs
410 * already mounted and selinuxmnt set above.
411 */
412
413 if (seconfig == -1) {
414 /* Runtime disable of SELinux. */
415 rc = security_disable();
416 if (rc == 0) {
417 /* Successfully disabled, so umount selinuxfs too. */
418 umount(selinux_mnt);
419 fini_selinuxmnt();
420 goto noload;
421 } else {
422 /*
423 * It's possible that this failed because policy has
424 * already been loaded. We can't disable SELinux now,
425 * so the best we can do is force it to be permissive.
426 */
427 *enforce = 0;
428 }
429 }
430
431 /*
432 * If necessary, change the kernel enforcing status to match
433 * the desired mode.
434 */
435 orig_enforce = rc = security_getenforce();
436 if (rc < 0)
437 goto noload;
438 if (orig_enforce != *enforce) {
439 rc = security_setenforce(*enforce);
440 if (rc < 0) {
441 fprintf(stderr, "SELinux: Unable to switch to %s mode: %s\n", (*enforce ? "enforcing" : "permissive"), strerror(errno));
442 if (*enforce)
443 goto noload;
444 }
445 }
446
447 if (seconfig == -1)
448 goto noload;
449
450 /* Load the policy. */
451 return selinux_mkload_policy(0);
452
453 noload:
454 /*
455 * Only return 0 on a successful completion of policy load.
456 * In any other case, we want to return an error so that init
457 * knows not to proceed with the re-exec for the domain transition.
458 * Depending on the *enforce setting, init will halt (> 0) or proceed
459 * normally (otherwise).
460 */
461 return -1;
462 }
463