libsemanage: change module disabled from rename to symlink

Change the way libsemanage handles disabled modules.  In the current
method libsemanage renames the FOO.pp file to FOO.pp.disabled and then
the rebuild process ignores *.disabled modules.

Since we want to start shipping

/etc/selinux/targeted/modules/active/modules/*.pp within the payload of
the rpm.  If we continued this method, a policy update would re-enable a
module.

The new mechanism will just create a symbolic link between FOO.pp and
FOO.pp.disabled.  Then the library will check all modules, and if a
module has a link, it will not be compiled into the policy.  This solves
the rpm update problem. and actually gives us an easier update
capability since if FOO.pp.disabled already exists using the old method,
it will continue to work with the new method.

Signed-off-by: Eric Paris <eparis@redhat.com>
Acked-by: Dan Walsh <dwalsh@redhat.com>
This commit is contained in:
Eric Paris 2011-06-29 01:38:51 -04:00
parent 1f8cf403be
commit 60c780ffb6
3 changed files with 73 additions and 55 deletions

View File

@ -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;
}
@ -1307,29 +1301,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 +1340,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 +1381,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]);

View File

@ -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
@ -425,6 +425,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 +442,41 @@ static int semanage_filename_select(const struct dirent *d)
return 1;
}
int semanage_module_enabled(const char *file) {
int len = strlen(file) - strlen(DISABLESTR);
return (len < 0 || strcmp(&file[len], DISABLESTR) != 0);
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) {
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 +484,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 +721,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 +734,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 *******************/

View File

@ -85,6 +85,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 +131,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