[PATCH 12/13] semodule: add priority, enabled, and extended listing

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This updates the semodule tool with the ability to set the priority for
commands, to enable/disable modules, and extended module listing options
for displaying extra module information (e.g., priority, enabled status,
and language extension).

[semodule priority]

-p --priority set the priority for following operations

Notes:

* This sets the priority for the following operations.

* It can be used any number of times with its effect continuing until
  the next priority is specified.

* The default priority is used if no priority has yet been specified.

Impact on current operations:

* Install module

  * Without priority - Install at default priority.

  * With priority - Install at specified priority.

  * New warning when overriding (issued by libsemanage).

* Upgrade module

  * Without priority - Upgrade at default priority (current upgrade
    semantics apply).

  * With priority - Upgrade at specified priority (current upgrade
    semantics apply).

  * New warning when overriding (issued by libsemanage).

* Remove module

  * Without priority - Remove a module at the default if exists.

  * With priority - Remove at that priority.

  * New info messages (issued by libsemanage):

    * If no modules exist at the given priority but do exist at other
      priorities, give an info message listing the modules and priority.

    * If a new module at a lower priority will become active print a
      message.

    * If the last module with this name is being removed print a
      message.

* Base

  * The name of base module on install is fixed to "_base" (performed by
    libsemanage).

  * Without priority - Install at default priority.

  * With priority - Install at specified priority.

  * New warning when overriding (issued by libsemanage).

* List modules

  * See listing changes below.

Examples:

# install a module at default - this will install the module at priority 400
semodule -i foo.pp

# Install a module at a specific priority
semodule -p 500 -i foo.pp

[semodule enable/disable]

Add enable/disable status:

-e   --enable   enable the module (at all priorities)
-d   --disable  disable the module (at all priorities)

Notes:

* Base modules are always enabled and cannot have their enabled/disabled
  status changed.

* New error when disabling a base module (from libsemanage).

* New warning when enabling a base module (from libsemanage).

Impact on current operations:

* Install module

  * If a module with that name is already installed, then the enabled
    status will remain the same after installing the new module.

  * New warning when installing a module which will be disabled by
    existing enabled status (from libsemanage).

* Upgrade module

  * If a module with that name is already installed, then the enabled
    status will remain the same after installing the new module.

  * New warning when installing a module which will be disabled by
    existing enabled status (from libsemanage).

* Remove module

  * When the last module with a given name is removed (no more exist at
    other priorities) then the enabled status is forgotten.

* Base

  * Base modules are always installed enabled and remain so (can't be
    disabled).

* List modules

  * See listing changes below.

Examples:

# enable module
semodule -e foo

# disable module
semodule -d foo

[semodule list]

-l		--list		list modules as if by -lstandard

-lstandard	--list=standard	list name and version of highest priority,
				enabled, non-base modules sorted alphabetical
				by name

-lfull		--list=full	list all fields of all modules columnated
				sorted high priority to low, within priority
				alphabetical by name

Impact on current operations:

* List modules

  * Default listing stays the same.

  * New long options for 'standard' and 'full'.

Examples:

# list modules using standard method
semodule -l
semodule -lstandard
semodule --list=standard

alsa 1.7.1
apm 1.9.1
apt 1.5.2
authlogin 2.0.0
avahi 1.10.3
bluetooth 3.1.3
...

# list modules using full method
semodule -lfull
semodule --list=full

600 alsa      1.7.1 disabled pp
400 _base     1.0.0          pp
400 alsa      1.7.1 disabled pp
400 apm       1.9.1          pp
400 apt       1.5.2          pp
400 authlogin 2.0.0          pp
...
100 alsa      1.7.1 disabled pp
---
 policycoreutils/semodule/semodule.8 |   25 ++++-
 policycoreutils/semodule/semodule.c |  242 +++++++++++++++++++++++++++++++----
 2 files changed, 239 insertions(+), 28 deletions(-)

diff --git a/policycoreutils/semodule/semodule.8 b/policycoreutils/semodule/semodule.8
index 1c1d206..4b52a63 100644
--- a/policycoreutils/semodule/semodule.8
+++ b/policycoreutils/semodule/semodule.8
@@ -38,9 +38,26 @@ install/replace base module package
 .B  \-r,\-\-remove=MODULE_NAME
 remove existing module
 .TP
