semanage_handle_t *semanage_handle_create(void) { semanage_handle_t *sh = NULL; const char *conf_name = NULL; /* Allocate handle */ if ((sh = calloc(1, sizeof(semanage_handle_t))) == NULL) goto err; if ((conf_name = semanage_conf_path()) == NULL) goto err; if ((sh->conf = semanage_conf_parse(conf_name)) == NULL) goto err; /* Link to sepol handle */ sh->sepolh = sepol_handle_create(); if (!sh->sepolh) goto err; sepol_msg_set_callback(sh->sepolh, semanage_msg_relay_handler, sh); /* By default do not rebuild the policy on commit * If any changes are made, this flag is ignored */ sh->do_rebuild = 0; /* By default always reload policy after commit if SELinux is enabled. */ sh->do_reload = (is_selinux_enabled() > 0); /* By default always check the file contexts file. */ sh->do_check_contexts = 1; /* By default do not create store */ sh->create_store = 0; /* Set timeout: some default value for now, later use config */ sh->timeout = SEMANAGE_COMMIT_READ_WAIT; /* Set callback */ sh->msg_callback = semanage_msg_default_handler; sh->msg_callback_arg = NULL; return sh; err: semanage_handle_destroy(sh); return NULL; }
// /sys/fs/selinux/load requires the entire policy to be written in a single // write(2) call. // See: http://marc.info/?l=selinux&m=141882521027239&w=2 bool selinux_write_policy(const std::string &path, policydb_t *pdb) { void *data; size_t len; sepol_handle_t *handle; int fd; // Don't print warnings to stderr handle = sepol_handle_create(); sepol_msg_set_callback(handle, nullptr, nullptr); auto destroy_handle = finally([&] { sepol_handle_destroy(handle); }); if (policydb_to_image(handle, pdb, &data, &len) < 0) { LOGE("Failed to write policydb to memory"); return false; } auto free_data = finally([&] { free(data); }); fd = open(path.c_str(), O_CREAT | O_TRUNC | O_RDWR, 0644); if (fd < 0) { LOGE("Failed to open %s: %s", path.c_str(), strerror(errno)); return false; } auto close_fd = finally([&] { close(fd); }); if (write(fd, data, len) < 0) { LOGE("Failed to write to %s: %s", path.c_str(), strerror(errno)); return false; } return true; }
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); } }