Esempio n. 1
0
static sepol_module_package_t *load_module(char *filename)
{
	int ret;
	FILE *fp = NULL;
	struct sepol_policy_file *pf = NULL;
	sepol_module_package_t *p = NULL;

	if (sepol_module_package_create(&p)) {
		fprintf(stderr, "%s:  Out of memory\n", progname);
		goto bad;
	}
	if (sepol_policy_file_create(&pf)) {
		fprintf(stderr, "%s:  Out of memory\n", progname);
		goto bad;
	}
	fp = fopen(filename, "r");
	if (!fp) {
		fprintf(stderr, "%s:  Could not open package %s:  %s", progname, filename, strerror(errno));
		goto bad;
	}
	sepol_policy_file_set_fp(pf, fp);
	
	printf("%s:  loading package from file %s\n", progname, filename);
	
	ret = sepol_module_package_read(p, pf, 0);
	if (ret) {
		fprintf(stderr, "%s:  Error while reading package from %s\n", progname, filename);
		goto bad;
	}
	fclose(fp);
	sepol_policy_file_free(pf);
	return p;
bad:
	sepol_module_package_free(p);
	sepol_policy_file_free(pf);
	if (fp)
		fclose(fp);
	return NULL;
}
Esempio n. 2
0
int main(int argc, char **argv)
{
	struct sepol_module_package *pkg;
	struct sepol_policy_file *mod, *out;
	char *module = NULL, *file_contexts = NULL, *seusers = NULL, *user_extra = NULL;
	char *fcdata = NULL, *outfile = NULL, *seusersdata = NULL, *user_extradata = NULL;
	size_t fclen = 0, seuserslen = 0, user_extralen = 0;
	int i;

        static struct option opts [] = {
                {"module", required_argument, NULL, 'm'},
                {"fc", required_argument, NULL, 'f'},
                {"seuser", required_argument, NULL, 's'},
                {"user_extra", required_argument, NULL, 'u'},
		{"outfile", required_argument, NULL, 'o'},
                {"help", 0, NULL, 'h'},
		{NULL, 0, NULL, 0}
	};

        while ((i = getopt_long(argc, argv, "m:f:s:u:o:h", opts, NULL)) != -1) {
                switch (i) {
		case 'h': usage(argv[0]); exit(0);
		case 'm':  
			if (module) {
				fprintf(stderr, "May not specify more than one module\n");
				exit(1);
			}
			module = strdup(optarg);
			if (!module)
				exit(1);
			break;
		case 'f':
			if (file_contexts) {
				fprintf(stderr, "May not specify more than one file context file\n");
				exit(1);
			}
			file_contexts = strdup(optarg);
			if (!file_contexts)
				exit(1);
			break;
		case 'o':
			if (outfile) {
				fprintf(stderr, "May not specify more than one output file\n");
				exit(1);
			}
			outfile = strdup(optarg);
			if (!outfile) 
				exit(1);
			break;
		case 's':
			if (seusers) {
				fprintf(stderr, "May not specify more than one seuser file\n");
				exit(1);
			}
			seusers = strdup(optarg);
			if (!seusers)
				exit(1);
			break;
		case 'u':
			if (user_extra) {
				fprintf(stderr, "May not specify more than one user_extra file\n");
				exit(1);
			}
			user_extra = strdup(optarg);
			if (!user_extra)
				exit(1);
		}
	}

	progname = argv[0];

	if (!module || !outfile) {
		usage(argv[0]);
		exit(0);
	}
	
        if (file_contexts) {
		if (file_to_data(file_contexts, &fcdata, &fclen))
			exit(1);
        }

        if (seusers) {
		if (file_to_data(seusers, &seusersdata, &seuserslen))
			exit(1);
        }

        if (user_extra) {
		if (file_to_data(user_extra, &user_extradata, &user_extralen))
			exit(1);
        }

	if (file_to_policy_file(module, &mod, "r"))
		exit(1);
	
	if (sepol_module_package_create(&pkg)) {
                fprintf(stderr, "%s:  Out of memory\n", argv[0]);
                exit(1);		
	}

	if (sepol_policydb_read(sepol_module_package_get_policy(pkg), mod)) {
                fprintf(stderr, "%s:  Error while reading policy module from %s\n",
			argv[0], module);
                exit(1);		
	}

	if (fclen)
		sepol_module_package_set_file_contexts(pkg, fcdata, fclen);

	if (seuserslen)
		sepol_module_package_set_seusers(pkg, seusersdata, seuserslen);

	if (user_extra)
		sepol_module_package_set_user_extra(pkg, user_extradata, user_extralen);
	
	if (file_to_policy_file(outfile, &out, "w"))
		exit(1);
		
        if (sepol_module_package_write(pkg, out)) {
                fprintf(stderr, "%s:  Error while writing module package to %s\n", argv[0], argv[1]);
                exit(1);
        }

	if (fclen)
		munmap(fcdata, fclen);
	sepol_policy_file_free(mod);
	sepol_policy_file_free(out);
	sepol_module_package_free(pkg);
	free(file_contexts);
	free(outfile);
	free(module);
	exit(0);
}
Esempio n. 3
0
int main(int argc, char **argv)
{
	char *basename, *outname;
	int ch, ret, show_version = 0, verbose = 0;
	struct sepol_policy_file *pf;
	sepol_module_package_t *base;
	sepol_policydb_t *out, *p;
	FILE *fp, *outfile;
	int check_assertions = 1;
	sepol_handle_t *handle;

	while ((ch = getopt(argc, argv, "c:Vva")) != EOF) {
		switch (ch) {
		case 'V':
			show_version = 1;
			break;
		case 'v':
			verbose = 1;
			break;
		case 'c':{
				long int n = strtol(optarg, NULL, 10);
				if (errno) {
					fprintf(stderr,
						"%s:  Invalid policyvers specified: %s\n",
						argv[0], optarg);
					usage(argv[0]);
					exit(1);
				}
				if (n < sepol_policy_kern_vers_min()
				    || n > sepol_policy_kern_vers_max()) {
					fprintf(stderr,
						"%s:  policyvers value %ld not in range %d-%d\n",
						argv[0], n,
						sepol_policy_kern_vers_min(),
						sepol_policy_kern_vers_max());
					usage(argv[0]);
					exit(1);
				}
				policyvers = n;
				break;
			}
		case 'a':{
				check_assertions = 0;
				break;
			}
		default:
			usage(argv[0]);
		}
	}

	if (verbose) {
		if (policyvers)
			printf("Building version %d policy\n", policyvers);
	}

	if (show_version) {
		printf("%s\n", EXPANDPOLICY_VERSION);
		exit(0);
	}

	/* check args */
	if (argc < 3 || !(optind != (argc - 1))) {
		fprintf(stderr,
			"%s:  You must provide the base module package and output filename\n",
			argv[0]);
		usage(argv[0]);
	}

	basename = argv[optind++];
	outname = argv[optind];

	handle = sepol_handle_create();
	if (!handle)
		exit(1);

	if (sepol_policy_file_create(&pf)) {
		fprintf(stderr, "%s:  Out of memory\n", argv[0]);
		exit(1);
	}

	/* read the base module */
	if (sepol_module_package_create(&base)) {
		fprintf(stderr, "%s:  Out of memory\n", argv[0]);
		exit(1);
	}
	fp = fopen(basename, "r");
	if (!fp) {
		fprintf(stderr, "%s:  Can't open '%s':  %s\n",
			argv[0], basename, strerror(errno));
		exit(1);
	}
	sepol_policy_file_set_fp(pf, fp);
	ret = sepol_module_package_read(base, pf, 0);
	if (ret) {
		fprintf(stderr, "%s:  Error in reading package from %s\n",
			argv[0], basename);
		exit(1);
	}
	fclose(fp);

	/* linking the base takes care of enabling optional avrules */
	p = sepol_module_package_get_policy(base);
	if (sepol_link_modules(handle, p, NULL, 0, 0)) {
		fprintf(stderr, "%s:  Error while enabling avrules\n", argv[0]);
		exit(1);
	}

	/* create the output policy */

	if (sepol_policydb_create(&out)) {
		fprintf(stderr, "%s:  Out of memory\n", argv[0]);
		exit(1);
	}

	sepol_set_expand_consume_base(handle, 1);

	if (sepol_expand_module(handle, p, out, verbose, check_assertions)) {
		fprintf(stderr, "%s:  Error while expanding policy\n", argv[0]);
		exit(1);
	}

	if (policyvers) {
		if (sepol_policydb_set_vers(out, policyvers)) {
			fprintf(stderr, "%s:  Invalid version %d\n", argv[0],
				policyvers);
			exit(1);
		}
	}

	sepol_module_package_free(base);

	outfile = fopen(outname, "w");
	if (!outfile) {
		perror(outname);
		exit(1);
	}

	sepol_policy_file_set_fp(pf, outfile);
	ret = sepol_policydb_write(out, pf);
	if (ret) {
		fprintf(stderr,
			"%s:  Error while writing expanded policy to %s\n",
			argv[0], outname);
		exit(1);
	}
	fclose(outfile);
	sepol_handle_destroy(handle);
	sepol_policydb_free(out);
	sepol_policy_file_free(pf);

	return 0;
}
Esempio n. 4
0
int sepol_module_package_info(struct sepol_policy_file *spf, int *type, char **name, char **version)
{
	struct policy_file *file = &spf->pf;
	sepol_module_package_t *mod = NULL;
	uint32_t *buf, len, nsec;
	size_t *offsets = NULL;
	unsigned i, seen = 0;

	if (sepol_module_package_create(&mod))
		return -1;

	if (module_package_read_offsets(mod, file, &offsets, &nsec)) {
		goto cleanup;
	}

	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 %u", i, len);
			goto cleanup;
		}

		/* read the magic number, so that we know which function to call */
		buf = next_entry(file, sizeof(uint32_t) * 2);
		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:
			/* skip file contexts */
			if (seen & SEEN_FC) {
				ERR(file->handle, "found multiple file contexts sections in module package (at section %u)", i);
				goto cleanup;
			}
			seen |= SEEN_FC;
			break;
		case SEPOL_PACKAGE_SECTION_SEUSER:
			/* skip seuser */
			if (seen & SEEN_SEUSER) {
				ERR(file->handle, "found seuser sections in module package (at section %u)", i);
				goto cleanup;
			}
			seen |= SEEN_SEUSER;
			break;
		case SEPOL_PACKAGE_SECTION_USER_EXTRA:
			/* skip user_extra*/
			if (seen & SEEN_USER_EXTRA) {
				ERR(file->handle, "found user_extra sections in module package (at section %u)", i);
				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;
			}
			len = le32_to_cpu(buf[1]);
			if (len != strlen(POLICYDB_MOD_STRING)) {
				ERR(file->handle, "module string length is wrong (at section %u)", i);
				goto cleanup;
			}
	
			/* skip id */
			buf = next_entry(file, len);
			if (!buf) {
				ERR(file->handle, "cannot get module string (at section %u)", i);
				goto cleanup;
			}
	
			buf = next_entry(file, sizeof(uint32_t)* 5);
			if (!buf) {
				ERR(file->handle, "cannot get module header (at section %u)", i);
				goto cleanup;
			}
	
			*type = le32_to_cpu(buf[0]);
			/* if base - we're done */
			if (*type == POLICY_BASE) {
				*name = NULL;
				*version = NULL;
				seen |= SEEN_MOD;
				break;
			} else if (*type != POLICY_MOD) {
				ERR(file->handle, "module has invalid type %d (at section %u)", *type, i);
				goto cleanup;	
			}
	
			/* read the name and version */
			buf = next_entry(file, sizeof(uint32_t));
		        if (!buf) {
				ERR(file->handle, "cannot get module name len (at section %u)", i);
                		goto cleanup;
			}
		        len = le32_to_cpu(buf[0]);
		        buf = next_entry(file, len);
		        if (!buf) {
				ERR(file->handle, "cannot get module name string (at section %u)", i);
		                goto cleanup;
			}
		        *name = malloc(len + 1);
		        if (!*name) {
				ERR(file->handle, "out of memory");
		                goto cleanup;
		        }
		        memcpy(*name, buf, len);
		        (*name)[len] = '\0';
		        buf = next_entry(file, sizeof(uint32_t));
		        if (!buf) {
				ERR(file->handle, "cannot get module version len (at section %u)", i);
		                goto cleanup;
			}
		        len = le32_to_cpu(buf[0]);
		        buf = next_entry(file, len);
		        if (!buf) {
				ERR(file->handle, "cannot get module version string (at section %u)", i);
		                goto cleanup;
			}
		        *version = malloc(len + 1);
		        if (!*version) {
				ERR(file->handle, "out of memory");
		                goto cleanup;
			}
		        memcpy(*version, buf, len);
		        (*version)[len] = '\0';
			seen |= SEEN_MOD;
			break;
		default:
			break;
		}

	}

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

	sepol_module_package_free(mod);
	free(offsets);
	return 0;

