static ssize_t sel_write_load(struct file *file, const char __user *buf,
			      size_t count, loff_t *ppos)

{
	ssize_t length;
	void *data = NULL;

	mutex_lock(&sel_mutex);

	length = task_has_security(current, SECURITY__LOAD_POLICY);
	if (length)
		goto out;

	/* No partial writes. */
	length = -EINVAL;
	if (*ppos != 0)
		goto out;

	length = -EFBIG;
	if (count > 64 * 1024 * 1024)
		goto out;

	length = -ENOMEM;
	data = vmalloc(count);
	if (!data)
		goto out;

	length = -EFAULT;
	if (copy_from_user(data, buf, count) != 0)
		goto out;

	length = security_load_policy(data, count);
	if (length)
		goto out;

	length = sel_make_bools();
	if (length)
		goto out1;

	length = sel_make_classes();
	if (length)
		goto out1;

	length = sel_make_policycap();
	if (length)
		goto out1;

	length = count;

out1:
	audit_log(current->audit_context, GFP_KERNEL, AUDIT_MAC_POLICY_LOAD,
		"policy loaded auid=%u ses=%u",
		audit_get_loginuid(current),
		audit_get_sessionid(current));
out:
	mutex_unlock(&sel_mutex);
	vfree(data);
	return length;
}
Ejemplo n.º 2
0
static int flask_security_load(struct xen_flask_load *load)
{
    int ret;
    void *buf = NULL;
    bool is_reload = ss_initialized;

    ret = domain_has_security(current->domain, SECURITY__LOAD_POLICY);
    if ( ret )
        return ret;

    if ( load->size > MAX_POLICY_SIZE )
        return -EINVAL;

    buf = xmalloc_bytes(load->size);
    if ( !buf )
        return -ENOMEM;

    if ( _copy_from_guest(buf, load->buffer, load->size) )
    {
        ret = -EFAULT;
        goto out_free;
    }

    spin_lock(&sel_sem);

    ret = security_load_policy(buf, load->size);
    if ( ret )
        goto out;

    if ( !is_reload )
        printk(XENLOG_INFO "Flask: Policy loaded, continuing in %s mode.\n",
            flask_enforcing ? "enforcing" : "permissive");

    xfree(bool_pending_values);
    bool_pending_values = NULL;
    ret = 0;

 out:
    spin_unlock(&sel_sem);
 out_free:
    xfree(buf);
    return ret;
}
Ejemplo n.º 3
0
int selinux_mkload_policy(int preservebools)
{	
	int kernvers = security_policyvers();
	int maxvers = kernvers, minvers = DEFAULT_POLICY_VERSION, vers;
	int setlocaldefs = load_setlocaldefs;
	char path[PATH_MAX];
	struct stat sb;
	struct utsname uts;
	size_t size;
	void *map, *data;
	int fd, rc = -1, prot;
	sepol_policydb_t *policydb;
	sepol_policy_file_t *pf;
	int usesepol = 0;
	int (*vers_max)(void) = NULL;
	int (*vers_min)(void) = NULL;
	int (*policy_file_create)(sepol_policy_file_t **) = NULL;
	void (*policy_file_free)(sepol_policy_file_t *) = NULL;
	void (*policy_file_set_mem)(sepol_policy_file_t *, char*, size_t) = NULL;
	int (*policydb_create)(sepol_policydb_t **) = NULL;
	void (*policydb_free)(sepol_policydb_t *) = NULL;
	int (*policydb_read)(sepol_policydb_t *, sepol_policy_file_t *) = NULL;
	int (*policydb_set_vers)(sepol_policydb_t *, unsigned int) = NULL;
	int (*policydb_to_image)(sepol_handle_t *, sepol_policydb_t *, void **, size_t *) = NULL;
	int (*genbools_array)(void *data, size_t len, char **names, int *values, int nel) = NULL;
	int (*genusers)(void *data, size_t len, const char *usersdir, void **newdata, size_t * newlen) = NULL;
	int (*genbools)(void *data, size_t len, char *boolpath) = NULL;

#ifdef SHARED
	char *errormsg = NULL;
	void *libsepolh = NULL;
	libsepolh = dlopen("libsepol.so.1", RTLD_NOW);
	if (libsepolh) {
		usesepol = 1;
		dlerror();
#define DLERR() if ((errormsg = dlerror())) goto dlclose;
		vers_max = dlsym(libsepolh, "sepol_policy_kern_vers_max");
		DLERR();
		vers_min = dlsym(libsepolh, "sepol_policy_kern_vers_min");
		DLERR();

		policy_file_create = dlsym(libsepolh, "sepol_policy_file_create");
		DLERR();
		policy_file_free = dlsym(libsepolh, "sepol_policy_file_free");
		DLERR();
		policy_file_set_mem = dlsym(libsepolh, "sepol_policy_file_set_mem");
		DLERR();
		policydb_create = dlsym(libsepolh, "sepol_policydb_create");
		DLERR();
		policydb_free = dlsym(libsepolh, "sepol_policydb_free");
		DLERR();
		policydb_read = dlsym(libsepolh, "sepol_policydb_read");
		DLERR();
		policydb_set_vers = dlsym(libsepolh, "sepol_policydb_set_vers");
		DLERR();
		policydb_to_image = dlsym(libsepolh, "sepol_policydb_to_image");
		DLERR();
		genbools_array = dlsym(libsepolh, "sepol_genbools_array");
		DLERR();
		genusers = dlsym(libsepolh, "sepol_genusers");
		DLERR();
		genbools = dlsym(libsepolh, "sepol_genbools");
		DLERR();

#undef DLERR
	}
#else
	usesepol = 1;
	vers_max = sepol_policy_kern_vers_max;
	vers_min = sepol_policy_kern_vers_min;
	policy_file_create = sepol_policy_file_create;
	policy_file_free = sepol_policy_file_free;
	policy_file_set_mem = sepol_policy_file_set_mem;
	policydb_create = sepol_policydb_create;
	policydb_free = sepol_policydb_free;
	policydb_read = sepol_policydb_read;
	policydb_set_vers = sepol_policydb_set_vers;
	policydb_to_image = sepol_policydb_to_image;
	genbools_array = sepol_genbools_array;
	genusers = sepol_genusers;
	genbools = sepol_genbools;

#endif

	/*
	 * Check whether we need to support local boolean and user definitions.
	 */
	if (setlocaldefs) {
		if (access(selinux_booleans_path(), F_OK) == 0)
			goto checkbool;
		snprintf(path, sizeof path, "%s.local", selinux_booleans_path());
		if (access(path, F_OK) == 0)
			goto checkbool;
		snprintf(path, sizeof path, "%s/local.users", selinux_users_path());
		if (access(path, F_OK) == 0)
			goto checkbool;
		/* No local definition files, so disable setlocaldefs. */
		setlocaldefs = 0;
	}

checkbool:
	/* 
	 * As of Linux 2.6.22, the kernel preserves boolean
	 * values across a reload, so we do not need to 
	 * preserve them in userspace.
	 */
	if (preservebools && uname(&uts) == 0 && strverscmp(uts.release, "2.6.22") >= 0)
		preservebools = 0;

	if (usesepol) {
		maxvers = vers_max();
		minvers = vers_min();
		if (!setlocaldefs && !preservebools)
			maxvers = max(kernvers, maxvers);
	}

	vers = maxvers;
      search:
	snprintf(path, sizeof(path), "%s.%d",
		 selinux_binary_policy_path(), vers);
	fd = open(path, O_RDONLY);
	while (fd < 0 && errno == ENOENT
	       && --vers >= minvers) {
		/* Check prior versions to see if old policy is available */
		snprintf(path, sizeof(path), "%s.%d",
			 selinux_binary_policy_path(), vers);
		fd = open(path, O_RDONLY);
	}
	if (fd < 0) {
		fprintf(stderr,
			"SELinux:  Could not open policy file <= %s.%d:  %s\n",
			selinux_binary_policy_path(), maxvers, strerror(errno));
		goto dlclose;
	}

	if (fstat(fd, &sb) < 0) {
		fprintf(stderr,
			"SELinux:  Could not stat policy file %s:  %s\n",
			path, strerror(errno));
		goto close;
	}

	prot = PROT_READ;
	if (setlocaldefs || preservebools)
		prot |= PROT_WRITE;

	size = sb.st_size;
	data = map = mmap(NULL, size, prot, MAP_PRIVATE, fd, 0);
	if (map == MAP_FAILED) {
		fprintf(stderr,
			"SELinux:  Could not map policy file %s:  %s\n",
			path, strerror(errno));
		goto close;
	}

	if (vers > kernvers && usesepol) {
		/* Need to downgrade to kernel-supported version. */
		if (policy_file_create(&pf))
			goto unmap;
		if (policydb_create(&policydb)) {
			policy_file_free(pf);
			goto unmap;
		}
		policy_file_set_mem(pf, data, size);
		if (policydb_read(policydb, pf)) {
			policy_file_free(pf);
			policydb_free(policydb);
			goto unmap;
		}
		if (policydb_set_vers(policydb, kernvers) ||
		    policydb_to_image(NULL, policydb, &data, &size)) {
			/* Downgrade failed, keep searching. */
			fprintf(stderr,
				"SELinux:  Could not downgrade policy file %s, searching for an older version.\n",
				path);
			policy_file_free(pf);
			policydb_free(policydb);
			munmap(map, sb.st_size);
			close(fd);
			vers--;
			goto search;
		}
		policy_file_free(pf);
		policydb_free(policydb);
	}

	if (usesepol) {
		if (setlocaldefs) {
			void *olddata = data;
			size_t oldsize = size;
			rc = genusers(olddata, oldsize, selinux_users_path(),
				      &data, &size);
			if (rc < 0) {
				/* Fall back to the prior image if genusers failed. */
				data = olddata;
				size = oldsize;
				rc = 0;
			} else {
				if (olddata != map)
					free(olddata);
			}
		}
		
#ifndef DISABLE_BOOL
		if (preservebools) {
			int *values, len, i;
			char **names;
			rc = security_get_boolean_names(&names, &len);
			if (!rc) {
				values = malloc(sizeof(int) * len);
				if (!values)
					goto unmap;
				for (i = 0; i < len; i++)
					values[i] =
						security_get_boolean_active(names[i]);
				(void)genbools_array(data, size, names, values,
						     len);
				free(values);
				for (i = 0; i < len; i++)
					free(names[i]);
				free(names);
			}
		} else if (setlocaldefs) {
			(void)genbools(data, size,
				       (char *)selinux_booleans_path());
		}
#endif
	}


	rc = security_load_policy(data, size);
	
	if (rc)
		fprintf(stderr,
			"SELinux:  Could not load policy file %s:  %s\n",
			path, strerror(errno));

      unmap:
	if (data != map)
		free(data);
	munmap(map, sb.st_size);
      close:
	close(fd);
      dlclose:
#ifdef SHARED
	if (errormsg)
		fprintf(stderr, "libselinux:  %s\n", errormsg);
	if (libsepolh)
		dlclose(libsepolh);
#endif
	return rc;
}
Ejemplo n.º 4
0
static ssize_t sel_write_load(struct file *file, const char __user *buf,
			      size_t count, loff_t *ppos)

