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
20int 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
42hidden_def(security_load_policy)
43
44int load_setlocaldefs hidden = 1;
45
46#undef max
47#define max(a, b) (((a) > (b)) ? (a) : (b))
48
49int 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
149checkbool:
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
302hidden_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 */
312int 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