cleanup:
	sepol_module_package_free(mod);
	free(offsets);
	return -1;
}
Esempio n. 5
0
int main(int argc, char **argv)
{
	int ch, i, show_version = 0, verbose = 0, num_mods;
	char *basename, *outname = NULL;
	sepol_module_package_t *base, **mods;
	FILE *outfile;
	struct sepol_policy_file *pf;

	progname = argv[0];
	
	while ((ch = getopt(argc, argv, "o:V")) != EOF) {
                switch (ch) {
                case 'V':
                        show_version = 1;
                        break;
                case 'v':
                	verbose = 1;
                	break;
		case 'o':
			outname = optarg;
			break;
                default:
                        usage(argv[0]);
                }
        }
        
        if (show_version) {
                printf("%s\n", LINKPOLICY_VERSION);
                exit(0);
        }
        
        /* check args */
        if (argc < 3 || !(optind != (argc - 1))) {
                fprintf(stderr, "%s:  You must provide the base module package and at least one other module package\n", argv[0]);
                usage(argv[0]);
        }
        
        basename = argv[optind++];
        base = load_module(basename);
        if (!base) {
        	fprintf(stderr, "%s:  Could not load base module from file %s\n", argv[0], basename);
        	exit(1);
        }
       
        num_mods = argc - optind;
        mods = (sepol_module_package_t**)malloc(sizeof(sepol_module_package_t*) * num_mods);
        if (!mods) {
        	fprintf(stderr, "%s:  Out of memory\n", argv[0]);
        	exit(1);	
        }
        memset(mods, 0, sizeof(sepol_module_package_t*) * num_mods);
        
        for (i = 0; optind < argc; optind++, i++) {
        	mods[i] = load_module(argv[optind]);
        	if (!mods[i]) {
			fprintf(stderr, "%s:  Could not load module from file %s\n", argv[0], argv[optind]);
        		exit(1);
		}
        }

        if (sepol_link_packages(NULL, base, mods, num_mods, verbose)) {
        	fprintf(stderr, "%s:  Error while linking packages\n", argv[0]);
        	exit(1);	
        }
        
        if (outname) {
        	outfile = fopen(outname, "w");
	        if (!outfile) {
	        	perror(outname);
	        	exit(1);	
	        }
	        
		if (sepol_policy_file_create(&pf)) {
			fprintf(stderr, "%s:  Out of memory\n", argv[0]);
			exit(1);
		}
		sepol_policy_file_set_fp(pf, outfile);
        	if (sepol_module_package_write(base, pf)) {
        		fprintf(stderr, "%s:  Error writing linked package.\n", argv[0]);
        		exit(1);	
        	}
		sepol_policy_file_free(pf);
        }

	sepol_module_package_free(base);
        for (i = 0; i < num_mods; i++)
        	sepol_module_package_free(mods[i]);
	exit(0);
}
Esempio n. 6
0
/* Commits all changes in sandbox to the actual kernel policy.
 * Returns commit number on success, -1 on error.
 */
