예제 #1
0
/* Writes a module (or a base) to the file given by a fully-qualified
 * 'filename'.	Returns 0 on success, -1 if file could not be written.
 */
static int semanage_write_module(semanage_handle_t *sh,
				 const char *filename, sepol_module_package_t *package)
{
	struct sepol_policy_file *pf;
	FILE *outfile;
	int retval;
	if (sepol_policy_file_create(&pf)) {
		ERR(sh, "Out of memory!");
		return -1;
	}
	if ((outfile = fopen(filename, "wb")) == NULL) {
		sepol_policy_file_free(pf);
		ERR(sh, "Could not open %s for writing.", filename);
		return -1;
	}
	sepol_policy_file_set_fp(pf, outfile);
	sepol_policy_file_set_handle(pf, sh->sepolh);
	retval = sepol_module_package_write(package, pf);
	fclose(outfile);
	sepol_policy_file_free(pf);
	if (retval == -1) {
		ERR(sh, "Error while writing module to %s.", filename);
		return -1;
	}
	return 0;
}
예제 #2
0
파일: modules.c 프로젝트: Chainfire/selinux
/* Takes a module stored in 'module_data' and parses its headers.
 * Sets reference variables 'module_name' to module's name and
 * 'version' to module's version. The caller is responsible for
 * free()ing 'module_name' and 'version'; they will be
 * set to NULL upon entering this function.  Returns 0 on success, -1
 * if out of memory, or -2 if data did not represent a module.
 */
static int parse_module_headers(semanage_handle_t * sh, char *module_data,
				size_t data_len, char **module_name, char **version)
{
	struct sepol_policy_file *pf;
	int file_type;
	*version = NULL;

	if (sepol_policy_file_create(&pf)) {
		ERR(sh, "Out of memory!");
		return -1;
	}
	sepol_policy_file_set_mem(pf, module_data, data_len);
	sepol_policy_file_set_handle(pf, sh->sepolh);
	if (module_data == NULL ||
	    data_len == 0 ||
	    sepol_module_package_info(pf, &file_type, module_name, version) == -1) {
		sepol_policy_file_free(pf);
		ERR(sh, "Could not parse module data.");
		return -2;
	}
	sepol_policy_file_free(pf);
	if (file_type != SEPOL_POLICY_MOD) {
		ERR(sh, "Data did not represent a pp module. Please upgrade to the latest version of libsemanage to support hll modules.");
		return -2;
	}

	return 0;
}
예제 #3
0
/* Takes a base module stored in 'module_data' and parse its headers.
 * Returns 0 on success, -1 if out of memory, or -2 if data did not
 * represent a module.
 */
static int parse_base_headers(semanage_handle_t *sh,
			      char *module_data, size_t data_len) {
	struct sepol_policy_file *pf;
	char *module_name = NULL, *version = NULL;
	int file_type;

	if (sepol_policy_file_create(&pf)) {
		ERR(sh, "Out of memory!");
		return -1;
	}
	sepol_policy_file_set_mem(pf, module_data, data_len);
	sepol_policy_file_set_handle(pf, sh->sepolh);
	if (module_data == NULL ||
	    data_len == 0 ||
	    sepol_module_package_info(pf, &file_type,
				      &module_name, &version) == -1) {
		sepol_policy_file_free(pf);
		ERR(sh, "Could not parse base module data.");
		return -2;
	}
	sepol_policy_file_free(pf);
	free(module_name);
	free(version);
	if (file_type != SEPOL_POLICY_BASE) {
		if (file_type == SEPOL_POLICY_MOD)
			ERR(sh, "Received a non-base module, expected a base module.");
		else
			ERR(sh, "Data did not represent a module.");
		return -2;
	}
	return 0;
}
예제 #4
0
static int file_to_policy_file(char *filename, struct sepol_policy_file **pf, char *mode)
{
	FILE *f;
	
	if (sepol_policy_file_create(pf)) {
		fprintf(stderr, "%s:  Out of memory\n", progname);
		return -1;	
	}
	
	f = fopen(filename, mode);
	if (!f) {
		fprintf(stderr, "%s:  Could not open file %s:  %s\n", progname, strerror(errno), filename);
		return -1;	
	}
	sepol_policy_file_set_fp(*pf, f);
	return 0;
}
예제 #5
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;
}
예제 #6
0
/* Takes a module stored in 'module_data' and parses its headers.
 * Sets reference variables 'filename' to module's fully qualified
 * path name into the sandbox, 'module_name' to module's name, and
 * 'version' to module's version.  The caller is responsible for
 * free()ing 'filename', 'module_name', and 'version'; they will be
 * set to NULL upon entering this function.  Returns 0 on success, -1
 * if out of memory, or -2 if data did not represent a module.
 */
