/* 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; }
/* 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; }
/* 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; }
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; }
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; }
/* 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; }
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; }
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); } }
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); }
/* 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; }