static int semanage_direct_commit(semanage_handle_t *sh) {
	char **mod_filenames = NULL;
	const char *linked_filename = NULL, *ofilename = NULL;
	sepol_module_package_t *base = NULL;
	int retval = -1, num_modfiles = 0, i;
	sepol_policydb_t* out = NULL;

	/* Declare some variables */
	int modified, fcontexts_modified, ports_modified, 
		seusers_modified, users_extra_modified;
	dbase_config_t* users = semanage_user_dbase_local(sh);
	dbase_config_t* users_base = semanage_user_base_dbase_local(sh);
	dbase_config_t* pusers_base = semanage_user_base_dbase_policy(sh);
	dbase_config_t* users_extra = semanage_user_extra_dbase_local(sh);
	dbase_config_t* pusers_extra = semanage_user_extra_dbase_policy(sh);
	dbase_config_t* ports = semanage_port_dbase_local(sh);
	dbase_config_t* pports = semanage_port_dbase_policy(sh);
	dbase_config_t* bools = semanage_bool_dbase_local(sh);
	dbase_config_t* pbools = semanage_bool_dbase_policy(sh);
	dbase_config_t* ifaces = semanage_iface_dbase_local(sh);
	dbase_config_t* pifaces = semanage_iface_dbase_policy(sh);
	dbase_config_t* nodes = semanage_node_dbase_local(sh);
	dbase_config_t* pnodes = semanage_node_dbase_policy(sh);
	dbase_config_t* fcontexts = semanage_fcontext_dbase_local(sh);
	dbase_config_t* pfcontexts = semanage_fcontext_dbase_policy(sh);
	dbase_config_t* seusers = semanage_seuser_dbase_local(sh);
	dbase_config_t* pseusers = semanage_seuser_dbase_policy(sh);

	/* Before we do anything else, flush the join to its component parts.
	 * This *does not* flush to disk automatically */
	if (users->dtable->is_modified(users->dbase) &&
	    users->dtable->flush(sh, users->dbase) < 0)
		goto cleanup;

	/* Decide if anything was modified */
	fcontexts_modified = fcontexts->dtable->is_modified(fcontexts->dbase);
	seusers_modified = seusers->dtable->is_modified(seusers->dbase);
	users_extra_modified = users_extra->dtable->is_modified(users_extra->dbase);
	ports_modified = ports->dtable->is_modified(ports->dbase);

	modified = sh->modules_modified;
	modified |= ports_modified;
	modified |= users->dtable->is_modified(users_base->dbase);
	modified |= bools->dtable->is_modified(bools->dbase);
	modified |= ifaces->dtable->is_modified(ifaces->dbase);
	modified |= nodes->dtable->is_modified(nodes->dbase);

	/* FIXME: get rid of these, once we support loading the existing policy,
	 * instead of rebuilding it */
	modified |= seusers_modified;
	modified |= fcontexts_modified;
	modified |= users_extra_modified;

	/* If there were policy changes, or explicitly requested, rebuild the policy */
	if (sh->do_rebuild || modified) {

		/* =================== Module expansion =============== */

		/* link all modules in the sandbox to the base module */
		if (semanage_get_modules_names(sh, &mod_filenames, &num_modfiles) != 0 ||
		    semanage_verify_modules(sh, mod_filenames, num_modfiles) == -1 ||
		    semanage_link_sandbox(sh, &base) < 0) {
			goto cleanup;
		}
	
		/* write the linked base */
		if ((linked_filename = semanage_path(SEMANAGE_TMP, SEMANAGE_LINKED)) == NULL ||
		    semanage_write_module(sh, linked_filename, base) == -1 ||
		    semanage_verify_linked(sh) != 0) {
			goto cleanup;
		}

		/* ==================== File-backed ================== */

		/* File Contexts */
		if ((ofilename = semanage_path(SEMANAGE_TMP, SEMANAGE_FC_TMPL)) == NULL ||
		    write_file(sh, ofilename, sepol_module_package_get_file_contexts(base), 
				sepol_module_package_get_file_contexts_len(base)) == -1) {
			goto cleanup;
		}

		if (semanage_split_fc(sh)) 
			goto cleanup;

		pfcontexts->dtable->drop_cache(pfcontexts->dbase);

		/* Seusers */
		if (sepol_module_package_get_seusers_len(base)) {
			if ((ofilename = semanage_path(SEMANAGE_TMP, SEMANAGE_SEUSERS)) == NULL ||
			    write_file(sh, ofilename, sepol_module_package_get_seusers(base), 
					sepol_module_package_get_seusers_len(base)) == -1) {
				goto cleanup;
			}
			pseusers->dtable->drop_cache(pseusers->dbase);

		} else {
			if (pseusers->dtable->clear(sh, pseusers->dbase) < 0)
				goto cleanup;
		}

		/* Users_extra */
		if (sepol_module_package_get_user_extra_len(base)) {
			if ((ofilename = semanage_path(SEMANAGE_TMP, SEMANAGE_USERS_EXTRA)) == NULL ||
			    write_file(sh, ofilename, sepol_module_package_get_user_extra(base), 
					sepol_module_package_get_user_extra_len(base)) == -1) {
				goto cleanup;
			}
			pusers_extra->dtable->drop_cache(pusers_extra->dbase);

		} else {
			if (pusers_extra->dtable->clear(sh, pusers_extra->dbase) < 0)
				goto cleanup;
		}

		/* ==================== Policydb-backed ================ */

		/* Create new policy object, then attach to policy databases
		 * that work with a policydb */
		if (semanage_expand_sandbox(sh, base, &out) < 0)
			goto cleanup;

		dbase_policydb_attach((dbase_policydb_t*) pusers_base->dbase, out);
		dbase_policydb_attach((dbase_policydb_t*) pports->dbase, out);
		dbase_policydb_attach((dbase_policydb_t*) pifaces->dbase, out);
		dbase_policydb_attach((dbase_policydb_t*) pbools->dbase, out);
		dbase_policydb_attach((dbase_policydb_t*) pnodes->dbase, out);

		/* ============= Apply changes, and verify  =============== */

		if (semanage_base_merge_components(sh) < 0)
			goto cleanup;

		if (semanage_write_policydb(sh, out) < 0)
			goto cleanup;

		if (semanage_verify_kernel(sh) != 0)
			goto cleanup;
	}

	/* FIXME: else if !modified, but seusers_modified, 
	 * load the existing policy instead of rebuilding */

	/* ======= Post-process: Validate non-policydb components ===== */

	/* Validate local modifications to file contexts.
	 * Note: those are still cached, even though they've been 
	 * merged into the main file_contexts. We won't check the 
	 * large file_contexts - checked at compile time */
	if (sh->do_rebuild || modified || fcontexts_modified) {
		if (semanage_fcontext_validate_local(sh, out) < 0)
			goto cleanup;
	}

	/* Validate local seusers against policy */
	if (sh->do_rebuild || modified || seusers_modified) {
		if (semanage_seuser_validate_local(sh, out) < 0) 
			goto cleanup;
	}

	/* Validate local ports for overlap */
	if (sh->do_rebuild || ports_modified) {
		if (semanage_port_validate_local(sh) < 0)
			goto cleanup;
	}

	/* ================== Write non-policydb components ========= */

	/* Commit changes to components */
	if (semanage_commit_components(sh) < 0)
		goto cleanup;

	retval = semanage_install_sandbox(sh);

 cleanup:
	for (i = 0; mod_filenames != NULL && i < num_modfiles; i++) {
		free(mod_filenames[i]);
	}

	/* Detach from policydb, so it can be freed */
	dbase_policydb_detach((dbase_policydb_t*) pusers_base->dbase);
	dbase_policydb_detach((dbase_policydb_t*) pports->dbase);
	dbase_policydb_detach((dbase_policydb_t*) pifaces->dbase);
	dbase_policydb_detach((dbase_policydb_t*) pnodes->dbase);
	dbase_policydb_detach((dbase_policydb_t*) pbools->dbase);

	free(mod_filenames);
	sepol_module_package_free(base);
	sepol_policydb_free(out);
	semanage_release_trans_lock(sh);

	/* regardless if the commit was successful or not, remove the
	   sandbox if it is still there */
	semanage_remove_directory(semanage_path(SEMANAGE_TMP, SEMANAGE_TOPLEVEL));
	return retval;
}