-.B  \-l,\-\-list-modules      
+.B  \-l,\-\-list-modules=[KIND]
 display list of installed modules (other than base)
 .TP
+.B  KIND:
+.TP
+standard
+list highest priority, enabled, non-base modules
+.TP
+full
+list all modules
+.TP
+.B  \-p,\-\-priority=PRIORITY
+set priority for following operations (1-999)
+.TP
+.B  \-e,\-\-enabled=MODULE_NAME
+enable module
+.TP
+.B  \-d,\-\-disable=MODULE_NAME
+disable module
+.TP
 .B  \-s,\-\-store	   
 name of the store to operate on
 .TP
@@ -69,6 +86,12 @@ $ semodule -B
 $ semodule -i *.pp
 # Install or replace all modules in the current directory.
 $ ls *.pp | grep -Ev "base.pp|enableaudit.pp" | xargs /usr/sbin/semodule -b base.pp -i
+# Disable a module.
+$ semodule -d alsa
+# Install a module at a specific priority.
+$ semodule -p 100 -i alsa.pp
+# List all modules.
+$ semodule -l full
 .fi
 
 .SH SEE ALSO
diff --git a/policycoreutils/semodule/semodule.c b/policycoreutils/semodule/semodule.c
index ad6adca..569b808 100644
--- a/policycoreutils/semodule/semodule.c
+++ b/policycoreutils/semodule/semodule.c
@@ -22,13 +22,16 @@
 
 #include <semanage/modules.h>
 
