static int read_binary_policy(policydb_t * p, char *file, char *progname)
{
	int fd;
	struct stat sb;
	void *map;
	struct policy_file f, *fp;

	fd = open(file, O_RDONLY);
	if (fd < 0) {
		fprintf(stderr, "Can't open '%s':  %s\n",
			file, strerror(errno));
		return -1;
	}
	if (fstat(fd, &sb) < 0) {
		fprintf(stderr, "Can't stat '%s':  %s\n",
			file, strerror(errno));
		close(fd);
		return -1;
	}
	map =
	    mmap(NULL, sb.st_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
	close(fd);
	if (map == MAP_FAILED) {
		fprintf(stderr, "Can't map '%s':  %s\n", file, strerror(errno));
		return -1;
	}
	policy_file_init(&f);
	f.type = PF_USE_MEMORY;
	f.data = map;
	f.len = sb.st_size;
	fp = &f;

	if (policydb_init(p)) {
		fprintf(stderr, "%s:  policydb_init:  Out of memory!\n",
			progname);
		return -1;
	}
	if (policydb_read(p, fp, 1)) {
		fprintf(stderr,
			"%s:  error(s) encountered while parsing configuration\n",
			progname);
		return -1;
	}

	/* Check Policy Consistency */
	if (p->mls) {
		if (!mlspol) {
			fprintf(stderr, "%s:  MLS policy, but non-MLS"
				" is specified\n", progname);
			return -1;
		}
	} else {
		if (mlspol) {
			fprintf(stderr, "%s:  non-MLS policy, but MLS"
				" is specified\n", progname);
			return -1;
		}
	}
	return 0;
}
Example #2
0
static void selinux_permissive(void)
{
    policydb_t policydb;
    struct policy_file pf;

    policydb_init(&policydb);
    sepol_set_policydb(&policydb);
    policy_file_init(&pf);

    // Read the current policy
    pf.fp = fopen("/sepolicy", "r");
    pf.type = PF_USE_STDIO;
    policydb_read(&policydb, &pf, 0);
    fclose(pf.fp);

    // Make init, recovery, and ueventd permissive
    set_permissive("init", &policydb);
    set_permissive("recovery", &policydb);
    set_permissive("ueventd", &policydb);

    // Write the new policy and load it
    pf.fp = fopen("/dev/sepolicy", "w+");
    policydb_write(&policydb, &pf);
    int size = ftell(pf.fp);
    fseek(pf.fp, SEEK_SET, 0);
    void *map = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fileno(pf.fp), 0);
    int load = open("/sys/fs/selinux/load", O_WRONLY);
    write(load, map, size);
    close(load);
    munmap(map, size);
    fclose(pf.fp);

    policydb_destroy(&policydb);
}
int load_policy(char *filename, policydb_t *policydb, struct policy_file *pf) {
	FILE*	f;
	size_t	size;
	void *data;
	int ret;

	f = fopen(filename, "rb");
	if (f == NULL) {
		fprintf(stderr, "Can't open '%s':  %s\n",
		        filename, strerror(errno));
		return 1;
	}

	fseek(f, 0, SEEK_END);
	size = ftell(f);
	fseek(f, 0, SEEK_SET);

	data = malloc(size);
	if (data == NULL) {
		fprintf(stderr, "Can't allocat memory\n");
		fclose(f);
		return 1;
	}

	if (fread(data, 1, size, f) != size) {
		fprintf(stderr, "Can't read policy file '%s':  %s\n", filename, strerror(errno));
		free(data);
		fclose(f);
		return 1;
	}

	policy_file_init(pf);
	pf->type = PF_USE_MEMORY;
	pf->data = (char*)data;
	pf->len = size;
	if (policydb_init(policydb)) {
		fprintf(stderr, "policydb_init: Out of memory!\n");
		free(data);
		fclose(f);
		return 1;
	}

	ret = policydb_read(policydb, pf, 1);
	if (ret) {
		fprintf(stderr, "error(s) encountered while parsing configuration\n");
		free(data);
		fclose(f);
		return 1;
	}

	free(data);
	fclose(f);
	return 0;
}
int load_policy(char *filename, policydb_t * policydb, struct policy_file *pf)
{
    int fd;
    struct stat sb;
    void *map;
    int ret;

    fd = open(filename, O_RDONLY);
    if (fd < 0) {
        fprintf(stderr, "Can't open '%s':  %s\n", filename, strerror(errno));
        return 1;
    }
    if (fstat(fd, &sb) < 0) {
        fprintf(stderr, "Can't stat '%s':  %s\n", filename, strerror(errno));
        close(fd);
        return 1;
    }
    map = mmap(NULL, sb.st_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
    if (map == MAP_FAILED) {
        fprintf(stderr, "Can't mmap '%s':  %s\n", filename, strerror(errno));
        close(fd);
        return 1;
    }

    policy_file_init(pf);
    pf->type = PF_USE_MEMORY;
    pf->data = map;
    pf->len = sb.st_size;
    if (policydb_init(policydb)) {
        fprintf(stderr, "Could not initialize policydb!\n");
        close(fd);
        munmap(map, sb.st_size);
        return 1;
    }
    ret = policydb_read(policydb, pf, 0);
    if (ret) {
        fprintf(stderr, "error(s) encountered while parsing configuration\n");
        close(fd);
        munmap(map, sb.st_size);
        return 1;
    }

    return 0;
}
Example #5
0
bool selinux_read_policy(const std::string &path, policydb_t *pdb)
{
    struct policy_file pf;
    struct stat sb;
    void *map;
    int fd;

    fd = open(path.c_str(), O_RDONLY);
    if (fd < 0) {
        LOGE("Failed to open %s: %s", path.c_str(), strerror(errno));
        return false;
    }

    auto close_fd = finally([&] {
        close(fd);
    });

    if (fstat(fd, &sb) < 0) {
        LOGE("Failed to stat %s: %s", path.c_str(), strerror(errno));
        return false;
    }

    map = mmap(nullptr, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
    if (map == MAP_FAILED) {
        LOGE("Failed to mmap %s: %s", path.c_str(), strerror(errno));
        return false;
    }

    auto unmap_map = finally([&] {
        munmap(map, sb.st_size);
    });

    policy_file_init(&pf);
    pf.type = PF_USE_MEMORY;
    pf.data = (char *) map;
    pf.len = sb.st_size;

    auto destroy_pf = finally([&] {
        sepol_handle_destroy(pf.handle);
    });

    return policydb_read(pdb, &pf, 0) == 0;
}
Example #6
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;
}
Example #7
0
/**
 * security_load_policy - Load a security policy configuration.
 * @data: binary policy data
 * @len: length of data in bytes
 *
 * Load a new set of security policy configuration data,
 * validate it and convert the SID table as necessary.
 * This function will flush the access vector cache after
 * loading the new policy.
 */
int security_load_policy(void *data, size_t len)
{
	struct policydb oldpolicydb, newpolicydb;
	struct sidtab oldsidtab, newsidtab;
	struct convert_context_args args;
	u32 seqno;
	int rc = 0;
	struct policy_file file = { data, len }, *fp = &file;

	LOAD_LOCK;

	if (!ss_initialized) {
		if (policydb_read(&policydb, fp)) {
			LOAD_UNLOCK;
			return -EINVAL;
		}
		if (policydb_load_isids(&policydb, &sidtab)) {
			LOAD_UNLOCK;
			policydb_destroy(&policydb);
			return -EINVAL;
		}
		ss_initialized = 1;
		LOAD_UNLOCK;
		selinux_complete_init();
		return 0;
	}

#if 0
	sidtab_hash_eval(&sidtab, "sids");
#endif

	if (policydb_read(&newpolicydb, fp)) {
		LOAD_UNLOCK;
		return -EINVAL;
	}

	sidtab_init(&newsidtab);

	/* Verify that the existing classes did not change. */
	if (hashtab_map(policydb.p_classes.table, validate_class, &newpolicydb)) {
		printk(KERN_ERR "security:  the definition of an existing "
		       "class changed\n");
		rc = -EINVAL;
		goto err;
	}

	/* Clone the SID table. */
	sidtab_shutdown(&sidtab);
	if (sidtab_map(&sidtab, clone_sid, &newsidtab)) {
		rc = -ENOMEM;
		goto err;
	}

	/* Convert the internal representations of contexts
	   in the new SID table and remove invalid SIDs. */
	args.oldp = &policydb;
	args.newp = &newpolicydb;
	sidtab_map_remove_on_error(&newsidtab, convert_context, &args);

	/* Save the old policydb and SID table to free later. */
	memcpy(&oldpolicydb, &policydb, sizeof policydb);
	sidtab_set(&oldsidtab, &sidtab);

	/* Install the new policydb and SID table. */
	POLICY_WRLOCK;
	memcpy(&policydb, &newpolicydb, sizeof policydb);
	sidtab_set(&sidtab, &newsidtab);
	seqno = ++latest_granting;
	POLICY_WRUNLOCK;
	LOAD_UNLOCK;

	/* Free the old policydb and SID table. */
	policydb_destroy(&oldpolicydb);
	sidtab_destroy(&oldsidtab);

	avc_ss_reset(seqno);

	return 0;

err:
	LOAD_UNLOCK;
	sidtab_destroy(&newsidtab);
	policydb_destroy(&newpolicydb);
	return rc;

}
Example #8
0
int sepol_module_package_read(sepol_module_package_t *mod, 
			      struct sepol_policy_file *spf, int verbose)
{
	struct policy_file *file= &spf->pf;
	uint32_t *buf, nsec;
	size_t *offsets, len;
        int retval = -1;
	unsigned i, seen = 0;

	if (module_package_read_offsets(mod, file, &offsets, &nsec))
		return -1;

	/* we know the section offsets, seek to them and read in the data */

	for (i = 0; i < nsec; i++ ) {
	
		if (policy_file_seek(file, offsets[i])) {
			ERR(file->handle, "error seeking to offset %zu for "
				"module package section %u", offsets[i], i);
			goto cleanup;
		}

		len = offsets[i + 1] - offsets[i];

		if (len < sizeof(uint32_t)) {
			ERR(file->handle, "module package section %u "
				"has too small length %zu", i, len);
			goto cleanup;
		}

		/* read the magic number, so that we know which function to call */
		buf = next_entry(file, sizeof(uint32_t));
		if (!buf) {
			ERR(file->handle, "module package section %u truncated, lacks magic number", i);
			goto cleanup;
		}

		switch(le32_to_cpu(buf[0])) {
		case SEPOL_PACKAGE_SECTION_FC:
			if (seen & SEEN_FC) {
				ERR(file->handle, "found multiple file contexts sections in module package (at section %u)", i);
				goto cleanup;
			}
				
			mod->file_contexts_len = len - sizeof(uint32_t);
			mod->file_contexts = (char *)malloc(mod->file_contexts_len);
			if (!mod->file_contexts) {
				ERR(file->handle, "out of memory");
				goto cleanup;
			}
			if (read_helper(mod->file_contexts, file, mod->file_contexts_len)) {
				ERR(file->handle, "invalid file contexts section at section %u", i);
                        	free(mod->file_contexts);
	                        mod->file_contexts = NULL;
				goto cleanup;
        	        }
			seen |= SEEN_FC;
			break;
		case SEPOL_PACKAGE_SECTION_SEUSER:
			if (seen & SEEN_SEUSER) {
				ERR(file->handle, "found multiple seuser sections in module package (at section %u)", i);
				goto cleanup;
			}
		
			mod->seusers_len = len - sizeof(uint32_t);
			mod->seusers = (char *)malloc(mod->seusers_len);
			if (!mod->seusers) {
				ERR(file->handle, "out of memory");
				goto cleanup;
			}
			if (read_helper(mod->seusers, file, mod->seusers_len)) {
				ERR(file->handle, "invalid seuser section at section %u", i);
                        	free(mod->seusers);
	                        mod->seusers = NULL;
				goto cleanup;
        	        }
			seen |= SEEN_SEUSER;
			break;
		case SEPOL_PACKAGE_SECTION_USER_EXTRA:
			if (seen & SEEN_USER_EXTRA) {
				ERR(file->handle, "found multiple user_extra sections in module package (at section %u)", i);
				goto cleanup;
			}
			
			mod->user_extra_len = len - sizeof(uint32_t);
			mod->user_extra = (char *)malloc(mod->user_extra_len);
			if (!mod->user_extra) {
				ERR(file->handle, "out of memory");
				goto cleanup;
			}
			if (read_helper(mod->user_extra, file, mod->user_extra_len)) {
				ERR(file->handle, "invalid user_extra section at section %u", i);
                        	free(mod->user_extra);
	                        mod->user_extra= NULL;
				goto cleanup;
        	        }
			seen |= SEEN_USER_EXTRA;
			break;
		case POLICYDB_MOD_MAGIC:
			if (seen & SEEN_MOD) {
				ERR(file->handle, "found multiple module sections in module package (at section %u)", i);
				goto cleanup;
			}

			/* seek back to where the magic number was */
			if (policy_file_seek(file, offsets[i])) 
				goto cleanup;

			retval = policydb_read(&mod->policy->p, file, verbose);
		        if (retval < 0) {
				ERR(file->handle, "invalid module in module package (at section %u)", i);
				goto cleanup;
			}
			seen |= SEEN_MOD;
			break;
		default:
			/* unknown section, ignore */	
			ERR(file->handle, "unknown magic number at section %u, offset: %zx, number: %ux ", 
				i, offsets[i],le32_to_cpu(buf[0]));
			break;
		}
	}

	if ((seen & SEEN_MOD) == 0) {
		ERR(file->handle, "missing module in module package");
		goto cleanup;
	}

	free(offsets);
	return 0;

cleanup:
	free(offsets);
        return retval;
}