16cd6a6acSopenharmony_ci#include <unistd.h>
26cd6a6acSopenharmony_ci#include <sys/types.h>
36cd6a6acSopenharmony_ci#include <sys/stat.h>
46cd6a6acSopenharmony_ci#include <sys/mman.h>
56cd6a6acSopenharmony_ci#include <sys/mount.h>
66cd6a6acSopenharmony_ci#include <sys/utsname.h>
76cd6a6acSopenharmony_ci#include <fcntl.h>
86cd6a6acSopenharmony_ci#include <stdlib.h>
96cd6a6acSopenharmony_ci#include <stdio.h>
106cd6a6acSopenharmony_ci#include <ctype.h>
116cd6a6acSopenharmony_ci#include <string.h>
126cd6a6acSopenharmony_ci#include <errno.h>
136cd6a6acSopenharmony_ci#include "selinux_internal.h"
146cd6a6acSopenharmony_ci#ifndef ANDROID
156cd6a6acSopenharmony_ci#include <sepol/sepol.h>
166cd6a6acSopenharmony_ci#include <sepol/policydb.h>
176cd6a6acSopenharmony_ci#endif
186cd6a6acSopenharmony_ci#include <dlfcn.h>
196cd6a6acSopenharmony_ci#include "policy.h"
206cd6a6acSopenharmony_ci#include <limits.h>
216cd6a6acSopenharmony_ci
226cd6a6acSopenharmony_ci#ifndef MNT_DETACH
236cd6a6acSopenharmony_ci#define MNT_DETACH 2
246cd6a6acSopenharmony_ci#endif
256cd6a6acSopenharmony_ci
266cd6a6acSopenharmony_ciint security_load_policy(const void *data, size_t len)
276cd6a6acSopenharmony_ci{
286cd6a6acSopenharmony_ci	char path[PATH_MAX];
296cd6a6acSopenharmony_ci	int fd, ret;
306cd6a6acSopenharmony_ci
316cd6a6acSopenharmony_ci	if (!selinux_mnt) {
326cd6a6acSopenharmony_ci		errno = ENOENT;
336cd6a6acSopenharmony_ci		return -1;
346cd6a6acSopenharmony_ci	}
356cd6a6acSopenharmony_ci
366cd6a6acSopenharmony_ci	snprintf(path, sizeof path, "%s/load", selinux_mnt);
376cd6a6acSopenharmony_ci	fd = open(path, O_RDWR | O_CLOEXEC);
386cd6a6acSopenharmony_ci	if (fd < 0)
396cd6a6acSopenharmony_ci		return -1;
406cd6a6acSopenharmony_ci
416cd6a6acSopenharmony_ci	ret = write(fd, data, len);
426cd6a6acSopenharmony_ci	close(fd);
436cd6a6acSopenharmony_ci	if (ret < 0)
446cd6a6acSopenharmony_ci		return -1;
456cd6a6acSopenharmony_ci	return 0;
466cd6a6acSopenharmony_ci}
476cd6a6acSopenharmony_ci
486cd6a6acSopenharmony_ci
496cd6a6acSopenharmony_ci#ifndef ANDROID
506cd6a6acSopenharmony_ci#undef max
516cd6a6acSopenharmony_ci#define max(a, b) (((a) > (b)) ? (a) : (b))
526cd6a6acSopenharmony_ci
536cd6a6acSopenharmony_ciint selinux_mkload_policy(int preservebools __attribute__((unused)))
546cd6a6acSopenharmony_ci{
556cd6a6acSopenharmony_ci	int kernvers = security_policyvers();
566cd6a6acSopenharmony_ci	int maxvers = kernvers, minvers = DEFAULT_POLICY_VERSION, vers;
576cd6a6acSopenharmony_ci	char path[PATH_MAX];
586cd6a6acSopenharmony_ci	struct stat sb;
596cd6a6acSopenharmony_ci	size_t size;
606cd6a6acSopenharmony_ci	void *map, *data;
616cd6a6acSopenharmony_ci	int fd, rc = -1;
626cd6a6acSopenharmony_ci	sepol_policydb_t *policydb;
636cd6a6acSopenharmony_ci	sepol_policy_file_t *pf;
646cd6a6acSopenharmony_ci	int usesepol = 0;
656cd6a6acSopenharmony_ci	int (*vers_max)(void) = NULL;
666cd6a6acSopenharmony_ci	int (*vers_min)(void) = NULL;
676cd6a6acSopenharmony_ci	int (*policy_file_create)(sepol_policy_file_t **) = NULL;
686cd6a6acSopenharmony_ci	void (*policy_file_free)(sepol_policy_file_t *) = NULL;
696cd6a6acSopenharmony_ci	void (*policy_file_set_mem)(sepol_policy_file_t *, char*, size_t) = NULL;
706cd6a6acSopenharmony_ci	int (*policydb_create)(sepol_policydb_t **) = NULL;
716cd6a6acSopenharmony_ci	void (*policydb_free)(sepol_policydb_t *) = NULL;
726cd6a6acSopenharmony_ci	int (*policydb_read)(sepol_policydb_t *, sepol_policy_file_t *) = NULL;
736cd6a6acSopenharmony_ci	int (*policydb_set_vers)(sepol_policydb_t *, unsigned int) = NULL;
746cd6a6acSopenharmony_ci	int (*policydb_to_image)(sepol_handle_t *, sepol_policydb_t *, void **, size_t *) = NULL;
756cd6a6acSopenharmony_ci
766cd6a6acSopenharmony_ci#ifdef SHARED
776cd6a6acSopenharmony_ci	char *errormsg = NULL;
786cd6a6acSopenharmony_ci	void *libsepolh = NULL;
796cd6a6acSopenharmony_ci	libsepolh = dlopen("libsepol.so.2", RTLD_NOW);
806cd6a6acSopenharmony_ci	if (libsepolh) {
816cd6a6acSopenharmony_ci		usesepol = 1;
826cd6a6acSopenharmony_ci		dlerror();
836cd6a6acSopenharmony_ci#define DLERR() do { if ((errormsg = dlerror())) goto dlclose; } while (0)
846cd6a6acSopenharmony_ci		vers_max = dlsym(libsepolh, "sepol_policy_kern_vers_max");
856cd6a6acSopenharmony_ci		DLERR();
866cd6a6acSopenharmony_ci		vers_min = dlsym(libsepolh, "sepol_policy_kern_vers_min");
876cd6a6acSopenharmony_ci		DLERR();
886cd6a6acSopenharmony_ci
896cd6a6acSopenharmony_ci		policy_file_create = dlsym(libsepolh, "sepol_policy_file_create");
906cd6a6acSopenharmony_ci		DLERR();
916cd6a6acSopenharmony_ci		policy_file_free = dlsym(libsepolh, "sepol_policy_file_free");
926cd6a6acSopenharmony_ci		DLERR();
936cd6a6acSopenharmony_ci		policy_file_set_mem = dlsym(libsepolh, "sepol_policy_file_set_mem");
946cd6a6acSopenharmony_ci		DLERR();
956cd6a6acSopenharmony_ci		policydb_create = dlsym(libsepolh, "sepol_policydb_create");
966cd6a6acSopenharmony_ci		DLERR();
976cd6a6acSopenharmony_ci		policydb_free = dlsym(libsepolh, "sepol_policydb_free");
986cd6a6acSopenharmony_ci		DLERR();
996cd6a6acSopenharmony_ci		policydb_read = dlsym(libsepolh, "sepol_policydb_read");
1006cd6a6acSopenharmony_ci		DLERR();
1016cd6a6acSopenharmony_ci		policydb_set_vers = dlsym(libsepolh, "sepol_policydb_set_vers");
1026cd6a6acSopenharmony_ci		DLERR();
1036cd6a6acSopenharmony_ci		policydb_to_image = dlsym(libsepolh, "sepol_policydb_to_image");
1046cd6a6acSopenharmony_ci		DLERR();
1056cd6a6acSopenharmony_ci#undef DLERR
1066cd6a6acSopenharmony_ci	}
1076cd6a6acSopenharmony_ci#else
1086cd6a6acSopenharmony_ci	usesepol = 1;
1096cd6a6acSopenharmony_ci	vers_max = sepol_policy_kern_vers_max;
1106cd6a6acSopenharmony_ci	vers_min = sepol_policy_kern_vers_min;
1116cd6a6acSopenharmony_ci	policy_file_create = sepol_policy_file_create;
1126cd6a6acSopenharmony_ci	policy_file_free = sepol_policy_file_free;
1136cd6a6acSopenharmony_ci	policy_file_set_mem = sepol_policy_file_set_mem;
1146cd6a6acSopenharmony_ci	policydb_create = sepol_policydb_create;
1156cd6a6acSopenharmony_ci	policydb_free = sepol_policydb_free;
1166cd6a6acSopenharmony_ci	policydb_read = sepol_policydb_read;
1176cd6a6acSopenharmony_ci	policydb_set_vers = sepol_policydb_set_vers;
1186cd6a6acSopenharmony_ci	policydb_to_image = sepol_policydb_to_image;
1196cd6a6acSopenharmony_ci#endif
1206cd6a6acSopenharmony_ci
1216cd6a6acSopenharmony_ci	if (usesepol) {
1226cd6a6acSopenharmony_ci		maxvers = max(kernvers, vers_max());
1236cd6a6acSopenharmony_ci		minvers = vers_min();
1246cd6a6acSopenharmony_ci	}
1256cd6a6acSopenharmony_ci
1266cd6a6acSopenharmony_ci	vers = maxvers;
1276cd6a6acSopenharmony_ci      search:
1286cd6a6acSopenharmony_ci	snprintf(path, sizeof(path), "%s.%d",
1296cd6a6acSopenharmony_ci		 selinux_binary_policy_path(), vers);
1306cd6a6acSopenharmony_ci	fd = open(path, O_RDONLY | O_CLOEXEC);
1316cd6a6acSopenharmony_ci	while (fd < 0 && errno == ENOENT
1326cd6a6acSopenharmony_ci	       && --vers >= minvers) {
1336cd6a6acSopenharmony_ci		/* Check prior versions to see if old policy is available */
1346cd6a6acSopenharmony_ci		snprintf(path, sizeof(path), "%s.%d",
1356cd6a6acSopenharmony_ci			 selinux_binary_policy_path(), vers);
1366cd6a6acSopenharmony_ci		fd = open(path, O_RDONLY | O_CLOEXEC);
1376cd6a6acSopenharmony_ci	}
1386cd6a6acSopenharmony_ci	if (fd < 0) {
1396cd6a6acSopenharmony_ci		fprintf(stderr,
1406cd6a6acSopenharmony_ci			"SELinux:  Could not open policy file <= %s.%d:  %m\n",
1416cd6a6acSopenharmony_ci			selinux_binary_policy_path(), maxvers);
1426cd6a6acSopenharmony_ci		goto dlclose;
1436cd6a6acSopenharmony_ci	}
1446cd6a6acSopenharmony_ci
1456cd6a6acSopenharmony_ci	if (fstat(fd, &sb) < 0) {
1466cd6a6acSopenharmony_ci		fprintf(stderr,
1476cd6a6acSopenharmony_ci			"SELinux:  Could not stat policy file %s:  %m\n",
1486cd6a6acSopenharmony_ci			path);
1496cd6a6acSopenharmony_ci		goto close;
1506cd6a6acSopenharmony_ci	}
1516cd6a6acSopenharmony_ci
1526cd6a6acSopenharmony_ci	size = sb.st_size;
1536cd6a6acSopenharmony_ci	data = map = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
1546cd6a6acSopenharmony_ci	if (map == MAP_FAILED) {
1556cd6a6acSopenharmony_ci		fprintf(stderr,
1566cd6a6acSopenharmony_ci			"SELinux:  Could not map policy file %s:  %m\n",
1576cd6a6acSopenharmony_ci			path);
1586cd6a6acSopenharmony_ci		goto close;
1596cd6a6acSopenharmony_ci	}
1606cd6a6acSopenharmony_ci
1616cd6a6acSopenharmony_ci	if (vers > kernvers && usesepol) {
1626cd6a6acSopenharmony_ci		/* Need to downgrade to kernel-supported version. */
1636cd6a6acSopenharmony_ci		if (policy_file_create(&pf))
1646cd6a6acSopenharmony_ci			goto unmap;
1656cd6a6acSopenharmony_ci		if (policydb_create(&policydb)) {
1666cd6a6acSopenharmony_ci			policy_file_free(pf);
1676cd6a6acSopenharmony_ci			goto unmap;
1686cd6a6acSopenharmony_ci		}
1696cd6a6acSopenharmony_ci		policy_file_set_mem(pf, data, size);
1706cd6a6acSopenharmony_ci		if (policydb_read(policydb, pf)) {
1716cd6a6acSopenharmony_ci			policy_file_free(pf);
1726cd6a6acSopenharmony_ci			policydb_free(policydb);
1736cd6a6acSopenharmony_ci			goto unmap;
1746cd6a6acSopenharmony_ci		}
1756cd6a6acSopenharmony_ci		if (policydb_set_vers(policydb, kernvers) ||
1766cd6a6acSopenharmony_ci		    policydb_to_image(NULL, policydb, &data, &size)) {
1776cd6a6acSopenharmony_ci			/* Downgrade failed, keep searching. */
1786cd6a6acSopenharmony_ci			fprintf(stderr,
1796cd6a6acSopenharmony_ci				"SELinux:  Could not downgrade policy file %s, searching for an older version.\n",
1806cd6a6acSopenharmony_ci				path);
1816cd6a6acSopenharmony_ci			policy_file_free(pf);
1826cd6a6acSopenharmony_ci			policydb_free(policydb);
1836cd6a6acSopenharmony_ci			munmap(map, sb.st_size);
1846cd6a6acSopenharmony_ci			close(fd);
1856cd6a6acSopenharmony_ci			vers--;
1866cd6a6acSopenharmony_ci			goto search;
1876cd6a6acSopenharmony_ci		}
1886cd6a6acSopenharmony_ci		policy_file_free(pf);
1896cd6a6acSopenharmony_ci		policydb_free(policydb);
1906cd6a6acSopenharmony_ci	}
1916cd6a6acSopenharmony_ci
1926cd6a6acSopenharmony_ci	rc = security_load_policy(data, size);
1936cd6a6acSopenharmony_ci
1946cd6a6acSopenharmony_ci	if (rc)
1956cd6a6acSopenharmony_ci		fprintf(stderr,
1966cd6a6acSopenharmony_ci			"SELinux:  Could not load policy file %s:  %m\n",
1976cd6a6acSopenharmony_ci			path);
1986cd6a6acSopenharmony_ci
1996cd6a6acSopenharmony_ci      unmap:
2006cd6a6acSopenharmony_ci	if (data != map)
2016cd6a6acSopenharmony_ci		free(data);
2026cd6a6acSopenharmony_ci	munmap(map, sb.st_size);
2036cd6a6acSopenharmony_ci      close:
2046cd6a6acSopenharmony_ci	close(fd);
2056cd6a6acSopenharmony_ci      dlclose:
2066cd6a6acSopenharmony_ci#ifdef SHARED
2076cd6a6acSopenharmony_ci	if (errormsg)
2086cd6a6acSopenharmony_ci		fprintf(stderr, "libselinux:  %s\n", errormsg);
2096cd6a6acSopenharmony_ci	if (libsepolh)
2106cd6a6acSopenharmony_ci		dlclose(libsepolh);
2116cd6a6acSopenharmony_ci#endif
2126cd6a6acSopenharmony_ci	return rc;
2136cd6a6acSopenharmony_ci}
2146cd6a6acSopenharmony_ci
2156cd6a6acSopenharmony_ci
2166cd6a6acSopenharmony_ci/*
2176cd6a6acSopenharmony_ci * Mount point for selinuxfs.
2186cd6a6acSopenharmony_ci * This definition is private to the function below.
2196cd6a6acSopenharmony_ci * Everything else uses the location determined during
2206cd6a6acSopenharmony_ci * libselinux startup via /proc/mounts (see init_selinuxmnt).
2216cd6a6acSopenharmony_ci * We only need the hardcoded definition for the initial mount
2226cd6a6acSopenharmony_ci * required for the initial policy load.
2236cd6a6acSopenharmony_ci */
2246cd6a6acSopenharmony_ciint selinux_init_load_policy(int *enforce)
2256cd6a6acSopenharmony_ci{
2266cd6a6acSopenharmony_ci	int rc = 0, orig_enforce = 0, seconfig = -2, secmdline = -1;
2276cd6a6acSopenharmony_ci	FILE *cfg;
2286cd6a6acSopenharmony_ci	char *buf;
2296cd6a6acSopenharmony_ci
2306cd6a6acSopenharmony_ci	/*
2316cd6a6acSopenharmony_ci	 * Reread the selinux configuration in case it has changed.
2326cd6a6acSopenharmony_ci	 * Example:  Caller has chroot'd and is now loading policy from
2336cd6a6acSopenharmony_ci	 * chroot'd environment.
2346cd6a6acSopenharmony_ci	 */
2356cd6a6acSopenharmony_ci	selinux_reset_config();
2366cd6a6acSopenharmony_ci
2376cd6a6acSopenharmony_ci	/*
2386cd6a6acSopenharmony_ci	 * Get desired mode (disabled, permissive, enforcing) from
2396cd6a6acSopenharmony_ci	 * /etc/selinux/config.
2406cd6a6acSopenharmony_ci	 */
2416cd6a6acSopenharmony_ci	selinux_getenforcemode(&seconfig);
2426cd6a6acSopenharmony_ci
2436cd6a6acSopenharmony_ci	/* Check for an override of the mode via the kernel command line. */
2446cd6a6acSopenharmony_ci	rc = mount("proc", "/proc", "proc", 0, 0);
2456cd6a6acSopenharmony_ci	cfg = fopen("/proc/cmdline", "re");
2466cd6a6acSopenharmony_ci	if (cfg) {
2476cd6a6acSopenharmony_ci		char *tmp;
2486cd6a6acSopenharmony_ci		buf = malloc(selinux_page_size);
2496cd6a6acSopenharmony_ci		if (!buf) {
2506cd6a6acSopenharmony_ci			fclose(cfg);
2516cd6a6acSopenharmony_ci			return -1;
2526cd6a6acSopenharmony_ci		}
2536cd6a6acSopenharmony_ci		if (fgets(buf, selinux_page_size, cfg) &&
2546cd6a6acSopenharmony_ci		    (tmp = strstr(buf, "enforcing="))) {
2556cd6a6acSopenharmony_ci			if (tmp == buf || isspace(*(tmp - 1))) {
2566cd6a6acSopenharmony_ci				secmdline =
2576cd6a6acSopenharmony_ci				    atoi(tmp + sizeof("enforcing=") - 1);
2586cd6a6acSopenharmony_ci			}
2596cd6a6acSopenharmony_ci		}
2606cd6a6acSopenharmony_ci		fclose(cfg);
2616cd6a6acSopenharmony_ci		free(buf);
2626cd6a6acSopenharmony_ci	}
2636cd6a6acSopenharmony_ci
2646cd6a6acSopenharmony_ci	/*
2656cd6a6acSopenharmony_ci	 * Determine the final desired mode.
2666cd6a6acSopenharmony_ci	 * Command line argument takes precedence, then config file.
2676cd6a6acSopenharmony_ci	 */
2686cd6a6acSopenharmony_ci	if (secmdline >= 0)
2696cd6a6acSopenharmony_ci		*enforce = secmdline;
2706cd6a6acSopenharmony_ci	else if (seconfig >= 0)
2716cd6a6acSopenharmony_ci		*enforce = seconfig;
2726cd6a6acSopenharmony_ci	else
2736cd6a6acSopenharmony_ci		*enforce = 0;	/* unspecified or disabled */
2746cd6a6acSopenharmony_ci
2756cd6a6acSopenharmony_ci	/*
2766cd6a6acSopenharmony_ci	 * Check for the existence of SELinux via selinuxfs, and
2776cd6a6acSopenharmony_ci	 * mount it if present for use in the calls below.
2786cd6a6acSopenharmony_ci	 */
2796cd6a6acSopenharmony_ci	const char *mntpoint = NULL;
2806cd6a6acSopenharmony_ci	/* First make sure /sys is mounted */
2816cd6a6acSopenharmony_ci	if (mount("sysfs", "/sys", "sysfs", 0, 0) == 0 || errno == EBUSY) {
2826cd6a6acSopenharmony_ci		/* MS_NODEV can't be set because of /sys/fs/selinux/null device, used by Android */
2836cd6a6acSopenharmony_ci		if (mount(SELINUXFS, SELINUXMNT, SELINUXFS, MS_NOEXEC | MS_NOSUID, 0) == 0 || errno == EBUSY) {
2846cd6a6acSopenharmony_ci			mntpoint = SELINUXMNT;
2856cd6a6acSopenharmony_ci		} else {
2866cd6a6acSopenharmony_ci			/* check old mountpoint */
2876cd6a6acSopenharmony_ci			if (mount(SELINUXFS, OLDSELINUXMNT, SELINUXFS, 0, 0) == 0 || errno == EBUSY) {
2886cd6a6acSopenharmony_ci				mntpoint = OLDSELINUXMNT;
2896cd6a6acSopenharmony_ci			}
2906cd6a6acSopenharmony_ci		}
2916cd6a6acSopenharmony_ci	} else {
2926cd6a6acSopenharmony_ci		/* check old mountpoint */
2936cd6a6acSopenharmony_ci		if (mount(SELINUXFS, OLDSELINUXMNT, SELINUXFS, 0, 0) == 0 || errno == EBUSY) {
2946cd6a6acSopenharmony_ci			mntpoint = OLDSELINUXMNT;
2956cd6a6acSopenharmony_ci		}
2966cd6a6acSopenharmony_ci	}
2976cd6a6acSopenharmony_ci
2986cd6a6acSopenharmony_ci	if (! mntpoint ) {
2996cd6a6acSopenharmony_ci		if (errno == ENODEV || !selinuxfs_exists()) {
3006cd6a6acSopenharmony_ci			/*
3016cd6a6acSopenharmony_ci			 * SELinux was disabled in the kernel, either
3026cd6a6acSopenharmony_ci			 * omitted entirely or disabled at boot via selinux=0.
3036cd6a6acSopenharmony_ci			 * This takes precedence over any config or
3046cd6a6acSopenharmony_ci			 * commandline enforcing setting.
3056cd6a6acSopenharmony_ci			 */
3066cd6a6acSopenharmony_ci			*enforce = 0;
3076cd6a6acSopenharmony_ci		} else {
3086cd6a6acSopenharmony_ci			/* Only emit this error if selinux was not disabled */
3096cd6a6acSopenharmony_ci			fprintf(stderr, "Mount failed for selinuxfs on %s:  %m\n", SELINUXMNT);
3106cd6a6acSopenharmony_ci		}
3116cd6a6acSopenharmony_ci
3126cd6a6acSopenharmony_ci		if (rc == 0)
3136cd6a6acSopenharmony_ci			umount2("/proc", MNT_DETACH);
3146cd6a6acSopenharmony_ci
3156cd6a6acSopenharmony_ci		goto noload;
3166cd6a6acSopenharmony_ci	}
3176cd6a6acSopenharmony_ci	set_selinuxmnt(mntpoint);
3186cd6a6acSopenharmony_ci
3196cd6a6acSopenharmony_ci	if (rc == 0)
3206cd6a6acSopenharmony_ci		umount2("/proc", MNT_DETACH);
3216cd6a6acSopenharmony_ci
3226cd6a6acSopenharmony_ci	/*
3236cd6a6acSopenharmony_ci	 * Note:  The following code depends on having selinuxfs
3246cd6a6acSopenharmony_ci	 * already mounted and selinuxmnt set above.
3256cd6a6acSopenharmony_ci	 */
3266cd6a6acSopenharmony_ci
3276cd6a6acSopenharmony_ci	if (seconfig == -1) {
3286cd6a6acSopenharmony_ci		/* Runtime disable of SELinux. */
3296cd6a6acSopenharmony_ci		rc = security_disable();
3306cd6a6acSopenharmony_ci		if (rc == 0) {
3316cd6a6acSopenharmony_ci			/* Successfully disabled, so umount selinuxfs too. */
3326cd6a6acSopenharmony_ci			umount(selinux_mnt);
3336cd6a6acSopenharmony_ci			fini_selinuxmnt();
3346cd6a6acSopenharmony_ci			goto noload;
3356cd6a6acSopenharmony_ci		} else {
3366cd6a6acSopenharmony_ci			/*
3376cd6a6acSopenharmony_ci			 * It's possible that this failed because policy has
3386cd6a6acSopenharmony_ci			 * already been loaded. We can't disable SELinux now,
3396cd6a6acSopenharmony_ci			 * so the best we can do is force it to be permissive.
3406cd6a6acSopenharmony_ci			 */
3416cd6a6acSopenharmony_ci			*enforce = 0;
3426cd6a6acSopenharmony_ci		}
3436cd6a6acSopenharmony_ci	}
3446cd6a6acSopenharmony_ci
3456cd6a6acSopenharmony_ci	/*
3466cd6a6acSopenharmony_ci	 * If necessary, change the kernel enforcing status to match
3476cd6a6acSopenharmony_ci	 * the desired mode.
3486cd6a6acSopenharmony_ci	 */
3496cd6a6acSopenharmony_ci	orig_enforce = rc = security_getenforce();
3506cd6a6acSopenharmony_ci	if (rc < 0)
3516cd6a6acSopenharmony_ci		goto noload;
3526cd6a6acSopenharmony_ci	if (orig_enforce != *enforce) {
3536cd6a6acSopenharmony_ci		rc = security_setenforce(*enforce);
3546cd6a6acSopenharmony_ci		if (rc < 0) {
3556cd6a6acSopenharmony_ci			fprintf(stderr, "SELinux:  Unable to switch to %s mode:  %m\n", (*enforce ? "enforcing" : "permissive"));
3566cd6a6acSopenharmony_ci			if (*enforce)
3576cd6a6acSopenharmony_ci				goto noload;
3586cd6a6acSopenharmony_ci		}
3596cd6a6acSopenharmony_ci	}
3606cd6a6acSopenharmony_ci
3616cd6a6acSopenharmony_ci	if (seconfig == -1) {
3626cd6a6acSopenharmony_ci		umount(selinux_mnt);
3636cd6a6acSopenharmony_ci		fini_selinuxmnt();
3646cd6a6acSopenharmony_ci		goto noload;
3656cd6a6acSopenharmony_ci	}
3666cd6a6acSopenharmony_ci
3676cd6a6acSopenharmony_ci	/* Load the policy. */
3686cd6a6acSopenharmony_ci	return selinux_mkload_policy(0);
3696cd6a6acSopenharmony_ci
3706cd6a6acSopenharmony_ci      noload:
3716cd6a6acSopenharmony_ci	/*
3726cd6a6acSopenharmony_ci	 * Only return 0 on a successful completion of policy load.
3736cd6a6acSopenharmony_ci	 * In any other case, we want to return an error so that init
3746cd6a6acSopenharmony_ci	 * knows not to proceed with the re-exec for the domain transition.
3756cd6a6acSopenharmony_ci	 * Depending on the *enforce setting, init will halt (> 0) or proceed
3766cd6a6acSopenharmony_ci	 * normally (otherwise).
3776cd6a6acSopenharmony_ci	 */
3786cd6a6acSopenharmony_ci	return -1;
3796cd6a6acSopenharmony_ci}
3806cd6a6acSopenharmony_ci#endif
381