All of lore.kernel.org
 help / color / mirror / Atom feed
* semodule/libsemanage patch to allow enable and disable of modules.
@ 2009-08-28 17:58 Daniel J Walsh
  2009-09-03 20:39 ` Chad Sellers
  0 siblings, 1 reply; 4+ messages in thread
From: Daniel J Walsh @ 2009-08-28 17:58 UTC (permalink / raw)
  To: SE Linux

[-- Attachment #1: Type: text/plain, Size: 973 bytes --]

The general idea is to relabel a disabled policy module as policymodule.pp.disabled

Then make sure -u and -i update this name.

Rebuilding policy does not include .disabled

Listing shows disabled as disabled.

semodule -r will remove disabled modules. If you reinstall they will come back.

# /usr/sbin/semodule -d unconfined
# /usr/sbin/semodule -l | grep unc
unconfined	3.0.1	Disabled
unconfineduser	1.0.0	
# ls -lZ /etc/selinux/targeted/modules/active/modules/unconfined.pp*
-rw-------. root root staff_u:object_r:semanage_store_t:s0 /etc/selinux/targeted/modules/active/modules/unconfined.pp.disabled
# /usr/sbin/semodule -i /usr/share/selinux/targeted/unconfined.pp.bz2 
# /usr/sbin/semodule -l | grep unc
unconfined	3.0.1	Disabled
unconfineduser	1.0.0	
# /usr/sbin/semodule -e unconfined
# /usr/sbin/semodule -l | grep unc
unconfined	3.0.1	
unconfineduser	1.0.0	

This would allow an admin to disable a module and the module will stay disabled until he enables it.

[-- Attachment #2: policycoreutils-enable.patch --]
[-- Type: text/plain, Size: 12479 bytes --]

diff --git a/libsemanage/include/semanage/modules.h b/libsemanage/include/semanage/modules.h
index e169279..d1043f9 100644
--- a/libsemanage/include/semanage/modules.h
+++ b/libsemanage/include/semanage/modules.h
@@ -40,6 +40,8 @@ int semanage_module_install_base(semanage_handle_t *,
 				 char *module_data, size_t data_len);
 int semanage_module_install_base_file(semanage_handle_t *,
 				      const char *module_name);
+int semanage_module_enable(semanage_handle_t *, char *module_name);
+int semanage_module_disable(semanage_handle_t *, char *module_name);
 int semanage_module_remove(semanage_handle_t *, char *module_name);
 
 /* semanage_module_info is for getting information on installed
diff --git a/libsemanage/src/direct_api.c b/libsemanage/src/direct_api.c
index f7d65eb..49a2357 100644
--- a/libsemanage/src/direct_api.c
+++ b/libsemanage/src/direct_api.c
@@ -53,6 +53,8 @@
 #include "policy.h"
 #include <sys/mman.h>
 
+static const char *DISABLESTR=".disabled";
+
 static void semanage_direct_destroy(semanage_handle_t * sh);
 static int semanage_direct_disconnect(semanage_handle_t * sh);
 static int semanage_direct_begintrans(semanage_handle_t * sh);
@@ -66,6 +68,8 @@ static int semanage_direct_upgrade_file(semanage_handle_t * sh, const char *modu
 static int semanage_direct_install_base(semanage_handle_t * sh, char *base_data,
 					size_t data_len);
 static int semanage_direct_install_base_file(semanage_handle_t * sh, const char *module_name);
+static int semanage_direct_enable(semanage_handle_t * sh, char *module_name);
+static int semanage_direct_disable(semanage_handle_t * sh, char *module_name);
 static int semanage_direct_remove(semanage_handle_t * sh, char *module_name);
 static int semanage_direct_list(semanage_handle_t * sh,
 				semanage_module_info_t ** modinfo,
@@ -83,6 +87,8 @@ static struct semanage_policy_table direct_funcs = {
 	.upgrade_file = semanage_direct_upgrade_file,
 	.install_base = semanage_direct_install_base,
 	.install_base_file = semanage_direct_install_base_file,
+	.enable = semanage_direct_enable,
+	.disable = semanage_direct_disable,
 	.remove = semanage_direct_remove,
 	.list = semanage_direct_list
 };
@@ -1002,6 +1008,17 @@ static int semanage_direct_commit(semanage_handle_t * sh)
 	return retval;
 }
 
+static char * get_store_name(const char *file) 
+{
+	int len = strlen(file) + strlen(DISABLESTR) + 1;
+	char *storename = calloc(1, len);
+	if (! storename) return NULL;
+	snprintf(storename,len, "%s%s", file, DISABLESTR);
+	if ( access(storename, F_OK) == 0) return storename;
+	free(storename);
+	return strdup(file);
+}
+
 /* Writes a module to the sandbox's module directory, overwriting any
  * previous module stored within.  Note that module data are not
  * free()d by this function; caller is responsible for deallocating it
@@ -1019,11 +1036,20 @@ static int semanage_direct_install(semanage_handle_t * sh,
 					   &filename)) != 0) {
 		goto cleanup;
 	}
-	if (bzip(sh, filename, data, data_len) <= 0) {
+
+	char *storename = get_store_name(filename);
+	if (!storename) {
+		ERR(sh, "Could not allocate memory");
+		retval = -1;
+		goto cleanup;
+	}
+	if (bzip(sh, storename, data, data_len) <= 0) {
 		ERR(sh, "Error while writing to %s.", filename);
 		retval = -3;
 		goto cleanup;
 	}
+	free(storename);
+
 	retval = 0;
       cleanup:
 	free(version);
@@ -1268,6 +1294,107 @@ 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;
+	}
+	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 + 3, DISABLESTR) == 0) {
+			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;
+		}
+	}
+	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);
+	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_disable(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 &&
+		    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;
+		}
+	}
+	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);
+	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)
diff --git a/libsemanage/src/libsemanage.map b/libsemanage/src/libsemanage.map
index 4c2996e..8230719 100644
--- a/libsemanage/src/libsemanage.map
+++ b/libsemanage/src/libsemanage.map
@@ -6,6 +6,8 @@ LIBSEMANAGE_1.0 {
 	  semanage_module_install; semanage_module_install_file;
 	  semanage_module_upgrade; semanage_module_upgrade_file;
 	  semanage_module_install_base; semanage_module_install_base_file;
+	  semanage_module_enable;
+	  semanage_module_disable;
 	  semanage_module_remove;
 	  semanage_module_list; semanage_module_info_datum_destroy;
 	  semanage_module_list_nth; semanage_module_get_name;
diff --git a/libsemanage/src/modules.c b/libsemanage/src/modules.c
index d99ee5b..8ea8c90 100644
--- a/libsemanage/src/modules.c
+++ b/libsemanage/src/modules.c
@@ -154,6 +154,40 @@ int semanage_module_install_base_file(semanage_handle_t * sh,
 	return sh->funcs->install_base_file(sh, module_name);
 }
 
+int semanage_module_enable(semanage_handle_t * sh, char *module_name)
+{
+	if (sh->funcs->enable == NULL) {
+		ERR(sh, "No enable function defined for this connection type.");
+		return -1;
+	} else if (!sh->is_connected) {
+		ERR(sh, "Not connected.");
+		return -1;
+	} else if (!sh->is_in_transaction) {
+		if (semanage_begin_transaction(sh) < 0) {
+			return -1;
+		}
+	}
+	sh->modules_modified = 1;
+	return sh->funcs->enable(sh, module_name);
+}
+
+int semanage_module_disable(semanage_handle_t * sh, char *module_name)
+{
+	if (sh->funcs->disable == NULL) {
+		ERR(sh, "No disable function defined for this connection type.");
+		return -1;
+	} else if (!sh->is_connected) {
+		ERR(sh, "Not connected.");
+		return -1;
+	} else if (!sh->is_in_transaction) {
+		if (semanage_begin_transaction(sh) < 0) {
+			return -1;
+		}
+	}
+	sh->modules_modified = 1;
+	return sh->funcs->disable(sh, module_name);
+}
+
 int semanage_module_remove(semanage_handle_t * sh, char *module_name)
 {
 	if (sh->funcs->remove == NULL) {
diff --git a/libsemanage/src/policy.h b/libsemanage/src/policy.h
index ebefc02..627b526 100644
--- a/libsemanage/src/policy.h
+++ b/libsemanage/src/policy.h
@@ -58,6 +58,12 @@ struct semanage_policy_table {
 	/* Upgrade a policy module */
 	int (*upgrade_file) (struct semanage_handle *, const char *);
 
+	/* Enable a policy module */
+	int (*enable) (struct semanage_handle *, char *);
+
+	/* Disable a policy module */
+	int (*disable) (struct semanage_handle *, char *);
+
 	/* Remove a policy module */
 	int (*remove) (struct semanage_handle *, char *);
 
diff --git a/policycoreutils/semodule/semodule.c b/policycoreutils/semodule/semodule.c
index ad6adca..94b3738 100644
--- a/policycoreutils/semodule/semodule.c
+++ b/policycoreutils/semodule/semodule.c
@@ -22,12 +22,12 @@
 
 #include <semanage/modules.h>
 
-enum client_modes { NO_MODE, INSTALL_M, UPGRADE_M, BASE_M, REMOVE_M,
+enum client_modes { NO_MODE, INSTALL_M, UPGRADE_M, BASE_M, ENABLE_M, DISABLE_M, REMOVE_M,
 	LIST_M, RELOAD
 };
 /* list of modes in which one ought to commit afterwards */
 static const int do_commit[] = {
-	0, 1, 1, 1, 1,
+	0, 1, 1, 1, 1, 1, 1,
 	0, 0
 };
 
@@ -104,6 +104,8 @@ static void usage(char *progname)
 	printf("  -R, --reload		    reload policy\n");
 	printf("  -B, --build		    build and reload policy\n");
 	printf("  -i,--install=MODULE_PKG   install a new module\n");
+	printf("  -e,--enable=MODULE_PKG    enable existing module\n");
+	printf("  -d,--disable=MODULE_PKG   disable existing module\n");
 	printf("  -u,--upgrade=MODULE_PKG   upgrades or install module to a newer version\n");
 	printf("  -b,--base=MODULE_PKG      install new base module\n");
 	printf("  -r,--remove=MODULE_NAME   remove existing module\n");
@@ -152,6 +154,8 @@ static void parse_command_line(int argc, char **argv)
 		{"install", required_argument, NULL, 'i'},
 		{"list-modules", 0, NULL, 'l'},
 		{"verbose", 0, NULL, 'v'},
+		{"enable", required_argument, NULL, 'e'},
+		{"disable", required_argument, NULL, 'd'},
 		{"remove", required_argument, NULL, 'r'},
 		{"upgrade", required_argument, NULL, 'u'},
 		{"reload", 0, NULL, 'R'},
@@ -166,7 +170,7 @@ static void parse_command_line(int argc, char **argv)
 	no_reload = 0;
 	create_store = 0;
 	while ((i =
-		getopt_long(argc, argv, "s:b:hi:lvqr:u:RnBD", opts,
+		getopt_long(argc, argv, "s:b:hi:lvqe:d:r:u:RnBD", opts,
 			    NULL)) != -1) {
 		switch (i) {
 		case 'b':
@@ -185,6 +189,12 @@ static void parse_command_line(int argc, char **argv)
 		case 'v':
 			verbose = 1;
 			break;
+		case 'e':
+			set_mode(ENABLE_M, optarg);
+			break;
+		case 'd':
+			set_mode(DISABLE_M, optarg);
+			break;
 		case 'r':
 			set_mode(REMOVE_M, optarg);
 			break;
@@ -238,6 +248,10 @@ static void parse_command_line(int argc, char **argv)
 			mode = UPGRADE_M;
 		} else if (commands && commands[num_commands - 1].mode == REMOVE_M) {
 			mode = REMOVE_M;
+		} else if (commands && commands[num_commands - 1].mode == ENABLE_M) {
+			mode = ENABLE_M;
+		} else if (commands && commands[num_commands - 1].mode == DISABLE_M) {
+			mode = DISABLE_M;
 		} else {
 			fprintf(stderr, "unknown additional arguments:\n");
 			while (optind < argc)
@@ -352,6 +366,30 @@ int main(int argc, char *argv[])
 				    semanage_module_install_base_file(sh, mode_arg);
 				break;
 			}
+		case ENABLE_M:{
+				if (verbose) {
+					printf
+					    ("Attempting to enable module '%s':\n",
+					     mode_arg);
+				}
+				result = semanage_module_enable(sh, mode_arg);
+				if ( result == -2 ) { 
+					continue;
+				}
+				break;
+			}
+		case DISABLE_M:{
+				if (verbose) {
+					printf
+					    ("Attempting to disable module '%s':\n",
+					     mode_arg);
+				}
+				result = semanage_module_disable(sh, mode_arg);
+				if ( result == -2 ) { 
+					continue;
+				}
+				break;
+			}
 		case REMOVE_M:{
 				if (verbose) {
 					printf

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: semodule/libsemanage patch to allow enable and disable of modules.
  2009-08-28 17:58 semodule/libsemanage patch to allow enable and disable of modules Daniel J Walsh
@ 2009-09-03 20:39 ` Chad Sellers
  2009-09-16 15:36   ` Joshua Brindle
  0 siblings, 1 reply; 4+ messages in thread
From: Chad Sellers @ 2009-09-03 20:39 UTC (permalink / raw)
  To: Daniel J Walsh, SE Linux

On 8/28/09 1:58 PM, "Daniel J Walsh" <dwalsh@redhat.com> wrote:

> The general idea is to relabel a disabled policy module as
> policymodule.pp.disabled
> 
> Then make sure -u and -i update this name.
> 
> Rebuilding policy does not include .disabled
> 
> Listing shows disabled as disabled.
> 
> semodule -r will remove disabled modules. If you reinstall they will come
> back.
> 
> # /usr/sbin/semodule -d unconfined
> # /usr/sbin/semodule -l | grep unc
> unconfined 3.0.1 Disabled
> unconfineduser 1.0.0 
> # ls -lZ /etc/selinux/targeted/modules/active/modules/unconfined.pp*
> -rw-------. root root staff_u:object_r:semanage_store_t:s0
> /etc/selinux/targeted/modules/active/modules/unconfined.pp.disabled
> # /usr/sbin/semodule -i /usr/share/selinux/targeted/unconfined.pp.bz2
> # /usr/sbin/semodule -l | grep unc
> unconfined 3.0.1 Disabled
> unconfineduser 1.0.0 
> # /usr/sbin/semodule -e unconfined
> # /usr/sbin/semodule -l | grep unc
> unconfined 3.0.1 
> unconfineduser 1.0.0 
> 
> This would allow an admin to disable a module and the module will stay
> disabled until he enables it.
<snip>
> diff --git a/libsemanage/src/direct_api.c b/libsemanage/src/direct_api.c
> index f7d65eb..49a2357 100644
> --- a/libsemanage/src/direct_api.c
> +++ b/libsemanage/src/direct_api.c
> @@ -53,6 +53,8 @@
>  #include "policy.h"
>  #include <sys/mman.h>
>  
> +static const char *DISABLESTR=".disabled";
> +
>  static void semanage_direct_destroy(semanage_handle_t * sh);
>  static int semanage_direct_disconnect(semanage_handle_t * sh);
>  static int semanage_direct_begintrans(semanage_handle_t * sh);
> @@ -66,6 +68,8 @@ static int semanage_direct_upgrade_file(semanage_handle_t *
> sh, const char *modu
>  static int semanage_direct_install_base(semanage_handle_t * sh, char
> *base_data,
>                      size_t data_len);
>  static int semanage_direct_install_base_file(semanage_handle_t * sh, const
> char *module_name);
> +static int semanage_direct_enable(semanage_handle_t * sh, char *module_name);
> +static int semanage_direct_disable(semanage_handle_t * sh, char
> *module_name);
>  static int semanage_direct_remove(semanage_handle_t * sh, char *module_name);
>  static int semanage_direct_list(semanage_handle_t * sh,
>                  semanage_module_info_t ** modinfo,
> @@ -83,6 +87,8 @@ static struct semanage_policy_table direct_funcs = {
>      .upgrade_file = semanage_direct_upgrade_file,
>      .install_base = semanage_direct_install_base,
>      .install_base_file = semanage_direct_install_base_file,
> +    .enable = semanage_direct_enable,
> +    .disable = semanage_direct_disable,
>      .remove = semanage_direct_remove,
>      .list = semanage_direct_list
>  };
> @@ -1002,6 +1008,17 @@ static int semanage_direct_commit(semanage_handle_t *
> sh)
>      return retval;
>  }
>  
> +static char * get_store_name(const char *file)
> +{
> +    int len = strlen(file) + strlen(DISABLESTR) + 1;
> +    char *storename = calloc(1, len);
> +    if (! storename) return NULL;
> +    snprintf(storename,len, "%s%s", file, DISABLESTR);
> +    if ( access(storename, F_OK) == 0) return storename;
> +    free(storename);
> +    return strdup(file);
> +}
> +
>  /* Writes a module to the sandbox's module directory, overwriting any
>   * previous module stored within.  Note that module data are not
>   * free()d by this function; caller is responsible for deallocating it
> @@ -1019,11 +1036,20 @@ static int semanage_direct_install(semanage_handle_t *
> sh,
>                         &filename)) != 0) {
>          goto cleanup;
>      }
> -    if (bzip(sh, filename, data, data_len) <= 0) {
> +
> +    char *storename = get_store_name(filename);
> +    if (!storename) {
> +        ERR(sh, "Could not allocate memory");
> +        retval = -1;
> +        goto cleanup;
> +    }
> +    if (bzip(sh, storename, data, data_len) <= 0) {

Should we present some sort of warning to the user if they install/upgrade a
module that is disabled? This seems to maintain the disabled status
silently, which might confuse users (e.g. "I just installed that module, why
isn't the policy working").

Also, I see that you patched direct_install, but not direct_upgrade. So,
upgrade will try to re-enable the module if it has been disabled.

>          ERR(sh, "Error while writing to %s.", filename);
>          retval = -3;
>          goto cleanup;
>      }
> +    free(storename);
> +
>      retval = 0;
>        cleanup:
>      free(version);
> @@ -1268,6 +1294,107 @@ 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;
> +    }
> +    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 + 3, DISABLESTR) == 0) {
> +            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;
> +        }
> +    }
> +    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);
> +    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_disable(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 &&
> +            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;
> +        }
> +    }
> +    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);
> +    return retval;
> +}
> +
While this function does succeed in renaming a file, it does not succeed in
preventing the module from being linked in. semanage_get_modules_names()
grabs everything in the modules directory, so the disabled modules here are
still linked into the policy. A quick sesearch confirms this.

To fix this, you'll either need to modify semanage_filename_select() to
filter out files ending in .disabled or perhaps just move them from the
modules directory to a disabled_modules directory (instead of the rename).
The latter option has the advantage of not requiring filtering that could go
wrong at some point, so I would lean toward it.

Thanks,
Chad


--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: semodule/libsemanage patch to allow enable and disable of modules.
  2009-09-03 20:39 ` Chad Sellers
