diff --git a/libsemanage/src/conf-parse.y b/libsemanage/src/conf-parse.y index bbdac1d..80d08ec 100644 --- a/libsemanage/src/conf-parse.y +++ b/libsemanage/src/conf-parse.y @@ -58,7 +58,7 @@ static int parse_errors; } %token MODULE_STORE VERSION EXPAND_CHECK FILE_MODE SAVE_PREVIOUS SAVE_LINKED -%token LOAD_POLICY_START SETFILES_START DISABLE_GENHOMEDIRCON HANDLE_UNKNOWN USEPASSWD IGNOREDIRS +%token LOAD_POLICY_START SETFILES_START SEFCONTEXT_COMPILE_START DISABLE_GENHOMEDIRCON HANDLE_UNKNOWN USEPASSWD IGNOREDIRS %token BZIP_BLOCKSIZE BZIP_SMALL %token VERIFY_MOD_START VERIFY_LINKED_START VERIFY_KERNEL_START BLOCK_END %token PROG_PATH PROG_ARGS @@ -230,6 +230,14 @@ command_start: YYABORT; } } + | SEFCONTEXT_COMPILE_START { + semanage_conf_external_prog_destroy(current_conf->sefcontext_compile); + current_conf->sefcontext_compile = NULL; + if (new_external_prog(¤t_conf->sefcontext_compile) == -1) { + parse_errors++; + YYABORT; + } + } ; verify_block: verify_start external_opts BLOCK_END { @@ -308,6 +316,20 @@ static int semanage_conf_init(semanage_conf_t * conf) return -1; } + if ((conf->sefcontext_compile = + calloc(1, sizeof(*(current_conf->sefcontext_compile)))) == NULL) { + return -1; + } + if (access("/sbin/sefcontext_compile", X_OK) == 0) { + conf->sefcontext_compile->path = strdup("/sbin/sefcontext_compile"); + } else { + conf->sefcontext_compile->path = strdup("/usr/sbin/sefcontext_compile"); + } + if ((conf->sefcontext_compile->path == NULL) || + (conf->sefcontext_compile->args = strdup("$@")) == NULL) { + return -1; + } + return 0; } @@ -363,6 +385,7 @@ void semanage_conf_destroy(semanage_conf_t * conf) free(conf->ignoredirs); semanage_conf_external_prog_destroy(conf->load_policy); semanage_conf_external_prog_destroy(conf->setfiles); + semanage_conf_external_prog_destroy(conf->sefcontext_compile); semanage_conf_external_prog_destroy(conf->mod_prog); semanage_conf_external_prog_destroy(conf->linked_prog); semanage_conf_external_prog_destroy(conf->kernel_prog); diff --git a/libsemanage/src/conf-scan.l b/libsemanage/src/conf-scan.l index 7ef4154..41ba044 100644 --- a/libsemanage/src/conf-scan.l +++ b/libsemanage/src/conf-scan.l @@ -53,6 +53,7 @@ bzip-blocksize return BZIP_BLOCKSIZE; bzip-small return BZIP_SMALL; "[load_policy]" return LOAD_POLICY_START; "[setfiles]" return SETFILES_START; +"[sefcontext_compile]" return SEFCONTEXT_COMPILE_START; "[verify module]" return VERIFY_MOD_START; "[verify linked]" return VERIFY_LINKED_START; "[verify kernel]" return VERIFY_KERNEL_START; diff --git a/libsemanage/src/direct_api.c b/libsemanage/src/direct_api.c index 4f919a6..64dc7d9 100644 --- a/libsemanage/src/direct_api.c +++ b/libsemanage/src/direct_api.c @@ -1306,80 +1306,67 @@ static int semanage_direct_install_base_file(semanage_handle_t * sh, return retval; } -/* Enables a module from the sandbox. Returns 0 on success, -1 if out - * of memory, -2 if module not found or could not be enabled. */ -static int semanage_direct_enable(semanage_handle_t * sh, char *module_name) -{ - int i, retval = -1; - char **module_filenames = NULL; - int num_mod_files; - size_t name_len = strlen(module_name); - if (semanage_get_modules_names(sh, &module_filenames, &num_mod_files) == - -1) { - return -1; +static int get_module_name(semanage_handle_t * sh, char *modulefile, char **module_name) { + FILE *fp = NULL; + int retval = -1; + char *data = NULL; + char *version = NULL; + ssize_t size; + int type; + struct sepol_policy_file *pf = NULL; + + if (sepol_policy_file_create(&pf)) { + ERR(sh, "Out of memory!"); + goto cleanup; } - for (i = 0; i < num_mod_files; i++) { - char *base = strrchr(module_filenames[i], '/'); - if (base == NULL) { - ERR(sh, "Could not read module names."); - retval = -2; - goto cleanup; - } - base++; - if (memcmp(module_name, base, name_len) == 0) { + sepol_policy_file_set_handle(pf, sh->sepolh); - if (semanage_enable_module(module_filenames[i]) < 0) { - ERR(sh, "Could not enable module %s.", module_name); - retval = -2; - goto cleanup; - } - retval = 0; - goto cleanup; - } + if ((fp = fopen(modulefile, "rb")) == NULL) { + goto cleanup; } - ERR(sh, "Module %s was not found.", module_name); - retval = -2; /* module not found */ - cleanup: - for (i = 0; module_filenames != NULL && i < num_mod_files; i++) { - free(module_filenames[i]); + if ((size = bunzip(sh, fp, &data)) > 0) { + sepol_policy_file_set_mem(pf, data, size); + } else { + rewind(fp); + __fsetlocking(fp, FSETLOCKING_BYCALLER); + sepol_policy_file_set_fp(pf, fp); } - free(module_filenames); + retval = sepol_module_package_info(pf, &type, module_name, &version); + +cleanup: + sepol_policy_file_free(pf); + if (fp) + fclose(fp); + free(data); + free(version); return retval; } -/* Disables a module from the sandbox. Returns 0 on success, -1 if out - * of memory, -2 if module not found or could not be enabled. */ -static int semanage_direct_disable(semanage_handle_t * sh, char *module_name) -{ +static int get_module_file_by_name(semanage_handle_t * sh, const char *module_name, char **module_file) { int i, retval = -1; char **module_filenames = NULL; + char *name = NULL; int num_mod_files; - size_t name_len = strlen(module_name); if (semanage_get_modules_names(sh, &module_filenames, &num_mod_files) == -1) { return -1; } for (i = 0; i < num_mod_files; i++) { - char *base = strrchr(module_filenames[i], '/'); - if (base == NULL) { - ERR(sh, "Could not read module names."); - retval = -2; - goto cleanup; - } - base++; - if ((memcmp(module_name, base, name_len) == 0) && - (strcmp(base + name_len, ".pp") == 0)) { - if (semanage_disable_module(module_filenames[i]) < 0) { - retval = -2; - goto cleanup; - } - retval=0; + int rc = get_module_name(sh, module_filenames[i], &name); + if (rc < 0) + continue; + if (strcmp(module_name, name) == 0) { + *module_file = strdup(module_filenames[i]); + if (*module_file) + retval = 0; goto cleanup; } + free(name); name = NULL; } ERR(sh, "Module %s was not found.", module_name); retval = -2; /* module not found */ cleanup: + free(name); for (i = 0; module_filenames != NULL && i < num_mod_files; i++) { free(module_filenames[i]); } @@ -1387,44 +1374,57 @@ static int semanage_direct_disable(semanage_handle_t * sh, char *module_name) return retval; } +/* Enables a module from the sandbox. Returns 0 on success, -1 if out + * of memory, -2 if module not found or could not be enabled. */ +static int semanage_direct_enable(semanage_handle_t * sh, char *module_name) +{ + char *module_filename = NULL; + int retval = get_module_file_by_name(sh, module_name, &module_filename); + if (retval < 0) + return -1; /* module not found */ + retval = semanage_enable_module(module_filename); + if (retval < 0) { + ERR(sh, "Could not enable module file %s.", + module_filename); + retval = -2; + } + free(module_filename); + return retval; +} + +/* Disables a module from the sandbox. Returns 0 on success, -1 if out + * of memory, -2 if module not found or could not be enabled. */ +static int semanage_direct_disable(semanage_handle_t * sh, char *module_name) +{ + char *module_filename = NULL; + int retval = get_module_file_by_name(sh, module_name, &module_filename); if (retval < 0) + return -1; /* module not found */ + retval = semanage_disable_module(module_filename); + if (retval < 0) { + ERR(sh, "Could not disable module file %s.", + module_filename); + retval = -2; + } + free(module_filename); + return retval; +} + /* Removes a module from the sandbox. Returns 0 on success, -1 if out * of memory, -2 if module not found or could not be removed. */ static int semanage_direct_remove(semanage_handle_t * sh, char *module_name) { - int i, retval = -1; - char **module_filenames = NULL; - int num_mod_files; - size_t name_len = strlen(module_name); - if (semanage_get_modules_names(sh, &module_filenames, &num_mod_files) == - -1) { - return -1; - } - for (i = 0; i < num_mod_files; i++) { - char *base = strrchr(module_filenames[i], '/'); - if (base == NULL) { - ERR(sh, "Could not read module names."); - retval = -2; - goto cleanup; - } - base++; - if (memcmp(module_name, base, name_len) == 0) { - semanage_enable_module(module_filenames[i]); - if (unlink(module_filenames[i]) == -1) { - ERR(sh, "Could not remove module file %s.", - module_filenames[i]); - retval = -2; - } - retval = 0; - goto cleanup; - } - } - ERR(sh, "Module %s was not found.", module_name); - retval = -2; /* module not found */ - cleanup: - for (i = 0; module_filenames != NULL && i < num_mod_files; i++) { - free(module_filenames[i]); - } - free(module_filenames); + char *module_filename = NULL; + int retval = get_module_file_by_name(sh, module_name, &module_filename); + if (retval < 0) + return -1; /* module not found */ + (void) semanage_enable_module(module_filename); /* Don't care if this fails */ + retval = unlink(module_filename); + if (retval < 0) { + ERR(sh, "Could not remove module file %s.", + module_filename); + retval = -2; + } + free(module_filename); return retval; } diff --git a/libsemanage/src/handle.c b/libsemanage/src/handle.c index 7fcd2b4..6aa9057 100644 --- a/libsemanage/src/handle.c +++ b/libsemanage/src/handle.c @@ -52,6 +52,26 @@ static char *private_usersconf_path = NULL; static char *private_netfilter_context_path = NULL; static char *private_policy_root = NULL; +static char *get_policy_path(void) { + char *dup_path = NULL; + int max = security_policyvers(); + if (max < 0) + max = sepol_policy_kern_vers_max(); + + char *policy_path = selinux_binary_policy_path_min_max(0, &max); + if (policy_path) { + dup_path = strdup(policy_path); + free(policy_path); + } else { + /* No Policy installed so just do max */ + int ret = asprintf(&policy_path, "%s.%d", selinux_binary_policy_path(), sepol_policy_kern_vers_max()); + if (ret > 0) + dup_path = strdup(policy_path); + free(policy_path); + } + return dup_path; +} + void semanage_free_root() { free(private_selinux_path); private_selinux_path = NULL; free(private_semanage_conf_path); private_semanage_conf_path = NULL; @@ -91,9 +111,15 @@ int semanage_set_root(const char *path) { goto error; } - if ( asprintf(&private_binary_policy_path, "%s/%s", path, selinux_binary_policy_path()) < 0 ) { + char *policy_path = get_policy_path(); + if (! policy_path) + goto error; + + if ( asprintf(&private_binary_policy_path, "%s/%s", path, policy_path) < 0 ) { + free(policy_path); goto error; } + free(policy_path); if ( asprintf(&private_usersconf_path, "%s/%s", path, selinux_usersconf_path()) < 0 ) { goto error; @@ -147,7 +173,9 @@ const char *semanage_binary_policy_path() { // printf("private_binary_policy_path %s\n", private_binary_policy_path); if (private_binary_policy_path) return private_binary_policy_path; - return selinux_binary_policy_path(); + + private_binary_policy_path = get_policy_path(); + return private_binary_policy_path; } const char *semanage_usersconf_path() { diff --git a/libsemanage/src/semanage_conf.h b/libsemanage/src/semanage_conf.h index 95f8ec3..9b7852c 100644 --- a/libsemanage/src/semanage_conf.h +++ b/libsemanage/src/semanage_conf.h @@ -46,6 +46,7 @@ typedef struct semanage_conf { char *ignoredirs; /* ";" separated of list for genhomedircon to ignore */ struct external_prog *load_policy; struct external_prog *setfiles; + struct external_prog *sefcontext_compile; struct external_prog *mod_prog, *linked_prog, *kernel_prog; } semanage_conf_t; diff --git a/libsemanage/src/semanage_store.c b/libsemanage/src/semanage_store.c index cd7ce68..13c25e3 100644 --- a/libsemanage/src/semanage_store.c +++ b/libsemanage/src/semanage_store.c @@ -448,7 +448,7 @@ int semanage_enable_module(const char *file) { char path[PATH_MAX]; int n = snprintf(path, PATH_MAX, "%s.%s", file, DISABLESTR); if (n < 0 || n >= PATH_MAX) - return 1; + return -1; if ((unlink(path) < 0) && (errno != ENOENT)) return -1; @@ -1100,6 +1100,17 @@ int semanage_split_fc(semanage_handle_t * sh) } +static int sefcontext_compile(semanage_handle_t * sh, const char *path) { + + int r; + if ((r = semanage_exec_prog(sh, sh->conf->sefcontext_compile, path, "")) != 0) { + ERR(sh, "sefcontext_compile returned error code %d. Compiling %s", r, path); + return -1; + } + + return 0; +} + /* Actually load the contents of the current active directory into the * kernel. Return 0 on success, -3 on error. */ static int semanage_install_active(semanage_handle_t * sh) @@ -1145,8 +1156,7 @@ static int semanage_install_active(semanage_handle_t * sh) if (asprintf(&storepath, "%s%s", semanage_selinux_path(), sh->conf->store_path) < 0) return retval; - snprintf(store_pol, PATH_MAX, "%s%s.%d", storepath, - running_policy, sh->conf->policyvers); + snprintf(store_pol, PATH_MAX, "%s%s", storepath, running_policy); if (semanage_copy_file(active_kernel, store_pol, sh->conf->file_mode) == -1) { ERR(sh, "Could not copy %s to %s.", active_kernel, store_pol); @@ -1233,6 +1243,16 @@ static int semanage_install_active(semanage_handle_t * sh) goto cleanup; } + if (sefcontext_compile(sh, store_fc) != 0) { + goto cleanup; + } + if (sefcontext_compile(sh, store_fc_loc) != 0) { + goto cleanup; + } + if (sefcontext_compile(sh, store_fc_hd) != 0) { + goto cleanup; + } + retval = 0; cleanup: free(storepath); @@ -1371,6 +1391,11 @@ int semanage_install_sandbox(semanage_handle_t * sh) goto cleanup; } + if (sh->conf->sefcontext_compile == NULL) { + ERR(sh, "No sefcontext_compile program specified in configuration file."); + goto cleanup; + } + if ((commit_num = semanage_commit_sandbox(sh)) < 0) { retval = commit_num; goto cleanup;