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