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