diff --git a/libsemanage/include/semanage/handle.h b/libsemanage/include/semanage/handle.h index e303713..c746930 100644 --- a/libsemanage/include/semanage/handle.h +++ b/libsemanage/include/semanage/handle.h @@ -129,6 +129,12 @@ int semanage_mls_enabled(semanage_handle_t *sh); /* Change to alternate selinux root path */ int semanage_set_root(const char *path); +/* Get whether or not needless unused branch of tunables would be preserved */ +int semanage_get_preserve_tunables(semanage_handle_t * handle); + +/* Set whether or not to preserve the needless unused branch of tunables */ +void semanage_set_preserve_tunables(semanage_handle_t * handle, int preserve_tunables); + /* META NOTES * * For all functions a non-negative number indicates success. For some diff --git a/libsemanage/src/direct_api.c b/libsemanage/src/direct_api.c index aac1974..8fcfb88 100644 --- a/libsemanage/src/direct_api.c +++ b/libsemanage/src/direct_api.c @@ -353,17 +353,11 @@ static int parse_module_headers(semanage_handle_t * sh, char *module_data, semanage_path(SEMANAGE_TMP, SEMANAGE_MODULES)) == NULL) { return -1; } - if (asprintf(filename, "%s/%s.pp%s", module_path, *module_name, DISABLESTR) == -1) { + if (asprintf(filename, "%s/%s.pp", module_path, *module_name) == -1) { ERR(sh, "Out of memory!"); return -1; } - if (access(*filename, F_OK) == -1) { - char *ptr = *filename; - int len = strlen(ptr) - strlen(DISABLESTR); - if (len > 0) ptr[len]='\0'; - } - return 0; } @@ -695,7 +689,8 @@ static int semanage_direct_commit(semanage_handle_t * sh) /* Declare some variables */ int modified = 0, fcontexts_modified, ports_modified, - seusers_modified, users_extra_modified, dontaudit_modified; + seusers_modified, users_extra_modified, dontaudit_modified, + preserve_tunables_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); @@ -737,6 +732,31 @@ static int semanage_direct_commit(semanage_handle_t * sh) } } + /* Create or remove the preserve_tunables flag file. */ + path = semanage_path(SEMANAGE_TMP, SEMANAGE_PRESERVE_TUNABLES); + if (access(path, F_OK) == 0) + preserve_tunables_modified = !(sepol_get_preserve_tunables(sh->sepolh) == 1); + else + preserve_tunables_modified = (sepol_get_preserve_tunables(sh->sepolh) == 1); + if (sepol_get_preserve_tunables(sh->sepolh) == 1) { + FILE *touch; + touch = fopen(path, "w"); + if (touch != NULL) { + if (fclose(touch) != 0) { + ERR(sh, "Error attempting to create preserve_tunable flag."); + goto cleanup; + } + } else { + ERR(sh, "Error attempting to create preserve_tunable flag."); + goto cleanup; + } + } else { + if (remove(path) == -1 && errno != ENOENT) { + ERR(sh, "Error removing the preserve_tunables flag."); + goto cleanup; + } + } + /* 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)) { @@ -759,6 +779,7 @@ static int semanage_direct_commit(semanage_handle_t * sh) modified |= ifaces->dtable->is_modified(ifaces->dbase); modified |= nodes->dtable->is_modified(nodes->dbase); modified |= dontaudit_modified; + modified |= preserve_tunables_modified; /* If there were policy changes, or explicitly requested, rebuild the policy */ if (sh->do_rebuild || modified) { @@ -1307,29 +1328,12 @@ static int semanage_direct_enable(semanage_handle_t * sh, char *module_name) base++; if (memcmp(module_name, base, name_len) == 0) { - if(strcmp(base + name_len + 3, DISABLESTR) != 0) { - ERR(sh, "Module %s is already enabled.", module_name); + if (semanage_enable_module(module_filenames[i]) < 0) { + ERR(sh, "Could not enable module %s.", module_name); retval = -2; goto cleanup; } - - int len = strlen(module_filenames[i]) - strlen(DISABLESTR); - char *enabled_name = calloc(1, len+1); - if (!enabled_name) { - ERR(sh, "Could not allocate memory"); - retval = -1; - goto cleanup; - } - - strncpy(enabled_name, module_filenames[i],len); - - if (rename(module_filenames[i], enabled_name) == -1) { - ERR(sh, "Could not enable module file %s.", - enabled_name); - retval = -2; - } retval = 0; - free(enabled_name); goto cleanup; } } @@ -1363,28 +1367,14 @@ static int semanage_direct_disable(semanage_handle_t * sh, char *module_name) goto cleanup; } base++; - if (memcmp(module_name, base, name_len) == 0) { - if (strcmp(base + name_len + 3, DISABLESTR) == 0) { - ERR(sh, "Module %s is already disabled.", module_name); + 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; - } else if (strcmp(base + name_len, ".pp") == 0) { - char disabled_name[PATH_MAX]; - if (snprintf(disabled_name, PATH_MAX, "%s%s", - module_filenames[i], DISABLESTR) == PATH_MAX) { - ERR(sh, "Could not disable module file %s.", - module_filenames[i]); - retval = -2; - goto cleanup; - } - if (rename(module_filenames[i], disabled_name) == -1) { - ERR(sh, "Could not disable module file %s.", - module_filenames[i]); - retval = -2; - } - retval = 0; - goto cleanup; } + retval=0; + goto cleanup; } } ERR(sh, "Module %s was not found.", module_name); @@ -1418,6 +1408,7 @@ static int semanage_direct_remove(semanage_handle_t * sh, char *module_name) } 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]); diff --git a/libsemanage/src/genhomedircon.c b/libsemanage/src/genhomedircon.c index 847d87e..2870fa8 100644 --- a/libsemanage/src/genhomedircon.c +++ b/libsemanage/src/genhomedircon.c @@ -314,6 +314,8 @@ static semanage_list_t *get_home_dirs(genhomedircon_settings_t * s) } if (strcmp(pwbuf->pw_dir, "/") == 0) continue; + if (strcmp(pwbuf->pw_dir, "/root") == 0) + continue; if (semanage_str_count(pwbuf->pw_dir, '/') <= 1) continue; if (!(path = strdup(pwbuf->pw_dir))) { @@ -829,6 +831,8 @@ static genhomedircon_user_entry_t *get_users(genhomedircon_settings_t * s, * /root */ continue; } + if (strcmp(pwent->pw_dir, "/root") == 0) + continue; if (push_user_entry(&head, name, seuname, prefix, pwent->pw_dir, level) != STATUS_SUCCESS) { *errors = STATUS_ERR; diff --git a/libsemanage/src/handle.c b/libsemanage/src/handle.c index 647f0ee..7adc1cc 100644 --- a/libsemanage/src/handle.c +++ b/libsemanage/src/handle.c @@ -261,6 +261,19 @@ void semanage_set_disable_dontaudit(semanage_handle_t * sh, int disable_dontaudi return; } +int semanage_get_preserve_tunables(semanage_handle_t * sh) +{ + assert(sh != NULL); + return sepol_get_preserve_tunables(sh->sepolh); +} + +void semanage_set_preserve_tunables(semanage_handle_t * sh, + int preserve_tunables) +{ + assert(sh != NULL); + sepol_set_preserve_tunables(sh->sepolh, preserve_tunables); +} + void semanage_set_check_contexts(semanage_handle_t * sh, int do_check_contexts) { diff --git a/libsemanage/src/libsemanage.map b/libsemanage/src/libsemanage.map index 3222e3d..2827abe 100644 --- a/libsemanage/src/libsemanage.map +++ b/libsemanage/src/libsemanage.map @@ -22,5 +22,6 @@ LIBSEMANAGE_1.0 { semanage_is_connected; semanage_get_disable_dontaudit; semanage_set_disable_dontaudit; semanage_mls_enabled; semanage_set_check_contexts; + semanage_get_preserve_tunables; semanage_set_preserve_tunables; local: *; }; diff --git a/libsemanage/src/semanage_store.c b/libsemanage/src/semanage_store.c index 8d6ff1c..e322992 100644 --- a/libsemanage/src/semanage_store.c +++ b/libsemanage/src/semanage_store.c @@ -57,7 +57,7 @@ typedef struct dbase_policydb dbase_t; #include "debug.h" -const char *DISABLESTR=".disabled"; +static const char *DISABLESTR="disabled"; #define SEMANAGE_CONF_FILE "semanage.conf" /* relative path names to enum semanage_paths to special files and @@ -117,6 +117,7 @@ static const char *semanage_sandbox_paths[SEMANAGE_STORE_NUM_PATHS] = { "/netfilter_contexts", "/file_contexts.homedirs", "/disable_dontaudit", + "/preserve_tunables", }; /* A node used in a linked list of file contexts; used for sorting. @@ -425,6 +426,13 @@ int semanage_store_access_check(void) /********************* other I/O functions *********************/ +static int is_disabled_file(const char *file) { + char *ptr = strrchr(file, '.'); + if (! ptr) return 0; + ptr++; + return (strcmp(ptr, DISABLESTR) == 0); +} + /* Callback used by scandir() to select files. */ static int semanage_filename_select(const struct dirent *d) { @@ -435,11 +443,41 @@ static int semanage_filename_select(const struct dirent *d) return 1; } +int semanage_disable_module(const char *file) { + char path[PATH_MAX]; + int in; + int n = snprintf(path, PATH_MAX, "%s.%s", file, DISABLESTR); + if (n < 0 || n >= PATH_MAX) + return -1; + if ((in = open(path, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR)) == -1) { + return -1; + } + close(in); + return 0; +} + +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; + + if ((unlink(path) < 0) && (errno != ENOENT)) + return -1; + return 0; +} + int semanage_module_enabled(const char *file) { - int len = strlen(file) - strlen(DISABLESTR); - return (len < 0 || strcmp(&file[len], DISABLESTR) != 0); + char path[PATH_MAX]; + if (is_disabled_file(file)) return 0; + int n = snprintf(path, PATH_MAX, "%s.%s", file, DISABLESTR); + if (n < 0 || n >= PATH_MAX) + return 1; + + return (access(path, F_OK ) != 0); } +/* Callback used by scandir() to select module files. */ static int semanage_modulename_select(const struct dirent *d) { if (d->d_name[0] == '.' @@ -447,7 +485,7 @@ static int semanage_modulename_select(const struct dirent *d) || (d->d_name[1] == '.' && d->d_name[2] == '\0'))) return 0; - return semanage_module_enabled(d->d_name); + return (! is_disabled_file(d->d_name)); } /* Copies a file from src to dst. If dst already exists then @@ -684,7 +722,7 @@ int semanage_get_modules_names(semanage_handle_t * sh, char ***filenames, int *len) { return semanage_get_modules_names_filter(sh, filenames, - len, semanage_filename_select); + len, semanage_modulename_select); } /* Scans the modules directory for the current semanage handler. This @@ -697,8 +735,25 @@ int semanage_get_modules_names(semanage_handle_t * sh, char ***filenames, int semanage_get_active_modules_names(semanage_handle_t * sh, char ***filenames, int *len) { - return semanage_get_modules_names_filter(sh, filenames, - len, semanage_modulename_select); + + int rc = semanage_get_modules_names_filter(sh, filenames, + len, semanage_modulename_select); + if ( rc != 0 ) return rc; + + int i = 0, num_modules = *len; + char **names=*filenames; + + while ( i < num_modules ) { + if (! semanage_module_enabled(names[i])) { + free(names[i]); + names[i]=names[num_modules-1]; + names[num_modules-1] = NULL; + num_modules--; + } + i++; + } + *len = num_modules; + return 0; } /******************* routines that run external programs *******************/ diff --git a/libsemanage/src/semanage_store.h b/libsemanage/src/semanage_store.h index a0b2dd8..b451308 100644 --- a/libsemanage/src/semanage_store.h +++ b/libsemanage/src/semanage_store.h @@ -59,6 +59,7 @@ enum semanage_sandbox_defs { SEMANAGE_NC, SEMANAGE_FC_HOMEDIRS, SEMANAGE_DISABLE_DONTAUDIT, + SEMANAGE_PRESERVE_TUNABLES, SEMANAGE_STORE_NUM_PATHS }; @@ -85,6 +86,8 @@ int semanage_get_modules_names(semanage_handle_t * sh, char ***filenames, int *len); int semanage_module_enabled(const char *file); +int semanage_enable_module(const char *file); +int semanage_disable_module(const char *file); /* lock file routines */ int semanage_get_trans_lock(semanage_handle_t * sh); int semanage_get_active_lock(semanage_handle_t * sh); @@ -129,6 +132,4 @@ int semanage_nc_sort(semanage_handle_t * sh, size_t buf_len, char **sorted_buf, size_t * sorted_buf_len); -extern const char *DISABLESTR; - #endif