{
	ssize_t length;
	void *data = NULL;

	mutex_lock(&sel_mutex);

	length = avc_has_perm(current_sid(), SECINITSID_SECURITY,
			      SECCLASS_SECURITY, SECURITY__LOAD_POLICY, NULL);
	if (length)
		goto out;

	/* No partial writes. */
	length = -EINVAL;
	if (*ppos != 0)
		goto out;

	length = -EFBIG;
	if (count > 64 * 1024 * 1024)
		goto out;

	length = -ENOMEM;
	data = vmalloc(count);
	if (!data)
		goto out;

	length = -EFAULT;
	if (copy_from_user(data, buf, count) != 0)
		goto out;

	length = security_load_policy(data, count);
	if (length) {
		pr_warn_ratelimited("SELinux: failed to load policy\n");
		goto out;
	}

	length = sel_make_bools();
	if (length) {
		pr_err("SELinux: failed to load policy booleans\n");
		goto out1;
	}

	length = sel_make_classes();
	if (length) {
		pr_err("SELinux: failed to load policy classes\n");
		goto out1;
	}

	length = sel_make_policycap();
	if (length) {
		pr_err("SELinux: failed to load policy capabilities\n");
		goto out1;
	}

	length = count;

out1:
	audit_log(current->audit_context, GFP_KERNEL, AUDIT_MAC_POLICY_LOAD,
		"policy loaded auid=%u ses=%u",
		from_kuid(&init_user_ns, audit_get_loginuid(current)),
		audit_get_sessionid(current));
out:
	mutex_unlock(&sel_mutex);
	vfree(data);
	return length;
}