-enum client_modes { NO_MODE, INSTALL_M, UPGRADE_M, BASE_M, REMOVE_M,
-	LIST_M, RELOAD
+#include <semanage/private/semanage.h>
+
+enum client_modes {
+	NO_MODE, INSTALL_M, UPGRADE_M, BASE_M, REMOVE_M,
+	LIST_M, RELOAD, PRIORITY_M, ENABLE_M, DISABLE_M
 };
 /* list of modes in which one ought to commit afterwards */
 static const int do_commit[] = {
 	0, 1, 1, 1, 1,
-	0, 0
+	0, 0, 0, 1, 1,
 };
 
 struct command {
@@ -45,6 +48,7 @@ static int no_reload;
 static int create_store;
 static int build;
 static int disable_dontaudit;
+static uint16_t priority;
 
 static semanage_handle_t *sh = NULL;
 static char *store;
@@ -107,8 +111,12 @@ static void usage(char *progname)
 	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");
-	printf
-	    ("  -l,--list-modules         display list of installed modules\n");
+	printf("  -l,--list-modules=[KIND]  display list of installed modules\n");
+	printf("     KIND:  standard  list highest priority, enabled, non-base modules\n");
+	printf("            full      list all modules\n");
+	printf("  -p,--priority=PRIORITY    set priority for following operations (1-999)\n");
+	printf("  -e,--enable=MODULE_NAME   enable module\n");
+	printf("  -d,--disable=MODULE_NAME  disable module\n");
 	printf("Other options:\n");
 	printf("  -s,--store	   name of the store to operate on\n");
 	printf("  -n,--noreload	   do not reload policy after commit\n");
@@ -150,7 +158,7 @@ static void parse_command_line(int argc, char **argv)
 		{"base", required_argument, NULL, 'b'},
 		{"help", 0, NULL, 'h'},
 		{"install", required_argument, NULL, 'i'},
-		{"list-modules", 0, NULL, 'l'},
+		{"list-modules", optional_argument, NULL, 'l'},
 		{"verbose", 0, NULL, 'v'},
 		{"remove", required_argument, NULL, 'r'},
 		{"upgrade", required_argument, NULL, 'u'},
@@ -158,6 +166,9 @@ static void parse_command_line(int argc, char **argv)
 		{"noreload", 0, NULL, 'n'},
 		{"build", 0, NULL, 'B'},
 		{"disable_dontaudit", 0, NULL, 'D'},
+		{"priority", required_argument, NULL, 'p'},
+		{"enable", required_argument, NULL, 'e'},
+		{"disable", required_argument, NULL, 'd'},
 		{NULL, 0, NULL, 0}
 	};
 	int i;
@@ -165,8 +176,9 @@ static void parse_command_line(int argc, char **argv)
 	reload = 0;
 	no_reload = 0;
 	create_store = 0;
+	priority = 400;
 	while ((i =
-		getopt_long(argc, argv, "s:b:hi:lvqr:u:RnBD", opts,
+		getopt_long(argc, argv, "s:b:hi:l::vqr:u:RnBDp:e:d:", opts,
 			    NULL)) != -1) {
 		switch (i) {
 		case 'b':
@@ -180,7 +192,7 @@ static void parse_command_line(int argc, char **argv)
 			set_mode(INSTALL_M, optarg);
 			break;
 		case 'l':
-			set_mode(LIST_M, NULL);
+			set_mode(LIST_M, optarg);
 			break;
 		case 'v':
 			verbose = 1;
@@ -206,6 +218,15 @@ static void parse_command_line(int argc, char **argv)
 		case 'D':
 			disable_dontaudit = 1;
 			break;
+		case 'p':
+			set_mode(PRIORITY_M, optarg);
+			break;
+		case 'e':
+			set_mode(ENABLE_M, optarg);
+			break;
+		case 'd':
+			set_mode(DISABLE_M, optarg);
+			break;
 		case '?':
 		default:{
 				usage(argv[0]);
@@ -318,9 +339,18 @@ int main(int argc, char *argv[])
 		}
 	}
 
+	if ((result = semanage_set_default_priority(sh, priority)) != 0) {
+		fprintf(stderr,
+			"%s: Invalid priority %d (needs to be between 1 and 999)\n",
+			argv[0],
+			priority);
+		goto cleanup;
+	}
+
 	for (i = 0; i < num_commands; i++) {
 		enum client_modes mode = commands[i].mode;
 		char *mode_arg = commands[i].arg;
+
 		switch (mode) {
 		case INSTALL_M:{
 				if (verbose) {
@@ -365,33 +395,191 @@ int main(int argc, char *argv[])
 				break;
 			}
 		case LIST_M:{
-				semanage_module_info_t *modinfo;
-				int num_modules;
+				semanage_module_info_t *modinfos = NULL;
+				int modinfos_len = 0;
+				semanage_module_info_t *m = NULL;
+				int j = 0;
+
 				if (verbose) {
 					printf
 					    ("Attempting to list active modules:\n");
 				}
-				if ((result =
-				     semanage_module_list(sh, &modinfo,
-							  &num_modules)) >= 0) {
-					int j;
-					if (num_modules == 0) {
+
+				if (mode_arg == NULL || strcmp(mode_arg, "standard") == 0) {
+					result = semanage_module_list(sh,
+								      &modinfos,
+								      &modinfos_len);
+					if (result < 0) goto cleanup_list;
+
+					if (modinfos_len == 0) {
+						printf("No modules.\n");
+					}
+
+					const char *name = NULL;
+					const char *version = NULL;
+
+					for (j = 0; j < modinfos_len; j++) {
+						m = semanage_module_list_nth(modinfos, j);
+
+						result = semanage_module_info_get_name(sh, m, &name);
+						if (result != 0) goto cleanup_list;
+
+						result = semanage_module_info_get_version(sh, m, &version);
+						if (result != 0) goto cleanup_list;
+
+						printf("%s\t%s\n", name, version);
+					}
+				}
+				else if (strcmp(mode_arg, "full") == 0) {
+					/* get the modules */
+					result = semanage_module_list_all(sh,
+									  &modinfos,
+									  &modinfos_len);
+					if (result != 0) goto cleanup_list;
+
+					if (modinfos_len == 0) {
 						printf("No modules.\n");
 					}
-					for (j = 0; j < num_modules; j++) {
-						semanage_module_info_t *m =
-						    semanage_module_list_nth
-						    (modinfo, j);
-						printf("%s\t%s\n",
-						       semanage_module_get_name
-						       (m),
-						       semanage_module_get_version
-						       (m));
-						semanage_module_info_datum_destroy
-						    (m);
+
+					/* calculate column widths */
+					size_t column[5] = { 0, 0, 0, 0, 0 };
+
+					/* fixed width columns */
+					column[0] = sizeof("000") - 1;
+					column[3] = sizeof("disabled") - 1;
+
+					/* variable width columns */
+					const char *tmp = NULL;
+					size_t size;
+					for (j = 0; j < modinfos_len; j++) {
+						m = semanage_module_list_nth(modinfos, j);
+
+						result = semanage_module_info_get_name(sh, m, &tmp);
+						if (result != 0) goto cleanup_list;
+
+						size = strlen(tmp);
+						if (size > column[1]) column[1] = size;
+
+						result = semanage_module_info_get_version(sh, m, &tmp);
+						if (result != 0) goto cleanup_list;
+
+						size = strlen(tmp);
+						if (size > column[2]) column[2] = size;
+
+						result = semanage_module_info_get_lang_ext(sh, m, &tmp);
+						if (result != 0) goto cleanup_list;
+
+						size = strlen(tmp);
+						if (size > column[4]) column[4] = size;
+					}
+
+					/* print out each module */
+					for (j = 0; j < modinfos_len; j++) {
+						uint16_t pri = 0;
+						const char *name = NULL;
+						const char *version = NULL;
+						int enabled = 0;
+						const char *lang_ext = NULL;
+
+						m = semanage_module_list_nth(modinfos, j);
+
+						result = semanage_module_info_get_priority(sh, m, &pri);
+						if (result != 0) goto cleanup_list;
+
+						result = semanage_module_info_get_name(sh, m, &name);
+						if (result != 0) goto cleanup_list;
+
+						result = semanage_module_info_get_version(sh, m, &version);
+						if (result != 0) goto cleanup_list;
+
+						result = semanage_module_info_get_enabled(sh, m, &enabled);
+						if (result != 0) goto cleanup_list;
+
+						result = semanage_module_info_get_lang_ext(sh, m, &lang_ext);
+						if (result != 0) goto cleanup_list;
+
+						printf("%0*u %-*s %-*s %*s %-*s\n",
+							(int)column[0], pri,
+							(int)column[1], name,
+							(int)column[2], version,
+							(int)column[3], enabled ? "" : "disabled",
+							(int)column[4], lang_ext);
 					}
-					free(modinfo);
 				}
+				else {
+					result = -1;
+				}
+
+cleanup_list:
+				for (j = 0; j < modinfos_len; j++) {
+					m = semanage_module_list_nth(modinfos, j);
+					semanage_module_info_destroy(sh, m);
+				}
+
+				free(modinfos);
+
+				break;
+			}
+		case PRIORITY_M:{
+				char *endptr = NULL;
+				priority = (uint16_t)strtoul(mode_arg, &endptr, 10);
+
+				if ((result = semanage_set_default_priority(sh, priority)) != 0) {
+					fprintf(stderr,
+						"%s: Invalid priority %d (needs to be between 1 and 999)\n",
+						argv[0],
+						priority);
+					goto cleanup;
+				}
+
+				break;
+			}
+		case ENABLE_M:{
+				if (verbose) {
+					printf
+					    ("Attempting to enable module '%s':\n",
+					     mode_arg);
+				}
+
+				semanage_module_key_t *modkey = NULL;
+
+				result = semanage_module_key_create(sh, &modkey);
+				if (result != 0) goto cleanup_enable;
+
+				result = semanage_module_key_set_name(sh, modkey, mode_arg);
+				if (result != 0) goto cleanup_enable;
+
+				result = semanage_module_set_enabled(sh, modkey, 1);
+				if (result != 0) goto cleanup_enable;
+
+cleanup_enable:
+				semanage_module_key_destroy(sh, modkey);
+				free(modkey);
+
+				break;
+			}
+		case DISABLE_M:{
+				if (verbose) {
+					printf
+					    ("Attempting to disable module '%s':\n",
+					     mode_arg);
+				}
+
+				semanage_module_key_t *modkey = NULL;
+
+				result = semanage_module_key_create(sh, &modkey);
+				if (result != 0) goto cleanup_disable;
+
+				result = semanage_module_key_set_name(sh, modkey, mode_arg);
+				if (result != 0) goto cleanup_disable;
+
+				result = semanage_module_set_enabled(sh, modkey, 0);
+				if (result != 0) goto cleanup_disable;
+
+cleanup_disable:
+				semanage_module_key_destroy(sh, modkey);
+				free(modkey);
+
 				break;
 			}
 		default:{
-- 
1.6.0.4


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

[Index of Archives]     [Selinux Refpolicy]     [Linux SGX]     [Fedora Users]     [Fedora Desktop]     [Yosemite Photos]     [Yosemite Camping]     [Yosemite Campsites]     [KDE Users]     [Gnome Users]

  Powered by Linux