@ 2009-09-16 15:36   ` Joshua Brindle
  2009-09-16 16:32     ` Daniel J Walsh
  0 siblings, 1 reply; 4+ messages in thread
From: Joshua Brindle @ 2009-09-16 15:36 UTC (permalink / raw)
  To: Daniel J Walsh; +Cc: Chad Sellers, SE Linux

[-- Attachment #1: Type: text/plain, Size: 9399 bytes --]



Chad Sellers wrote:
> On 8/28/09 1:58 PM, "Daniel J Walsh"<dwalsh@redhat.com>  wrote:
>
>    
>> The general idea is to relabel a disabled policy module as
>> policymodule.pp.disabled
>>
>> Then make sure -u and -i update this name.
>>
>> Rebuilding policy does not include .disabled
>>
>> Listing shows disabled as disabled.
>>
>> semodule -r will remove disabled modules. If you reinstall they will come
>> back.
>>
>> # /usr/sbin/semodule -d unconfined
>> # /usr/sbin/semodule -l | grep unc
>> unconfined 3.0.1 Disabled
>> unconfineduser 1.0.0
>> # ls -lZ /etc/selinux/targeted/modules/active/modules/unconfined.pp*
>> -rw-------. root root staff_u:object_r:semanage_store_t:s0
>> /etc/selinux/targeted/modules/active/modules/unconfined.pp.disabled
>> # /usr/sbin/semodule -i /usr/share/selinux/targeted/unconfined.pp.bz2
>> # /usr/sbin/semodule -l | grep unc
>> unconfined 3.0.1 Disabled
>> unconfineduser 1.0.0
>> # /usr/sbin/semodule -e unconfined
>> # /usr/sbin/semodule -l | grep unc
>> unconfined 3.0.1
>> unconfineduser 1.0.0
>>
>> This would allow an admin to disable a module and the module will stay
>> disabled until he enables it.
>>      
> <snip>
>    
>> diff --git a/libsemanage/src/direct_api.c b/libsemanage/src/direct_api.c
>> index f7d65eb..49a2357 100644
>> --- a/libsemanage/src/direct_api.c
>> +++ b/libsemanage/src/direct_api.c
>> @@ -53,6 +53,8 @@
>>   #include "policy.h"
>>   #include<sys/mman.h>
>>
>> +static const char *DISABLESTR=".disabled";
>> +
>>   static void semanage_direct_destroy(semanage_handle_t * sh);
>>   static int semanage_direct_disconnect(semanage_handle_t * sh);
>>   static int semanage_direct_begintrans(semanage_handle_t * sh);
>> @@ -66,6 +68,8 @@ static int semanage_direct_upgrade_file(semanage_handle_t *
>> sh, const char *modu
>>   static int semanage_direct_install_base(semanage_handle_t * sh, char
>> *base_data,
>>                       size_t data_len);
>>   static int semanage_direct_install_base_file(semanage_handle_t * sh, const
>> char *module_name);
>> +static int semanage_direct_enable(semanage_handle_t * sh, char *module_name);
>> +static int semanage_direct_disable(semanage_handle_t * sh, char
>> *module_name);
>>   static int semanage_direct_remove(semanage_handle_t * sh, char *module_name);
>>   static int semanage_direct_list(semanage_handle_t * sh,
>>                   semanage_module_info_t ** modinfo,
>> @@ -83,6 +87,8 @@ static struct semanage_policy_table direct_funcs = {
>>       .upgrade_file = semanage_direct_upgrade_file,
>>       .install_base = semanage_direct_install_base,
>>       .install_base_file = semanage_direct_install_base_file,
>> +    .enable = semanage_direct_enable,
>> +    .disable = semanage_direct_disable,
>>       .remove = semanage_direct_remove,
>>       .list = semanage_direct_list
>>   };
>> @@ -1002,6 +1008,17 @@ static int semanage_direct_commit(semanage_handle_t *
>> sh)
>>       return retval;
>>   }
>>
>> +static char * get_store_name(const char *file)
>> +{
>> +    int len = strlen(file) + strlen(DISABLESTR) + 1;
>> +    char *storename = calloc(1, len);
>> +    if (! storename) return NULL;
>> +    snprintf(storename,len, "%s%s", file, DISABLESTR);
>> +    if ( access(storename, F_OK) == 0) return storename;
>> +    free(storename);
>> +    return strdup(file);
>> +}
>> +
>>   /* Writes a module to the sandbox's module directory, overwriting any
>>    * previous module stored within.  Note that module data are not
>>    * free()d by this function; caller is responsible for deallocating it
>> @@ -1019,11 +1036,20 @@ static int semanage_direct_install(semanage_handle_t *
>> sh,
>>                          &filename)) != 0) {
>>           goto cleanup;
>>       }
>> -    if (bzip(sh, filename, data, data_len)<= 0) {
>> +
>> +    char *storename = get_store_name(filename);
>> +    if (!storename) {
>> +        ERR(sh, "Could not allocate memory");
>> +        retval = -1;
>> +        goto cleanup;
>> +    }
>> +    if (bzip(sh, storename, data, data_len)<= 0) {
>>      
>
> Should we present some sort of warning to the user if they install/upgrade a
> module that is disabled? This seems to maintain the disabled status
> silently, which might confuse users (e.g. "I just installed that module, why
> isn't the policy working").
>
> Also, I see that you patched direct_install, but not direct_upgrade. So,
> upgrade will try to re-enable the module if it has been disabled.
>
>    
>>           ERR(sh, "Error while writing to %s.", filename);
>>           retval = -3;
>>           goto cleanup;
>>       }
>> +    free(storename);
>> +
>>       retval = 0;
>>         cleanup:
>>       free(version);
>> @@ -1268,6 +1294,107 @@ 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;
>> +    }
>> +    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 + 3, DISABLESTR) == 0) {
>> +            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;
>> +        }
>> +    }
>> +    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);
>> +    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_disable(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&&
>> +            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;
>> +        }
>> +    }
>> +    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);
>> +    return retval;
>> +}
>> +
>>      
> While this function does succeed in renaming a file, it does not succeed in
> preventing the module from being linked in. semanage_get_modules_names()
> grabs everything in the modules directory, so the disabled modules here are
> still linked into the policy. A quick sesearch confirms this.
>
> To fix this, you'll either need to modify semanage_filename_select() to
> filter out files ending in .disabled or perhaps just move them from the
> modules directory to a disabled_modules directory (instead of the rename).
> The latter option has the advantage of not requiring filtering that could go
> wrong at some point, so I would lean toward it.
>
> Thanks,
> Chad
>
>
>    


Do you have an updated version of this?

[-- Attachment #2: Type: text/html, Size: 9466 bytes --]

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: semodule/libsemanage patch to allow enable and disable of modules.
  2009-09-16 15:36   ` Joshua Brindle
@ 2009-09-16 16:32     ` Daniel J Walsh
  0 siblings, 0 replies; 4+ messages in thread
From: Daniel J Walsh @ 2009-09-16 16:32 UTC (permalink / raw)
  To: Joshua Brindle; +Cc: Chad Sellers, SE Linux

On 09/16/2009 11:36 AM, Joshua Brindle wrote:
> 
> 
> Chad Sellers wrote:
>> On 8/28/09 1:58 PM, "Daniel J Walsh"<dwalsh@redhat.com>  wrote:
>>
>>   
>>> The general idea is to relabel a disabled policy module as
>>> policymodule.pp.disabled
>>>
>>> Then make sure -u and -i update this name.
>>>
>>> Rebuilding policy does not include .disabled
>>>
>>> Listing shows disabled as disabled.
>>>
>>> semodule -r will remove disabled modules. If you reinstall they will
>>> come
>>> back.
>>>
>>> # /usr/sbin/semodule -d unconfined
>>> # /usr/sbin/semodule -l | grep unc
>>> unconfined 3.0.1 Disabled
>>> unconfineduser 1.0.0
>>> # ls -lZ /etc/selinux/targeted/modules/active/modules/unconfined.pp*
>>> -rw-------. root root staff_u:object_r:semanage_store_t:s0
>>> /etc/selinux/targeted/modules/active/modules/unconfined.pp.disabled
>>> # /usr/sbin/semodule -i /usr/share/selinux/targeted/unconfined.pp.bz2
>>> # /usr/sbin/semodule -l | grep unc
>>> unconfined 3.0.1 Disabled
>>> unconfineduser 1.0.0
>>> # /usr/sbin/semodule -e unconfined
>>> # /usr/sbin/semodule -l | grep unc
>>> unconfined 3.0.1
>>> unconfineduser 1.0.0
>>>
>>> This would allow an admin to disable a module and the module will stay
>>> disabled until he enables it.
>>>      
>> <snip>
>>   
>>> diff --git a/libsemanage/src/direct_api.c b/libsemanage/src/direct_api.c
>>> index f7d65eb..49a2357 100644
>>> --- a/libsemanage/src/direct_api.c
>>> +++ b/libsemanage/src/direct_api.c
>>> @@ -53,6 +53,8 @@
>>>   #include "policy.h"
>>>   #include<sys/mman.h>
>>>
>>> +static const char *DISABLESTR=".disabled";
>>> +
>>>   static void semanage_direct_destroy(semanage_handle_t * sh);
>>>   static int semanage_direct_disconnect(semanage_handle_t * sh);
>>>   static int semanage_direct_begintrans(semanage_handle_t * sh);
>>> @@ -66,6 +68,8 @@ static int
>>> semanage_direct_upgrade_file(semanage_handle_t *
>>> sh, const char *modu
>>>   static int semanage_direct_install_base(semanage_handle_t * sh, char
>>> *base_data,
>>>                       size_t data_len);
>>>   static int semanage_direct_install_base_file(semanage_handle_t *
>>> sh, const
>>> char *module_name);
>>> +static int semanage_direct_enable(semanage_handle_t * sh, char
>>> *module_name);
>>> +static int semanage_direct_disable(semanage_handle_t * sh, char
>>> *module_name);
>>>   static int semanage_direct_remove(semanage_handle_t * sh, char
>>> *module_name);
>>>   static int semanage_direct_list(semanage_handle_t * sh,
>>>                   semanage_module_info_t ** modinfo,
>>> @@ -83,6 +87,8 @@ static struct semanage_policy_table direct_funcs = {
>>>       .upgrade_file = semanage_direct_upgrade_file,
>>>       .install_base = semanage_direct_install_base,
>>>       .install_base_file = semanage_direct_install_base_file,
>>> +    .enable = semanage_direct_enable,
>>> +    .disable = semanage_direct_disable,
>>>       .remove = semanage_direct_remove,
>>>       .list = semanage_direct_list
>>>   };
>>> @@ -1002,6 +1008,17 @@ static int
>>> semanage_direct_commit(semanage_handle_t *
>>> sh)
>>>       return retval;
>>>   }
>>>
>>> +static char * get_store_name(const char *file)
>>> +{
>>> +    int len = strlen(file) + strlen(DISABLESTR) + 1;
>>> +    char *storename = calloc(1, len);
>>> +    if (! storename) return NULL;
>>> +    snprintf(storename,len, "%s%s", file, DISABLESTR);
>>> +    if ( access(storename, F_OK) == 0) return storename;
>>> +    free(storename);
>>> +    return strdup(file);
>>> +}
>>> +
>>>   /* Writes a module to the sandbox's module directory, overwriting any
>>>    * previous module stored within.  Note that module data are not
>>>    * free()d by this function; caller is responsible for deallocating it
>>> @@ -1019,11 +1036,20 @@ static int
>>> semanage_direct_install(semanage_handle_t *
>>> sh,
>>>                          &filename)) != 0) {
>>>           goto cleanup;
>>>       }
>>> -    if (bzip(sh, filename, data, data_len)<= 0) {
>>> +
>>> +    char *storename = get_store_name(filename);
>>> +    if (!storename) {
>>> +        ERR(sh, "Could not allocate memory");
>>> +        retval = -1;
>>> +        goto cleanup;
>>> +    }
>>> +    if (bzip(sh, storename, data, data_len)<= 0) {
>>>      
>>
>> Should we present some sort of warning to the user if they
>> install/upgrade a
>> module that is disabled? This seems to maintain the disabled status
>> silently, which might confuse users (e.g. "I just installed that
>> module, why
>> isn't the policy working").
>>
>> Also, I see that you patched direct_install, but not direct_upgrade. So,
>> upgrade will try to re-enable the module if it has been disabled.
>>
>>   
>>>           ERR(sh, "Error while writing to %s.", filename);
>>>           retval = -3;
>>>           goto cleanup;
>>>       }
>>> +    free(storename);
>>> +
>>>       retval = 0;
>>>         cleanup:
>>>       free(version);
>>> @@ -1268,6 +1294,107 @@ 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;
>>> +    }
>>> +    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 + 3, DISABLESTR) == 0) {
>>> +            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;
>>> +        }
>>> +    }
>>> +    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);
>>> +    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_disable(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&&
>>> +            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;
>>> +        }
>>> +    }
>>> +    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);
>>> +    return retval;
>>> +}
>>> +
>>>      
>> While this function does succeed in renaming a file, it does not
>> succeed in
>> preventing the module from being linked in. semanage_get_modules_names()
>> grabs everything in the modules directory, so the disabled modules
>> here are
>> still linked into the policy. A quick sesearch confirms this.
>>
>> To fix this, you'll either need to modify semanage_filename_select() to
>> filter out files ending in .disabled or perhaps just move them from the
>> modules directory to a disabled_modules directory (instead of the
>> rename).
>> The latter option has the advantage of not requiring filtering that
>> could go
>> wrong at some point, so I would lean toward it.
>>
>> Thanks,
>> Chad
>>
>>
>>    
> 
> 
> Do you have an updated version of this?
> 
Not yet, we need to hold off on this,  Maybe we can hack it out next week.  Moving to /disabled versus .disabled is not as easy as I would have liked.

--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2009-09-16 16:32 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-08-28 17:58 semodule/libsemanage patch to allow enable and disable of modules Daniel J Walsh
2009-09-03 20:39 ` Chad Sellers
2009-09-16 15:36   ` Joshua Brindle
2009-09-16 16:32     ` Daniel J Walsh

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.