static int parse_module_headers(semanage_handle_t *sh, char *module_data,
				size_t data_len, char **module_name,
				char **version, char **filename) {
	struct sepol_policy_file *pf;
	int file_type;
	const char *module_path;
	*module_name = *version = *filename = NULL;
	
	if (sepol_policy_file_create(&pf)) {
		ERR(sh, "Out of memory!");
		return -1;
	}
	sepol_policy_file_set_mem(pf, module_data, data_len);
	sepol_policy_file_set_handle(pf, sh->sepolh);
	if (module_data == NULL ||
	    data_len == 0 ||
	    sepol_module_package_info(pf, &file_type, module_name,
				      version) == -1) {
		sepol_policy_file_free(pf);
		ERR(sh, "Could not parse module data.");
		return -2;
	}
	sepol_policy_file_free(pf);
	if (file_type != SEPOL_POLICY_MOD) {
		if (file_type == SEPOL_POLICY_BASE)
			ERR(sh, "Received a base module, expected a non-base module.");
		else
			ERR(sh, "Data did not represent a module.");
		return -2;
	}
	if ((module_path = semanage_path(SEMANAGE_TMP, SEMANAGE_MODULES)) == NULL) {
		return -1;
	}
	if (asprintf(filename, "%s/%s.pp", module_path, *module_name) == -1) {
		ERR(sh, "Out of memory!");
		return -1;
	}
	return 0;
}
예제 #7
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;
}
예제 #8
0
static void do_fc_check_and_die_on_error(struct selinux_opt opts[], unsigned int backend, filemode mode,
        const char *sepolicy_file, const char *context_file, bool allow_empty)
{
    struct stat sb;
    if (stat(context_file, &sb) < 0) {
        perror("Error: could not get stat on file contexts file");
        exit(1);
    }

    if (sb.st_size == 0) {
        /* Nothing to check on empty file_contexts file if allowed*/
        if (allow_empty) {
            return;
        }
        /* else: We could throw the error here, but libselinux backend will catch it */
    }

    global_state.sepolicy.file = fopen(sepolicy_file, "r");
    if (!global_state.sepolicy.file) {
      perror("Error: could not open policy file");
      exit(1);
    }

    global_state.sepolicy.handle = sepol_handle_create();
    if (!global_state.sepolicy.handle) {
        fprintf(stderr, "Error: could not create policy handle: %s\n", strerror(errno));
        exit(1);
    }

    if (sepol_policy_file_create(&global_state.sepolicy.pf) < 0) {
      perror("Error: could not create policy handle");
      exit(1);
    }

    sepol_policy_file_set_fp(global_state.sepolicy.pf, global_state.sepolicy.file);
    sepol_policy_file_set_handle(global_state.sepolicy.pf, global_state.sepolicy.handle);

    int rc = sepol_policydb_create(&global_state.sepolicy.sdb);
    if (rc < 0) {
      perror("Error: could not create policy db");
      exit(1);
    }

    rc = sepol_policydb_read(global_state.sepolicy.sdb, global_state.sepolicy.pf);
    if (rc < 0) {
      perror("Error: could not read file into policy db");
      exit(1);
    }

    global_state.assert.attrs = filemode_to_assert_attrs(mode);

    bool ret = ebitmap_attribute_assertion_init(&global_state.assert.set, global_state.assert.attrs);
    if (!ret) {
        /* error messages logged by ebitmap_attribute_assertion_init() */
        exit(1);
    }

    selinux_set_callback(SELINUX_CB_VALIDATE,
                         (union selinux_callback)&validate);

    opts[1].value = context_file;

    global_state.sepolicy.sehnd[0] = selabel_open(backend, opts, 2);
    if (!global_state.sepolicy.sehnd[0]) {
      fprintf(stderr, "Error: could not load context file from %s\n", context_file);
      exit(1);
    }
}
예제 #9
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);
}
예제 #10
0
/* Allocate an array of module_info structures for each readable
 * module within the store.  Note that if the calling program has
 * already begun a transaction then this function will get a list of
 * modules within the sandbox.	The caller is responsible for calling
 * semanage_module_info_datum_destroy() on each element of the array
 * as well as free()ing the entire list.
 */
static int semanage_direct_list(semanage_handle_t *sh,
				semanage_module_info_t **modinfo, int *num_modules) {
	struct sepol_policy_file *pf = NULL;
	int i, retval = -1;
	char **module_filenames = NULL;
	int num_mod_files;
	*modinfo = NULL;
	*num_modules = 0;

        /* get the read lock when reading from the active
           (non-transaction) directory */
	if (!sh->is_in_transaction) 
		if (semanage_get_active_lock(sh) < 0) 
			return -1;

	if (semanage_get_modules_names(sh, &module_filenames, &num_mod_files) == -1) {
		goto cleanup;
	}
	if (num_mod_files == 0) {
		retval = semanage_get_commit_number(sh);
		goto cleanup;
	}

	if (sepol_policy_file_create(&pf)) {
		ERR(sh, "Out of memory!");
		goto cleanup;
	}
	sepol_policy_file_set_handle(pf, sh->sepolh);
	
	if ((*modinfo = calloc(num_mod_files, sizeof(**modinfo))) == NULL) {
		ERR(sh, "Out of memory!");
		goto cleanup;
	}
	
	for (i = 0; i < num_mod_files; i++) {
		FILE *fp;
		char *name = NULL, *version = NULL;
		int type;
		if ((fp = fopen(module_filenames[i], "rb")) == NULL) {
			/* could not open this module file, so don't
			 * report it */
			continue;
		}
		sepol_policy_file_set_fp(pf, fp);
		if (sepol_module_package_info(pf, &type, &name, &version)) {
			fclose(fp);
			free(name);
			free(version);
			continue;
		}
		fclose(fp);
		if (type == SEPOL_POLICY_MOD) {
			(*modinfo)[*num_modules].name = name;
			(*modinfo)[*num_modules].version = version;
			(*num_modules)++;
		}
		else {
			/* file was not a module, so don't report it */
			free(name);
			free(version);
		}
	}
	retval = semanage_get_commit_number(sh);
	
 cleanup:
	sepol_policy_file_free(pf);
	for (i = 0; module_filenames != NULL && i < num_mod_files; i++) {
		free(module_filenames[i]);
	}
	free(module_filenames);
        if (!sh->is_in_transaction) {
                semanage_release_active_lock(sh);
        }
	return retval;
}