All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/13] RFC libsemanage move to var, enable/disable module, and priority support
@ 2009-12-23 23:25 Caleb Case
  2009-12-23 23:25 ` [PATCH 01/13] libsemanage: fix typo in tests makefile -o -> -O Caleb Case
  2010-01-07 22:28 ` [PATCH 00/13] RFC libsemanage move to var, enable/disable module, and priority support Chad Sellers
  0 siblings, 2 replies; 39+ messages in thread
From: Caleb Case @ 2009-12-23 23:25 UTC (permalink / raw)
  To: selinux; +Cc: csellers, kmacmillan, jwcart2, jbrindle, sds, Caleb Case

Our motivations for this patchset are to:

* Move the semanage store - the portion of the SELinux configuration
  managed by libsemanage - to a more appropriate location in the
  filesystem. The current location - in /etc - is designated for
  administrator controlled configuration and is sometimes mounted
  read-only. By storing binary, program managed data in /etc libsemanage
  breaks administrator expectations. 

* Enable the overriding of modules in the module store without require
  the original modules to removed or modified. This allows
  administrators to customize the policy more fully while allowing the
  distribution provided policies to be left unmodified and continue to
  be updated by the package manager.

* Provide the ability for an administrator to disable a module without
  removing or overriding that module.

[Move to /var/lib/selinux]

Move the libsemanage private store
from /etc/selinux/<policy type>/modules
to   /var/lib/selinux/<policy type>

The benefits of this are:

* Permits the use of a read-only /etc.

* Conforms to the Filesystem Hierarchy Standard.

An additional change in layout structure moves the temporary space for
the active policy to an external temporary space. This has the benefit
of permitting source control management to be used on the private
policy.

[Module Priorities]

Module priorities modify libsemanage and the module store to allow
multiple modules with the same name to exist with different priorities.
Only the highest priority module is used to create the final system
policy. The addition of module priorities enables the modification of
the system policy without modifying individual modules. For example, it
allows an administrator to add his own policy module for apache,
completely replacing the distribution provided module, without changing
or removing the distribution policy. This has several benefits:

* Distribution provided policy package updates proceed normally - the
  distribution policy is inserted but the administrator provided policy
  remains active.

* Multiple levels allows distributors, 3rd party applications, system
  management tools (e.g., puppet), and local administrators to all make
  changes without conflicting.

* Semanage modifications of policy (e.g., port labeling) will be able to
  use high priority modules in the future to override defaults (requires
  the CIL[1] language changes).

[Enable/Disable Modules]

Modules gain an enabled / disabled status. Enabled modules are used by
semanage when building the active policy, and disabled modules are
ignored. The main benefit of this is that modules can be disabled
without out removing them from the store.

[Patchset Breakdown]

The patchset is broken down as follows:

Bug fixes:

libsemanage: fix type in tests makefile -o -> -O

Move the libsemanage store to /var/lib/selinux:

semanage: move permissive module creation to /tmp
libsemanage: move the module store to /var/lib/selinux
libsemanage: split final files into /var/lib/selinux/tmp
libsemanage: update unit tests for move to /var/lib/selinux

Implement support for the new libsemanage store layout:

libsemanage: add default priority to semanage_handle_t
libsemanage: augment semanage_module_info_t and provide semanage_module_key_t
libsemanage: get/set module info and enabled status
libsemanage: provide function to get new base module path
libsemanage: provide function to get new base module path
libsemanage: installing/upgrading/removing modules via info and key

Provide private headers for upstream tools to use:

libsemanage: new private api for unstable functions

Extend semodule to support enable/disable, priorities, and detailed listings:

semodule: add priority, enabled, and extended listing

Migration script for moving the libsemanage store:

semanage store migration script

Thanks for you feedback!

Caleb

[1] CIL RFC: http://marc.info/?l=selinux&m=124759244409438&w=2

Caleb Case (13):
  libsemanage: fix typo in tests makefile -o -> -O
  semanage: move permissive module creation to /tmp
  libsemanage: move the module store to /var/lib/selinux
  libsemanage: split final files into /var/lib/selinux/tmp
  libsemanage: update unit tests for move to /var/lib/selinux
  libsemanage: add default priority to semanage_handle_t
  libsemanage: augment semanage_module_info_t and provide
    semanage_module_key_t
  libsemanage: get/set module info and enabled status
  libsemanage: provide function to get new base module path
  libsemanage: installing/upgrading/removing modules via info and key
  libsemanage: new private api for unstable functions
  semodule: add priority, enabled, and extended listing
  semanage store migration script

 libsemanage/include/Makefile                     |    3 +
 libsemanage/include/semanage/private/handle.h    |   31 +
 libsemanage/include/semanage/private/modules.h   |  281 ++++
 libsemanage/include/semanage/private/semanage.h  |   26 +
 libsemanage/src/boolean_internal.h               |    4 +-
 libsemanage/src/booleans_file.c                  |    7 +-
 libsemanage/src/booleans_policydb.c              |    6 +-
 libsemanage/src/database_file.c                  |   45 +-
 libsemanage/src/database_file.h                  |    3 +-
 libsemanage/src/database_policydb.c              |   37 +-
 libsemanage/src/database_policydb.h              |    3 +-
 libsemanage/src/direct_api.c                     | 1652 +++++++++++++++++++---
 libsemanage/src/fcontext_internal.h              |    3 +-
 libsemanage/src/fcontexts_file.c                 |    7 +-
 libsemanage/src/genhomedircon.c                  |    3 +-
 libsemanage/src/handle.c                         |   23 +
 libsemanage/src/handle.h                         |    3 +
 libsemanage/src/handle_internal.h                |    1 +
 libsemanage/src/iface_internal.h                 |    4 +-
 libsemanage/src/interfaces_file.c                |    7 +-
 libsemanage/src/interfaces_policydb.c            |    6 +-
 libsemanage/src/libsemanage.map                  |   26 +
 libsemanage/src/module_internal.h                |   21 +
 libsemanage/src/modules.c                        |  999 +++++++++++++-
 libsemanage/src/modules.h                        |   76 +-
 libsemanage/src/node_internal.h                  |    4 +-
 libsemanage/src/nodes_file.c                     |    7 +-
 libsemanage/src/nodes_policydb.c                 |    6 +-
 libsemanage/src/policy.h                         |   36 +
 libsemanage/src/port_internal.h                  |    4 +-
 libsemanage/src/ports_file.c                     |    7 +-
 libsemanage/src/ports_policydb.c                 |    6 +-
 libsemanage/src/semanage_store.c                 |  794 ++++++++---
 libsemanage/src/semanage_store.h                 |   47 +-
 libsemanage/src/seuser_internal.h                |    4 +-
 libsemanage/src/seusers_file.c                   |    7 +-
 libsemanage/src/user_internal.h                  |    6 +-
 libsemanage/src/users_base_file.c                |    7 +-
 libsemanage/src/users_base_policydb.c            |    6 +-
 libsemanage/src/users_extra_file.c               |    7 +-
 libsemanage/tests/Makefile                       |    2 +-
 libsemanage/tests/test_semanage_store.c          |   34 +-
 libsemanage/utils/semanage_migrate_etc_to_var.py |  301 ++++
 policycoreutils/semanage/seobject.py             |   15 +-
 policycoreutils/semodule/semodule.8              |   25 +-
 policycoreutils/semodule/semodule.c              |  242 +++-
 46 files changed, 4267 insertions(+), 577 deletions(-)
 create mode 100644 libsemanage/include/semanage/private/handle.h
 create mode 100644 libsemanage/include/semanage/private/modules.h
 create mode 100644 libsemanage/include/semanage/private/semanage.h
 create mode 100755 libsemanage/utils/semanage_migrate_etc_to_var.py


--
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] 39+ messages in thread

* [PATCH 01/13] libsemanage: fix typo in tests makefile -o -> -O
  2009-12-23 23:25 [PATCH 00/13] RFC libsemanage move to var, enable/disable module, and priority support Caleb Case
@ 2009-12-23 23:25 ` Caleb Case
  2009-12-23 23:25   ` [PATCH 02/13] semanage: move permissive module creation to /tmp Caleb Case
  2010-01-07 22:28 ` [PATCH 00/13] RFC libsemanage move to var, enable/disable module, and priority support Chad Sellers
  1 sibling, 1 reply; 39+ messages in thread
From: Caleb Case @ 2009-12-23 23:25 UTC (permalink / raw)
  To: selinux; +Cc: csellers, kmacmillan, jwcart2, jbrindle, sds, Caleb Case

Fixed typo in the tests Makefile where '-o' should have been '-O'.
---
 libsemanage/tests/Makefile |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/libsemanage/tests/Makefile b/libsemanage/tests/Makefile
index f92455c..46968d5 100644
--- a/libsemanage/tests/Makefile
+++ b/libsemanage/tests/Makefile
@@ -11,7 +11,7 @@ LIBS = ../src/libsemanage.a ../../libselinux/src/libselinux.a ../../libsepol/src
 
 EXECUTABLE = libsemanage-tests
 CC = gcc
-CFLAGS = -c -g -o0 -Wall -W -Wundef -Wmissing-noreturn -Wmissing-format-attribute -Wno-unused-parameter
+CFLAGS = -c -g -O0 -Wall -W -Wundef -Wmissing-noreturn -Wmissing-format-attribute -Wno-unused-parameter
 INCLUDE = -I$(TESTSRC) -I$(TESTSRC)/../include
 LDFLAGS = -lcunit -lustr -lbz2
 OBJECTS = $(SOURCES:.c=.o) 
-- 
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@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

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

* [PATCH 02/13] semanage: move permissive module creation to /tmp
  2009-12-23 23:25 ` [PATCH 01/13] libsemanage: fix typo in tests makefile -o -> -O Caleb Case
@ 2009-12-23 23:25   ` Caleb Case
  2009-12-23 23:25     ` [PATCH 03/13] libsemanage: move the module store to /var/lib/selinux Caleb Case
  0 siblings, 1 reply; 39+ messages in thread
From: Caleb Case @ 2009-12-23 23:25 UTC (permalink / raw)
  To: selinux; +Cc: csellers, kmacmillan, jwcart2, jbrindle, sds, Caleb Case

semanage currently uses /var/lib/selinux/tmp to create permissive
modules. However, with the move to /var, the same tmp directory is used
for building policy binaries, causing a conflict. This patch creates a
random temporary directory in /tmp and moves permissive module creation
to that directory, avoiding the directory conflict.

This patch also imports shutil for rmtree to easily delete all created
temporary files.
---
 policycoreutils/semanage/seobject.py |   15 +++++----------
 1 files changed, 5 insertions(+), 10 deletions(-)

diff --git a/policycoreutils/semanage/seobject.py b/policycoreutils/semanage/seobject.py
index b7d257b..0aa7759 100644
--- a/policycoreutils/semanage/seobject.py
+++ b/policycoreutils/semanage/seobject.py
@@ -21,7 +21,7 @@
 #
 #  
 
-import pwd, grp, string, selinux, tempfile, os, re, sys, stat
+import pwd, grp, string, selinux, tempfile, os, re, sys, stat, shutil
 from semanage import *;
 PROGNAME = "policycoreutils"
 import sepolgen.module as module
@@ -271,7 +271,8 @@ class permissiveRecords(semanageRecords):
 	def add(self, type):
                import glob
                name = "permissive_%s" % type
-               dirname = "/var/lib/selinux"
+               dirname = tempfile.mkdtemp("-semanage")
+               savedir = os.getcwd()
                os.chdir(dirname)
                filename = "%s.te" % name
                modtxt = """
@@ -296,14 +297,8 @@ permissive %s;
                if rc >= 0:
                       self.commit()
 
-               for root, dirs, files in os.walk("tmp", topdown = False):
-                      for name in files:
-                             os.remove(os.path.join(root, name))
-                      for name in dirs:
-                             os.rmdir(os.path.join(root, name))
-               os.removedirs("tmp")
-               for i in glob.glob("permissive_%s.*" % type):
-                      os.remove(i)
+               os.chdir(savedir)
+               shutil.rmtree(dirname)
                if rc < 0:
 			raise ValueError(_("Could not set permissive domain %s (module installation failed)") % name)
 
-- 
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@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

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

* [PATCH 03/13] libsemanage: move the module store to /var/lib/selinux
  2009-12-23 23:25   ` [PATCH 02/13] semanage: move permissive module creation to /tmp Caleb Case
@ 2009-12-23 23:25     ` Caleb Case
  2009-12-23 23:25       ` [PATCH 04/13] libsemanage: split final files into /var/lib/selinux/tmp Caleb Case
  2010-01-08 14:28       ` [PATCH 03/13] libsemanage: move the module store to /var/lib/selinux Stephen Smalley
  0 siblings, 2 replies; 39+ messages in thread
From: Caleb Case @ 2009-12-23 23:25 UTC (permalink / raw)
  To: selinux; +Cc: csellers, kmacmillan, jwcart2, jbrindle, sds, Caleb Case

This patch moves the module store from /etc/selinux/<store>/modules to
/var/lib/selinux/<store>.

This move will allow for the use of a read-only /etc/selinux. Currently
that is not possible with semanage because of the lock files.

A consequence of this move is that packagers of libsemanage should
create the /var/lib/selinux directory.
---
 libsemanage/src/direct_api.c     |   20 ++----------------
 libsemanage/src/semanage_store.c |   39 ++++++++++++++++++++++++-------------
 libsemanage/src/semanage_store.h |    5 +++-
 3 files changed, 32 insertions(+), 32 deletions(-)

diff --git a/libsemanage/src/direct_api.c b/libsemanage/src/direct_api.c
index f09c7cf..5fb4523 100644
--- a/libsemanage/src/direct_api.c
+++ b/libsemanage/src/direct_api.c
@@ -89,12 +89,7 @@ static struct semanage_policy_table direct_funcs = {
 
 int semanage_direct_is_managed(semanage_handle_t * sh)
 {
-	char polpath[PATH_MAX];
-
-	snprintf(polpath, PATH_MAX, "%s%s", selinux_path(),
-		 sh->conf->store_path);
-
-	if (semanage_check_init(polpath))
+	if (semanage_check_init(sh, semanage_root_path()))
 		goto err;
 
 	if (semanage_access_check(sh) < 0)
@@ -111,13 +106,9 @@ int semanage_direct_is_managed(semanage_handle_t * sh)
  */
 int semanage_direct_connect(semanage_handle_t * sh)
 {
-	char polpath[PATH_MAX];
 	const char *path;
 
-	snprintf(polpath, PATH_MAX, "%s%s", selinux_path(),
-		 sh->conf->store_path);
-
-	if (semanage_check_init(polpath))
+	if (semanage_check_init(sh, semanage_root_path()))
 		goto err;
 
 	if (sh->create_store)
@@ -1416,12 +1407,7 @@ static int semanage_direct_list(semanage_handle_t * sh,
 
 int semanage_direct_access_check(semanage_handle_t * sh)
 {
-	char polpath[PATH_MAX];
-
-	snprintf(polpath, PATH_MAX, "%s%s", selinux_path(),
-		 sh->conf->store_path);
-
-	if (semanage_check_init(polpath))
+	if (semanage_check_init(sh, semanage_root_path()))
 		return -1;
 
 	return semanage_store_access_check(sh);
diff --git a/libsemanage/src/semanage_store.c b/libsemanage/src/semanage_store.c
index 0a55ce0..049818a 100644
--- a/libsemanage/src/semanage_store.c
+++ b/libsemanage/src/semanage_store.c
@@ -3,8 +3,9 @@
  *	    Jason Tang <jtang@tresys.com>
  *          Christopher Ashworth <cashworth@tresys.com>
  *          Chris PeBenito <cpebenito@tresys.com>
+ *	    Caleb Case <ccase@tresys.com>
  *
- * Copyright (C) 2004-2006 Tresys Technology, LLC
+ * Copyright (C) 2004-2006,2009 Tresys Technology, LLC
  * Copyright (C) 2005 Red Hat, Inc.
  *
  *  This library is free software; you can redistribute it and/or
@@ -88,8 +89,6 @@ static const char *semanage_store_paths[SEMANAGE_NUM_STORES] = {
 	"/tmp"
 };
 
-/* this is the module store path relative to selinux_policy_root() */
-#define SEMANAGE_MOD_DIR "/modules"
 /* relative path names to enum sandbox_paths for special files within
  * a sandbox */
 static const char *semanage_sandbox_paths[SEMANAGE_STORE_NUM_PATHS] = {
@@ -157,14 +156,14 @@ static int semanage_init_paths(const char *root)
 	if (!root)
 		return -1;
 
-	prefix_len = (strlen(root) + strlen(SEMANAGE_MOD_DIR));
+	prefix_len = strlen(root);
 
 	for (i = 0; i < SEMANAGE_NUM_FILES; i++) {
 		len = (strlen(semanage_relative_files[i]) + prefix_len);
 		semanage_files[i] = calloc(len + 1, sizeof(char));
 		if (!semanage_files[i])
 			return -1;
-		sprintf(semanage_files[i], "%s%s%s", root, SEMANAGE_MOD_DIR,
+		sprintf(semanage_files[i], "%s%s", root,
 			semanage_relative_files[i]);
 	}
 
@@ -186,16 +185,11 @@ static int semanage_init_store_paths(const char *root)
 	int i, j;
 	size_t len;
 	size_t prefix_len;
-	char *prefix;
 
 	if (!root)
 		return -1;
 
-	prefix_len = (strlen(root) + strlen(SEMANAGE_MOD_DIR));
-	prefix = calloc(prefix_len + 1, sizeof(char));
-	if (!prefix)
-		return -1;
-	sprintf(prefix, "%s%s", root, SEMANAGE_MOD_DIR);
+	prefix_len = strlen(root);
 
 	for (i = 0; i < SEMANAGE_NUM_STORES; i++) {
 		for (j = 0; j < SEMANAGE_STORE_NUM_PATHS; j++) {
@@ -204,14 +198,13 @@ static int semanage_init_store_paths(const char *root)
 			semanage_paths[i][j] = calloc(len + 1, sizeof(char));
 			if (!semanage_paths[i][j])
 				goto cleanup;
-			sprintf(semanage_paths[i][j], "%s%s%s", prefix,
+			sprintf(semanage_paths[i][j], "%s%s%s", root,
 				semanage_store_paths[i],
 				semanage_sandbox_paths[j]);
 		}
 	}
 
       cleanup:
-	free(prefix);
 	return 0;
 }
 
@@ -223,16 +216,28 @@ static int semanage_init_store_paths(const char *root)
  *
  * Note that this function is NOT thread-safe.
  */
-int semanage_check_init(const char *root)
+int semanage_check_init(semanage_handle_t *sh, const char *prefix)
 {
 	int rc;
 	if (semanage_paths_initialized == 0) {
+		char root[PATH_MAX];
+
+		rc = snprintf(root,
+			      sizeof(root),
+			      "%s/%s",
+			      prefix,
+			      sh->conf->store_path);
+		if (rc < 0 || rc >= (int)sizeof(root))
+			return -1;
+
 		rc = semanage_init_paths(root);
 		if (rc)
 			return rc;
+
 		rc = semanage_init_store_paths(root);
 		if (rc)
 			return rc;
+
 		semanage_paths_initialized = 1;
 	}
 	return 0;
@@ -259,6 +264,12 @@ const char *semanage_path(enum semanage_store_defs store,
 	return semanage_paths[store][path_name];
 }
 
+/* Return the root of the semanage store. */
+const char *semanage_root_path(void)
+{
+	return "/var/lib/selinux";
+}
+
 /* Return a fully-qualified path + filename to the semanage
  * configuration file.  The caller must not alter the string returned
  * (and hence why this function return type is const).
diff --git a/libsemanage/src/semanage_store.h b/libsemanage/src/semanage_store.h
index 112edb6..c76ecfe 100644
--- a/libsemanage/src/semanage_store.h
+++ b/libsemanage/src/semanage_store.h
@@ -62,11 +62,14 @@ enum semanage_sandbox_defs {
 	SEMANAGE_STORE_NUM_PATHS
 };
 
+const char *semanage_root_path(void);
+
 /* FIXME: this needs to be made a module store specific init and the
  * global configuration moved to another file.
  */
 const char *semanage_conf_path(void);
-int semanage_check_init(const char *root);
+
+int semanage_check_init(semanage_handle_t *sh, const char *prefix);
 
 extern const char *semanage_fname(enum semanage_sandbox_defs file_enum);
 
-- 
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@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

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

* [PATCH 04/13] libsemanage: split final files into /var/lib/selinux/tmp
  2009-12-23 23:25     ` [PATCH 03/13] libsemanage: move the module store to /var/lib/selinux Caleb Case
@ 2009-12-23 23:25       ` Caleb Case
  2009-12-23 23:25         ` [PATCH 05/13] libsemanage: update unit tests for move to /var/lib/selinux Caleb Case
  2010-01-08 14:30         ` [PATCH 04/13] libsemanage: split final files into /var/lib/selinux/tmp Stephen Smalley
  2010-01-08 14:28       ` [PATCH 03/13] libsemanage: move the module store to /var/lib/selinux Stephen Smalley
  1 sibling, 2 replies; 39+ messages in thread
From: Caleb Case @ 2009-12-23 23:25 UTC (permalink / raw)
  To: selinux; +Cc: csellers, kmacmillan, jwcart2, jbrindle, sds, Caleb Case

This patch moves the final files from inside
/var/lib/selinux/<store>/[active|previous|tmp] to
/var/lib/selinux/tmp/<store>. The move is done to facilitate using
source control management on the /var/lib/selinux/<store> directory. If
these files remain in /var/lib/selinux/<store> they will pose a size
problem if an SCM like git is used as we'd be storing lots of binary
diffs. We are suggesting making this change now, rather than later when
source policy, SCM, and CIL[1] support are available, to ease the
migration burden.

These are the files that have been moved:

/var/lib/selinux/<store>/active/...	/var/lib/selinux/tmp/<store>/...

file_contexts				contexts/files/file_contexts
file_contexts.homedirs			contexts/files/file_contexts.homedirs
file_contexts.local			contexts/files/file_contexts.local
netfilter_contexts			contexts/netfilter_contexts
policy.kern				policy/policy.<policyversion>
seusers.final				seusers

The layout of these files in /var/lib/selinux/tmp/<store> is designed to
mirror their locations in /etc/selinux/<store>. This should help clarify
the relationship between these final files and the files installed in
etc.

One consequence of this move is that reverting to the previous policy
version requires a policy rebuild. Currently you can revert without
rebuilding.

[1] CIL RFC: http://marc.info/?l=selinux&m=124759244409438&w=2
---
 libsemanage/src/boolean_internal.h    |    4 +-
 libsemanage/src/booleans_file.c       |    7 +-
 libsemanage/src/booleans_policydb.c   |    6 +-
 libsemanage/src/database_file.c       |   45 +---
 libsemanage/src/database_file.h       |    3 +-
 libsemanage/src/database_policydb.c   |   37 +--
 libsemanage/src/database_policydb.h   |    3 +-
 libsemanage/src/direct_api.c          |   76 ++++-
 libsemanage/src/fcontext_internal.h   |    3 +-
 libsemanage/src/fcontexts_file.c      |    7 +-
 libsemanage/src/genhomedircon.c       |    3 +-
 libsemanage/src/iface_internal.h      |    4 +-
 libsemanage/src/interfaces_file.c     |    7 +-
 libsemanage/src/interfaces_policydb.c |    6 +-
 libsemanage/src/node_internal.h       |    4 +-
 libsemanage/src/nodes_file.c          |    7 +-
 libsemanage/src/nodes_policydb.c      |    6 +-
 libsemanage/src/port_internal.h       |    4 +-
 libsemanage/src/ports_file.c          |    7 +-
 libsemanage/src/ports_policydb.c      |    6 +-
 libsemanage/src/semanage_store.c      |  517 +++++++++++++++++++++++++--------
 libsemanage/src/semanage_store.h      |   31 ++-
 libsemanage/src/seuser_internal.h     |    4 +-
 libsemanage/src/seusers_file.c        |    7 +-
 libsemanage/src/user_internal.h       |    6 +-
 libsemanage/src/users_base_file.c     |    7 +-
 libsemanage/src/users_base_policydb.c |    6 +-
 libsemanage/src/users_extra_file.c    |    7 +-
 28 files changed, 585 insertions(+), 245 deletions(-)

diff --git a/libsemanage/src/boolean_internal.h b/libsemanage/src/boolean_internal.h
index 66e7f35..ad12b82 100644
--- a/libsemanage/src/boolean_internal.h
+++ b/libsemanage/src/boolean_internal.h
@@ -25,7 +25,9 @@ hidden_proto(semanage_bool_clone)
 extern record_table_t SEMANAGE_BOOL_RTABLE;
 
 extern int bool_file_dbase_init(semanage_handle_t * handle,
-				const char *fname, dbase_config_t * dconfig);
+				const char *path_ro,
+				const char *path_rw,
+				dbase_config_t * dconfig);
 
 extern void bool_file_dbase_release(dbase_config_t * dconfig);
 
diff --git a/libsemanage/src/booleans_file.c b/libsemanage/src/booleans_file.c
index af5b1b3..f79d0b4 100644
--- a/libsemanage/src/booleans_file.c
+++ b/libsemanage/src/booleans_file.c
@@ -107,11 +107,14 @@ record_file_table_t SEMANAGE_BOOL_FILE_RTABLE = {
 };
 
 int bool_file_dbase_init(semanage_handle_t * handle,
-			 const char *fname, dbase_config_t * dconfig)
+			 const char *path_ro,
+			 const char *path_rw,
+			 dbase_config_t * dconfig)
 {
 
 	if (dbase_file_init(handle,
-			    fname,
+			    path_ro,
+			    path_rw,
 			    &SEMANAGE_BOOL_RTABLE,
 			    &SEMANAGE_BOOL_FILE_RTABLE, &dconfig->dbase) < 0)
 		return STATUS_ERR;
diff --git a/libsemanage/src/booleans_policydb.c b/libsemanage/src/booleans_policydb.c
index 925940c..74af2a3 100644
--- a/libsemanage/src/booleans_policydb.c
+++ b/libsemanage/src/booleans_policydb.c
@@ -33,6 +33,7 @@ typedef struct dbase_policydb dbase_t;
 #include "boolean_internal.h"
 #include "debug.h"
 #include "database_policydb.h"
+#include "semanage_store.h"
 
 /* BOOLEAN RECRORD (SEPOL): POLICYDB extension: method table */
 record_policydb_table_t SEMANAGE_BOOL_POLICYDB_RTABLE = {
@@ -54,7 +55,10 @@ int bool_policydb_dbase_init(semanage_handle_t * handle,
 {
 
 	if (dbase_policydb_init(handle,
-				"policy.kern",
+				semanage_final_path(SEMANAGE_FINAL_SELINUX,
+						    SEMANAGE_KERNEL),
+				semanage_final_path(SEMANAGE_FINAL_TMP,
+						    SEMANAGE_KERNEL),
 				&SEMANAGE_BOOL_RTABLE,
 				&SEMANAGE_BOOL_POLICYDB_RTABLE,
 				&dconfig->dbase) < 0)
diff --git a/libsemanage/src/database_file.c b/libsemanage/src/database_file.c
index 2b53521..a21b3ee 100644
--- a/libsemanage/src/database_file.c
+++ b/libsemanage/src/database_file.c
@@ -30,34 +30,13 @@ struct dbase_file {
 	 * a linked list to store the records */
 	dbase_llist_t llist;
 
-	/* Backing file suffix */
-	const char *suffix;
+	/* Backing path for read-only[0] and transaction[1] */
+	const char *path[2];
 
 	/* FILE extension */
 	record_file_table_t *rftable;
 };
 
-static int construct_filename(semanage_handle_t * handle,
-			      dbase_file_t * dbase, char **filename)
-{
-
-	const char *path = (handle->is_in_transaction) ?
-	    semanage_path(SEMANAGE_TMP, SEMANAGE_TOPLEVEL) :
-	    semanage_path(SEMANAGE_ACTIVE, SEMANAGE_TOPLEVEL);
-
-	size_t fname_length = strlen(path) + strlen(dbase->suffix) + 2;
-
-	char *fname = malloc(fname_length);
-	if (!fname) {
-		ERR(handle, "out of memory, could not construct filename");
-		return STATUS_ERR;
-	}
-	snprintf(fname, fname_length, "%s/%s", path, dbase->suffix);
-
-	*filename = fname;
-	return STATUS_SUCCESS;
-}
-
 static int dbase_file_cache(semanage_handle_t * handle, dbase_file_t * dbase)
 {
 
@@ -68,7 +47,7 @@ static int dbase_file_cache(semanage_handle_t * handle, dbase_file_t * dbase)
 	int pstatus = STATUS_SUCCESS;
 
 	parse_info_t *parse_info = NULL;
-	char *fname = NULL;
+	const char *fname = NULL;
 
 	/* Already cached */
 	if (!dbase_llist_needs_resync(handle, &dbase->llist))
@@ -79,8 +58,7 @@ static int dbase_file_cache(semanage_handle_t * handle, dbase_file_t * dbase)
 	if (dbase_llist_set_serial(handle, &dbase->llist) < 0)
 		goto err;
 
-	if (construct_filename(handle, dbase, &fname) < 0)
-		goto err;
+	fname = dbase->path[handle->is_in_transaction];
 
 	if (parse_init(handle, fname, NULL, &parse_info) < 0)
 		goto err;
@@ -119,7 +97,6 @@ static int dbase_file_cache(semanage_handle_t * handle, dbase_file_t * dbase)
 	rtable->free(process_record);
 	parse_close(parse_info);
 	parse_release(parse_info);
-	free(fname);
 	return STATUS_SUCCESS;
 
       err:
@@ -130,7 +107,6 @@ static int dbase_file_cache(semanage_handle_t * handle, dbase_file_t * dbase)
 		parse_release(parse_info);
 	}
 	dbase_llist_drop_cache(&dbase->llist);
-	free(fname);
 	return STATUS_ERR;
 }
 
@@ -141,14 +117,13 @@ static int dbase_file_flush(semanage_handle_t * handle, dbase_file_t * dbase)
 	record_file_table_t *rftable = dbase->rftable;
 
 	cache_entry_t *ptr;
-	char *fname = NULL;
+	const char *fname = NULL;
 	FILE *str = NULL;
 
 	if (!dbase_llist_is_modified(&dbase->llist))
 		return STATUS_SUCCESS;
 
-	if (construct_filename(handle, dbase, &fname) < 0)
-		goto err;
+	fname = dbase->path[handle->is_in_transaction];
 
 	str = fopen(fname, "w");
 	if (!str) {
@@ -172,7 +147,6 @@ static int dbase_file_flush(semanage_handle_t * handle, dbase_file_t * dbase)
 
 	dbase_llist_set_modified(&dbase->llist, 0);
 	fclose(str);
-	free(fname);
 	return STATUS_SUCCESS;
 
       err:
@@ -180,12 +154,12 @@ static int dbase_file_flush(semanage_handle_t * handle, dbase_file_t * dbase)
 		fclose(str);
 
 	ERR(handle, "could not flush database to file");
-	free(fname);
 	return STATUS_ERR;
 }
 
 int dbase_file_init(semanage_handle_t * handle,
-		    const char *suffix,
+		    const char *path_ro,
+		    const char *path_rw,
 		    record_table_t * rtable,
 		    record_file_table_t * rftable, dbase_file_t ** dbase)
 {
@@ -195,7 +169,8 @@ int dbase_file_init(semanage_handle_t * handle,
 	if (!tmp_dbase)
 		goto omem;
 
-	tmp_dbase->suffix = suffix;
+	tmp_dbase->path[0] = path_ro;
+	tmp_dbase->path[1] = path_rw;
 	tmp_dbase->rftable = rftable;
 	dbase_llist_init(&tmp_dbase->llist, rtable, &SEMANAGE_FILE_DTABLE);
 
diff --git a/libsemanage/src/database_file.h b/libsemanage/src/database_file.h
index 717e349..dbd11bc 100644
--- a/libsemanage/src/database_file.h
+++ b/libsemanage/src/database_file.h
@@ -28,7 +28,8 @@ typedef struct record_file_table {
 
 /* FILE - initialization */
 extern int dbase_file_init(semanage_handle_t * handle,
-			   const char *suffix,
+			   const char *path_ro,
+			   const char *path_rw,
 			   record_table_t * rtable,
 			   record_file_table_t * rftable,
 			   dbase_file_t ** dbase);
diff --git a/libsemanage/src/database_policydb.c b/libsemanage/src/database_policydb.c
index 839dcbe..fb2fe48 100644
--- a/libsemanage/src/database_policydb.c
+++ b/libsemanage/src/database_policydb.c
@@ -25,8 +25,8 @@ typedef struct dbase_policydb dbase_t;
 /* POLICYDB dbase */
 struct dbase_policydb {
 
-	/* Backing file suffix */
-	const char *suffix;
+        /* Backing path for read-only[0] and transaction[1] */
+        const char *path[2];
 
 	/* Base record table */
 	record_table_t *rtable;
@@ -86,26 +86,6 @@ static int dbase_policydb_needs_resync(semanage_handle_t * handle,
 	return 0;
 }
 
-static int construct_filename(semanage_handle_t * handle,
-			      dbase_policydb_t * dbase, char **filename)
-{
-
-	const char *path = (handle->is_in_transaction) ?
-	    semanage_path(SEMANAGE_TMP, SEMANAGE_TOPLEVEL) :
-	    semanage_path(SEMANAGE_ACTIVE, SEMANAGE_TOPLEVEL);
-	size_t fname_length = strlen(path) + strlen(dbase->suffix) + 2;
-
-	char *fname = malloc(fname_length);
-	if (!fname) {
-		ERR(handle, "out of memory, could not construct database name");
-		return STATUS_ERR;
-	}
-	snprintf(fname, fname_length, "%s/%s", path, dbase->suffix);
-
-	*filename = fname;
-	return STATUS_SUCCESS;
-}
-
 static int dbase_policydb_cache(semanage_handle_t * handle,
 				dbase_policydb_t * dbase)
 {
@@ -113,7 +93,7 @@ static int dbase_policydb_cache(semanage_handle_t * handle,
 	FILE *fp = NULL;
 	sepol_policydb_t *policydb = NULL;
 	sepol_policy_file_t *pf = NULL;
-	char *fname = NULL;
+	const char *fname = NULL;
 
 	/* Check if cache is needed */
 	if (dbase->attached)
@@ -122,8 +102,7 @@ static int dbase_policydb_cache(semanage_handle_t * handle,
 	if (!dbase_policydb_needs_resync(handle, dbase))
 		return STATUS_SUCCESS;
 
-	if (construct_filename(handle, dbase, &fname) < 0)
-		goto err;
+	fname = dbase->path[handle->is_in_transaction];
 
 	if (sepol_policydb_create(&policydb) < 0) {
 		ERR(handle, "could not create policydb object");
@@ -164,7 +143,6 @@ static int dbase_policydb_cache(semanage_handle_t * handle,
 
 	/* Update the database policydb */
 	dbase->policydb = policydb;
-	free(fname);
 	return STATUS_SUCCESS;
 
       err:
@@ -173,7 +151,6 @@ static int dbase_policydb_cache(semanage_handle_t * handle,
 		fclose(fp);
 	sepol_policydb_free(policydb);
 	sepol_policy_file_free(pf);
-	free(fname);
 	return STATUS_ERR;
 }
 
@@ -199,7 +176,8 @@ static int dbase_policydb_is_modified(dbase_policydb_t * dbase)
 }
 
 int dbase_policydb_init(semanage_handle_t * handle,
-			const char *suffix,
+			const char *path_ro,
+			const char *path_rw,
 			record_table_t * rtable,
 			record_policydb_table_t * rptable,
 			dbase_policydb_t ** dbase)
@@ -211,7 +189,8 @@ int dbase_policydb_init(semanage_handle_t * handle,
 	if (!tmp_dbase)
 		goto omem;
 
-	tmp_dbase->suffix = suffix;
+	tmp_dbase->path[0] = path_ro;
+	tmp_dbase->path[1] = path_rw;
 	tmp_dbase->rtable = rtable;
 	tmp_dbase->rptable = rptable;
 	tmp_dbase->policydb = NULL;
diff --git a/libsemanage/src/database_policydb.h b/libsemanage/src/database_policydb.h
index 88cde5e..f782e0d 100644
--- a/libsemanage/src/database_policydb.h
+++ b/libsemanage/src/database_policydb.h
@@ -86,7 +86,8 @@ typedef struct record_policydb_table {
 
 /* Initialize database */
 extern int dbase_policydb_init(semanage_handle_t * handle,
-			       const char *suffix,
+			       const char *path_ro,
+			       const char *path_rw,
 			       record_table_t * rtable,
 			       record_policydb_table_t * rptable,
 			       dbase_policydb_t ** dbase);
diff --git a/libsemanage/src/direct_api.c b/libsemanage/src/direct_api.c
index 5fb4523..e438b87 100644
--- a/libsemanage/src/direct_api.c
+++ b/libsemanage/src/direct_api.c
@@ -126,13 +126,18 @@ int semanage_direct_connect(semanage_handle_t * sh)
 
 	/* Object databases: local modifications */
 	if (user_base_file_dbase_init(sh,
-				      semanage_fname(SEMANAGE_USERS_BASE_LOCAL),
+				      semanage_path(SEMANAGE_ACTIVE,
+						    SEMANAGE_USERS_BASE_LOCAL),
+				      semanage_path(SEMANAGE_TMP,
+						    SEMANAGE_USERS_BASE_LOCAL),
 				      semanage_user_base_dbase_local(sh)) < 0)
 		goto err;
 
 	if (user_extra_file_dbase_init(sh,
-				       semanage_fname
-				       (SEMANAGE_USERS_EXTRA_LOCAL),
+				       semanage_path(SEMANAGE_ACTIVE,
+						     SEMANAGE_USERS_EXTRA_LOCAL),
+				       semanage_path(SEMANAGE_TMP,
+						     SEMANAGE_USERS_EXTRA_LOCAL),
 				       semanage_user_extra_dbase_local(sh)) < 0)
 		goto err;
 
@@ -143,32 +148,50 @@ int semanage_direct_connect(semanage_handle_t * sh)
 		goto err;
 
 	if (port_file_dbase_init(sh,
-				 semanage_fname(SEMANAGE_PORTS_LOCAL),
+				 semanage_path(SEMANAGE_ACTIVE,
+					       SEMANAGE_PORTS_LOCAL),
+				 semanage_path(SEMANAGE_TMP,
+					       SEMANAGE_PORTS_LOCAL),
 				 semanage_port_dbase_local(sh)) < 0)
 		goto err;
 
 	if (iface_file_dbase_init(sh,
-				  semanage_fname(SEMANAGE_INTERFACES_LOCAL),
+				  semanage_path(SEMANAGE_ACTIVE,
+						SEMANAGE_INTERFACES_LOCAL),
+				  semanage_path(SEMANAGE_TMP,
+						SEMANAGE_INTERFACES_LOCAL),
 				  semanage_iface_dbase_local(sh)) < 0)
 		goto err;
 
 	if (bool_file_dbase_init(sh,
-				 semanage_fname(SEMANAGE_BOOLEANS_LOCAL),
+				 semanage_path(SEMANAGE_ACTIVE,
+					       SEMANAGE_BOOLEANS_LOCAL),
+				 semanage_path(SEMANAGE_TMP,
+					       SEMANAGE_BOOLEANS_LOCAL),
 				 semanage_bool_dbase_local(sh)) < 0)
 		goto err;
 
 	if (fcontext_file_dbase_init(sh,
-				     semanage_fname(SEMANAGE_FC_LOCAL),
+				     semanage_final_path(SEMANAGE_FINAL_SELINUX,
+							 SEMANAGE_FC_LOCAL),
+				     semanage_final_path(SEMANAGE_FINAL_TMP,
+							 SEMANAGE_FC_LOCAL),
 				     semanage_fcontext_dbase_local(sh)) < 0)
 		goto err;
 
 	if (seuser_file_dbase_init(sh,
-				   semanage_fname(SEMANAGE_SEUSERS_LOCAL),
+				   semanage_path(SEMANAGE_ACTIVE,
+						 SEMANAGE_SEUSERS_LOCAL),
+				   semanage_path(SEMANAGE_TMP,
+						 SEMANAGE_SEUSERS_LOCAL),
 				   semanage_seuser_dbase_local(sh)) < 0)
 		goto err;
 
 	if (node_file_dbase_init(sh,
-				 semanage_fname(SEMANAGE_NODES_LOCAL),
+				 semanage_path(SEMANAGE_ACTIVE,
+					       SEMANAGE_NODES_LOCAL),
+				 semanage_path(SEMANAGE_TMP,
+					       SEMANAGE_NODES_LOCAL),
 				 semanage_node_dbase_local(sh)) < 0)
 		goto err;
 
@@ -179,7 +202,10 @@ int semanage_direct_connect(semanage_handle_t * sh)
 		goto err;
 
 	if (user_extra_file_dbase_init(sh,
-				       semanage_fname(SEMANAGE_USERS_EXTRA),
+				       semanage_path(SEMANAGE_ACTIVE,
+						     SEMANAGE_USERS_EXTRA),
+				       semanage_path(SEMANAGE_TMP,
+						     SEMANAGE_USERS_EXTRA),
 				       semanage_user_extra_dbase_policy(sh)) <
 	    0)
 		goto err;
@@ -200,12 +226,18 @@ int semanage_direct_connect(semanage_handle_t * sh)
 		goto err;
 
 	if (fcontext_file_dbase_init(sh,
-				     semanage_fname(SEMANAGE_FC),
+				     semanage_final_path(SEMANAGE_FINAL_SELINUX,
+							 SEMANAGE_FC),
+				     semanage_final_path(SEMANAGE_FINAL_TMP,
+							 SEMANAGE_FC),
 				     semanage_fcontext_dbase_policy(sh)) < 0)
 		goto err;
 
 	if (seuser_file_dbase_init(sh,
-				   semanage_fname(SEMANAGE_SEUSERS),
+				   semanage_final_path(SEMANAGE_FINAL_SELINUX,
+						       SEMANAGE_SEUSERS),
+				   semanage_final_path(SEMANAGE_FINAL_TMP,
+						       SEMANAGE_SEUSERS),
 				   semanage_seuser_dbase_policy(sh)) < 0)
 		goto err;
 
@@ -247,6 +279,14 @@ static int semanage_direct_disconnect(semanage_handle_t * sh)
 			    semanage_path(SEMANAGE_TMP, SEMANAGE_TOPLEVEL));
 			return -1;
 		}
+		if (semanage_remove_directory
+		    (semanage_final_path(SEMANAGE_FINAL_TMP,
+					 SEMANAGE_FINAL_TOPLEVEL)) < 0) {
+			ERR(sh, "Could not cleanly remove tmp %s.",
+			    semanage_final_path(SEMANAGE_FINAL_TMP,
+						SEMANAGE_FINAL_TOPLEVEL));
+			return -1;
+		}
 		semanage_release_trans_lock(sh);
 	}
 
@@ -290,6 +330,9 @@ static int semanage_direct_begintrans(semanage_handle_t * sh)
 	if ((semanage_make_sandbox(sh)) < 0) {
 		return -1;
 	}
+	if ((semanage_make_final(sh)) < 0) {
+		return -1;
+	}
 	return 0;
 }
 
@@ -639,7 +682,8 @@ static int semanage_direct_update_seuser(semanage_handle_t * sh, sepol_module_pa
 	dbase_config_t *pseusers = semanage_seuser_dbase_policy(sh);
 
 	if (sepol_module_package_get_seusers_len(base)) {
-		ofilename = semanage_path(SEMANAGE_TMP, SEMANAGE_SEUSERS);
+		ofilename = semanage_final_path(SEMANAGE_FINAL_TMP,
+						SEMANAGE_SEUSERS);
 		if (ofilename == NULL) {
 			return -1;
 		}
@@ -840,7 +884,8 @@ static int semanage_direct_commit(semanage_handle_t * sh)
 		/* Write the contexts to a single file.  The buffer returned by
 		 * the sort function has a trailing \0 character, which we do
 		 * NOT want to write out to disk, so we pass sorted_fc_buffer_len-1. */
-		ofilename = semanage_path(SEMANAGE_TMP, SEMANAGE_NC);
+		ofilename = semanage_final_path(SEMANAGE_FINAL_TMP,
+						SEMANAGE_NC);
 		retval = write_file
 		    (sh, ofilename, sorted_nc_buffer, sorted_nc_buffer_len - 1);
 
@@ -995,6 +1040,9 @@ static int semanage_direct_commit(semanage_handle_t * sh)
 	   sandbox if it is still there */
 	semanage_remove_directory(semanage_path
 				  (SEMANAGE_TMP, SEMANAGE_TOPLEVEL));
+	semanage_remove_directory(semanage_final_path
+				  (SEMANAGE_FINAL_TMP,
+				   SEMANAGE_FINAL_TOPLEVEL));
 	return retval;
 }
 
diff --git a/libsemanage/src/fcontext_internal.h b/libsemanage/src/fcontext_internal.h
index 4f45fa6..a6008ea 100644
--- a/libsemanage/src/fcontext_internal.h
+++ b/libsemanage/src/fcontext_internal.h
@@ -30,7 +30,8 @@ hidden_proto(semanage_fcontext_key_create)
 extern record_table_t SEMANAGE_FCONTEXT_RTABLE;
 
 extern int fcontext_file_dbase_init(semanage_handle_t * handle,
-				    const char *fname,
+				    const char *path_ro,
+				    const char *path_rw,
 				    dbase_config_t * dconfig);
 
 extern void fcontext_file_dbase_release(dbase_config_t * dconfig);
diff --git a/libsemanage/src/fcontexts_file.c b/libsemanage/src/fcontexts_file.c
index b1a2f82..1e59651 100644
--- a/libsemanage/src/fcontexts_file.c
+++ b/libsemanage/src/fcontexts_file.c
@@ -165,11 +165,14 @@ record_file_table_t SEMANAGE_FCONTEXT_FILE_RTABLE = {
 };
 
 int fcontext_file_dbase_init(semanage_handle_t * handle,
-			     const char *fname, dbase_config_t * dconfig)
+			     const char *path_ro,
+			     const char *path_rw,
+			     dbase_config_t * dconfig)
 {
 
 	if (dbase_file_init(handle,
-			    fname,
+			    path_ro,
+			    path_rw,
 			    &SEMANAGE_FCONTEXT_RTABLE,
 			    &SEMANAGE_FCONTEXT_FILE_RTABLE,
 			    &dconfig->dbase) < 0)
diff --git a/libsemanage/src/genhomedircon.c b/libsemanage/src/genhomedircon.c
index 8a7d5e2..94ddfbe 100644
--- a/libsemanage/src/genhomedircon.c
+++ b/libsemanage/src/genhomedircon.c
@@ -964,7 +964,8 @@ int semanage_genhomedircon(semanage_handle_t * sh,
 
 	s.homedir_template_path =
 	    semanage_path(SEMANAGE_TMP, SEMANAGE_HOMEDIR_TMPL);
-	s.fcfilepath = semanage_path(SEMANAGE_TMP, SEMANAGE_FC_HOMEDIRS);
+	s.fcfilepath = semanage_final_path(SEMANAGE_FINAL_TMP,
+					   SEMANAGE_FC_HOMEDIRS);
 
 	s.fallback_user = strdup(FALLBACK_USER);
 	s.fallback_user_prefix = strdup(FALLBACK_USER_PREFIX);
diff --git a/libsemanage/src/iface_internal.h b/libsemanage/src/iface_internal.h
index 7fe80fd..1f67836 100644
--- a/libsemanage/src/iface_internal.h
+++ b/libsemanage/src/iface_internal.h
@@ -31,7 +31,9 @@ extern int iface_policydb_dbase_init(semanage_handle_t * handle,
 extern void iface_policydb_dbase_release(dbase_config_t * dconfig);
 
 extern int iface_file_dbase_init(semanage_handle_t * handle,
-				 const char *fname, dbase_config_t * dconfig);
+				 const char *path_ro,
+				 const char *path_rw,
+				 dbase_config_t * dconfig);
 
 extern void iface_file_dbase_release(dbase_config_t * dconfig);
 
diff --git a/libsemanage/src/interfaces_file.c b/libsemanage/src/interfaces_file.c
index 78871a2..1478af9 100644
--- a/libsemanage/src/interfaces_file.c
+++ b/libsemanage/src/interfaces_file.c
@@ -152,11 +152,14 @@ record_file_table_t SEMANAGE_IFACE_FILE_RTABLE = {
 };
 
 int iface_file_dbase_init(semanage_handle_t * handle,
-			  const char *fname, dbase_config_t * dconfig)
+			  const char *path_ro,
+			  const char *path_rw,
+			  dbase_config_t * dconfig)
 {
 
 	if (dbase_file_init(handle,
-			    fname,
+			    path_ro,
+			    path_rw,
 			    &SEMANAGE_IFACE_RTABLE,
 			    &SEMANAGE_IFACE_FILE_RTABLE, &dconfig->dbase) < 0)
 		return STATUS_ERR;
diff --git a/libsemanage/src/interfaces_policydb.c b/libsemanage/src/interfaces_policydb.c
index b67963d..6a42eed 100644
--- a/libsemanage/src/interfaces_policydb.c
+++ b/libsemanage/src/interfaces_policydb.c
@@ -33,6 +33,7 @@ typedef struct dbase_policydb dbase_t;
 #include "iface_internal.h"
 #include "debug.h"
 #include "database_policydb.h"
+#include "semanage_store.h"
 
 /* INTERFACE RECRORD (SEPOL): POLICYDB extension: method table */
 record_policydb_table_t SEMANAGE_IFACE_POLICYDB_RTABLE = {
@@ -50,7 +51,10 @@ int iface_policydb_dbase_init(semanage_handle_t * handle,
 {
 
 	if (dbase_policydb_init(handle,
-				"policy.kern",
+				semanage_final_path(SEMANAGE_FINAL_SELINUX,
+						    SEMANAGE_KERNEL),
+				semanage_final_path(SEMANAGE_FINAL_TMP,
+						    SEMANAGE_KERNEL),
 				&SEMANAGE_IFACE_RTABLE,
 				&SEMANAGE_IFACE_POLICYDB_RTABLE,
 				&dconfig->dbase) < 0)
diff --git a/libsemanage/src/node_internal.h b/libsemanage/src/node_internal.h
index 7653af8..5817560 100644
--- a/libsemanage/src/node_internal.h
+++ b/libsemanage/src/node_internal.h
@@ -34,7 +34,9 @@ hidden_proto(semanage_node_create)
 extern record_table_t SEMANAGE_NODE_RTABLE;
 
 extern int node_file_dbase_init(semanage_handle_t * handle,
-				const char *fname, dbase_config_t * dconfig);
+				const char *path_ro,
+				const char *path_rw,
+				dbase_config_t * dconfig);
 
 extern void node_file_dbase_release(dbase_config_t * dconfig);
 
diff --git a/libsemanage/src/nodes_file.c b/libsemanage/src/nodes_file.c
index b80de2d..f6c8895 100644
--- a/libsemanage/src/nodes_file.c
+++ b/libsemanage/src/nodes_file.c
@@ -161,11 +161,14 @@ record_file_table_t SEMANAGE_NODE_FILE_RTABLE = {
 };
 
 int node_file_dbase_init(semanage_handle_t * handle,
-			 const char *fname, dbase_config_t * dconfig)
+			 const char *path_ro,
+			 const char *path_rw,
+			 dbase_config_t * dconfig)
 {
 
 	if (dbase_file_init(handle,
-			    fname,
+			    path_ro,
+			    path_rw,
 			    &SEMANAGE_NODE_RTABLE,
 			    &SEMANAGE_NODE_FILE_RTABLE, &dconfig->dbase) < 0)
 		return STATUS_ERR;
diff --git a/libsemanage/src/nodes_policydb.c b/libsemanage/src/nodes_policydb.c
index e732e0e..56012fb 100644
--- a/libsemanage/src/nodes_policydb.c
+++ b/libsemanage/src/nodes_policydb.c
@@ -32,6 +32,7 @@ typedef struct dbase_policydb dbase_t;
 #include "node_internal.h"
 #include "debug.h"
 #include "database_policydb.h"
+#include "semanage_store.h"
 
 /* NODE RECORD (SEPOL): POLICYDB extension : method table */
 record_policydb_table_t SEMANAGE_NODE_POLICYDB_RTABLE = {
@@ -49,7 +50,10 @@ int node_policydb_dbase_init(semanage_handle_t * handle,
 {
 
 	if (dbase_policydb_init(handle,
-				"policy.kern",
+				semanage_final_path(SEMANAGE_FINAL_SELINUX,
+						    SEMANAGE_KERNEL),
+				semanage_final_path(SEMANAGE_FINAL_TMP,
+						    SEMANAGE_KERNEL),
 				&SEMANAGE_NODE_RTABLE,
 				&SEMANAGE_NODE_POLICYDB_RTABLE,
 				&dconfig->dbase) < 0)
diff --git a/libsemanage/src/port_internal.h b/libsemanage/src/port_internal.h
index b3d36ce..ebd2bc8 100644
--- a/libsemanage/src/port_internal.h
+++ b/libsemanage/src/port_internal.h
@@ -30,7 +30,9 @@ hidden_proto(semanage_port_create)
 extern record_table_t SEMANAGE_PORT_RTABLE;
 
 extern int port_file_dbase_init(semanage_handle_t * handle,
-				const char *fname, dbase_config_t * dconfig);
+				const char *path_ro,
+				const char *path_rw,
+				dbase_config_t * dconfig);
 
 extern void port_file_dbase_release(dbase_config_t * dconfig);
 
diff --git a/libsemanage/src/ports_file.c b/libsemanage/src/ports_file.c
index 41d2f60..46ee2f0 100644
--- a/libsemanage/src/ports_file.c
+++ b/libsemanage/src/ports_file.c
@@ -164,11 +164,14 @@ record_file_table_t SEMANAGE_PORT_FILE_RTABLE = {
 };
 
 int port_file_dbase_init(semanage_handle_t * handle,
-			 const char *fname, dbase_config_t * dconfig)
+			 const char *path_ro,
+			 const char *path_rw,
+			 dbase_config_t * dconfig)
 {
 
 	if (dbase_file_init(handle,
-			    fname,
+			    path_ro,
+			    path_rw,
 			    &SEMANAGE_PORT_RTABLE,
 			    &SEMANAGE_PORT_FILE_RTABLE, &dconfig->dbase) < 0)
 		return STATUS_ERR;
diff --git a/libsemanage/src/ports_policydb.c b/libsemanage/src/ports_policydb.c
index 429ed72..b9600f0 100644
--- a/libsemanage/src/ports_policydb.c
+++ b/libsemanage/src/ports_policydb.c
@@ -32,6 +32,7 @@ typedef struct dbase_policydb dbase_t;
 #include "port_internal.h"
 #include "debug.h"
 #include "database_policydb.h"
+#include "semanage_store.h"
 
 /* PORT RECORD (SEPOL): POLICYDB extension : method table */
 record_policydb_table_t SEMANAGE_PORT_POLICYDB_RTABLE = {
@@ -49,7 +50,10 @@ int port_policydb_dbase_init(semanage_handle_t * handle,
 {
 
 	if (dbase_policydb_init(handle,
-				"policy.kern",
+				semanage_final_path(SEMANAGE_FINAL_SELINUX,
+						    SEMANAGE_KERNEL),
+				semanage_final_path(SEMANAGE_FINAL_TMP,
+						    SEMANAGE_KERNEL),
 				&SEMANAGE_PORT_RTABLE,
 				&SEMANAGE_PORT_POLICYDB_RTABLE,
 				&dconfig->dbase) < 0)
diff --git a/libsemanage/src/semanage_store.c b/libsemanage/src/semanage_store.c
index 049818a..62779b3 100644
--- a/libsemanage/src/semanage_store.c
+++ b/libsemanage/src/semanage_store.c
@@ -94,10 +94,8 @@ static const char *semanage_store_paths[SEMANAGE_NUM_STORES] = {
 static const char *semanage_sandbox_paths[SEMANAGE_STORE_NUM_PATHS] = {
 	"",
 	"/modules",
-	"/policy.kern",
 	"/base.pp",
 	"/base.linked",
-	"/file_contexts",
 	"/homedir_template",
 	"/file_contexts.template",
 	"/commit_num",
@@ -105,17 +103,23 @@ static const char *semanage_sandbox_paths[SEMANAGE_STORE_NUM_PATHS] = {
 	"/interfaces.local",
 	"/nodes.local",
 	"/booleans.local",
-	"/file_contexts.local",
-	"/seusers",
+	"/seusers.local",
 	"/users.local",
 	"/users_extra.local",
-	"/seusers.final",
 	"/users_extra",
-	"/netfilter_contexts",
-	"/file_contexts.homedirs",
 	"/disable_dontaudit",
+	"/modules/disabled",
 };
 
+static char const * const semanage_final_prefix[SEMANAGE_FINAL_NUM] = {
+	"/tmp",
+	"",
+};
+
+static char *semanage_final[SEMANAGE_FINAL_NUM] = { NULL };
+static char *semanage_final_suffix[SEMANAGE_FINAL_PATH_NUM] = { NULL };
+static char *semanage_final_paths[SEMANAGE_FINAL_NUM][SEMANAGE_FINAL_PATH_NUM] = {{ NULL }};
+
 /* A node used in a linked list of file contexts; used for sorting.
  */
 typedef struct semanage_file_context_node {
@@ -208,6 +212,184 @@ static int semanage_init_store_paths(const char *root)
 	return 0;
 }
 
+static int semanage_init_final(semanage_handle_t *sh, const char *prefix)
+{
+	assert(sh);
+	assert(prefix);
+
+	int status = 0;
+	size_t len;
+	const char *store_path = sh->conf->store_path;
+	size_t store_len = strlen(store_path);
+
+	/* SEMANAGE_FINAL_TMP */
+	len = strlen(prefix) +
+	      strlen(semanage_final_prefix[SEMANAGE_FINAL_TMP]) +
+	      store_len;
+	semanage_final[SEMANAGE_FINAL_TMP] = malloc(len + 2);
+	if (semanage_final[SEMANAGE_FINAL_TMP] == NULL) {
+		status = -1;
+		goto cleanup;
+	}
+
+	sprintf(semanage_final[SEMANAGE_FINAL_TMP],
+		"%s%s/%s",
+		prefix,
+		semanage_final_prefix[SEMANAGE_FINAL_TMP],
+		store_path);
+
+	/* SEMANAGE_FINAL_SELINUX */
+	const char *selinux_root = selinux_path();
+	len = strlen(selinux_root) +
+	      strlen(semanage_final_prefix[SEMANAGE_FINAL_SELINUX]) +
+	      store_len;
+	semanage_final[SEMANAGE_FINAL_SELINUX] = malloc(len + 1);
+	if (semanage_final[SEMANAGE_FINAL_SELINUX] == NULL) {
+		status = -1;
+		goto cleanup;
+	}
+
+	sprintf(semanage_final[SEMANAGE_FINAL_SELINUX],
+		"%s%s%s",
+		selinux_root,
+		semanage_final_prefix[SEMANAGE_FINAL_SELINUX],
+		store_path);
+
+cleanup:
+	if (status != 0) {
+		int i;
+		for (i = 0; i < SEMANAGE_FINAL_NUM; i++) {
+			free(semanage_final[i]);
+			semanage_final[i] = NULL;
+		}
+	}
+
+	return status;
+}
+
+static int semanage_init_final_suffix(semanage_handle_t *sh)
+{
+	int ret = 0;
+	int status = 0;
+	char path[PATH_MAX];
+	size_t offset = strlen(selinux_policy_root());
+
+	semanage_final_suffix[SEMANAGE_FINAL_TOPLEVEL] = strdup("");
+	if (semanage_final_suffix[SEMANAGE_FINAL_TOPLEVEL] == NULL) {
+		ERR(sh, "Unable to allocate space for policy top level path.");
+		status = -1;
+		goto cleanup;
+	}
+
+	semanage_final_suffix[SEMANAGE_FC] =
+		strdup(selinux_file_context_path() + offset);
+	if (semanage_final_suffix[SEMANAGE_FC] == NULL) {
+		ERR(sh, "Unable to allocate space for file context path.");
+		status = -1;
+		goto cleanup;
+	}
+
+	semanage_final_suffix[SEMANAGE_FC_HOMEDIRS] =
+		strdup(selinux_file_context_homedir_path() + offset);
+	if (semanage_final_suffix[SEMANAGE_FC_HOMEDIRS] == NULL) {
+		ERR(sh, "Unable to allocate space for file context home directory path.");
+		status = -1;
+		goto cleanup;
+	}
+
+	semanage_final_suffix[SEMANAGE_FC_LOCAL] =
+		strdup(selinux_file_context_local_path() + offset);
+	if (semanage_final_suffix[SEMANAGE_FC_LOCAL] == NULL) {
+		ERR(sh, "Unable to allocate space for local file context path.");
+		status = -1;
+		goto cleanup;
+	}
+
+	semanage_final_suffix[SEMANAGE_NC] =
+		strdup(selinux_netfilter_context_path() + offset);
+	if (semanage_final_suffix[SEMANAGE_NC] == NULL) {
+		ERR(sh, "Unable to allocate space for netfilter context path.");
+		status = -1;
+		goto cleanup;
+	}
+
+	semanage_final_suffix[SEMANAGE_SEUSERS] =
+		strdup(selinux_usersconf_path() + offset);
+	if (semanage_final_suffix[SEMANAGE_SEUSERS] == NULL) {
+		ERR(sh, "Unable to allocate space for userconf path.");
+		status = -1;
+		goto cleanup;
+	}
+
+	ret = snprintf(path,
+		       sizeof(path),
+		       "%s.%d",
+		       selinux_binary_policy_path() + offset,
+		       sh->conf->policyvers);
+	if (ret < 0 || ret >= (int)sizeof(path)) {
+		ERR(sh, "Unable to compose policy binary path.");
+		status = -1;
+		goto cleanup;
+	}
+
+	semanage_final_suffix[SEMANAGE_KERNEL] = strdup(path);
+	if (semanage_final_suffix[SEMANAGE_KERNEL] == NULL) {
+		ERR(sh, "Unable to allocate space for policy binary path.");
+		status = -1;
+		goto cleanup;
+	}
+
+cleanup:
+	if (status != 0) {
+		int i;
+		for (i = 0; i < SEMANAGE_FINAL_PATH_NUM; i++) {
+			free(semanage_final_suffix[i]);
+			semanage_final_suffix[i] = NULL;
+		}
+	}
+
+	return status;
+}
+
+/* Initialize final paths. */
+static int semanage_init_final_paths(semanage_handle_t *sh)
+{
+	int status = 0;
+	int i, j;
+	size_t len;
+
+	for (i = 0; i < SEMANAGE_FINAL_NUM; i++) {
+		for (j = 0; j < SEMANAGE_FINAL_PATH_NUM; j++) {
+			len = 	  strlen(semanage_final[i])
+				+ strlen(semanage_final_suffix[j]);
+
+			semanage_final_paths[i][j] = malloc(len + 1);
+			if (semanage_final_paths[i][j] == NULL) {
+				ERR(sh, "Unable to allocate space for policy final path.");
+				status = -1;
+				goto cleanup;
+			}
+
+			sprintf(semanage_final_paths[i][j],
+				"%s%s",
+				semanage_final[i],
+				semanage_final_suffix[j]);
+		}
+	}
+
+cleanup:
+	if (status != 0) {
+		for (i = 0; i < SEMANAGE_FINAL_NUM; i++) {
+			for (j = 0; j < SEMANAGE_FINAL_PATH_NUM; j++) {
+				free(semanage_final_paths[i][j]);
+				semanage_final_paths[i][j] = NULL;
+			}
+		}
+	}
+
+	return status;
+}
+
 /* THIS MUST BE THE FIRST FUNCTION CALLED IN THIS LIBRARY.  If the
  * library has nnot been initialized yet then call the functions that
  * initialize the path variables.  This function does nothing if it
@@ -238,6 +420,18 @@ int semanage_check_init(semanage_handle_t *sh, const char *prefix)
 		if (rc)
 			return rc;
 
+		rc = semanage_init_final(sh, prefix);
+		if (rc)
+			return rc;
+
+		rc = semanage_init_final_suffix(sh);
+		if (rc)
+			return rc;
+
+		rc = semanage_init_final_paths(sh);
+		if (rc)
+			return rc;
+
 		semanage_paths_initialized = 1;
 	}
 	return 0;
@@ -264,6 +458,21 @@ const char *semanage_path(enum semanage_store_defs store,
 	return semanage_paths[store][path_name];
 }
 
+/* Given a store location (tmp or selinux) and a definition
+ * number, return a fully-qualified path to that file or directory.
+ * The caller must not alter the string returned (and hence why this
+ * function return type is const).
+ *
+ * This function shall never return a NULL, assuming that
+ * semanage_check_init() was previously called.
+ */
+const char *semanage_final_path(enum semanage_final_defs store,
+				enum semanage_final_path_defs path_name)
+{
+	assert(semanage_final_paths[store][path_name]);
+	return semanage_final_paths[store][path_name];
+}
+
 /* Return the root of the semanage store. */
 const char *semanage_root_path(void)
 {
@@ -493,10 +702,20 @@ out:
 	return retval;
 }
 
+static int semanage_copy_dir_flags(const char *src, const char *dst, int flag);
+
 /* Copies all of the files from src to dst, recursing into
  * subdirectories.  Returns 0 on success, -1 on error. */
 static int semanage_copy_dir(const char *src, const char *dst)
 {
+	return semanage_copy_dir_flags(src, dst, 1);
+}
+
+/* Copies all of the dirs from src to dst, recursing into
+ * subdirectories. If flag == 1, then copy regular files as
+ * well. Returns 0 on success, -1 on error. */
+static int semanage_copy_dir_flags(const char *src, const char *dst, int flag)
+{
 	int i, len = 0, retval = -1;
 	struct stat sb;
 	struct dirent **names = NULL;
@@ -505,6 +724,13 @@ static int semanage_copy_dir(const char *src, const char *dst)
 	if ((len = scandir(src, &names, semanage_filename_select, NULL)) == -1) {
 		return -1;
 	}
+
+	if (stat(dst, &sb) != 0) {
+		if (mkdir(dst, S_IRWXU) != 0) {
+			goto cleanup;
+		}
+	}
+
 	for (i = 0; i < len; i++) {
 		snprintf(path, sizeof(path), "%s/%s", src, names[i]->d_name);
 		/* stat() to see if this entry is a file or not since
@@ -515,11 +741,11 @@ static int semanage_copy_dir(const char *src, const char *dst)
 		snprintf(path2, sizeof(path2), "%s/%s", dst, names[i]->d_name);
 		if (S_ISDIR(sb.st_mode)) {
 			if (mkdir(path2, 0700) == -1 ||
-			    semanage_copy_dir(path, path2) == -1) {
+			    semanage_copy_dir_flags(path, path2, flag) == -1) {
 				goto cleanup;
 			}
-		} else if (S_ISREG(sb.st_mode)) {
-			if (semanage_copy_file(path, path2, sb.st_mode) == -1) {
+		} else if (S_ISREG(sb.st_mode) && flag == 1) {
+			if (semanage_copy_file(path, path2, sb.st_mode) < 0) {
 				goto cleanup;
 			}
 		}
@@ -569,6 +795,34 @@ int semanage_remove_directory(const char *path)
 	return 0;
 }
 
+int semanage_mkdir(semanage_handle_t *sh, const char *path)
+{
+	int status = 0;
+	struct stat sb;
+
+	/* check if directory already exists */
+	if (stat(path, &sb) != 0) {
+		/* make the modules directory */
+		if (mkdir(path, S_IRWXU) != 0) {
+			ERR(sh, "Cannot make directory at %s", path);
+			status = -1;
+			goto cleanup;
+
+		}
+	}
+	else {
+		/* check that it really is a directory */
+		if (!S_ISDIR(sb.st_mode)) {
+			ERR(sh, "Directory path taken by non-directory file at %s.", path);
+			status = -1;
+			goto cleanup;
+		}
+	}
+
+cleanup:
+	return status;
+}
+
 /********************* sandbox management routines *********************/
 
 /* Creates a sandbox for a single client. Returns 0 if a
@@ -610,6 +864,69 @@ int semanage_make_sandbox(semanage_handle_t * sh)
 	return -1;
 }
 
+/* Create final temporary space. Returns -1 on error 0 on success. */
+int semanage_make_final(semanage_handle_t *sh)
+{
+	int status = 0;
+	int ret = 0;
+	char fn[PATH_MAX];
+
+	/* Create tmp dir if it does not exist. */
+	ret = snprintf(fn,
+		       sizeof(fn),
+		       "%s%s",
+		       semanage_root_path(),
+		       semanage_final_prefix[SEMANAGE_FINAL_TMP]);
+	if (ret < 0 || ret >= (int)sizeof(fn)) {
+		ERR(sh, "Unable to compose the final tmp path.");
+		status = -1;
+		goto cleanup;
+	}
+
+	ret = semanage_mkdir(sh, fn);
+	if (ret != 0) {
+		ERR(sh, "Unable to create temporary directory for final files at %s", fn);
+		status = -1;
+		goto cleanup;
+	}
+
+	/* Delete store specific dir if it exists. */
+	ret = semanage_remove_directory(
+		semanage_final_path(SEMANAGE_FINAL_TMP,
+				    SEMANAGE_FINAL_TOPLEVEL));
+	if (ret < -1) {
+		status = -1;
+		goto cleanup;
+	}
+
+	/* Copy dir format of selinux store in. */
+	ret = semanage_copy_dir_flags(
+		semanage_final_path(SEMANAGE_FINAL_SELINUX,
+				    SEMANAGE_FINAL_TOPLEVEL),
+		semanage_final_path(SEMANAGE_FINAL_TMP,
+				    SEMANAGE_FINAL_TOPLEVEL),
+		0);
+	if (ret != 0) {
+		status = -1;
+		goto cleanup;
+	}
+
+	/* Copy in exported databases.
+	 * i = 1 to avoid copying the top level directory.
+	 */
+	int i;
+	for (i = 1; i < SEMANAGE_FINAL_PATH_NUM; i++) {
+		semanage_copy_file(
+			semanage_final_path(SEMANAGE_FINAL_SELINUX, i),
+			semanage_final_path(SEMANAGE_FINAL_TMP, i),
+			sh->conf->file_mode);
+		/* ignore errors, these files may not exist */
+	}
+
+cleanup:
+	return status;
+}
+
 /* Scans the modules directory for the current semanage handler.  This
  * might be the active directory or sandbox, depending upon if the
  * handler has a transaction lock.  Allocates and fills in *filenames
@@ -978,16 +1295,16 @@ int semanage_split_fc(semanage_handle_t * sh)
 		goto cleanup;
 	}
 
-	fc = open(semanage_path(SEMANAGE_TMP, SEMANAGE_FC),
+	fc = open(semanage_final_path(SEMANAGE_FINAL_TMP, SEMANAGE_FC),
 		  O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
-	if (!fc) {
+	if (fc < 0) {
 		ERR(sh, "Could not open %s for writing.",
-		    semanage_path(SEMANAGE_TMP, SEMANAGE_FC));
+		    semanage_final_path(SEMANAGE_FINAL_TMP, SEMANAGE_FC));
 		goto cleanup;
 	}
 	hd = open(semanage_path(SEMANAGE_TMP, SEMANAGE_HOMEDIR_TMPL),
 		  O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
-	if (!hd) {
+	if (hd < 0) {
 		ERR(sh, "Could not open %s for writing.",
 		    semanage_path(SEMANAGE_TMP, SEMANAGE_HOMEDIR_TMPL));
 		goto cleanup;
@@ -1007,7 +1324,8 @@ int semanage_split_fc(semanage_handle_t * sh)
 		} else {
 			if (write(fc, buf, strlen(buf)) < 0) {
 				ERR(sh, "Write to %s failed.",
-				    semanage_path(SEMANAGE_TMP, SEMANAGE_FC));
+				    semanage_final_path(SEMANAGE_FINAL_TMP,
+							SEMANAGE_FC));
 				goto cleanup;
 			}
 		}
@@ -1026,118 +1344,53 @@ int semanage_split_fc(semanage_handle_t * sh)
 
 }
 
-/* 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)
+/* Load the contexts of the final tmp into the final selinux directory.
+ * Return 0 on success, -3 on error.
+ */
+static int semanage_install_final_tmp(semanage_handle_t * sh)
 {
-	int retval = -3, r, len;
-	char *storepath = NULL;
-	struct stat astore, istore;
-	const char *active_kernel =
-	    semanage_path(SEMANAGE_ACTIVE, SEMANAGE_KERNEL);
-	const char *active_fc = semanage_path(SEMANAGE_ACTIVE, SEMANAGE_FC);
-	const char *active_fc_loc =
-	    semanage_path(SEMANAGE_ACTIVE, SEMANAGE_FC_LOCAL);
-	const char *active_seusers =
-	    semanage_path(SEMANAGE_ACTIVE, SEMANAGE_SEUSERS);
-	const char *active_nc = semanage_path(SEMANAGE_ACTIVE, SEMANAGE_NC);
-	const char *active_fc_hd =
-	    semanage_path(SEMANAGE_ACTIVE, SEMANAGE_FC_HOMEDIRS);
-
-	const char *running_fc = selinux_file_context_path();
-	const char *running_fc_loc = selinux_file_context_local_path();
-	const char *running_fc_hd = selinux_file_context_homedir_path();
-	const char *running_hd = selinux_homedir_context_path();
-	const char *running_policy = selinux_binary_policy_path();
-	const char *running_seusers = selinux_usersconf_path();
-	const char *running_nc = selinux_netfilter_context_path();
-	const char *really_active_store = selinux_policy_root();
-
-	/* This is very unelegant, the right thing to do is export the path 
-	 * building code in libselinux so that you can get paths for a given 
-	 * POLICYTYPE and should probably be done in the future. */
-	char store_fc[PATH_MAX];
-	char store_fc_loc[PATH_MAX];
-	char store_pol[PATH_MAX];
-	char store_seusers[PATH_MAX];
-	char store_nc[PATH_MAX];
-	char store_fc_hd[PATH_MAX];
-
-	len = strlen(really_active_store);
-	running_fc += len;
-	running_fc_loc += len;
-	running_fc_hd += len;
-	running_hd += len;
-	running_policy += len;
-	running_seusers += len;
-	running_nc += len;
-
-	len = strlen(selinux_path()) + strlen(sh->conf->store_path) + 1;
-	storepath = (char *)malloc(len);
-	if (!storepath)
-		goto cleanup;
-	snprintf(storepath, PATH_MAX, "%s%s", selinux_path(),
-		 sh->conf->store_path);
-
-	snprintf(store_pol, PATH_MAX, "%s%s.%d", storepath,
-		 running_policy, sh->conf->policyvers);
-	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);
-		goto cleanup;
-	}
-
-	if (!sh->conf->disable_genhomedircon) {
-		snprintf(store_fc_hd, PATH_MAX, "%s%s", storepath, running_fc_hd);
-		if (semanage_copy_file(active_fc_hd, store_fc_hd, sh->conf->file_mode)
-			== -1) {
-			ERR(sh, "Could not copy %s to %s.", active_fc_hd, store_fc_hd);
-			goto cleanup;
-		}
-	}
+	int status = -3;
+	int ret = 0;
+	int i = 0;
+	const char *src = NULL;
+	const char *dst = NULL;
+	struct stat sb;
 
-	snprintf(store_fc, PATH_MAX, "%s%s", storepath, running_fc);
-	if (semanage_copy_file(active_fc, store_fc, sh->conf->file_mode) == -1) {
-		ERR(sh, "Could not copy %s to %s.", active_fc, store_fc);
-		goto cleanup;
-	}
+	/* For each of the final files install it if it exists.
+	 * i = 1 to avoid copying the top level directory.
+	 */
+	for (i = 1; i < SEMANAGE_FINAL_PATH_NUM; i++) {
+		src = semanage_final_path(SEMANAGE_FINAL_TMP, i);
+		dst = semanage_final_path(SEMANAGE_FINAL_SELINUX, i);
 
-	snprintf(store_fc_loc, PATH_MAX, "%s%s", storepath, running_fc_loc);
-	if (semanage_copy_file(active_fc_loc, store_fc_loc, sh->conf->file_mode)
-	    == -1 && errno != ENOENT) {
-		ERR(sh, "Could not copy %s to %s.", active_fc_loc,
-		    store_fc_loc);
-		goto cleanup;
-	}
-	errno = 0;
+		/* skip file if src doesn't exist */
+		if (stat(src, &sb) != 0) continue;
 
-	snprintf(store_seusers, PATH_MAX, "%s%s", storepath, running_seusers);
-	if (semanage_copy_file
-	    (active_seusers, store_seusers, sh->conf->file_mode) == -1
-	    && errno != ENOENT) {
-		ERR(sh, "Could not copy %s to %s.", active_seusers,
-		    store_seusers);
-		goto cleanup;
-	}
-	errno = 0;
+		/* skip genhomedircon if configured */
+		if (sh->conf->disable_genhomedircon &&
+		    i == SEMANAGE_FC_HOMEDIRS) continue;
 
-	snprintf(store_nc, PATH_MAX, "%s%s", storepath, running_nc);
-	if (semanage_copy_file(active_nc, store_nc, sh->conf->file_mode) == -1
-	    && errno != ENOENT) {
-		ERR(sh, "Could not copy %s to %s.", active_nc, store_nc);
-		goto cleanup;
+		ret = semanage_copy_file(src, dst, sh->conf->file_mode);
+		if (ret < 0) {
+			ERR(sh, "Could not copy %s to %s.", src, dst);
+			goto cleanup;
+		}
 	}
-	errno = 0;
 
 	if (!sh->do_reload)
 		goto skip_reload;
 
 	/* This stats what libselinux says the active store is (according to config)
 	 * and what we are installing to, to decide if they are the same store. If
-	 * they are not then we do not reload policy */
+	 * they are not then we do not reload policy.
+	 */
+	const char *really_active_store = selinux_policy_root();
+	struct stat astore;
+	struct stat istore;
+	const char *storepath = semanage_final_path(SEMANAGE_FINAL_SELINUX,
+						    SEMANAGE_FINAL_TOPLEVEL);
 
 	if (stat(really_active_store, &astore) == 0) {
-
 		if (stat(storepath, &istore)) {
 			ERR(sh, "Could not stat store path %s.", storepath);
 			goto cleanup;
@@ -1158,19 +1411,24 @@ static int semanage_install_active(semanage_handle_t * sh)
 		goto cleanup;
 	}
 
-      skip_reload:
-
-	if (sh->do_check_contexts && (r =
-	     semanage_exec_prog(sh, sh->conf->setfiles, store_pol,
-				store_fc)) != 0) {
-		ERR(sh, "setfiles returned error code %d.", r);
-		goto cleanup;
+skip_reload:
+	if (sh->do_check_contexts) {
+		ret = semanage_exec_prog(
+			sh,
+			sh->conf->setfiles,
+			semanage_final_path(SEMANAGE_FINAL_SELINUX,
+					    SEMANAGE_KERNEL),
+			semanage_final_path(SEMANAGE_FINAL_SELINUX,
+					    SEMANAGE_FC));
+		if (ret != 0) {
+			ERR(sh, "setfiles returned error code %d.", ret);
+			goto cleanup;
+		}
 	}
 
-	retval = 0;
-      cleanup:
-	free(storepath);
-	return retval;
+	status = 0;
+cleanup:
+	return status;
 }
 
 /* Prepare the sandbox to be installed by making a backup of the
@@ -1252,7 +1510,7 @@ static int semanage_commit_sandbox(semanage_handle_t * sh)
 		retval = -1;
 		goto cleanup;
 	}
-	if (semanage_install_active(sh) != 0) {
+	if (semanage_install_final_tmp(sh) != 0) {
 		/* note that if an error occurs during the next three
 		 * function then the store will be left in an
 		 * inconsistent state */
@@ -1264,7 +1522,7 @@ static int semanage_commit_sandbox(semanage_handle_t * sh)
 			ERR(sh, "Error while renaming %s back to %s.", backup,
 			    active);
 		else
-			semanage_install_active(sh);
+			semanage_install_final_tmp(sh);
 		errno = errsv;
 		retval = -1;
 		goto cleanup;
@@ -1721,7 +1979,8 @@ int semanage_read_policydb(semanage_handle_t * sh, sepol_policydb_t * in)
 	FILE *infile = NULL;
 
 	if ((kernel_filename =
-	     semanage_path(SEMANAGE_ACTIVE, SEMANAGE_KERNEL)) == NULL) {
+	     semanage_final_path(SEMANAGE_FINAL_SELINUX,
+				 SEMANAGE_KERNEL)) == NULL) {
 		goto cleanup;
 	}
 	if ((infile = fopen(kernel_filename, "r")) == NULL) {
@@ -1762,7 +2021,7 @@ int semanage_write_policydb(semanage_handle_t * sh, sepol_policydb_t * out)
 	FILE *outfile = NULL;
 
 	if ((kernel_filename =
-	     semanage_path(SEMANAGE_TMP, SEMANAGE_KERNEL)) == NULL) {
+	     semanage_final_path(SEMANAGE_FINAL_TMP, SEMANAGE_KERNEL)) == NULL) {
 		goto cleanup;
 	}
 	if ((outfile = fopen(kernel_filename, "wb")) == NULL) {
@@ -1847,7 +2106,7 @@ int semanage_verify_kernel(semanage_handle_t * sh)
 {
 	int retval = -1;
 	const char *kernel_filename =
-	    semanage_path(SEMANAGE_TMP, SEMANAGE_KERNEL);
+	    semanage_path(SEMANAGE_FINAL_TMP, SEMANAGE_KERNEL);
 	semanage_conf_t *conf = sh->conf;
 	external_prog_t *e;
 	if (conf->kernel_prog == NULL) {
diff --git a/libsemanage/src/semanage_store.h b/libsemanage/src/semanage_store.h
index c76ecfe..d3fd554 100644
--- a/libsemanage/src/semanage_store.h
+++ b/libsemanage/src/semanage_store.h
@@ -39,10 +39,8 @@ enum semanage_store_defs {
 enum semanage_sandbox_defs {
 	SEMANAGE_TOPLEVEL,
 	SEMANAGE_MODULES,
-	SEMANAGE_KERNEL,
 	SEMANAGE_BASE,
 	SEMANAGE_LINKED,
-	SEMANAGE_FC,
 	SEMANAGE_HOMEDIR_TMPL,
 	SEMANAGE_FC_TMPL,
 	SEMANAGE_COMMIT_NUM_FILE,
@@ -50,18 +48,32 @@ enum semanage_sandbox_defs {
 	SEMANAGE_INTERFACES_LOCAL,
 	SEMANAGE_NODES_LOCAL,
 	SEMANAGE_BOOLEANS_LOCAL,
-	SEMANAGE_FC_LOCAL,
 	SEMANAGE_SEUSERS_LOCAL,
 	SEMANAGE_USERS_BASE_LOCAL,
 	SEMANAGE_USERS_EXTRA_LOCAL,
-	SEMANAGE_SEUSERS,
 	SEMANAGE_USERS_EXTRA,
-	SEMANAGE_NC,
-	SEMANAGE_FC_HOMEDIRS,
 	SEMANAGE_DISABLE_DONTAUDIT,
+	SEMANAGE_MODULES_DISABLED,
 	SEMANAGE_STORE_NUM_PATHS
 };
 
+enum semanage_final_defs {
+	SEMANAGE_FINAL_TMP,
+	SEMANAGE_FINAL_SELINUX,
+	SEMANAGE_FINAL_NUM
+};
+
+enum semanage_final_path_defs {
+	SEMANAGE_FINAL_TOPLEVEL,
+	SEMANAGE_FC,
+	SEMANAGE_FC_HOMEDIRS,
+	SEMANAGE_FC_LOCAL,
+	SEMANAGE_KERNEL,
+	SEMANAGE_NC,
+	SEMANAGE_SEUSERS,
+	SEMANAGE_FINAL_PATH_NUM
+};
+
 const char *semanage_root_path(void);
 
 /* FIXME: this needs to be made a module store specific init and the
@@ -76,14 +88,21 @@ extern const char *semanage_fname(enum semanage_sandbox_defs file_enum);
 extern const char *semanage_path(enum semanage_store_defs store,
 				 enum semanage_sandbox_defs file);
 
+extern const char *semanage_final_path(enum semanage_final_defs root,
+				       enum semanage_final_path_defs suffix);
+
 int semanage_create_store(semanage_handle_t * sh, int create);
 
 int semanage_store_access_check(semanage_handle_t * sh);
 
 int semanage_remove_directory(const char *path);
 
+int semanage_mkdir(semanage_handle_t *sh, const char *path);
+
 int semanage_make_sandbox(semanage_handle_t * sh);
 
+int semanage_make_final(semanage_handle_t * sh);
+
 int semanage_get_modules_names(semanage_handle_t * sh,
 			       char ***filenames, int *len);
 
diff --git a/libsemanage/src/seuser_internal.h b/libsemanage/src/seuser_internal.h
index e6f2972..bf9cab0 100644
--- a/libsemanage/src/seuser_internal.h
+++ b/libsemanage/src/seuser_internal.h
@@ -30,7 +30,9 @@ hidden_proto(semanage_seuser_clone)
 extern record_table_t SEMANAGE_SEUSER_RTABLE;
 
 extern int seuser_file_dbase_init(semanage_handle_t * handle,
-				  const char *fname, dbase_config_t * dconfig);
+				  const char *path_ro,
+				  const char *path_rw,
+				  dbase_config_t * dconfig);
 
 extern void seuser_file_dbase_release(dbase_config_t * dconfig);
 
diff --git a/libsemanage/src/seusers_file.c b/libsemanage/src/seusers_file.c
index b5c8075..910bedf 100644
--- a/libsemanage/src/seusers_file.c
+++ b/libsemanage/src/seusers_file.c
@@ -115,11 +115,14 @@ record_file_table_t SEMANAGE_SEUSER_FILE_RTABLE = {
 };
 
 int seuser_file_dbase_init(semanage_handle_t * handle,
-			   const char *fname, dbase_config_t * dconfig)
+			   const char *path_ro,
+			   const char *path_rw,
+			   dbase_config_t * dconfig)
 {
 
 	if (dbase_file_init(handle,
-			    fname,
+			    path_ro,
+			    path_rw,
 			    &SEMANAGE_SEUSER_RTABLE,
 			    &SEMANAGE_SEUSER_FILE_RTABLE, &dconfig->dbase) < 0)
 		return STATUS_ERR;
diff --git a/libsemanage/src/user_internal.h b/libsemanage/src/user_internal.h
index 5c86418..ce1ac31 100644
--- a/libsemanage/src/user_internal.h
+++ b/libsemanage/src/user_internal.h
@@ -41,14 +41,16 @@ extern record_table_t SEMANAGE_USER_EXTRA_RTABLE;
 
 /* USER BASE record, FILE backend */
 extern int user_base_file_dbase_init(semanage_handle_t * handle,
-				     const char *fname,
+				     const char *path_ro,
+				     const char *path_rw,
 				     dbase_config_t * dconfig);
 
 extern void user_base_file_dbase_release(dbase_config_t * dconfig);
 
 /* USER EXTRA record, FILE backend */
 extern int user_extra_file_dbase_init(semanage_handle_t * handle,
-				      const char *fname,
+				      const char *path_ro,
+				      const char *path_rw,
 				      dbase_config_t * dconfig);
 
 extern void user_extra_file_dbase_release(dbase_config_t * dconfig);
diff --git a/libsemanage/src/users_base_file.c b/libsemanage/src/users_base_file.c
index affde51..0f0a8fd 100644
--- a/libsemanage/src/users_base_file.c
+++ b/libsemanage/src/users_base_file.c
@@ -202,11 +202,14 @@ record_file_table_t SEMANAGE_USER_BASE_FILE_RTABLE = {
 };
 
 int user_base_file_dbase_init(semanage_handle_t * handle,
-			      const char *fname, dbase_config_t * dconfig)
+			      const char *path_ro,
+			      const char *path_rw,
+			      dbase_config_t * dconfig)
 {
 
 	if (dbase_file_init(handle,
-			    fname,
+			    path_ro,
+			    path_rw,
 			    &SEMANAGE_USER_BASE_RTABLE,
 			    &SEMANAGE_USER_BASE_FILE_RTABLE,
 			    &dconfig->dbase) < 0)
diff --git a/libsemanage/src/users_base_policydb.c b/libsemanage/src/users_base_policydb.c
index 6bf6bb0..0a6ab9c 100644
--- a/libsemanage/src/users_base_policydb.c
+++ b/libsemanage/src/users_base_policydb.c
@@ -32,6 +32,7 @@ typedef struct dbase_policydb dbase_t;
 #include "user_internal.h"
 #include "debug.h"
 #include "database_policydb.h"
+#include "semanage_store.h"
 
 /* USER BASE record: POLICYDB extension: method table */
 record_policydb_table_t SEMANAGE_USER_BASE_POLICYDB_RTABLE = {
@@ -49,7 +50,10 @@ int user_base_policydb_dbase_init(semanage_handle_t * handle,
 {
 
 	if (dbase_policydb_init(handle,
-				"policy.kern",
+				semanage_final_path(SEMANAGE_FINAL_SELINUX,
+						    SEMANAGE_KERNEL),
+				semanage_final_path(SEMANAGE_FINAL_TMP,
+						    SEMANAGE_KERNEL),
 				&SEMANAGE_USER_BASE_RTABLE,
 				&SEMANAGE_USER_BASE_POLICYDB_RTABLE,
 				&dconfig->dbase) < 0)
diff --git a/libsemanage/src/users_extra_file.c b/libsemanage/src/users_extra_file.c
index 5f7eb1a..8f2bebd 100644
--- a/libsemanage/src/users_extra_file.c
+++ b/libsemanage/src/users_extra_file.c
@@ -106,11 +106,14 @@ record_file_table_t SEMANAGE_USER_EXTRA_FILE_RTABLE = {
 };
 
 int user_extra_file_dbase_init(semanage_handle_t * handle,
-			       const char *fname, dbase_config_t * dconfig)
+			       const char *path_ro,
+			       const char *path_rw,
+			       dbase_config_t * dconfig)
 {
 
 	if (dbase_file_init(handle,
-			    fname,
+			    path_ro,
+			    path_rw,
 			    &SEMANAGE_USER_EXTRA_RTABLE,
 			    &SEMANAGE_USER_EXTRA_FILE_RTABLE,
 			    &dconfig->dbase) < 0)
-- 
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@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

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

* [PATCH 05/13] libsemanage: update unit tests for move to /var/lib/selinux
  2009-12-23 23:25       ` [PATCH 04/13] libsemanage: split final files into /var/lib/selinux/tmp Caleb Case
@ 2009-12-23 23:25         ` Caleb Case
  2009-12-23 23:25           ` [PATCH 06/13] libsemanage: add default priority to semanage_handle_t Caleb Case
  2010-01-08 14:30         ` [PATCH 04/13] libsemanage: split final files into /var/lib/selinux/tmp Stephen Smalley
  1 sibling, 1 reply; 39+ messages in thread
From: Caleb Case @ 2009-12-23 23:25 UTC (permalink / raw)
  To: selinux; +Cc: csellers, kmacmillan, jwcart2, jbrindle, sds, Caleb Case

This updates the unit tests to accommodate the change in layout (no top
level 'modules' directory).
---
 libsemanage/tests/test_semanage_store.c |   34 +++++++++++++++---------------
 1 files changed, 17 insertions(+), 17 deletions(-)

diff --git a/libsemanage/tests/test_semanage_store.c b/libsemanage/tests/test_semanage_store.c
index e6814e8..2fa94b4 100644
--- a/libsemanage/tests/test_semanage_store.c
+++ b/libsemanage/tests/test_semanage_store.c
@@ -44,12 +44,12 @@
 #include <CUnit/Basic.h>
 
 semanage_handle_t *sh = NULL;
-const char *polpath = "./test-policy";
-const char *lockpath = "./test-policy/modules";
-const char *readlockpath = "./test-policy/modules/semanage.read.LOCK";
-const char *translockpath = "./test-policy/modules/semanage.trans.LOCK";
-const char *actpath = "./test-policy/modules/active";
-const char *modpath = "./test-policy/modules/active/modules";
+const char *rootpath = "./test-policy";
+const char *polpath = "./test-policy/store/";
+const char *readlockpath = "./test-policy/store/semanage.read.LOCK";
+const char *translockpath = "./test-policy/store/semanage.trans.LOCK";
+const char *actpath = "./test-policy/store/active";
+const char *modpath = "./test-policy/store/active/modules";
 
 /* The suite initialization function.
  * Returns zero on success, non-zero otherwise.
@@ -59,11 +59,11 @@ int semanage_store_test_init(void)
 	int err;
 
 	/* create directories */
-	err = mkdir(polpath, S_IRUSR | S_IWUSR | S_IXUSR);
+	err = mkdir(rootpath, S_IRUSR | S_IWUSR | S_IXUSR);
 	if (err != 0)
 		return -1;
 
-	err = mkdir(lockpath, S_IRUSR | S_IWUSR | S_IXUSR);
+	err = mkdir(polpath, S_IRUSR | S_IWUSR | S_IXUSR);
 	if (err != 0)
 		return -1;
 
@@ -83,8 +83,12 @@ int semanage_store_test_init(void)
 	/* hide error messages */
 	sh->msg_callback = test_msg_handler;
 
+	/* use our own policy store */
+	free(sh->conf->store_path);
+	sh->conf->store_path = strdup("store");
+
 	/* initialize paths */
-	err = semanage_check_init(polpath);
+	err = semanage_check_init(sh, rootpath);
 	if (err != 0)
 		return -1;
 
@@ -107,11 +111,11 @@ int semanage_store_test_cleanup(void)
 	if (err != 0)
 		return -1;
 
-	err = rmdir(lockpath);
+	err = rmdir(polpath);
 	if (err != 0)
 		return -1;
 
-	err = rmdir(polpath);
+	err = rmdir(rootpath);
 	if (err != 0)
 		return -1;
 
@@ -217,8 +221,6 @@ void test_semanage_store_access_check(void)
 	/* check with no lock file and 000 */
 	err = chmod(modpath, 0);
 	CU_ASSERT(err == 0);
-	err = chmod(lockpath, 0);
-	CU_ASSERT(err == 0);
 	err = chmod(polpath, 0);
 	CU_ASSERT(err == 0);
 
@@ -228,16 +230,14 @@ void test_semanage_store_access_check(void)
 	/* check with no lock file and 500 */
 	err = chmod(polpath, S_IRUSR | S_IXUSR);
 	CU_ASSERT(err == 0);
-	err = chmod(lockpath, S_IRUSR | S_IXUSR);
-	CU_ASSERT(err == 0);
 	err = chmod(modpath, S_IRUSR | S_IXUSR);
 	CU_ASSERT(err == 0);
 
 	err = semanage_store_access_check(sh);
 	CU_ASSERT(err == 0);
 
-	/* check with no lock file but write in lockpath */
-	err = chmod(lockpath, S_IRUSR | S_IWUSR | S_IXUSR);
+	/* check with no lock file but write in polpath */
+	err = chmod(polpath, S_IRUSR | S_IWUSR | S_IXUSR);
 	CU_ASSERT(err == 0);
 
 	err = semanage_store_access_check(sh);
-- 
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@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

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

* [PATCH 06/13] libsemanage: add default priority to semanage_handle_t
  2009-12-23 23:25         ` [PATCH 05/13] libsemanage: update unit tests for move to /var/lib/selinux Caleb Case
@ 2009-12-23 23:25           ` Caleb Case
  2009-12-23 23:25             ` [PATCH 07/13] libsemanage: augment semanage_module_info_t and provide semanage_module_key_t Caleb Case
  0 siblings, 1 reply; 39+ messages in thread
From: Caleb Case @ 2009-12-23 23:25 UTC (permalink / raw)
  To: selinux; +Cc: csellers, kmacmillan, jwcart2, jbrindle, sds, Caleb Case

For backwards compatiblity purposes we need to provide a default
priority that the current set of module install/upgrade/remove functions
can use.

The default priority is 400.

Adds semanage_module_validate_priority so that it can be used to verify
the given priority. See next patch for other validation functions.
---
 libsemanage/src/handle.c  |   23 +++++++++++++++++++++++
 libsemanage/src/handle.h  |    3 +++
 libsemanage/src/modules.c |   17 +++++++++++++++++
 libsemanage/src/modules.h |    4 ++++
 4 files changed, 47 insertions(+), 0 deletions(-)

diff --git a/libsemanage/src/handle.c b/libsemanage/src/handle.c
index 76caefd..8300cae 100644
--- a/libsemanage/src/handle.c
+++ b/libsemanage/src/handle.c
@@ -59,6 +59,9 @@ semanage_handle_t *semanage_handle_create(void)
 		goto err;
 	sepol_msg_set_callback(sh->sepolh, semanage_msg_relay_handler, sh);
 
+	/* Default priority is 400 */
+	sh->priority = 400;
+
 	/* By default do not rebuild the policy on commit
 	 * If any changes are made, this flag is ignored */
 	sh->do_rebuild = 0;
@@ -137,6 +140,26 @@ void semanage_set_check_contexts(semanage_handle_t * sh, int do_check_contexts)
 	return;
 }
 
+uint16_t semanage_get_default_priority(semanage_handle_t *sh)
+{
+	assert(sh != NULL);
+	return sh->priority;
+}
+
+int semanage_set_default_priority(semanage_handle_t *sh, uint16_t priority)
+{
+	assert(sh != NULL);
+
+	/* Verify priority */
+	if (semanage_module_validate_priority(priority) < 0) {
+		ERR(sh, "Priority %d is invalid.", priority);
+		return -1;
+	}
+
+	sh->priority = priority;
+	return 0;
+}
+
 int semanage_is_connected(semanage_handle_t * sh)
 {
 	assert(sh != NULL);
diff --git a/libsemanage/src/handle.h b/libsemanage/src/handle.h
index 723d811..64175c4 100644
--- a/libsemanage/src/handle.h
+++ b/libsemanage/src/handle.h
@@ -23,6 +23,7 @@
 #ifndef _SEMANAGE_INTERNAL_HANDLE_H_
 #define _SEMANAGE_INTERNAL_HANDLE_H_
 
+#include <stdint.h>
 #include <stddef.h>
 #include "handle_internal.h"
 #include <sepol/handle.h>
@@ -55,6 +56,8 @@ struct semanage_handle {
 	sepol_handle_t *sepolh;
 
 	semanage_conf_t *conf;
+
+	uint16_t priority;
 	int is_connected;
 	int is_in_transaction;
 	int do_reload;		/* whether to reload policy after commit */
diff --git a/libsemanage/src/modules.c b/libsemanage/src/modules.c
index d99ee5b..c7ae301 100644
--- a/libsemanage/src/modules.c
+++ b/libsemanage/src/modules.c
@@ -215,3 +215,20 @@ const char *semanage_module_get_version(semanage_module_info_t * modinfo)
 }
 
 hidden_def(semanage_module_get_version)
+
+#define PRIORITY_MIN 1
+#define PRIORITY_MAX 999
+
+/* Validates priority.
+ *
+ * returns -1 if priority is not in the valid range, returns 0 otherwise
+ */
+int semanage_module_validate_priority(uint16_t priority)
+{
+	if (priority >= PRIORITY_MIN && priority <= PRIORITY_MAX) {
+		return 0;
+	}
+
+	return -1;
+}
+
diff --git a/libsemanage/src/modules.h b/libsemanage/src/modules.h
index 381b108..cac567b 100644
--- a/libsemanage/src/modules.h
+++ b/libsemanage/src/modules.h
@@ -21,6 +21,8 @@
 #ifndef _SEMANAGE_INTERNAL_MODULES_H_
 #define _SEMANAGE_INTERNAL_MODULES_H_
 
+#include <stdint.h>
+
 #include "module_internal.h"
 
 struct semanage_module_info {
@@ -28,4 +30,6 @@ struct semanage_module_info {
 	char *version;
 };
 
+int semanage_module_validate_priority(uint16_t priority);
+
 #endif
-- 
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@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

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

* [PATCH 07/13] libsemanage: augment semanage_module_info_t and provide semanage_module_key_t
  2009-12-23 23:25           ` [PATCH 06/13] libsemanage: add default priority to semanage_handle_t Caleb Case
@ 2009-12-23 23:25             ` Caleb Case
  2009-12-23 23:25               ` [PATCH 08/13] libsemanage: get/set module info and enabled status Caleb Case
  0 siblings, 1 reply; 39+ messages in thread
From: Caleb Case @ 2009-12-23 23:25 UTC (permalink / raw)
  To: selinux; +Cc: csellers, kmacmillan, jwcart2, jbrindle, sds, Caleb Case

Adds priority, language ext, and enabled fields to
semanage_module_info_t.

Adds get/set functions for all semanage_module_info_t/key_t fields. This
is necessary so that semanage_module_info_t/key_t can be used in the
specifing meta data on source policies.

Adds create, destroy, and init functions for semanage_module_info_t and
semanage_module_key_t. Create initializes and allocates, destroy
deallocates fields (but not struct), and init initializes fields.

Provide several utility functions for converting a string priority to a
uint16_t and validating fields.

Adds semanage_module_get_path for getting module specific file paths.
---
 libsemanage/src/modules.c |  798 ++++++++++++++++++++++++++++++++++++++++++++-
 libsemanage/src/modules.h |  229 +++++++++++++-
 2 files changed, 1023 insertions(+), 4 deletions(-)

diff --git a/libsemanage/src/modules.c b/libsemanage/src/modules.c
index c7ae301..df0f15c 100644
--- a/libsemanage/src/modules.c
+++ b/libsemanage/src/modules.c
@@ -1,7 +1,8 @@
 /* Author: Joshua Brindle <jbrindle@tresys.co
  *	   Jason Tang	  <jtang@tresys.com>
+ *	   Caleb Case	  <ccase@tresys.com>
  *
- * Copyright (C) 2004-2005 Tresys Technology, LLC
+ * Copyright (C) 2004-2005,2009 Tresys Technology, LLC
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Lesser General Public
@@ -28,6 +29,13 @@
 #include <assert.h>
 #include <stdlib.h>
 #include <stdio.h>
+#include <string.h>
+#include <limits.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <ctype.h>
 
 #include "handle.h"
 #include "modules.h"
@@ -187,8 +195,18 @@ int semanage_module_list(semanage_handle_t * sh,
 void semanage_module_info_datum_destroy(semanage_module_info_t * modinfo)
 {
 	if (modinfo != NULL) {
+		modinfo->priority = 0;
+
 		free(modinfo->name);
+		modinfo->name = NULL;
+
 		free(modinfo->version);
+		modinfo->version = NULL;
+
+		free(modinfo->lang_ext);
+		modinfo->lang_ext = NULL;
+
+		modinfo->enabled = -1;
 	}
 }
 
@@ -216,6 +234,642 @@ const char *semanage_module_get_version(semanage_module_info_t * modinfo)
 
 hidden_def(semanage_module_get_version)
 
+int semanage_module_info_create(semanage_handle_t *sh,
+				semanage_module_info_t **modinfo)
+{
+	assert(sh);
+	assert(modinfo);
+
+	*modinfo = malloc(sizeof(semanage_module_info_t));
+	if (*modinfo == NULL) return -1;
+
+	return semanage_module_info_init(sh, *modinfo);
+}
+
+int semanage_module_info_destroy(semanage_handle_t *sh,
+				 semanage_module_info_t *modinfo)
+{
+	assert(sh);
+
+	if (!modinfo) {
+		return 0;
+	}
+
+	free(modinfo->name);
+	free(modinfo->version);
+	free(modinfo->lang_ext);
+
+	return semanage_module_info_init(sh, modinfo);
+}
+
+int semanage_module_info_init(semanage_handle_t *sh,
+			      semanage_module_info_t *modinfo)
+{
+	assert(sh);
+	assert(modinfo);
+
+	modinfo->priority = 0;
+	modinfo->name = NULL;
+	modinfo->version = NULL;
+	modinfo->lang_ext = NULL;
+	modinfo->enabled = -1;
+
+	return 0;
+}
+
+int semanage_module_info_clone(semanage_handle_t *sh,
+			       const semanage_module_info_t *source,
+			       semanage_module_info_t *target)
+{
+	assert(sh);
+	assert(source);
+	assert(target);
+
+	int status = 0;
+	int ret = 0;
+
+	ret = semanage_module_info_destroy(sh, target);
+	if (ret != 0) {
+		status = -1;
+		goto cleanup;
+	}
+
+	ret = semanage_module_info_set_priority(sh, target, source->priority);
+	if (ret != 0) {
+		status = -1;
+		goto cleanup;
+	}
+
+	ret = semanage_module_info_set_name(sh, target, source->name);
+	if (ret != 0) {
+		status = -1;
+		goto cleanup;
+	}
+
+	ret = semanage_module_info_set_version(sh, target, source->version);
+	if (ret != 0) {
+		status = -1;
+		goto cleanup;
+	}
+
+	ret = semanage_module_info_set_lang_ext(sh, target, source->lang_ext);
+	if (ret != 0) {
+		status = -1;
+		goto cleanup;
+	}
+
+	ret = semanage_module_info_set_enabled(sh, target, source->enabled);
+	if (ret != 0) {
+		status = -1;
+		goto cleanup;
+	}
+
+cleanup:
+	if (status != 0) semanage_module_info_destroy(sh, target);
+	return status;
+}
+
+int semanage_module_info_get_priority(semanage_handle_t *sh,
+				      semanage_module_info_t *modinfo,
+				      uint16_t *priority)
+{
+	assert(sh);
+	assert(modinfo);
+	assert(priority);
+
+	*priority = modinfo->priority;
+
+	return 0;
+}
+
+int semanage_module_info_get_name(semanage_handle_t *sh,
+				  semanage_module_info_t *modinfo,
+				  const char **name)
+{
+	assert(sh);
+	assert(modinfo);
+	assert(name);
+
+	*name = modinfo->name;
+
+	return 0;
+}
+
+int semanage_module_info_get_version(semanage_handle_t *sh,
+				     semanage_module_info_t *modinfo,
+				     const char **version)
+{
+	assert(sh);
+	assert(modinfo);
+	assert(version);
+
+	*version = modinfo->version;
+
+	return 0;
+}
+
+int semanage_module_info_get_lang_ext(semanage_handle_t *sh,
+				      semanage_module_info_t *modinfo,
+				      const char **lang_ext)
+{
+	assert(sh);
+	assert(modinfo);
+	assert(lang_ext);
+
+	*lang_ext = modinfo->lang_ext;
+
+	return 0;
+}
+
+int semanage_module_info_get_enabled(semanage_handle_t *sh,
+				     semanage_module_info_t *modinfo,
+				     int *enabled)
+{
+	assert(sh);
+	assert(modinfo);
+	assert(enabled);
+
+	*enabled = modinfo->enabled;
+
+	return 0;
+}
+
+int semanage_module_info_set_priority(semanage_handle_t *sh,
+				      semanage_module_info_t *modinfo,
+				      uint16_t priority)
+{
+	assert(sh);
+	assert(modinfo);
+
+	/* Verify priority */
+	if (semanage_module_validate_priority(priority) < 0) {
+		errno = 0;
+		ERR(sh, "Priority %d is invalid.", priority);
+		return -1;
+	}
+
+	modinfo->priority = priority;
+
+	return 0;
+}
+
+int semanage_module_info_set_name(semanage_handle_t *sh,
+				  semanage_module_info_t *modinfo,
+				  const char *name)
+{
+	assert(sh);
+	assert(modinfo);
+	assert(name);
+
+	char * tmp;
+
+	/* Verify name */
+	if (semanage_module_validate_name(name) < 0) {
+		errno = 0;
+		ERR(sh, "Name %s is invalid.", name);
+		return -1;
+	}
+
+	tmp = strdup(name);
+	if (!tmp) {
+		return -1;
+	}
+
+	free(modinfo->name);
+	modinfo->name = tmp;
+
+	return 0;
+}
+
+int semanage_module_info_set_version(semanage_handle_t *sh,
+				     semanage_module_info_t *modinfo,
+				     const char *version)
+{
+	assert(sh);
+	assert(modinfo);
+	assert(version);
+
+	char * tmp;
+
+	/* Verify version */
+	if (semanage_module_validate_version(version) < 0) {
+		errno = 0;
+		ERR(sh, "Version %s is invalid.", version);
+		return -1;
+	}
+
+	tmp = strdup(version);
+	if (!tmp) {
+		return -1;
+	}
+
+	free(modinfo->version);
+	modinfo->version = tmp;
+
+	return 0;
+}
+
+int semanage_module_info_set_lang_ext(semanage_handle_t *sh,
+				      semanage_module_info_t *modinfo,
+				      const char *lang_ext)
+{
+	assert(sh);
+	assert(modinfo);
+	assert(lang_ext);
+
+	char * tmp;
+
+	/* Verify extension */
+	if (semanage_module_validate_lang_ext(lang_ext) < 0) {
+		errno = 0;
+		ERR(sh, "Language extensions %s is invalid.", lang_ext);
+		return -1;
+	}
+
+	tmp = strdup(lang_ext);
+	if (!tmp) {
+		return -1;
+	}
+
+	free(modinfo->lang_ext);
+	modinfo->lang_ext = tmp;
+
+	return 0;
+}
+
+int semanage_module_info_set_enabled(semanage_handle_t *sh,
+				     semanage_module_info_t *modinfo,
+				     int enabled)
+{
+	assert(sh);
+	assert(modinfo);
+
+	/* Verify enabled */
+	if (semanage_module_validate_enabled(enabled) < 0) {
+		errno = 0;
+		ERR(sh, "Enabled status %d is invalid.", enabled);
+		return -1;
+	}
+
+	modinfo->enabled = enabled;
+
+	return 0;
+}
+
+int semanage_module_get_path(semanage_handle_t *sh,
+			     const semanage_module_info_t *modinfo,
+			     enum semanage_module_path_type type,
+			     char *path,
+			     size_t len)
+{
+	assert(sh);
+	assert(modinfo);
+	assert(path);
+
+	int status = 0;
+	int ret = 0;
+
+	const char *modules_path = NULL;
+	const char *file = NULL;
+
+	modules_path = sh->is_in_transaction ?
+		semanage_path(SEMANAGE_TMP, SEMANAGE_MODULES):
+		semanage_path(SEMANAGE_ACTIVE, SEMANAGE_MODULES);
+
+	switch (type) {
+		case SEMANAGE_MODULE_PATH_PRIORITY:
+			/* verify priority */
+			ret = semanage_module_validate_priority(modinfo->priority);
+			if (ret < 0) {
+				errno = 0;
+				ERR(sh,
+				    "Priority %d is invalid.",
+				    modinfo->priority);
+				status = ret;
+				goto cleanup;
+			}
+
+			ret = snprintf(path,
+				       len,
+				       "%s/%03u",
+				       modules_path,
+				       modinfo->priority);
+			if (ret < 0 || (size_t)ret >= len) {
+				ERR(sh, "Unable to compose priority path.");
+				status = -1;
+				goto cleanup;
+			}
+			break;
+		case SEMANAGE_MODULE_PATH_NAME:
+			/* verify priority and name */
+			ret = semanage_module_validate_priority(modinfo->priority);
+			if (ret < 0) {
+				errno = 0;
+				ERR(sh,
+				    "Priority %d is invalid.",
+				    modinfo->priority);
+				status = -1;
+				goto cleanup;
+			}
+
+			ret = semanage_module_validate_name(modinfo->name);
+			if (ret < 0) {
+				errno = 0;
+				ERR(sh, "Name %s is invalid.", modinfo->name);
+				status = -1;
+				goto cleanup;
+			}
+
+			ret = snprintf(path,
+				       len,
+				       "%s/%03u/%s",
+				       modules_path,
+				       modinfo->priority,
+				       modinfo->name);
+			if (ret < 0 || (size_t)ret >= len) {
+				ERR(sh, "Unable to compose name path.");
+				status = -1;
+				goto cleanup;
+			}
+			break;
+		case SEMANAGE_MODULE_PATH_HLL:
+			/* verify priority, name, and ext */
+			ret = semanage_module_validate_lang_ext(modinfo->lang_ext);
+			if (ret < 0) {
+				errno = 0;
+				ERR(sh,
+				    "Language extensions %s is invalid.",
+				    modinfo->lang_ext);
+				status = -1;
+				goto cleanup;
+			}
+
+			ret = semanage_module_validate_priority(modinfo->priority);
+			if (ret < 0) {
+				errno = 0;
+				ERR(sh,
+				    "Priority %d is invalid.",
+				    modinfo->priority);
+				status = -1;
+				goto cleanup;
+			}
+
+			ret = semanage_module_validate_name(modinfo->name);
+			if (ret < 0) {
+				errno = 0;
+				ERR(sh, "Name %s is invalid.", modinfo->name);
+				status = -1;
+				goto cleanup;
+			}
+
+			ret = snprintf(path,
+				       len,
+				       "%s/%03u/%s/%s.%s",
+				       modules_path,
+				       modinfo->priority,
+				       modinfo->name,
+				       modinfo->name,
+				       modinfo->lang_ext);
+			if (ret < 0 || (size_t)ret >= len) {
+				ERR(sh, "Unable to compose hll path.");
+				status = -1;
+				goto cleanup;
+			}
+			break;
+		case SEMANAGE_MODULE_PATH_CIL:
+			if (file == NULL) file = "cil";
+		case SEMANAGE_MODULE_PATH_LANG_EXT:
+			if (file == NULL) file = "lang_ext";
+		case SEMANAGE_MODULE_PATH_VERSION:
+			if (file == NULL) file = "version";
+
+			/* verify priority and name */
+			ret = semanage_module_validate_priority(modinfo->priority);
+			if (ret < 0) {
+				errno = 0;
+				ERR(sh,
+				    "Priority %d is invalid.",
+				    modinfo->priority);
+				status = -1;
+				goto cleanup;
+			}
+
+			ret = semanage_module_validate_name(modinfo->name);
+			if (ret < 0) {
+				errno = 0;
+				ERR(sh, "Name %s is invalid.", modinfo->name);
+				status = -1;
+				goto cleanup;
+			}
+
+			ret = snprintf(path,
+				       len,
+				       "%s/%03u/%s/%s",
+				       modules_path,
+				       modinfo->priority,
+				       modinfo->name,
+				       file);
+			if (ret < 0 || (size_t)ret >= len) {
+				ERR(sh,
+				    "Unable to compose path for %s file.",
+				    file);
+				status = -1;
+				goto cleanup;
+			}
+			break;
+		case SEMANAGE_MODULE_PATH_DISABLED:
+			/* verify name */
+			ret = semanage_module_validate_name(modinfo->name);
+			if (ret < 0) {
+				errno = 0;
+				ERR(sh, "Name %s is invalid.", modinfo->name);
+				status = -1;
+				goto cleanup;
+			}
+
+			ret = snprintf(path,
+				       len,
+				       "%s/disabled/%s",
+				       modules_path,
+				       modinfo->name);
+			if (ret < 0 || (size_t)ret >= len) {
+				ERR(sh,
+				    "Unable to compose disabled status path.");
+				status = -1;
+				goto cleanup;
+			}
+			break;
+		default:
+			ERR(sh, "Invalid module path type %d.", type);
+			status = -1;
+			goto cleanup;
+	}
+
+cleanup:
+	return status;
+}
+
+int semanage_module_key_create(semanage_handle_t *sh,
+			       semanage_module_key_t **modkey)
+{
+	assert(sh);
+	assert(modkey);
+
+	*modkey = malloc(sizeof(semanage_module_key_t));
+	if (*modkey == NULL) return -1;
+
+	return semanage_module_key_init(sh, *modkey);
+}
+
+int semanage_module_key_destroy(semanage_handle_t *sh,
+				semanage_module_key_t *modkey)
+{
+	assert(sh);
+
+	if (modkey) {
+		free(modkey->name);
+	}
+
+	return semanage_module_key_init(sh, modkey);
+}
+
+int semanage_module_key_init(semanage_handle_t *sh,
+			     semanage_module_key_t *modkey)
+{
+	assert(sh);
+	assert(modkey);
+
+	modkey->name = NULL;
+	modkey->priority = 0;
+
+	return 0;
+}
+
+int semanage_module_key_get_name(semanage_handle_t *sh,
+				 semanage_module_key_t *modkey,
+				 const char **name)
+{
+	assert(sh);
+	assert(modkey);
+	assert(name);
+
+	*name = modkey->name;
+
+	return 0;
+}
+
+int semanage_module_key_get_priority(semanage_handle_t *sh,
+				     semanage_module_key_t *modkey,
+				     uint16_t *priority)
+{
+	assert(sh);
+	assert(modkey);
+	assert(priority);
+
+	*priority = modkey->priority;
+
+	return 0;
+}
+
+int semanage_module_key_set_name(semanage_handle_t *sh,
+				 semanage_module_key_t *modkey,
+				 const char *name)
+{
+	assert(sh);
+	assert(modkey);
+	assert(name);
+
+	int status = 0;
+	char *tmp = NULL;
+
+	if (semanage_module_validate_name(name) < 0) {
+		errno = 0;
+		ERR(sh, "Name %s is invalid.", name);
+		return -1;
+	}
+
+	tmp = strdup(name);
+	if (tmp == NULL) {
+		status = -1;
+		goto cleanup;
+	}
+
+	free(modkey->name);
+	modkey->name = tmp;
+
+cleanup:
+	return status;
+}
+
+int semanage_module_key_set_priority(semanage_handle_t *sh,
+				     semanage_module_key_t *modkey,
+				     uint16_t priority)
+{
+	assert(sh);
+	assert(modkey);
+
+	if (semanage_module_validate_priority(priority) < 0) {
+		errno = 0;
+		ERR(sh, "Priority %d is invalid.", priority);
+		return -1;
+	}
+
+	modkey->priority = priority;
+
+	return 0;
+}
+
+
+/* Converts a string to a priority
+ *
+ * returns -1 if str is not a valid priority.
+ * returns 0 and sets priority if str is a valid priority
+ */
+int semanage_string_to_priority(const char *str, uint16_t *priority)
+{
+	unsigned long val;
+	char *endptr = NULL;
+	int status = -1;
+
+	if (str == NULL || priority == NULL) {
+		goto exit;
+	}
+
+	errno = 0;
+
+	val = strtoul(str, &endptr, 10);
+
+	if (errno != 0 || endptr == str || *endptr != '\0' || val > UINT16_MAX) {
+		goto exit;
+	}
+
+	if (semanage_module_validate_priority((uint16_t)val) < 0) {
+		goto exit;
+	}
+
+	*priority = val;
+	status = 0;
+
+exit:
+	return status;
+}
+
+/* Validates a module info struct.
+ *
+ * Returns -1 if module is invalid, 0 otherwise.
+ */
+int semanage_module_info_validate(const semanage_module_info_t *modinfo)
+{
+	if (semanage_module_validate_priority(modinfo->priority) != 0 ||
+	    semanage_module_validate_name(modinfo->name) != 0 ||
+	    semanage_module_validate_version(modinfo->version) != 0 ||
+	    semanage_module_validate_lang_ext(modinfo->lang_ext) != 0 ||
+	    semanage_module_validate_enabled(modinfo->enabled) != 0) {
+		return -1;
+	}
+	return 0;
+}
+
 #define PRIORITY_MIN 1
 #define PRIORITY_MAX 999
 
@@ -232,3 +886,145 @@ int semanage_module_validate_priority(uint16_t priority)
 	return -1;
 }
 
+/* Validates module name.
+ *
+ * A module name must match one of the following regular expressions
+ * to be considered valid:
+ *
+ * ^[a-zA-Z](\.?[a-zA-Z0-9_-])*$
+ * ^_base$
+ *
+ * returns -1 if name is not valid, returns 0 otherwise
+ */
+int semanage_module_validate_name(const char * name)
+{
+	int status = 0;
+
+	if (name == NULL) {
+		status = -1;
+		goto exit;
+	}
+
+	if (strcmp(name, "_base") == 0) {
+		goto exit;
+	}
+
+	if (!isalpha(*name)) {
+		status = -1;
+		goto exit;
+	}
+
+#define ISVALIDCHAR(c) (isalnum(c) || c == '_' || c == '-')
+
+	for (name++; *name; name++) {
+		if (ISVALIDCHAR(*name)) {
+			continue;
+		}
+		if (*name == '.' && name++ && ISVALIDCHAR(*name)) {
+			continue;
+		}
+		status = -1;
+		goto exit;
+	}
+
+#undef ISVALIDCHAR
+
+exit:
+	return status;
+}
+
+/* Validates module enabled status.
+ *
+ * Valid enabled values are 1, 0, and -1.
+ *
+ * returns 0 if enabled is a valid value, returns -1 otherwise.
+ */
+int semanage_module_validate_enabled(int enabled)
+{
+	if (enabled == 1 || enabled == 0 || enabled == -1) {
+		return 0;
+	}
+
+	return -1;
+}
+
+/* Validate extension.
+ *
+ * An extension must match the following regular expression to be
+ * considered valid:
+ *
+ * ^[a-zA-Z0-9][a-zA-Z0-9_-]*$
+ *
+ * returns 0 if ext is a valid value, returns -1 otherwise.
+ */
+int semanage_module_validate_lang_ext(const char *ext)
+{
+	int status = 0;
+
+	if (ext == NULL) {
+		status = -1;
+		goto exit;
+	}
+
+	if (!isalnum(*ext)) {
+		status = -1;
+		goto exit;
+	}
+
+#define ISVALIDCHAR(c) (isalnum(c) || c == '_' || c == '-')
+
+	for (ext++; *ext; ext++) {
+		if (ISVALIDCHAR(*ext)) {
+			continue;
+		}
+		status = -1;
+		goto exit;
+	}
+
+#undef ISVALIDCHAR
+
+exit:
+	return status;
+}
+
+/* Validate version.
+ *
+ * A version must match the following regular expression to be
+ * considered valid:
+ *
+ * ^[:print:]+$
+ *
+ * returns 0 if version is valid, returns -1 otherwise.
+ */
+int semanage_module_validate_version(const char *version)
+{
+	int status = 0;
+
+	if (version == NULL) {
+		status = -1;
+		goto exit;
+	}
+
+	/* must start with a printable char */
+	if (!isprint(*version)) {
+		status = -1;
+		goto exit;
+	}
+
+	/* everything else must be printable */
+#define ISVALIDCHAR(c) (isprint(c))
+
+	for (version++; *version; version++) {
+		if (ISVALIDCHAR(*version)) {
+			continue;
+		}
+		status = -1;
+		goto exit;
+	}
+
+#undef ISVALIDCHAR
+
+exit:
+	return status;
+}
+
diff --git a/libsemanage/src/modules.h b/libsemanage/src/modules.h
index cac567b..7bed3ef 100644
--- a/libsemanage/src/modules.h
+++ b/libsemanage/src/modules.h
@@ -1,7 +1,8 @@
 /* Author: Joshua Brindle <jbrindle@tresys.com>
  *         Jason Tang     <jtang@tresys.com>
+ *         Caleb Case     <ccase@tresys.com>
  *
- * Copyright (C) 2005 Tresys Technology, LLC
+ * Copyright (C) 2005,2009 Tresys Technology, LLC
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Lesser General Public
@@ -25,11 +26,233 @@
 
 #include "module_internal.h"
 
+/* Module Info */
 struct semanage_module_info {
-	char *name;		/* Key */
-	char *version;
+	uint16_t priority;	/* key, module priority */
+	char *name;		/* key, module name */
+	char *version;		/* module version */
+	char *lang_ext;		/* module source language extension */
+	int enabled;		/* module enabled/disabled status */
 };
 
+/* Creates a module info struct.
+ *
+ * Returns 0 on success and -1 on failure.
+ *
+ * The @modinfo should be destroyed with semanage_module_info_destroy.
+ * The caller should call free() on the struct.
+ */
+int semanage_module_info_create(semanage_handle_t *sh,
+				semanage_module_info_t **modinfo);
+
+/* Frees the members of the module info struct.
+ *
+ * Returns 0 on success and -1 on failure.
+ *
+ * The caller should call free() on the struct.
+ */
+int semanage_module_info_destroy(semanage_handle_t *handle,
+				 semanage_module_info_t *modinfo);
+
+/* Initializes a pre-allocated module info struct.
+ *
+ * Returns 0 on success and -1 on error.
+ */
+int semanage_module_info_init(semanage_handle_t *sh,
+			      semanage_module_info_t *modinfo);
+
+/* Clones module info @source's members into module info @target.
+ *
+ * Returns 0 on success and -1 on error.
+ */
+int semanage_module_info_clone(semanage_handle_t *sh,
+			       const semanage_module_info_t *source,
+			       semanage_module_info_t *target);
+
+/* Module Info Getters */
+
+/* Get @priority from @modinfo.
+ *
+ * Returns 0 on success and -1 on error.
+ */
+int semanage_module_info_get_priority(semanage_handle_t *sh,
+				      semanage_module_info_t *modinfo,
+				      uint16_t *priority);
+
+/* Get @name from @modinfo. Caller should not free @name.
+ *
+ * Returns 0 on success and -1 on error.
+ */
+int semanage_module_info_get_name(semanage_handle_t *sh,
+				  semanage_module_info_t *modinfo,
+				  const char **name);
+
+/* Get @version from @modinfo. Caller should not free @version.
+ *
+ * Returns 0 on success and -1 on error.
+ */
+int semanage_module_info_get_version(semanage_handle_t *sh,
+				     semanage_module_info_t *modinfo,
+				     const char **version);
+
+/* Get @lang_ext from @modinfo. Caller should not free @lang_ext.
+ *
+ * Returns 0 on success and -1 on error.
+ */
+int semanage_module_info_get_lang_ext(semanage_handle_t *sh,
+				      semanage_module_info_t *modinfo,
+				      const char **lang_ext);
+
+/* Get @enabled from @modinfo.
+ *
+ * Returns 0 on success and -1 on error.
+ */
+int semanage_module_info_get_enabled(semanage_handle_t *sh,
+				     semanage_module_info_t *modinfo,
+				     int *enabled);
+
+/* Module Info Setters */
+
+/* Set @priority in @modinfo.
+ *
+ * Returns 0 on success and -1 on error.
+ */
+int semanage_module_info_set_priority(semanage_handle_t *sh,
+				      semanage_module_info_t *modinfo,
+				      uint16_t priority);
+
+/* Set @name in @modinfo.
+ *
+ * Returns 0 on success and -1 on error.
+ */
+int semanage_module_info_set_name(semanage_handle_t *sh,
+				  semanage_module_info_t *modinfo,
+				  const char *name);
+
+/* Set @version in @modinfo.
+ *
+ * Returns 0 on success and -1 on error.
+ */
+int semanage_module_info_set_version(semanage_handle_t *sh,
+				     semanage_module_info_t *modinfo,
+				     const char *version);
+
+/* Set @lang_ext in @modinfo.
+ *
+ * Returns 0 on success and -1 on error.
+ */
+int semanage_module_info_set_lang_ext(semanage_handle_t *sh,
+				      semanage_module_info_t *modinfo,
+				      const char *lang_ext);
+
+/* Set @enabled in @modinfo.
+ *
+ * Returns 0 on success and -1 on error.
+ */
+int semanage_module_info_set_enabled(semanage_handle_t *sh,
+				     semanage_module_info_t *modinfo,
+				     int enabled);
+
+/* Convert a cstring to a priority.
+ *
+ * Returns 0 on success and -1 on error.
+ */
+int semanage_string_to_priority(const char *str, uint16_t *priority);
+
+int semanage_module_info_validate(const semanage_module_info_t *modinfo);
 int semanage_module_validate_priority(uint16_t priority);
+int semanage_module_validate_name(const char *name);
+int semanage_module_validate_enabled(int enabled);
+int semanage_module_validate_lang_ext(const char *ext);
+int semanage_module_validate_version(const char *version);
+
+/* Module Key */
+typedef struct semanage_module_key {
+	uint16_t priority;	/* module priority */
+	char *name;		/* module name */
+} semanage_module_key_t;
+
+/* Creates a module key struct.
+ *
+ * Return 0 on success, and -1 on error.
+ *
+ * The @modkey should be destroyed with semanage_module_key_destroy.
+ * The caller should call free() on the struct.
+ */
+int semanage_module_key_create(semanage_handle_t *sh,
+			       semanage_module_key_t **modkey);
+
+/* Frees members of the @modkey, but not the struct. The caller should
+ * call free() on struct.
+ *
+ * Returns 0 on success, and -1 on error.
+ */
+int semanage_module_key_destroy(semanage_handle_t *sh,
+				semanage_module_key_t *modkey);
+
+/* Initializes a pre-allocated module key struct.
+ *
+ * Returns 0 on success, and -1 on error.
+ */
+int semanage_module_key_init(semanage_handle_t *sh,
+			     semanage_module_key_t *modkey);
+
+/* Module Key Getters */
+
+/* Get @name from @modkey. Caller should not free @name.
+ *
+ * Returns 0 on success and -1 on error.
+ */
+int semanage_module_key_get_name(semanage_handle_t *sh,
+				 semanage_module_key_t *modkey,
+				 const char **name);
+
+/* Get @name from @modkey.
+ *
+ * Returns 0 on success and -1 on error.
+ */
+int semanage_module_key_get_priority(semanage_handle_t *sh,
+				     semanage_module_key_t *modkey,
+				     uint16_t *priority);
+
+/* Module Key Setters */
+
+/* Set @name in @modkey.
+ *
+ * Returns 0 on success and -1 on error.
+ */
+int semanage_module_key_set_name(semanage_handle_t *sh,
+				 semanage_module_key_t *modkey,
+				 const char *name);
+
+/* Set @priority in @modkey.
+ *
+ * Returns 0 on success and -1 on error.
+ */
+int semanage_module_key_set_priority(semanage_handle_t *sh,
+				     semanage_module_key_t *modkey,
+				     uint16_t priority);
+
+/* Module Paths */
+
+enum semanage_module_path_type {
+	SEMANAGE_MODULE_PATH_PRIORITY,
+	SEMANAGE_MODULE_PATH_NAME,
+	SEMANAGE_MODULE_PATH_HLL,
+	SEMANAGE_MODULE_PATH_CIL,
+	SEMANAGE_MODULE_PATH_LANG_EXT,
+	SEMANAGE_MODULE_PATH_VERSION,
+	SEMANAGE_MODULE_PATH_DISABLED,
+};
+
+/* Get the module path for the given path @type.
+ *
+ * Returns 0 on success and -1 on error.
+ */
+int semanage_module_get_path(semanage_handle_t *sh,
+			     const semanage_module_info_t *module,
+			     enum semanage_module_path_type type,
+			     char *path,
+			     size_t len);
 
 #endif
-- 
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@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

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

* [PATCH 08/13] libsemanage: get/set module info and enabled status
  2009-12-23 23:25             ` [PATCH 07/13] libsemanage: augment semanage_module_info_t and provide semanage_module_key_t Caleb Case
@ 2009-12-23 23:25               ` Caleb Case
  2009-12-23 23:25                 ` [PATCH 09/13] libsemanage: provide function to get new base module path Caleb Case
  0 siblings, 1 reply; 39+ messages in thread
From: Caleb Case @ 2009-12-23 23:25 UTC (permalink / raw)
  To: selinux; +Cc: csellers, kmacmillan, jwcart2, jbrindle, sds, Caleb Case

This provides the functions for enabling/disabling modules via a
semanage_module_key_t and getting/setting module info.

Enabled/disabled status is indicated by the presence of an empty file in
the disabled directory:

/var/lib/selinux/<policy type>/disabled/<module name>

The presence of a file there indicates that the module is disabled at
all priorities. Enable/disabling of modules is done across all
priorities simultaneously to avoid confusion that would likely arise
from per priority settings.

semanage_module_get_module_info gathers up the on disk information about
a module indicated by the module key and puts the information into
module info. In order to facilitate an easy mechanism for getting the
highest priority module of a given name, the key's priority value may
be 0 and the highest priority module with the given name will be located.

semanage_direct_set_module_info is a helper function that writes module
info to disk. The unused attribute is used to suppress warnings for
compilation and is removed in the module install patch later in the
series.

semanage_module_list_all behaves similar to semanage_module_list except
it returns all modules at all priorities. semanage_module_list will only
include the highest priority, enabled, non-base modules (this is its
current behavior). See the module install patch later in the series for
the modified semanage_module_list.

Adds a helper function for creating a directory if it doesn't already
exist (used to automatically create the disabled, priority, and module
dirs).
---
 libsemanage/src/direct_api.c |  908 +++++++++++++++++++++++++++++++++++++++++-
 libsemanage/src/modules.c    |   83 ++++
 libsemanage/src/modules.h    |   44 ++
 libsemanage/src/policy.h     |   21 +
 4 files changed, 1055 insertions(+), 1 deletions(-)

diff --git a/libsemanage/src/direct_api.c b/libsemanage/src/direct_api.c
index e438b87..7964eaa 100644
--- a/libsemanage/src/direct_api.c
+++ b/libsemanage/src/direct_api.c
@@ -34,6 +34,7 @@
 #include <sys/types.h>
 #include <limits.h>
 #include <errno.h>
+#include <dirent.h>
 
 #include "user_internal.h"
 #include "seuser_internal.h"
@@ -70,6 +71,20 @@ 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,
 				int *num_modules);
+static int semanage_direct_get_enabled(semanage_handle_t *sh,
+				       const semanage_module_key_t *modkey,
+				       int *enabled);
+static int semanage_direct_set_enabled(semanage_handle_t *sh,
+				       const semanage_module_key_t *modkey,
+				       int enabled);
+
+static int semanage_direct_get_module_info(semanage_handle_t *sh,
+					   const semanage_module_key_t *modkey,
+					   semanage_module_info_t **modinfo);
+
+static int semanage_direct_list_all(semanage_handle_t *sh,
+				    semanage_module_info_t **modinfo,
+				    int *num_modules);
 
 static struct semanage_policy_table direct_funcs = {
 	.get_serial = semanage_direct_get_serial,
@@ -84,7 +99,11 @@ static struct semanage_policy_table direct_funcs = {
 	.install_base = semanage_direct_install_base,
 	.install_base_file = semanage_direct_install_base_file,
 	.remove = semanage_direct_remove,
-	.list = semanage_direct_list
+	.list = semanage_direct_list,
+	.get_enabled = semanage_direct_get_enabled,
+	.set_enabled = semanage_direct_set_enabled,
+	.get_module_info = semanage_direct_get_module_info,
+	.list_all = semanage_direct_list_all,
 };
 
 int semanage_direct_is_managed(semanage_handle_t * sh)
@@ -1453,6 +1472,197 @@ static int semanage_direct_list(semanage_handle_t * sh,
 	return retval;
 }
 
+static int semanage_direct_get_enabled(semanage_handle_t *sh,
+				       const semanage_module_key_t *modkey,
+				       int *enabled)
+{
+	assert(sh);
+	assert(modkey);
+	assert(enabled);
+
+	int status = 0;
+	int ret = 0;
+
+	char path[PATH_MAX];
+	struct stat sb;
+	semanage_module_info_t *modinfo = NULL;
+
+	/* get module info */
+	ret = semanage_module_get_module_info(
+			sh,
+			modkey,
+			&modinfo);
+	if (ret != 0) {
+		status = -1;
+		goto cleanup;
+	}
+
+	/* get disabled file path */
+	ret = semanage_module_get_path(
+			sh,
+			modinfo,
+			SEMANAGE_MODULE_PATH_DISABLED,
+			path,
+			sizeof(path));
+	if (ret != 0) {
+		status = -1;
+		goto cleanup;
+	}
+
+	if (stat(path, &sb) < 0) {
+		*enabled = 1;
+	}
+	else {
+		*enabled = 0;
+	}
+
+cleanup:
+	semanage_module_info_destroy(sh, modinfo);
+	free(modinfo);
+
+	return status;
+}
+
+static int semanage_direct_set_enabled(semanage_handle_t *sh,
+				       const semanage_module_key_t *modkey,
+				       int enabled)
+{
+	assert(sh);
+	assert(modkey);
+
+	int status = 0;
+	int ret = 0;
+
+	char fn[PATH_MAX];
+	const char *path = NULL;
+	FILE *fp = NULL;
+	semanage_module_info_t *modinfo = NULL;
+
+	/* check transaction */
+	if (!sh->is_in_transaction) {
+		if (semanage_begin_transaction(sh) < 0) {
+			status = -1;
+			goto cleanup;
+		}
+	}
+
+	/* validate name */
+	ret = semanage_module_validate_name(modkey->name);
+	if (ret != 0) {
+		errno = 0;
+		ERR(sh, "Name %s is invalid.", modkey->name);
+		status = -1;
+		goto cleanup;
+	}
+
+	/* validate enabled */
+	ret = semanage_module_validate_enabled(enabled);
+	if (ret != 0) {
+		errno = 0;
+		ERR(sh, "Enabled status %d is invalid.", enabled);
+		status = -1;
+		goto cleanup;
+	}
+
+	/* check for base module */
+	if (strcmp(modkey->name, "_base") == 0) {
+		if (enabled == 0) {
+			errno = 0;
+			ERR(sh, "Base module cannot be disabled.");
+			status = -1;
+			goto cleanup;
+		}
+		else {
+			errno = 0;
+			WARN(sh, "Base module is always enabled, redundant enabling of base module requested.");
+		}
+	}
+
+	/* check for disabled path, create if missing */
+	path = semanage_path(SEMANAGE_TMP, SEMANAGE_MODULES_DISABLED);
+
+	ret = semanage_mkdir(sh, path);
+	if (ret != 0) {
+		status = -1;
+		goto cleanup;
+	}
+
+	/* get module info */
+	ret = semanage_module_get_module_info(
+			sh,
+			modkey,
+			&modinfo);
+	if (ret != 0) {
+		status = -1;
+		goto cleanup;
+	}
+
+	/* get module disabled file */
+	ret = semanage_module_get_path(
+			sh,
+			modinfo,
+			SEMANAGE_MODULE_PATH_DISABLED,
+			fn,
+			sizeof(fn));
+	if (ret != 0) {
+		status = -1;
+		goto cleanup;
+	}
+
+	switch (enabled) {
+		case 0: /* disable the module */
+			fp = fopen(fn, "w");
+
+			if (fp == NULL) {
+				ERR(sh,
+				    "Unable to disable module %s",
+				    modkey->name);
+				status = -1;
+				goto cleanup;
+			}
+
+			if (fclose(fp) != 0) {
+				ERR(sh,
+				    "Unable to close disabled file for module %s",
+				    modkey->name);
+				status = -1;
+				goto cleanup;
+			}
+
+			fp = NULL;
+
+			break;
+		case 1: /* enable the module */
+			if (unlink(fn) < 0) {
+				if (errno != ENOENT) {
+					ERR(sh,
+					    "Unable to enable module %s",
+					    modkey->name);
+					status = -1;
+					goto cleanup;
+				}
+				else {
+					/* module already enabled */
+					errno = 0;
+				}
+			}
+
+			break;
+		case -1: /* warn about ignored setting to default */
+			WARN(sh,
+			     "Setting module %s to 'default' state has no effect",
+			     modkey->name);
+			break;
+	}
+
+cleanup:
+	semanage_module_info_destroy(sh, modinfo);
+	free(modinfo);
+
+	if (fp != NULL) fclose(fp);
+	return status;
+}
+
 int semanage_direct_access_check(semanage_handle_t * sh)
 {
 	if (semanage_check_init(sh, semanage_root_path()))
@@ -1479,3 +1689,699 @@ cleanup:
 	sepol_policydb_free(p);
 	return retval;
 }
+
+static int semanage_direct_get_module_info(semanage_handle_t *sh,
+					   const semanage_module_key_t *modkey,
+					   semanage_module_info_t **modinfo)
+{
+	assert(sh);
+	assert(modkey);
+	assert(modinfo);
+
+	int status = 0;
+	int ret = 0;
+
+	char fn[PATH_MAX];
+	FILE *fp = NULL;
+	const char *modules_path = NULL;
+	size_t size = 0;
+	struct stat sb;
+	char *tmp = NULL;
+
+	int i = 0;
+
+	semanage_module_info_t *modinfos = NULL;
+	int modinfos_len = 0;
+	semanage_module_info_t *highest = NULL;
+
+	if (sh->is_in_transaction) {
+		modules_path = semanage_path(SEMANAGE_TMP, SEMANAGE_MODULES);
+	} else {
+		modules_path = semanage_path(SEMANAGE_ACTIVE, SEMANAGE_MODULES);
+	}
+
+	/* check module name */
+	ret = semanage_module_validate_name(modkey->name);
+	if (ret < 0) {
+		errno = 0;
+		ERR(sh, "Name %s is invalid.", modkey->name);
+		status = -1;
+		goto cleanup;
+	}
+
+	/* if priority == 0, then find the highest priority available */
+	if (modkey->priority == 0) {
+		ret = semanage_direct_list_all(sh, &modinfos, &modinfos_len);
+		if (ret != 0) {
+			status = -1;
+			goto cleanup;
+		}
+
+		for (i = 0; i < modinfos_len; i++) {
+			ret = strcmp(modinfos[i].name, modkey->name);
+			if (ret == 0) {
+				highest = &modinfos[i];
+				break;
+			}
+		}
+
+		if (highest == NULL) {
+			status = -1;
+			goto cleanup;
+		}
+
+		ret = semanage_module_info_create(sh, modinfo);
+		if (ret != 0) {
+			status = -1;
+			goto cleanup;
+		}
+
+		ret = semanage_module_info_clone(sh, highest, *modinfo);
+		if (ret != 0) {
+			status = -1;
+		}
+
+		/* skip to cleanup, module was found */
+		goto cleanup;
+	}
+
+	/* check module priority */
+	ret = semanage_module_validate_priority(modkey->priority);
+	if (ret != 0) {
+		errno = 0;
+		ERR(sh, "Priority %d is invalid.", modkey->priority);
+		status = -1;
+		goto cleanup;
+	}
+
+	/* copy in key values */
+	ret = semanage_module_info_create(sh, modinfo);
+	if (ret != 0) {
+		status = -1;
+		goto cleanup;
+	}
+
+	ret = semanage_module_info_set_priority(sh, *modinfo, modkey->priority);
+	if (ret != 0) {
+		status = -1;
+		goto cleanup;
+	}
+
+	ret = semanage_module_info_set_name(sh, *modinfo, modkey->name);
+	if (ret != 0) {
+		status = -1;
+		goto cleanup;
+	}
+
+	/* lookup module ext */
+	ret = semanage_module_get_path(sh,
+				       *modinfo,
+				       SEMANAGE_MODULE_PATH_LANG_EXT,
+				       fn,
+				       sizeof(fn));
+	if (ret != 0) {
+		status = -1;
+		goto cleanup;
+	}
+
+	fp = fopen(fn, "r");
+
+	if (fp == NULL) {
+		ERR(sh,
+		    "Unable to open %s module lang ext file at %s.",
+		    (*modinfo)->name, fn);
+		status = -1;
+		goto cleanup;
+	}
+
+	/* set module ext */
+	if (getline(&tmp, &size, fp) < 0) {
+		ERR(sh,
+		    "Unable to read %s module lang ext file.",
+		    (*modinfo)->name);
+		status = -1;
+		goto cleanup;
+	}
+
+	ret = semanage_module_info_set_lang_ext(sh, *modinfo, tmp);
+	if (ret != 0) {
+		status = -1;
+		goto cleanup;
+	}
+	free(tmp);
+	tmp = NULL;
+
+	if (fclose(fp) != 0) {
+		ERR(sh,
+		    "Unable to close %s module lang ext file.",
+		    (*modinfo)->name);
+		status = -1;
+		goto cleanup;
+	}
+
+	fp = NULL;
+
+	/* lookup module version */
+	ret = semanage_module_get_path(sh,
+				       *modinfo,
+				       SEMANAGE_MODULE_PATH_VERSION,
+				       fn,
+				       sizeof(fn));
+	if (ret != 0) {
+		status = -1;
+		goto cleanup;
+	}
+
+	fp = fopen(fn, "r");
+
+	if (fp == NULL) {
+		ERR(sh,
+		    "Unable to open %s module version file.",
+		    (*modinfo)->name);
+		status = -1;
+		goto cleanup;
+	}
+
+	/* set module version */
+	if (getline(&tmp, &size, fp) < 0) {
+		ERR(sh,
+		    "Unable to read %s module version file.",
+		    (*modinfo)->name);
+		status = -1;
+		goto cleanup;
+	}
+
+	ret = semanage_module_info_set_version(sh, (*modinfo), tmp);
+	if (ret != 0) {
+		status = -1;
+		goto cleanup;
+	}
+	free(tmp);
+	tmp = NULL;
+
+	if (fclose(fp) != 0) {
+		ERR(sh,
+		    "Unable to close %s module version file.",
+		    (*modinfo)->name);
+		status = -1;
+		goto cleanup;
+	}
+
+	fp = NULL;
+
+	/* lookup enabled/disabled status */
+	ret = semanage_module_get_path(sh,
+				       *modinfo,
+				       SEMANAGE_MODULE_PATH_DISABLED,
+				       fn,
+				       sizeof(fn));
+	if (ret != 0) {
+		status = -1;
+		goto cleanup;
+	}
+
+	/* set enabled/disabled status */
+	if (stat(fn, &sb) < 0) {
+		ret = semanage_module_info_set_enabled(sh, *modinfo, 1);
+		if (ret != 0) {
+			status = -1;
+			goto cleanup;
+		}
+	}
+	else {
+		ret = semanage_module_info_set_enabled(sh, *modinfo, 0);
+		if (ret != 0) {
+			status = -1;
+			goto cleanup;
+		}
+	}
+
+cleanup:
+	free(tmp);
+
+	if (modinfos != NULL) {
+		for (i = 0; i < modinfos_len; i++) {
+			semanage_module_info_destroy(sh, &modinfos[i]);
+		}
+		free(modinfos);
+	}
+
+	if (fp != NULL) fclose(fp);
+	return status;
+}
+
+__attribute__ ((unused))
+static int semanage_direct_set_module_info(semanage_handle_t *sh,
+					   const semanage_module_info_t *modinfo)
+{
+	int status = 0;
+	int ret = 0;
+
+	char fn[PATH_MAX];
+	const char *path = NULL;
+	FILE *fp = NULL;
+	int enabled = 0;
+
+	semanage_module_key_t modkey;
+	ret = semanage_module_key_init(sh, &modkey);
+	if (ret != 0) {
+		status = -1;
+		goto cleanup;
+	}
+
+	semanage_module_info_t *modinfo_tmp = NULL;
+
+	/* check transaction */
+	if (!sh->is_in_transaction) {
+		if (semanage_begin_transaction(sh) < 0) {
+			status = -1;
+			goto cleanup;
+		}
+	}
+
+	/* validate module */
+	ret = semanage_module_info_validate(modinfo);
+	if (ret != 0) {
+		status = -1;
+		goto cleanup;
+	}
+
+	/* check for base module */
+	if (strcmp(modinfo->name, "_base") == 0) {
+		if (modinfo->enabled == 0) {
+			errno = 0;
+			ERR(sh, "Base module cannot be disabled.");
+			status = -1;
+			goto cleanup;
+		}
+	}
+
+	sh->modules_modified = 1;
+
+	/* check for modules path, create if missing */
+	path = semanage_path(SEMANAGE_TMP, SEMANAGE_MODULES);
+
+	ret = semanage_mkdir(sh, path);
+	if (ret != 0) {
+		status = -1;
+		goto cleanup;
+	}
+
+	/* write priority */
+	ret = semanage_module_get_path(sh,
+				       modinfo,
+				       SEMANAGE_MODULE_PATH_PRIORITY,
+				       fn,
+				       sizeof(fn));
+	if (ret != 0) {
+		status = -1;
+		goto cleanup;
+	}
+
+	ret = semanage_mkdir(sh, fn);
+	if (ret != 0) {
+		status = -1;
+		goto cleanup;
+	}
+
+	/* write name */
+	ret = semanage_module_get_path(sh,
+				       modinfo,
+				       SEMANAGE_MODULE_PATH_NAME,
+				       fn,
+				       sizeof(fn));
+	if (ret != 0) {
+		status = -1;
+		goto cleanup;
+	}
+
+	ret = semanage_mkdir(sh, fn);
+	if (ret != 0) {
+		status = -1;
+		goto cleanup;
+	}
+
+	/* write ext */
+	ret = semanage_module_get_path(sh,
+				       modinfo,
+				       SEMANAGE_MODULE_PATH_LANG_EXT,
+				       fn,
+				       sizeof(fn));
+	if (ret != 0) {
+		status = -1;
+		goto cleanup;
+	}
+
+	fp = fopen(fn, "w");
+
+	if (fp == NULL) {
+		ERR(sh, "Unable to open %s module ext file.", modinfo->name);
+		status = -1;
+		goto cleanup;
+	}
+
+	if (fputs(modinfo->lang_ext, fp) < 0) {
+		ERR(sh, "Unable to write %s module ext file.", modinfo->name);
+		status = -1;
+		goto cleanup;
+	}
+
+	if (fclose(fp) != 0) {
+		ERR(sh, "Unable to close %s module ext file.", modinfo->name);
+		status = -1;
+		goto cleanup;
+	}
+
+	fp = NULL;
+
+	/* write version */
+	ret = semanage_module_get_path(sh,
+				       modinfo,
+				       SEMANAGE_MODULE_PATH_VERSION,
+				       fn,
+				       sizeof(fn));
+	if (ret != 0) {
+		status = -1;
+		goto cleanup;
+	}
+
+	fp = fopen(fn, "w");
+
+	if (fp == NULL) {
+		ERR(sh,
+		    "Unable to open %s module version file.",
+		    modinfo->name);
+		status = -1;
+		goto cleanup;
+	}
+
+	if (fputs(modinfo->version, fp) < 0) {
+		ERR(sh,
+		    "Unable to write %s module version file.",
+		    modinfo->name);
+		status = -1;
+		goto cleanup;
+	}
+
+	if (fclose(fp) != 0) {
+		ERR(sh,
+		    "Unable to close %s module version file.",
+		    modinfo->name);
+		status = -1;
+		goto cleanup;
+	}
+
+	fp = NULL;
+
+	/* write enabled/disabled status */
+
+	/* check for disabled path, create if missing */
+	path = semanage_path(SEMANAGE_TMP, SEMANAGE_MODULES_DISABLED);
+
+	ret = semanage_mkdir(sh, path);
+	if (ret != 0) {
+		status = -1;
+		goto cleanup;
+	}
+
+	ret = semanage_module_get_path(sh,
+				       modinfo,
+				       SEMANAGE_MODULE_PATH_DISABLED,
+				       fn,
+				       sizeof(fn));
+	if (ret != 0) {
+		status = -1;
+		goto cleanup;
+	}
+
+	ret = semanage_module_key_set_name(sh, &modkey, modinfo->name);
+	if (ret != 0) {
+		status = -1;
+		goto cleanup;
+	}
+
+	if (modinfo->enabled == -1) {
+		/* default to enabled */
+		enabled = 1;
+
+		/* check if a module is already installed */
+		ret = semanage_module_get_module_info(sh,
+						      &modkey,
+						      &modinfo_tmp);
+		if (ret == 0) {
+			/* set enabled status to current one */
+			enabled = modinfo_tmp->enabled;
+		}
+	}
+	else {
+		enabled = modinfo->enabled;
+	}
+
+	ret = semanage_module_set_enabled(sh, &modkey, enabled);
+	if (ret != 0) {
+		status = -1;
+		goto cleanup;
+	}
+
+cleanup:
+	if (fp != NULL) fclose(fp);
+
+	semanage_module_key_destroy(sh, &modkey);
+
+	semanage_module_info_destroy(sh, modinfo_tmp);
+	free(modinfo_tmp);
+
+	return status;
+}
+
+static int semanage_priorities_filename_select(const struct dirent *d)
+{
+	if (d->d_name[0] == '.' ||
+	    strcmp(d->d_name, "disabled") == 0)
+		return 0;
+	return 1;
+}
+
+static int semanage_modules_filename_select(const struct dirent *d)
+{
+	if (d->d_name[0] == '.')
+		return 0;
+	return 1;
+}
+
+static int semanage_direct_list_all(semanage_handle_t *sh,
+				    semanage_module_info_t **modinfos,
+				    int *modinfos_len)
+{
+	assert(sh);
+	assert(modinfos);
+	assert(modinfos_len);
+
+	int status = 0;
+	int ret = 0;
+
+	int i = 0;
+	int j = 0;
+
+	*modinfos = NULL;
+	*modinfos_len = 0;
+	void *tmp = NULL;
+
+	const char *toplevel = NULL;
+
+	struct dirent **priorities = NULL;
+	int priorities_len = 0;
+	char priority_path[PATH_MAX];
+
+	struct dirent **modules = NULL;
+	int modules_len = 0;
+
+	uint16_t priority = 0;
+
+	semanage_module_info_t modinfo;
+	ret = semanage_module_info_init(sh, &modinfo);
+	if (ret != 0) {
+		status = -1;
+		goto cleanup;
+	}
+
+	semanage_module_info_t *modinfo_tmp = NULL;
+
+	if (sh->is_in_transaction) {
+		toplevel = semanage_path(SEMANAGE_TMP, SEMANAGE_MODULES);
+	} else {
+		toplevel = semanage_path(SEMANAGE_ACTIVE, SEMANAGE_MODULES);
+	}
+
+	/* find priorities */
+	priorities_len = scandir(toplevel,
+				 &priorities,
+				 semanage_priorities_filename_select,
+				 versionsort);
+	if (priorities_len == -1) {
+		ERR(sh, "Error while scanning directory %s.", toplevel);
+		status = -1;
+		goto cleanup;
+	}
+
+	/* for each priority directory */
+	/* loop through in reverse so that highest priority is first */
+	for (i = priorities_len - 1; i >= 0; i--) {
+		/* convert priority string to uint16_t */
+		ret = semanage_string_to_priority(priorities[i]->d_name,
+						  &priority);
+		if (ret != 0) {
+			status = -1;
+			goto cleanup;
+		}
+
+		/* set our priority */
+		ret = semanage_module_info_set_priority(sh,
+							&modinfo,
+							priority);
+		if (ret != 0) {
+			status = -1;
+			goto cleanup;
+		}
+
+		/* get the priority path */
+		ret = semanage_module_get_path(sh,
+					       &modinfo,
+					       SEMANAGE_MODULE_PATH_PRIORITY,
+					       priority_path,
+					       sizeof(priority_path));
+		if (ret != 0) {
+			status = -1;
+			goto cleanup;
+		}
+
+		/* cleanup old modules */
+		if (modules != NULL) {
+			for (j = 0; j < modules_len; j++) {
+				free(modules[j]);
+				modules[j] = NULL;
+			}
+			free(modules);
+			modules = NULL;
+			modules_len = 0;
+		}
+
+		/* find modules at this priority */
+		modules_len = scandir(priority_path,
+				      &modules,
+				      semanage_modules_filename_select,
+				      versionsort);
+		if (modules_len == -1) {
+			ERR(sh,
+			    "Error while scanning directory %s.",
+			    priority_path);
+			status = -1;
+			goto cleanup;
+		}
+
+		if (modules_len == 0) continue;
+
+		/* add space for modules */
+		tmp = realloc(*modinfos,
+			      sizeof(semanage_module_info_t) *
+				(*modinfos_len + modules_len));
+		if (tmp == NULL) {
+			ERR(sh, "Error allocating memory for module array.");
+			status = -1;
+			goto cleanup;
+		}
+		*modinfos = tmp;
+
+		/* for each module directory */
+		for(j = 0; j < modules_len; j++) {
+			/* set module name */
+			ret = semanage_module_info_set_name(
+					sh,
+					&modinfo,
+					modules[j]->d_name);
+			if (ret != 0) {
+				status = -1;
+				goto cleanup;
+			}
+
+			/* get module values */
+			ret = semanage_direct_get_module_info(
+					sh,
+					(const semanage_module_key_t *)
+						(&modinfo),
+					&modinfo_tmp);
+			if (ret != 0) {
+				status = -1;
+				goto cleanup;
+			}
+
+			/* copy into array */
+			ret = semanage_module_info_init(
+					sh,
+					&((*modinfos)[*modinfos_len]));
+			if (ret != 0) {
+				status = -1;
+				goto cleanup;
+			}
+
+			ret = semanage_module_info_clone(
+					sh,
+					modinfo_tmp,
+					&((*modinfos)[*modinfos_len]));
+			if (ret != 0) {
+				status = -1;
+				goto cleanup;
+			}
+
+			ret = semanage_module_info_destroy(sh, modinfo_tmp);
+			if (ret != 0) {
+				status = -1;
+				goto cleanup;
+			}
+			free(modinfo_tmp);
+			modinfo_tmp = NULL;
+
+			*modinfos_len += 1;
+		}
+	}
+
+cleanup:
+	semanage_module_info_destroy(sh, &modinfo);
+
+	if (priorities != NULL) {
+		for (i = 0; i < priorities_len; i++) {
+			free(priorities[i]);
+		}
+		free(priorities);
+	}
+
+	if (modules != NULL) {
+		for (i = 0; i < modules_len; i++) {
+			free(modules[i]);
+		}
+		free(modules);
+	}
+
+	ret = semanage_module_info_destroy(sh, modinfo_tmp);
+	if (ret != 0) {
+		status = -1;
+		goto cleanup;
+	}
+	free(modinfo_tmp);
+	modinfo_tmp = NULL;
+
+	if (status != 0) {
+		if (modinfos != NULL) {
+			for (i = 0; i < *modinfos_len; i++) {
+				semanage_module_info_destroy(
+						sh, 
+						&(*modinfos)[i]);
+			}
+			free(*modinfos);
+			*modinfos = NULL;
+			*modinfos_len = 0;
+		}
+	}
+
+	return status;
+}
diff --git a/libsemanage/src/modules.c b/libsemanage/src/modules.c
index df0f15c..3f7b652 100644
--- a/libsemanage/src/modules.c
+++ b/libsemanage/src/modules.c
@@ -819,6 +819,49 @@ int semanage_module_key_set_priority(semanage_handle_t *sh,
 	return 0;
 }
 
+int semanage_module_get_enabled(semanage_handle_t *sh,
+				const semanage_module_key_t *modkey,
+				int *enabled)
+{
+	assert(sh);
+	assert(modkey);
+	assert(enabled);
+
+	if (sh->funcs->get_enabled == NULL) {
+		ERR(sh,
+		    "No get_enabled function defined for this connection type.");
+		return -1;
+	} else if (!sh->is_connected) {
+		ERR(sh, "Not connected.");
+		return -1;
+	}
+
+	return sh->funcs->get_enabled(sh, modkey, enabled);
+}
+
+int semanage_module_set_enabled(semanage_handle_t *sh,
+				const semanage_module_key_t *modkey,
+				int enabled)
+{
+	assert(sh);
+	assert(modkey);
+
+	if (sh->funcs->set_enabled == NULL) {
+		ERR(sh,
+		    "No set_enabled 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->set_enabled(sh, modkey, enabled);
+}
 
 /* Converts a string to a priority
  *
@@ -1028,3 +1071,43 @@ exit:
 	return status;
 }
 
+int semanage_module_get_module_info(semanage_handle_t *sh,
+				    const semanage_module_key_t *modkey,
+				    semanage_module_info_t **modinfo)
+{
+	assert(sh);
+	assert(modkey);
+	assert(modinfo);
+
+	if (sh->funcs->get_module_info == NULL) {
+		ERR(sh,
+		    "No get module info function defined for this connection type.");
+		return -1;
+	} else if (!sh->is_connected) {
+		ERR(sh, "Not connected.");
+		return -1;
+	}
+
+	return sh->funcs->get_module_info(sh, modkey, modinfo);
+}
+
+int semanage_module_list_all(semanage_handle_t *sh,
+			     semanage_module_info_t **modinfos,
+			     int *modinfos_len)
+{
+	assert(sh);
+	assert(modinfos);
+	assert(modinfos_len);
+
+	if (sh->funcs->list_all == NULL) {
+		ERR(sh,
+		    "No list all function defined for this connection type.");
+		return -1;
+	} else if (!sh->is_connected) {
+		ERR(sh, "Not connected.");
+		return -1;
+	}
+
+	return sh->funcs->list_all(sh, modinfos, modinfos_len);
+}
+
diff --git a/libsemanage/src/modules.h b/libsemanage/src/modules.h
index 7bed3ef..8b5b9b8 100644
--- a/libsemanage/src/modules.h
+++ b/libsemanage/src/modules.h
@@ -255,4 +255,48 @@ int semanage_module_get_path(semanage_handle_t *sh,
 			     char *path,
 			     size_t len);
 
+/* Module Enabled */
+
+/* Get module @enabled status from @modkey. Modules are enabled on a per
+ * module name basis (across all priorities). @modkey only needs to have
+ * name set (priority is ignored).
+ *
+ * Returns 0 on success and -1 on error.
+ */
+int semanage_module_get_enabled(semanage_handle_t *sh,
+				const semanage_module_key_t *modkey,
+				int *enabled);
+
+/* Set module @enabled status from @modkey. Modules are enabled on a per
+ * module name basis (across all priorities). @modkey only needs to have
+ * name set (priority is ignored).
+ *
+ * Returns 0 on success and -1 on error.
+ */
+int semanage_module_set_enabled(semanage_handle_t *sh,
+				const semanage_module_key_t *modkey,
+				int enabled);
+
+/* Lookup @modinfo by @modkey. Caller should use
+ * semanage_module_info_destroy and free on @modinfo.
+ * 
+ * Returns 0 on success and -1 on error.
+ */
+int semanage_module_get_module_info(semanage_handle_t *sh,
+				    const semanage_module_key_t *modkey,
+				    semanage_module_info_t **modinfo);
+
+/* Create a list of all modules in @modinfos of length @modinfos_len.
+ * The list will be sorted from high priority to low and alphabetically
+ * by module name within a priority.
+ *
+ * Caller should use semanage_module_info_destroy on each modinfo in
+ * @modinfos and free on @modinfos.
+ *
+ * Returns 0 on success and -1 on error.
+ */
+int semanage_module_list_all(semanage_handle_t *sh,
+			     semanage_module_info_t **modinfos,
+			     int *modinfos_len);
+
 #endif
diff --git a/libsemanage/src/policy.h b/libsemanage/src/policy.h
index ebefc02..d232ba8 100644
--- a/libsemanage/src/policy.h
+++ b/libsemanage/src/policy.h
@@ -70,6 +70,27 @@ struct semanage_policy_table {
 
 	/* Install a base module */
 	int (*install_base_file) (struct semanage_handle *, const char *);
+
+	/* Get module enabled status */
+	int (*get_enabled) (struct semanage_handle *sh,
+			    const semanage_module_key_t *key,
+			    int *enabled);
+
+	/* Set module enabled status */
+	int (*set_enabled) (struct semanage_handle *sh,
+			    const semanage_module_key_t *key,
+			    int enabled);
+
+	/* Get a module info */
+	int (*get_module_info) (struct semanage_handle *,
+				const semanage_module_key_t *,
+				semanage_module_info_t **);
+
+	/* List all policy modules */
+	int (*list_all) (struct semanage_handle *,
+			 semanage_module_info_t **,
+			 int *);
+
 };
 
 /* Should be backend independent */
-- 
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@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

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

* [PATCH 09/13] libsemanage: provide function to get new base module path
  2009-12-23 23:25               ` [PATCH 08/13] libsemanage: get/set module info and enabled status Caleb Case
@ 2009-12-23 23:25                 ` Caleb Case
  2009-12-23 23:25                   ` [PATCH 10/13] libsemanage: installing/upgrading/removing modules via info and key Caleb Case
  0 siblings, 1 reply; 39+ messages in thread
From: Caleb Case @ 2009-12-23 23:25 UTC (permalink / raw)
  To: selinux; +Cc: csellers, kmacmillan, jwcart2, jbrindle, sds, Caleb Case

The base module is being moved in with the other modules so that it can
benefit from the priority framework. This patch provides a utility
function for getting the highest priority base module path.
---
 libsemanage/src/semanage_store.c |   61 ++++++++++++++++++++++++++++++++++++++
 libsemanage/src/semanage_store.h |   10 ++++++
 2 files changed, 71 insertions(+), 0 deletions(-)

diff --git a/libsemanage/src/semanage_store.c b/libsemanage/src/semanage_store.c
index 62779b3..6b4c2e0 100644
--- a/libsemanage/src/semanage_store.c
+++ b/libsemanage/src/semanage_store.c
@@ -491,6 +491,67 @@ const char *semanage_conf_path(void)
 	return "/etc/selinux/semanage.conf";
 }
 
+/* Locates the highest priority enabled base module
+ * and fills @path in with that value. @path must be
+ * pre-allocated with size @len.
+ *
+ * Returns 0 on success and -1 on error.
+ */
+int semanage_base_path(semanage_handle_t *sh,
+		       char *path,
+		       size_t len)
+{
+	assert(sh);
+	assert(path);
+
+	int status = 0;
+	int ret = 0;
+
+	semanage_module_info_t *base = NULL;
+
+	/* set key for getting base module */
+	semanage_module_key_t modkey;
+	ret = semanage_module_key_init(sh, &modkey);
+	if (ret != 0) {
+		status = -1;
+		goto cleanup;
+	}
+
+	ret = semanage_module_key_set_name(sh, &modkey, "_base");
+	if (ret != 0) {
+		status = -1;
+		goto cleanup;
+	}
+
+	/* get highest priority base module */
+	ret = semanage_module_get_module_info(sh, &modkey, &base);
+	if (ret != 0) {
+		/* no base module found */
+		status = -1;
+		goto cleanup;
+	}
+
+	/* get the highest priority base module path */
+	ret = semanage_module_get_path(
+			sh,
+			base,
+			SEMANAGE_MODULE_PATH_HLL,
+			path,
+			len);
+	if (ret != 0) {
+		status = -1;
+		goto cleanup;
+	}
+
+cleanup:
+	semanage_module_key_destroy(sh, &modkey);
+
+	semanage_module_info_destroy(sh, base);
+	free(base);
+
+	return status;
+}
+
 /**************** functions that create module store ***************/
 
 /* Check that the semanage store exists.  If 'create' is non-zero then
diff --git a/libsemanage/src/semanage_store.h b/libsemanage/src/semanage_store.h
index d3fd554..c6711ce 100644
--- a/libsemanage/src/semanage_store.h
+++ b/libsemanage/src/semanage_store.h
@@ -150,4 +150,14 @@ int semanage_nc_sort(semanage_handle_t * sh,
 		     size_t buf_len,
 		     char **sorted_buf, size_t * sorted_buf_len);
 
+/* Locates the highest priority enabled base module
+ * and fills @path in with that value. @path must be
+ * pre-allocated with size @len.
+ *
+ * Returns 0 on success and -1 on error.
+ */
+int semanage_base_path(semanage_handle_t *sh,
+		       char *path,
+		       size_t len);
+
 #endif
-- 
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@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

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

* [PATCH 10/13] libsemanage: installing/upgrading/removing modules via info and key
  2009-12-23 23:25                 ` [PATCH 09/13] libsemanage: provide function to get new base module path Caleb Case
@ 2009-12-23 23:25                   ` Caleb Case
  2009-12-23 23:25                     ` [PATCH 11/13] libsemanage: new private api for unstable functions Caleb Case
  0 siblings, 1 reply; 39+ messages in thread
From: Caleb Case @ 2009-12-23 23:25 UTC (permalink / raw)
  To: selinux; +Cc: csellers, kmacmillan, jwcart2, jbrindle, sds, Caleb Case

These functions install/upgrade/remove modules based on the module
info/key. The motivation for these interfaces is to provide the
additional information about a module (version, language, and enabled
status) at install time and also to separate the meta-data in
preparation for supporting source policies.

This patch combines the implementations of all the
install/upgrade/remove functions to use the
semanage_direct_install_info, semanage_direct_upgrade_info, and
semanage_direct_remove_key functions. The motivation here is to reduce
the amount of duplicate installation code (for example,
semanage_direct_install and semanage_direct_install_file have separate
but similar implementations).

With this patch the transition from the old store layout to the new one
is finished. This is accomplished mostly through the modification of
install functions and semanage_get_modules_names.
---
 libsemanage/src/direct_api.c     |  652 +++++++++++++++++++++++++++-----------
 libsemanage/src/modules.c        |   61 ++++
 libsemanage/src/modules.h        |   48 +++
 libsemanage/src/policy.h         |   15 +
 libsemanage/src/semanage_store.c |  177 ++++++++---
 libsemanage/src/semanage_store.h |    1 -
 6 files changed, 713 insertions(+), 241 deletions(-)

diff --git a/libsemanage/src/direct_api.c b/libsemanage/src/direct_api.c
index 7964eaa..9bbe96d 100644
--- a/libsemanage/src/direct_api.c
+++ b/libsemanage/src/direct_api.c
@@ -86,6 +86,19 @@ static int semanage_direct_list_all(semanage_handle_t *sh,
 				    semanage_module_info_t **modinfo,
 				    int *num_modules);
 
+static int semanage_direct_install_info(semanage_handle_t *sh,
+					const semanage_module_info_t *modinfo,
+					char *data,
+					size_t data_len);
+
+static int semanage_direct_upgrade_info(semanage_handle_t *sh,
+					const semanage_module_info_t *modinfo,
+					char *data,
+					size_t data_len);
+
+static int semanage_direct_remove_key(semanage_handle_t *sh,
+				      const semanage_module_key_t *modkey);
+
 static struct semanage_policy_table direct_funcs = {
 	.get_serial = semanage_direct_get_serial,
 	.destroy = semanage_direct_destroy,
@@ -104,6 +117,9 @@ static struct semanage_policy_table direct_funcs = {
 	.set_enabled = semanage_direct_set_enabled,
 	.get_module_info = semanage_direct_get_module_info,
 	.list_all = semanage_direct_list_all,
+	.install_info = semanage_direct_install_info,
+	.upgrade_info = semanage_direct_upgrade_info,
+	.remove_key = semanage_direct_remove_key,
 };
 
 int semanage_direct_is_managed(semanage_handle_t * sh)
@@ -358,21 +374,19 @@ static int semanage_direct_begintrans(semanage_handle_t * sh)
 /********************* utility functions *********************/
 
 /* Takes a module stored in 'module_data' and parses its headers.
- * Sets reference variables 'filename' to module's fully qualified
- * path name into the sandbox, 'module_name' to module's name, and
+ * Sets reference variables 'module_name' to module's name, and
  * 'version' to module's version.  The caller is responsible for
- * free()ing 'filename', 'module_name', and 'version'; they will be
+ * free()ing 'module_name', and 'version'; they will be
  * set to NULL upon entering this function.  Returns 0 on success, -1
  * if out of memory, or -2 if data did not represent a module.
  */
 static int parse_module_headers(semanage_handle_t * sh, char *module_data,
 				size_t data_len, char **module_name,
-				char **version, char **filename)
+				char **version)
 {
 	struct sepol_policy_file *pf;
 	int file_type;
-	const char *module_path;
-	*module_name = *version = *filename = NULL;
+	*module_name = *version = NULL;
 
 	if (sepol_policy_file_create(&pf)) {
 		ERR(sh, "Out of memory!");
@@ -397,14 +411,7 @@ static int parse_module_headers(semanage_handle_t * sh, char *module_data,
 			ERR(sh, "Data did not represent a module.");
 		return -2;
 	}
-	if ((module_path =
-	     semanage_path(SEMANAGE_TMP, SEMANAGE_MODULES)) == NULL) {
-		return -1;
-	}
-	if (asprintf(filename, "%s/%s.pp", module_path, *module_name) == -1) {
-		ERR(sh, "Out of memory!");
-		return -1;
-	}
+
 	return 0;
 }
 
@@ -592,27 +599,6 @@ static ssize_t map_file(semanage_handle_t *sh, int fd, char **data,
 	return size;
 }
 
-static int dupfile( const char *dest, int src_fd) {
-	int dest_fd = -1;
-	int retval = 0;
-	int cnt;
-	char    buf[1<<18];
-
-	if (lseek(src_fd, 0, SEEK_SET)  == -1 ) return -1;
-
-	if ((dest_fd = open(dest, O_WRONLY | O_CREAT | O_TRUNC,
-			   S_IRUSR | S_IWUSR)) == -1) {
-		return -1;
-	}
-
-	while (( retval == 0 ) && 
-	       ( cnt = read(src_fd, buf, sizeof(buf)))> 0 ) {
-		if (write(dest_fd, buf, cnt) < cnt) retval = -1;
-	}
-	close(dest_fd);
-	return retval;
-}
-
 /* Writes a block of data to a file.  Returns 0 on success, -1 on
  * error. */
 static int write_file(semanage_handle_t * sh,
@@ -1074,25 +1060,61 @@ static int semanage_direct_commit(semanage_handle_t * sh)
 static int semanage_direct_install(semanage_handle_t * sh,
 				   char *data, size_t data_len)
 {
+	int status = 0;
+	int ret = 0;
 
-	int retval;
-	char *module_name = NULL, *version = NULL, *filename = NULL;
-	if ((retval = parse_module_headers(sh, data, data_len,
-					   &module_name, &version,
-					   &filename)) != 0) {
+	char *module_name = NULL, *version = NULL;
+	if ((status = parse_module_headers(sh, data, data_len,
+					   &module_name, &version)) != 0) {
 		goto cleanup;
 	}
-	if (bzip(sh, filename, data, data_len) <= 0) {
-		ERR(sh, "Error while writing to %s.", filename);
-		retval = -3;
+
+	semanage_module_info_t modinfo;
+	ret = semanage_module_info_init(sh, &modinfo);
+	if (ret != 0) {
+		status = -1;
 		goto cleanup;
 	}
-	retval = 0;
-      cleanup:
+
+	ret = semanage_module_info_set_priority(sh, &modinfo, sh->priority);
+	if (ret != 0) {
+		status = -1;
+		goto cleanup;
+	}
+
+	ret = semanage_module_info_set_name(sh, &modinfo, module_name);
+	if (ret != 0) {
+		status = -1;
+		goto cleanup;
+	}
+
+	ret = semanage_module_info_set_version(sh, &modinfo, version);
+	if (ret != 0) {
+		status = -1;
+		goto cleanup;
+	}
+
+	ret = semanage_module_info_set_lang_ext(sh, &modinfo, "pp");
+	if (ret != 0) {
+		status = -1;
+		goto cleanup;
+	}
+
+	ret = semanage_module_info_set_enabled(sh, &modinfo, -1);
+	if (ret != 0) {
+		status = -1;
+		goto cleanup;
+	}
+
+	status = semanage_direct_install_info(sh, &modinfo, data, data_len);
+
+cleanup:
 	free(version);
-	free(filename);
 	free(module_name);
-	return retval;
+
+	semanage_module_info_destroy(sh, &modinfo);
+
+	return status;
 }
 
 /* Attempts to link a module to the sandbox's module directory, unlinking any
@@ -1118,24 +1140,7 @@ static int semanage_direct_install_file(semanage_handle_t * sh,
 		goto cleanup;
 	}
 		
-	if (compressed) {
-		char *module_name = NULL, *version = NULL, *filename = NULL;
-		if ((retval = parse_module_headers(sh, data, data_len,
-						   &module_name, &version,
-						   &filename)) != 0) {
-			goto cleanup;
-		}
-
-		if (data_len > 0) munmap(data, data_len);
-		data_len = 0;
-		retval = dupfile(filename, in_fd);
-		free(version);
-		free(filename);
-		free(module_name);
-
-	} else {
-		retval = semanage_direct_install(sh, data, data_len);
-	}
+	retval = semanage_direct_install(sh, data, data_len);
 
       cleanup:
 	close(in_fd);
@@ -1144,54 +1149,6 @@ static int semanage_direct_install_file(semanage_handle_t * sh,
 	return retval;
 }
 
-
-static int get_direct_upgrade_filename(semanage_handle_t * sh,
-				       char *data, size_t data_len, char **outfilename) {
-	int i, retval, num_modules = 0;
-	char *module_name = NULL, *version = NULL, *filename = NULL;
-	semanage_module_info_t *modinfo = NULL;
-	if ((retval = parse_module_headers(sh, data, data_len,
-					   &module_name, &version,
-					   &filename)) != 0) {
-		goto cleanup;
-	}
-	if (semanage_direct_list(sh, &modinfo, &num_modules) < 0) {
-		goto cleanup;
-	}
-	retval = -5;
-	for (i = 0; i < num_modules; i++) {
-		semanage_module_info_t *m =
-		    semanage_module_list_nth(modinfo, i);
-		if (strcmp(semanage_module_get_name(m), module_name) == 0) {
-			if (strverscmp(version, semanage_module_get_version(m))
-			    > 0) {
-				retval = 0;
-				break;
-			} else {
-				ERR(sh, "Previous module %s is same or newer.",
-				    module_name);
-				retval = -4;
-				goto cleanup;
-			}
-		}
-	}
-      cleanup:
-	free(version);
-	free(module_name);
-	for (i = 0; modinfo != NULL && i < num_modules; i++) {
-		semanage_module_info_t *m =
-		    semanage_module_list_nth(modinfo, i);
-		semanage_module_info_datum_destroy(m);
-	}
-	free(modinfo);
-	if (retval == 0) {
-		*outfilename = filename;
-	} else {
-		free(filename);
-	}
-	return retval;
-}
-
 /* Similar to semanage_direct_install(), except that it checks that
  * there already exists a module with the same name and that the
  * module is an older version then the one in 'data'.  Returns 0 on
@@ -1203,18 +1160,64 @@ static int get_direct_upgrade_filename(semanage_handle_t * sh,
 static int semanage_direct_upgrade(semanage_handle_t * sh,
 				   char *data, size_t data_len)
 {
-	char *filename = NULL;
-	int retval = get_direct_upgrade_filename(sh,
-						 data, data_len, 
-						 &filename);
-	if (retval == 0) {
-		if (bzip(sh, filename, data, data_len) <= 0) {
-			ERR(sh, "Error while writing to %s.", filename);
-			retval = -3;
-		}
-		free(filename);
+	int status = 0;
+	int ret = 0;
+
+	char *module_name = NULL, *version = NULL;
+	status = parse_module_headers(
+			sh,
+			data,
+			data_len,
+			&module_name,
+			&version);
+	if (status != 0) {
+		goto cleanup;
 	}
-	return retval;
+
+	semanage_module_info_t modinfo;
+	ret = semanage_module_info_init(sh, &modinfo);
+	if (ret != 0) {
+		status = -1;
+		goto cleanup;
+	}
+
+	ret = semanage_module_info_set_priority(sh, &modinfo, sh->priority);
+	if (ret != 0) {
+		status = -1;
+		goto cleanup;
+	}
+
+	ret = semanage_module_info_set_name(sh, &modinfo, module_name);
+	if (ret != 0) {
+		status = -1;
+		goto cleanup;
+	}
+
+	ret = semanage_module_info_set_version(sh, &modinfo, version);
+	if (ret != 0) {
+		status = -1;
+		goto cleanup;
+	}
+
+	ret = semanage_module_info_set_lang_ext(sh, &modinfo, "pp");
+	if (ret != 0) {
+		status = -1;
+		goto cleanup;
+	}
+
+	ret = semanage_module_info_set_enabled(sh, &modinfo, -1);
+	if (ret != 0) {
+		status = -1;
+		goto cleanup;
+	}
+
+	status = semanage_direct_upgrade_info(sh, &modinfo, data, data_len);
+
+cleanup:
+	free(module_name);
+	free(version);
+
+	return status;
 }
 
 /* Attempts to link a module to the sandbox's module directory, unlinking any
@@ -1240,19 +1243,7 @@ static int semanage_direct_upgrade_file(semanage_handle_t * sh,
 		goto cleanup;
 	}
 
-	if (compressed) {
-		char *filename = NULL;
-		retval = get_direct_upgrade_filename(sh,
-					 	     data, data_len, 
-						     &filename);
-		
-		if (retval != 0)  goto cleanup;
-
-		retval = dupfile(filename, in_fd);
-		free(filename);
-	} else {
-		retval = semanage_direct_upgrade(sh, data, data_len);
-	}
+	retval = semanage_direct_upgrade(sh, data, data_len);
 
       cleanup:
 	close(in_fd);
@@ -1270,22 +1261,62 @@ static int semanage_direct_upgrade_file(semanage_handle_t * sh,
 static int semanage_direct_install_base(semanage_handle_t * sh,
 					char *base_data, size_t data_len)
 {
-	int retval = -1;
-	const char *filename = NULL;
-	if ((retval = parse_base_headers(sh, base_data, data_len)) != 0) {
+	int status = 0;
+	int ret = 0;
+
+	ret = parse_base_headers(sh, base_data, data_len);
+	if (ret != 0) {
+		status = -1;
 		goto cleanup;
 	}
-	if ((filename = semanage_path(SEMANAGE_TMP, SEMANAGE_BASE)) == NULL) {
+
+	semanage_module_info_t modinfo;
+	ret = semanage_module_info_init(sh, &modinfo);
+	if (ret != 0) {
+		status = -1;
 		goto cleanup;
 	}
-	if (bzip(sh, filename, base_data, data_len) <= 0) {
-		ERR(sh, "Error while writing to %s.", filename);
-		retval = -3;
+
+	ret = semanage_module_info_set_priority(sh, &modinfo, sh->priority);
+	if (ret != 0) {
+		status = -1;
 		goto cleanup;
 	}
-	retval = 0;
-      cleanup:
-	return retval;
+
+	ret = semanage_module_info_set_name(sh, &modinfo, "_base");
+	if (ret != 0) {
+		status = -1;
+		goto cleanup;
+	}
+
+	ret = semanage_module_info_set_version(sh, &modinfo, "1.0.0");
+	if (ret != 0) {
+		status = -1;
+		goto cleanup;
+	}
+
+	ret = semanage_module_info_set_lang_ext(sh, &modinfo, "pp");
+	if (ret != 0) {
+		status = -1;
+		goto cleanup;
+	}
+
+	ret = semanage_module_info_set_enabled(sh, &modinfo, 1);
+	if (ret != 0) {
+		status = -1;
+		goto cleanup;
+	}
+
+	status = semanage_direct_install_info(
+			sh,
+			&modinfo,
+			base_data,
+			data_len);
+
+cleanup:
+	semanage_module_info_destroy(sh, &modinfo);
+
+	return status;
 }
 
 /* Writes a base module into a sandbox, overwriting any previous base
@@ -1310,19 +1341,7 @@ static int semanage_direct_install_base_file(semanage_handle_t * sh,
 		goto cleanup;
 	}
 		
-	if (compressed) {
-		const char *filename = NULL;
-		if ((retval = parse_base_headers(sh, data, data_len)) != 0) {
-			goto cleanup;
-		}
-		if ((filename = semanage_path(SEMANAGE_TMP, SEMANAGE_BASE)) == NULL) {
-			goto cleanup;
-		}
-
-		retval = dupfile(filename, in_fd);
-	} else {
-		retval = semanage_direct_install_base(sh, data, data_len);
-	}
+	retval = semanage_direct_install_base(sh, data, data_len);
 
       cleanup:
 	close(in_fd);
@@ -1335,41 +1354,32 @@ static int semanage_direct_install_base_file(semanage_handle_t * sh,
  * 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;
+	int status = 0;
+	int ret = 0;
+
+	semanage_module_key_t modkey;
+	ret = semanage_module_key_init(sh, &modkey);
+	if (ret != 0) {
+		status = -1;
+		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 &&
-		    strcmp(base + name_len, ".pp") == 0) {
-			if (unlink(module_filenames[i]) == -1) {
-				ERR(sh, "Could not remove module file %s.",
-				    module_filenames[i]);
-				retval = -2;
-			}
-			retval = 0;
-			goto cleanup;
-		}
+
+	ret = semanage_module_key_set_priority(sh, &modkey, sh->priority);
+	if (ret != 0) {
+		status = -1;
+		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]);
+
+	ret = semanage_module_key_set_name(sh, &modkey, module_name);
+	if (ret != 0) {
+		status = -1;
+		goto cleanup;
 	}
-	free(module_filenames);
-	return retval;
+
+	status = semanage_direct_remove_key(sh, &modkey);
+
+cleanup:
+	return status;
 }
 
 /* Allocate an array of module_info structures for each readable
@@ -1930,7 +1940,6 @@ cleanup:
 	return status;
 }
 
-__attribute__ ((unused))
 static int semanage_direct_set_module_info(semanage_handle_t *sh,
 					   const semanage_module_info_t *modinfo)
 {
@@ -2385,3 +2394,260 @@ cleanup:
 
 	return status;
 }
+
+static int semanage_direct_install_info(semanage_handle_t *sh,
+					const semanage_module_info_t *modinfo,
+					char *data,
+					size_t data_len)
+{
+	assert(sh);
+	assert(modinfo);
+	assert(data);
+
+	int status = 0;
+	int ret = 0;
+
+	char path[PATH_MAX];
+
+	semanage_module_info_t *higher_info = NULL;
+	semanage_module_key_t higher_key;
+	ret = semanage_module_key_init(sh, &higher_key);
+	if (ret != 0) {
+		status = -1;
+		goto cleanup;
+	}
+
+	/* validate module info */
+	ret = semanage_module_info_validate(modinfo);
+	if (ret != 0) {
+		status = -2;
+		goto cleanup;
+	}
+
+	/* Check for higher priority module and warn if there is one as
+	 * it will override the module currently being installed.
+	 */
+	ret = semanage_module_key_set_name(sh, &higher_key, modinfo->name);
+	if (ret != 0) {
+		status = -1;
+		goto cleanup;
+	}
+
+	ret = semanage_direct_get_module_info(sh, &higher_key, &higher_info);
+	if (ret == 0) {
+		if (higher_info->priority > modinfo->priority) {
+			errno = 0;
+			WARN(sh,
+			     "A higher priority %s module exists at priority %d and will override the module currently being installed at priority %d.",
+			     modinfo->name,
+			     higher_info->priority,
+			     modinfo->priority);
+		}
+		else if (higher_info->priority < modinfo->priority) {
+			errno = 0;
+			INFO(sh,
+			     "Overriding %s module at lower priority %d with module at priority %d.",
+			     modinfo->name,
+			     higher_info->priority,
+			     modinfo->priority);
+		}
+
+		if (higher_info->enabled == 0 && modinfo->enabled == -1) {
+			errno = 0;
+			WARN(sh,
+			     "%s module will be disabled after install due to default enabled status.",
+			     modinfo->name);
+		}
+	}
+
+	/* set module meta data */
+	ret = semanage_direct_set_module_info(sh, modinfo);
+	if (ret != 0) {
+		status = -2;
+		goto cleanup;
+	}
+
+	/* install module source file */
+	ret = semanage_module_get_path(
+			sh,
+			modinfo,
+			SEMANAGE_MODULE_PATH_HLL,
+			path,
+			sizeof(path));
+	if (ret != 0) {
+		status = -3;
+		goto cleanup;
+	}
+	
+	ret = bzip(sh, path, data, data_len);
+	if (ret <= 0) {
+		ERR(sh, "Error while writing to %s.", path);
+		status = -3;
+		goto cleanup;
+	}
+
+cleanup:
+	semanage_module_key_destroy(sh, &higher_key);
+	semanage_module_info_destroy(sh, higher_info);
+	free(higher_info);
+
+	return status;
+}
+
+static int semanage_direct_upgrade_info(semanage_handle_t *sh,
+					const semanage_module_info_t *modinfo,
+					char *data,
+					size_t data_len)
+{
+	assert(sh);
+	assert(modinfo);
+	assert(data);
+
+	int status = 0;
+	int ret = 0;
+
+	semanage_module_info_t *existing = NULL;
+
+	/* get existing module data */
+	ret = semanage_direct_get_module_info(
+			sh,
+			(const semanage_module_key_t *)modinfo,
+			&existing);
+	if (ret == 0) {
+		/* verify this is an upgrade */
+		ret = strverscmp(existing->version, modinfo->version);
+		if (ret >= 0) {
+			ERR(sh,
+			    "Existing module %s version %s >= %s.",
+			    existing->name,
+			    existing->version,
+			    modinfo->version);
+			status = -4;
+			goto cleanup;
+		}
+	}
+
+	/* install the module */
+	status = semanage_direct_install_info(sh, modinfo, data, data_len);
+
+cleanup:
+	semanage_module_info_destroy(sh, existing);
+	free(existing);
+
+	return status;
+}
+
+static int semanage_direct_remove_key(semanage_handle_t *sh,
+				      const semanage_module_key_t *modkey)
+{
+	assert(sh);
+	assert(modkey);
+
+	int status = 0;
+	int ret = 0;
+
+	char path[PATH_MAX];
+	semanage_module_info_t *modinfo = NULL;
+
+	semanage_module_key_t modkey_tmp;
+	ret = semanage_module_key_init(sh, &modkey_tmp);
+	if (ret != 0) {
+		status = -1;
+		goto cleanup;
+	}
+
+	/* validate module key */
+	ret = semanage_module_validate_priority(modkey->priority);
+	if (ret != 0) {
+		errno = 0;
+		ERR(sh, "Priority %d is invalid.", modkey->priority);
+		status = -1;
+		goto cleanup;
+	}
+
+	ret = semanage_module_validate_name(modkey->name);
+	if (ret != 0) {
+		errno = 0;
+		ERR(sh, "Name %s is invalid.", modkey->name);
+		status = -1;
+		goto cleanup;
+	}
+
+	ret = semanage_module_key_set_name(sh, &modkey_tmp, modkey->name);
+	if (ret != 0) {
+		status = -1;
+		goto cleanup;
+	}
+
+	/* get module path */
+	ret = semanage_module_get_path(
+			sh,
+			(const semanage_module_info_t *)modkey,
+			SEMANAGE_MODULE_PATH_NAME,
+			path,
+			sizeof(path));
+	if (ret != 0) {
+		status = -2;
+		goto cleanup;
+	}
+
+	/* remove directory */
+	ret = semanage_remove_directory(path);
+	if (ret != 0) {
+		ERR(sh, "Unable to remove module directory %s.", path);
+		status = -2;
+		goto cleanup;
+	}
+
+	/* check if its the last module at any priority */
+	ret = semanage_module_get_module_info(sh, &modkey_tmp, &modinfo);
+	if (ret != 0) {
+		/* info that no other module will override */
+		errno = 0;
+		INFO(sh,
+		     "Removing last %s module (no other %s module exists at another priority).",
+		     modkey->name,
+		     modkey->name);
+
+		/* remove disabled status file */
+		ret = semanage_module_get_path(
+				sh,
+				(const semanage_module_info_t *)modkey,
+				SEMANAGE_MODULE_PATH_DISABLED,
+				path,
+				sizeof(path));
+		if (ret != 0) {
+			status = -1;
+			goto cleanup;
+		}
+
+		struct stat sb;
+		if (stat(path, &sb) == 0) {
+			ret = unlink(path);
+			if (ret != 0) {
+				status = -1;
+				goto cleanup;
+			}
+		}
+	}
+	else {
+		/* if a lower priority module is going to become active */
+		if (modkey->priority > modinfo->priority) {
+			/* inform what the new active module will be */
+			errno = 0;
+			INFO(sh,
+			     "%s module at priority %d is now active.",
+			     modinfo->name,
+			     modinfo->priority);
+		}
+	}
+
+cleanup:
+	semanage_module_key_destroy(sh, &modkey_tmp);
+
+	semanage_module_info_destroy(sh, modinfo);
+	free(modinfo);
+
+	return status;
+}
+
diff --git a/libsemanage/src/modules.c b/libsemanage/src/modules.c
index 3f7b652..817da80 100644
--- a/libsemanage/src/modules.c
+++ b/libsemanage/src/modules.c
@@ -1111,3 +1111,64 @@ int semanage_module_list_all(semanage_handle_t *sh,
 	return sh->funcs->list_all(sh, modinfos, modinfos_len);
 }
 
+int semanage_module_install_info(semanage_handle_t *sh,
+				 const semanage_module_info_t *modinfo,
+				 char *data,
+				 size_t data_len)
+{
+	if (sh->funcs->install_info == NULL) {
+		ERR(sh,
+		    "No install info 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->install_info(sh, modinfo, data, data_len);
+}
+
+int semanage_module_upgrade_info(semanage_handle_t *sh,
+				 const semanage_module_info_t *modinfo,
+				 char *data,
+				 size_t data_len)
+{
+	if (sh->funcs->upgrade_info == NULL) {
+		ERR(sh,
+		    "No upgrade info 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->upgrade_info(sh, modinfo, data, data_len);
+}
+
+int semanage_module_remove_key(semanage_handle_t *sh,
+			       const semanage_module_key_t *modkey)
+{
+	if (sh->funcs->remove_key== NULL) {
+		ERR(sh,
+		    "No remove key 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->remove_key(sh, modkey);
+}
+
diff --git a/libsemanage/src/modules.h b/libsemanage/src/modules.h
index 8b5b9b8..7faead4 100644
--- a/libsemanage/src/modules.h
+++ b/libsemanage/src/modules.h
@@ -299,4 +299,52 @@ int semanage_module_list_all(semanage_handle_t *sh,
 			     semanage_module_info_t **modinfos,
 			     int *modinfos_len);
 
+/* Install the module indicated by @modinfo with input data from 
+ * @module_data with length @data_len.
+ *
+ * @modinfo must have all values filled in.
+ * @module_data may be bzip compressed.
+ *
+ * Returns:
+ *	 0	success
+ *	-1	failure, out of memory
+ *	-2	failure, invalid @modinfo
+ *	-3	failure, error writing file
+ */
+int semanage_module_install_info(semanage_handle_t *sh,
+				 const semanage_module_info_t *modinfo,
+				 char *data,
+				 size_t data_len);
+
+/* Upgrade the module indicated by @modinfo with input data from
+ * @module_data with length @data_len.
+ *
+ * If the module is not already installed, then this will install it.
+ *
+ * @modinfo must have all values filled in.
+ * @module_data may be bzip compressed.
+ *
+ * Returns:
+ *	 0	success
+ *	-1	failure, out of memory
+ *	-2	failure, invalid @modinfo
+ *	-3	failure, error writing file
+ *	-4	failure, same or newer version module exists
+ */
+int semanage_module_upgrade_info(semanage_handle_t *sh,
+				 const semanage_module_info_t *modinfo,
+				 char *data,
+				 size_t data_len);
+
+/* Remove the module indicated by @modkey.
+ * @modkey must have key values filled in.
+ *
+ * Returns:
+ * 	 0	success
+ *	-1	failure, out of memeory
+ *	-2	failure, @module not found or couldn't be removed
+ */
+int semanage_module_remove_key(semanage_handle_t *sh,
+			       const semanage_module_key_t *modkey);
+
 #endif
diff --git a/libsemanage/src/policy.h b/libsemanage/src/policy.h
index d232ba8..397863f 100644
--- a/libsemanage/src/policy.h
+++ b/libsemanage/src/policy.h
@@ -91,6 +91,21 @@ struct semanage_policy_table {
 			 semanage_module_info_t **,
 			 int *);
 
+	/* Install via module info */
+	int (*install_info) (struct semanage_handle *,
+			     const semanage_module_info_t *,
+			     char *,
+			     size_t);
+
+	/* Upgrade via module info */
+	int (*upgrade_info) (struct semanage_handle *,
+			     const semanage_module_info_t *,
+			     char *,
+			     size_t);
+
+	/* Remove via module key */
+	int (*remove_key) (struct semanage_handle *,
+			   const semanage_module_key_t *);
 };
 
 /* Should be backend independent */
diff --git a/libsemanage/src/semanage_store.c b/libsemanage/src/semanage_store.c
index 6b4c2e0..4ac5b5b 100644
--- a/libsemanage/src/semanage_store.c
+++ b/libsemanage/src/semanage_store.c
@@ -55,8 +55,10 @@ typedef struct dbase_policydb dbase_t;
 #include <sys/types.h>
 #include <sys/wait.h>
 #include <limits.h>
+#include <libgen.h>
 
 #include "debug.h"
+#include "utilities.h"
 
 #define SEMANAGE_CONF_FILE "semanage.conf"
 /* relative path names to enum semanage_paths to special files and
@@ -94,7 +96,6 @@ static const char *semanage_store_paths[SEMANAGE_NUM_STORES] = {
 static const char *semanage_sandbox_paths[SEMANAGE_STORE_NUM_PATHS] = {
 	"",
 	"/modules",
-	"/base.pp",
 	"/base.linked",
 	"/homedir_template",
 	"/file_contexts.template",
@@ -988,6 +989,29 @@ cleanup:
 	return status;
 }
 
+/* qsort comparison function for semanage_get_modules_names. */
+static int semanage_get_modules_names_cmp(const void *a, const void *b)
+{
+	const char *aa = *(const char **)a;
+	const char *bb = *(const char **)b;
+
+	/* copy into a buffer since basename/dirname can modify */
+	char ap[PATH_MAX];
+	char bp[PATH_MAX];
+
+	strncpy(ap, aa, sizeof(ap));
+	ap[PATH_MAX - 1] = '\0';
+
+	strncpy(bp, bb, sizeof(bp));
+	bp[PATH_MAX - 1] = '\0';
+
+	/* compare the module dir names */
+	const char *an = basename(dirname((char *)ap));
+	const char *bn = basename(dirname((char *)bp));
+
+	return strverscmp(an, bn);
+}
+
 /* Scans the modules directory for the current semanage handler.  This
  * might be the active directory or sandbox, depending upon if the
  * handler has a transaction lock.  Allocates and fills in *filenames
@@ -998,58 +1022,119 @@ cleanup:
 int semanage_get_modules_names(semanage_handle_t * sh, char ***filenames,
 			       int *len)
 {
-	const char *modules_path;
-	struct dirent **namelist = NULL;
-	int num_files, i, retval = -1;
+	assert(sh);
+	assert(filenames);
+	assert(len);
 
-	if (sh->is_in_transaction) {
-		modules_path = semanage_path(SEMANAGE_TMP, SEMANAGE_MODULES);
-	} else {
-		modules_path = semanage_path(SEMANAGE_ACTIVE, SEMANAGE_MODULES);
-	}
+	int status = 0;
+	int ret = 0;
 
-	*filenames = NULL;
-	*len = 0;
-	if ((num_files = scandir(modules_path, &namelist,
-				 semanage_filename_select, alphasort)) == -1) {
-		ERR(sh, "Error while scanning directory %s.", modules_path);
-		goto cleanup;
-	}
-	if (num_files == 0) {
-		retval = 0;
+	int i = 0;
+	int j = 0;
+
+	semanage_list_t *list = NULL;
+	semanage_list_t *found = NULL;
+
+	semanage_module_info_t *modinfos = NULL;
+	int modinfos_len = 0;
+
+	char path[PATH_MAX];
+
+	void *tmp = NULL;
+
+	/* get all modules */
+	ret = semanage_module_list_all(sh, &modinfos, &modinfos_len);
+	if (ret != 0) {
+		status = -1;
 		goto cleanup;
 	}
-	if ((*filenames =
-	     (char **)calloc(num_files, sizeof(**filenames))) == NULL) {
-		ERR(sh, "Out of memory!");
+
+	/* allocate enough for worst case */
+	(*filenames) = calloc(modinfos_len, sizeof(char *));
+	if ((*filenames) == NULL) {
+		ERR(sh, "Error allocating space for filenames.");
+		status = -1;
 		goto cleanup;
 	}
-	for (i = 0; i < num_files; i++) {
-		char *filename;
-		char path[PATH_MAX];
 
-		snprintf(path, PATH_MAX, "%s/%s", modules_path,
-			 namelist[i]->d_name);
-		if ((filename = strdup(path)) == NULL) {
-			int j;
-			ERR(sh, "Out of memory!");
-			for (j = 0; j < i; j++) {
-				free((*filenames)[j]);
+	*len = modinfos_len;
+
+	/* for each highest priority, non-base, enabled module get its path */
+	semanage_list_destroy(&list);
+	j = 0;
+	for (i = 0; i < modinfos_len; i++) {
+		/* check if base */
+		ret = strcmp(modinfos[i].name, "_base");
+		if (ret == 0) continue;
+
+		/* check if enabled */
+		if (modinfos[i].enabled != 1) continue;
+
+		/* check if we've seen this before (i.e. highest priority) */
+		found = semanage_list_find(list, modinfos[i].name);
+		if (found == NULL) {
+			ret = semanage_list_push(&list, modinfos[i].name);
+			if (ret != 0) {
+				ERR(sh, "Failed to add module name to list of known names.");
+				status = -1;
+				goto cleanup;
 			}
-			free(*filenames);
-			*filenames = NULL;
+		}
+		else continue;
+
+		ret = semanage_module_get_path(
+				sh,
+				&modinfos[i],
+				SEMANAGE_MODULE_PATH_HLL,
+				path,
+				sizeof(path));
+		if (ret != 0) {
+			status = -1;
+			goto cleanup;
+		}
+
+		(*filenames)[j] = strdup(path);
+		if ((*filenames)[j] == NULL) {
+			status = -1;
 			goto cleanup;
 		}
-		(*filenames)[i] = filename;
+
+		j += 1;
 	}
-	*len = num_files;
-	retval = 0;
-      cleanup:
-	for (i = 0; i < num_files; i++) {
-		free(namelist[i]);
+
+	/* realloc the array to its min size */
+	tmp = realloc(*filenames, j * sizeof(char *));
+	if (tmp == NULL) {
+		ERR(sh, "Error allocating space for filenames.");
+		status = -1;
+		goto cleanup;
 	}
-	free(namelist);
-	return retval;
+	*filenames = tmp;
+	*len = j;
+
+	/* sort array on module name */
+	qsort(*filenames,
+	      *len,
+	      sizeof(char *),
+	      semanage_get_modules_names_cmp);
+
+cleanup:
+	semanage_list_destroy(&list);
+
+	for (i = 0; i < modinfos_len; i++) {
+		semanage_module_info_destroy(sh, &modinfos[i]);
+	}
+	free(modinfos);
+
+	if (status != 0) {
+		for (i = 0; i < j; j++) {
+			free((*filenames)[i]);
+		}
+
+		free(*filenames);
+	}
+
+	return status;
 }
 
 /******************* routines that run external programs *******************/
@@ -1899,7 +1984,7 @@ static int semanage_load_module(semanage_handle_t * sh, const char *filename,
 int semanage_link_sandbox(semanage_handle_t * sh,
 			  sepol_module_package_t ** base)
 {
-	const char *base_filename = NULL;
+	char base_filename[PATH_MAX];
 	char **module_filenames = NULL;
 	int retval = -1, i;
 	int num_modules = 0;
@@ -1908,8 +1993,7 @@ int semanage_link_sandbox(semanage_handle_t * sh,
 	*base = NULL;
 
 	/* first make sure that base module is readable */
-	if ((base_filename =
-	     semanage_path(SEMANAGE_TMP, SEMANAGE_BASE)) == NULL) {
+	if (semanage_base_path(sh, base_filename, sizeof(base_filename)) != 0) {
 		goto cleanup;
 	}
 	if (access(base_filename, R_OK) == -1) {
@@ -1963,14 +2047,13 @@ int semanage_link_sandbox(semanage_handle_t * sh,
 int semanage_link_base(semanage_handle_t * sh,
 			  sepol_module_package_t ** base)
 {
-	const char *base_filename = NULL;
+	char base_filename[PATH_MAX];
 	int retval = -1;
 
 	*base = NULL;
 
 	/* first make sure that base module is readable */
-	if ((base_filename =
-	     semanage_path(SEMANAGE_TMP, SEMANAGE_BASE)) == NULL) {
+	if (semanage_base_path(sh, base_filename, sizeof(base_filename)) != 0) {
 		goto cleanup;
 	}
 	if (access(base_filename, R_OK) == -1) {
diff --git a/libsemanage/src/semanage_store.h b/libsemanage/src/semanage_store.h
index c6711ce..16148ef 100644
--- a/libsemanage/src/semanage_store.h
+++ b/libsemanage/src/semanage_store.h
@@ -39,7 +39,6 @@ enum semanage_store_defs {
 enum semanage_sandbox_defs {
 	SEMANAGE_TOPLEVEL,
 	SEMANAGE_MODULES,
-	SEMANAGE_BASE,
 	SEMANAGE_LINKED,
 	SEMANAGE_HOMEDIR_TMPL,
 	SEMANAGE_FC_TMPL,
-- 
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@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

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

* [PATCH 11/13] libsemanage: new private api for unstable functions
  2009-12-23 23:25                   ` [PATCH 10/13] libsemanage: installing/upgrading/removing modules via info and key Caleb Case
@ 2009-12-23 23:25                     ` Caleb Case
  2009-12-23 23:25                       ` [PATCH 12/13] semodule: add priority, enabled, and extended listing Caleb Case
  0 siblings, 1 reply; 39+ messages in thread
From: Caleb Case @ 2009-12-23 23:25 UTC (permalink / raw)
  To: selinux; +Cc: csellers, kmacmillan, jwcart2, jbrindle, sds, Caleb Case

Rather than export the new functions as part of the stable API we
chose to create a private API. The private API is unstable, may change
in the future, and is mainly intended to be used by upstream tools like
semodule. Keeping these new APIs private for a time will allow them to
both get tested through upstream tools and be changed as necessary
without causing the same change burdens as they would if they were in
the public API.

The private API is found in the includes:

include/semanage/private/handle.h

* Exports the handle get/set default priority functions.

include/semanage/private/module.h

* Exports the module info management functions.
* Exports the get/set enabled status functions.
* Exports the module key management functions.
* Exports the module install, upgrade, remove info/key functions.

include/semanage/private/semanage.h

* Includes the other private headers.

This patch includes the modifications to the map file for exporting the
necessary functions.

Internal prototypes were moved to the private API and the private
headers included as necessary.

Examples:

/* changing the default priority for a distro install */
semanage_set_default_priority(sh, 100);

/* creating module meta data */
semanage_module_info_t *modinfo = NULL;
semanage_module_info_create(sh, &modinfo);

/* filling in that data */
semanage_module_info_set_priority(
	sh,
	modinfo,
	semanage_get_default_priority(sh));

semanage_module_info_set_name(
	sh,
	modinfo,
	"mymodule");

semanage_module_info_set_version(
	sh,
	modinfo,
	"0.1.2");

semanage_module_info_set_lang_ext(
	sh,
	modinfo,
	"pp");

semanage_module_info_set_enabled(
	sh,
	modinfo,
	-1); 	/* Sets enabled to default:
		 * If the module was already enabled/disabled
		 * then it will remain so after install.
		 * If it wasn't, then it will be enabled.
		 */

/* install the module */
semanage_module_install_info(sh, modinfo, data, data_len);

/* cleanup modinfo */
semanage_module_info_destroy(sh, modinfo);

/* create a key for retrieving a module's meta data */
semanage_module_key_t *modkey = NULL;
semanage_module_key_create(sh, &modkey);

/* Only set the module name, this will find the highest
 * priority module of that name.
 */
semanage_module_key_set_name(sh, modkey, "mymodule");

/* get the newly installed module */
semanage_module_get_module_info(sh, modkey, &modinfo);

/* get the priority of the module found */
uint16_t priority = 0;
semanage_module_info_get_priority(sh, modinfo, &priority);

/* set the priority in the key to the one found */
semanage_module_key_set_priority(sh, modkey, priority);

/* remove the highest priority module with the name "mymodule" */
semanage_module_remove_key(sh, modkey);

/* print all the modules installed */
semanage_module_info_t *modinfos = NULL;
int modinfos_len = 0;
semanage_module_list_all(sh, &modinfos, &modinfos_len);

char *name = NULL;
int i = 0;
for (i = 0; i < modinfos_len; i++) {
	semanage_module_info_get_priority(
		sh,
		semanage_module_list_nth(modinfos, i),
		&priority);
	semanage_module_info_get_name(
		sh,
		semanage_module_list_nth(modinfos, i),
		&name);
	printf("%d\t%s\n", priority, name);
}
---
 libsemanage/include/Makefile                    |    3 +
 libsemanage/include/semanage/private/handle.h   |   31 +++
 libsemanage/include/semanage/private/modules.h  |  281 +++++++++++++++++++++++
 libsemanage/include/semanage/private/semanage.h |   26 ++
 libsemanage/src/handle_internal.h               |    1 +
 libsemanage/src/libsemanage.map                 |   26 ++
 libsemanage/src/module_internal.h               |   21 ++
 libsemanage/src/modules.c                       |   40 ++++
 libsemanage/src/modules.h                       |  253 +--------------------
 9 files changed, 431 insertions(+), 251 deletions(-)
 create mode 100644 libsemanage/include/semanage/private/handle.h
 create mode 100644 libsemanage/include/semanage/private/modules.h
 create mode 100644 libsemanage/include/semanage/private/semanage.h

diff --git a/libsemanage/include/Makefile b/libsemanage/include/Makefile
index 391f950..f42824d 100644
--- a/libsemanage/include/Makefile
+++ b/libsemanage/include/Makefile
@@ -5,6 +5,9 @@ INCDIR ?= $(PREFIX)/include/semanage
 install:
 	test -d $(INCDIR) || install -m 755 -d $(INCDIR)
 	install -m 644 $(wildcard semanage/*.h) $(INCDIR)
+	test -d $(INCDIR)/private || install -m 755 -d $(INCDIR)/private
+	install -m 644 $(wildcard semanage/private/*.h) $(INCDIR)/private
 
 indent:
 	../../scripts/Lindent $(wildcard semanage/*.h)
+	../../scripts/Lindent $(wildcard semanage/private/*.h)
diff --git a/libsemanage/include/semanage/private/handle.h b/libsemanage/include/semanage/private/handle.h
new file mode 100644
index 0000000..6efd664
--- /dev/null
+++ b/libsemanage/include/semanage/private/handle.h
@@ -0,0 +1,31 @@
+/* Authors:	Caleb Case	<ccase@tresys.com>
+ *
+ * Copyright (C) 2009 Tresys Technology, LLC
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef _SEMANAGE_PRIVATE_HANDLE_H_
+#define _SEMANAGE_PRIVATE_HANDLE_H_
+
+#include <stdint.h>
+
+/* Get the default priority. */
+uint16_t semanage_get_default_priority(semanage_handle_t *sh);
+
+/* Set the default priority. */
+int semanage_set_default_priority(semanage_handle_t *sh, uint16_t priority);
+
+#endif
diff --git a/libsemanage/include/semanage/private/modules.h b/libsemanage/include/semanage/private/modules.h
new file mode 100644
index 0000000..2ffaa5b
--- /dev/null
+++ b/libsemanage/include/semanage/private/modules.h
@@ -0,0 +1,281 @@
+/* Authors:	Caleb Case	<ccase@tresys.com>
+ *
+ * Copyright (C) 2009 Tresys Technology, LLC
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef _SEMANAGE_PRIVATE_MODULES_H_
+#define _SEMANAGE_PRIVATE_MODULES_H_
+
+#include <stdio.h>
+#include <stdint.h>
+
+typedef struct semanage_module_key semanage_module_key_t;
+
+/* Module Info */
+
+/* Creates a module info struct.
+ *
+ * Returns 0 on success and -1 on failure.
+ *
+ * The @modinfo should be destroyed with semanage_module_info_destroy.
+ * The caller should call free() on the struct.
+ */
+int semanage_module_info_create(semanage_handle_t *sh,
+				semanage_module_info_t **modinfo);
+
+/* Frees the members of the module info struct.
+ *
+ * Returns 0 on success and -1 on failure.
+ *
+ * The caller should call free() on the struct.
+ */
+int semanage_module_info_destroy(semanage_handle_t *handle,
+				 semanage_module_info_t *modinfo);
+
+/* Module Info Getters */
+
+/* Get @priority from @modinfo.
+ *
+ * Returns 0 on success and -1 on error.
+ */
+int semanage_module_info_get_priority(semanage_handle_t *sh,
+				      semanage_module_info_t *modinfo,
+				      uint16_t *priority);
+
+/* Get @name from @modinfo. Caller should not free @name.
+ *
+ * Returns 0 on success and -1 on error.
+ */
+int semanage_module_info_get_name(semanage_handle_t *sh,
+				  semanage_module_info_t *modinfo,
+				  const char **name);
+
+/* Get @version from @modinfo. Caller should not free @version.
+ *
+ * Returns 0 on success and -1 on error.
+ */
+int semanage_module_info_get_version(semanage_handle_t *sh,
+				     semanage_module_info_t *modinfo,
+				     const char **version);
+
+/* Get @lang_ext from @modinfo. Caller should not free @lang_ext.
+ *
+ * Returns 0 on success and -1 on error.
+ */
+int semanage_module_info_get_lang_ext(semanage_handle_t *sh,
+				      semanage_module_info_t *modinfo,
+				      const char **lang_ext);
+
+/* Get @enabled from @modinfo.
+ *
+ * Returns 0 on success and -1 on error.
+ */
+int semanage_module_info_get_enabled(semanage_handle_t *sh,
+				     semanage_module_info_t *modinfo,
+				     int *enabled);
+
+/* Module Info Setters */
+
+/* Set @priority in @modinfo.
+ *
+ * Returns 0 on success and -1 on error.
+ */
+int semanage_module_info_set_priority(semanage_handle_t *sh,
+				      semanage_module_info_t *modinfo,
+				      uint16_t priority);
+
+/* Set @name in @modinfo.
+ *
+ * Returns 0 on success and -1 on error.
+ */
+int semanage_module_info_set_name(semanage_handle_t *sh,
+				  semanage_module_info_t *modinfo,
+				  const char *name);
+
+/* Set @version in @modinfo.
+ *
+ * Returns 0 on success and -1 on error.
+ */
+int semanage_module_info_set_version(semanage_handle_t *sh,
+				     semanage_module_info_t *modinfo,
+				     const char *version);
+
+/* Set @lang_ext in @modinfo.
+ *
+ * Returns 0 on success and -1 on error.
+ */
+int semanage_module_info_set_lang_ext(semanage_handle_t *sh,
+				      semanage_module_info_t *modinfo,
+				      const char *lang_ext);
+
+/* Set @enabled in @modinfo.
+ *
+ * Returns 0 on success and -1 on error.
+ */
+int semanage_module_info_set_enabled(semanage_handle_t *sh,
+				     semanage_module_info_t *modinfo,
+				     int enabled);
+
+/* Module Key */
+
+/* Creates a module key struct.
+ *
+ * Return 0 on success, and -1 on error.
+ *
+ * The @modkey should be destroyed with semanage_module_key_destroy.
+ * The caller should call free() on the struct.
+ */
+int semanage_module_key_create(semanage_handle_t *sh,
+			       semanage_module_key_t **modkey);
+
+/* Frees members of the @modkey, but not the struct. The caller should
+ * call free() on struct.
+ *
+ * Returns 0 on success, and -1 on error.
+ */
+int semanage_module_key_destroy(semanage_handle_t *sh,
+				semanage_module_key_t *modkey);
+
+/* Module Key Getters */
+
+/* Get @name from @modkey. Caller should not free @name.
+ *
+ * Returns 0 on success and -1 on error.
+ */
+int semanage_module_key_get_name(semanage_handle_t *sh,
+				 semanage_module_key_t *modkey,
+				 const char **name);
+
+/* Get @name from @modkey.
+ *
+ * Returns 0 on success and -1 on error.
+ */
+int semanage_module_key_get_priority(semanage_handle_t *sh,
+				     semanage_module_key_t *modkey,
+				     uint16_t *priority);
+
+/* Module Key Setters */
+
+/* Set @name in @modkey.
+ *
+ * Returns 0 on success and -1 on error.
+ */
+int semanage_module_key_set_name(semanage_handle_t *sh,
+				 semanage_module_key_t *modkey,
+				 const char *name);
+
+/* Set @priority in @modkey.
+ *
+ * Returns 0 on success and -1 on error.
+ */
+int semanage_module_key_set_priority(semanage_handle_t *sh,
+				     semanage_module_key_t *modkey,
+				     uint16_t priority);
+
+/* Module Enabled */
+
+/* Get module @enabled status from @modkey. Modules are enabled on a per
+ * module name basis (across all priorities). @modkey only needs to have
+ * name set (priority is ignored).
+ *
+ * Returns 0 on success and -1 on error.
+ */
+int semanage_module_get_enabled(semanage_handle_t *sh,
+				const semanage_module_key_t *modkey,
+				int *enabled);
+
+/* Set module @enabled status from @modkey. Modules are enabled on a per
+ * module name basis (across all priorities). @modkey only needs to have
+ * name set (priority is ignored).
+ *
+ * Returns 0 on success and -1 on error.
+ */
+int semanage_module_set_enabled(semanage_handle_t *sh,
+				const semanage_module_key_t *modkey,
+				int enabled);
+
+/* Lookup @modinfo by @modkey. Caller should use
+ * semanage_module_info_destroy and free on @modinfo.
+ * 
+ * Returns 0 on success and -1 on error.
+ */
+int semanage_module_get_module_info(semanage_handle_t *sh,
+				    const semanage_module_key_t *modkey,
+				    semanage_module_info_t **modinfo);
+
+/* Create a list of all modules in @modinfos of length @modinfos_len.
+ * The list will be sorted from high priority to low and alphabetically
+ * by module name within a priority.
+ *
+ * Caller should use semanage_module_info_destroy on each modinfo in
+ * @modinfos and free on @modinfos.
+ *
+ * Returns 0 on success and -1 on error.
+ */
+int semanage_module_list_all(semanage_handle_t *sh,
+			     semanage_module_info_t **modinfos,
+			     int *modinfos_len);
+
+/* Install the module indicated by @modinfo with input data from 
+ * @module_data with length @data_len.
+ *
+ * @modinfo must have all values filled in.
+ * @module_data may be bzip compressed.
+ *
+ * Returns:
+ *	 0	success
+ *	-1	failure, out of memory
+ *	-2	failure, invalid @modinfo
+ *	-3	failure, error writing file
+ */
+int semanage_module_install_info(semanage_handle_t *sh,
+				 const semanage_module_info_t *modinfo,
+				 char *data,
+				 size_t data_len);
+
+/* Upgrade the module indicated by @modinfo with input data from
+ * @module_data with length @data_len.
+ *
+ * If the module is not already installed, then this will install it.
+ *
+ * @modinfo must have all values filled in.
+ * @module_data may be bzip compressed.
+ *
+ * Returns:
+ *	 0	success
+ *	-1	failure, out of memory
+ *	-2	failure, invalid @modinfo
+ *	-3	failure, error writing file
+ *	-4	failure, same or newer version module exists
+ */
+int semanage_module_upgrade_info(semanage_handle_t *sh,
+				 const semanage_module_info_t *modinfo,
+				 char *data,
+				 size_t data_len);
+
+/* Remove the module indicated by @modkey.
+ * @modkey must have key values filled in.
+ *
+ * Returns:
+ * 	 0	success
+ *	-1	failure, out of memeory
+ *	-2	failure, @module not found or couldn't be removed
+ */
+int semanage_module_remove_key(semanage_handle_t *sh,
+			       const semanage_module_key_t *modkey);
+
+#endif
diff --git a/libsemanage/include/semanage/private/semanage.h b/libsemanage/include/semanage/private/semanage.h
new file mode 100644
index 0000000..f083c60
--- /dev/null
+++ b/libsemanage/include/semanage/private/semanage.h
@@ -0,0 +1,26 @@
+/* Authors:	Caleb Case	<ccase@tresys.com>
+ *
+ * Copyright (C) 2009 Tresys Technology, LLC
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef _SEMANAGE_PRIVATE_SEMANAGE_H_
+#define _SEMANAGE_PRIVATE_SEMANAGE_H_
+
+#include <semanage/private/handle.h>
+#include <semanage/private/modules.h>
+
+#endif
diff --git a/libsemanage/src/handle_internal.h b/libsemanage/src/handle_internal.h
index 8493a39..f009195 100644
--- a/libsemanage/src/handle_internal.h
+++ b/libsemanage/src/handle_internal.h
@@ -2,6 +2,7 @@
 #define _SEMANAGE_HANDLE_INTERNAL_H_
 
 #include <semanage/handle.h>
+#include <semanage/private/handle.h>
 #include "dso.h"
 
 hidden_proto(semanage_begin_transaction)
diff --git a/libsemanage/src/libsemanage.map b/libsemanage/src/libsemanage.map
index d15f69d..3526256 100644
--- a/libsemanage/src/libsemanage.map
+++ b/libsemanage/src/libsemanage.map
@@ -18,5 +18,31 @@ LIBSEMANAGE_1.0 {
 	  semanage_is_connected; semanage_get_disable_dontaudit; semanage_set_disable_dontaudit;
 	  semanage_mls_enabled;
 	  semanage_set_check_contexts;
+	  semanage_get_default_priority; semanage_set_default_priority;
+	  semanage_module_info_create;
+	  semanage_module_info_destroy;
+	  semanage_module_info_get_priority;
+	  semanage_module_info_get_name;
+	  semanage_module_info_get_version;
+	  semanage_module_info_get_lang_ext;
+	  semanage_module_info_get_enabled;
+	  semanage_module_info_set_priority;
+	  semanage_module_info_set_name;
+	  semanage_module_info_set_version;
+	  semanage_module_info_set_lang_ext;
+	  semanage_module_info_set_enabled;
+	  semanage_module_key_create;
+	  semanage_module_key_destroy;
+	  semanage_module_key_get_priority;
+	  semanage_module_key_get_name;
+	  semanage_module_key_set_priority;
+	  semanage_module_key_set_name;
+	  semanage_module_get_module;
+	  semanage_module_list_all;
+	  semanage_module_get_enabled;
+	  semanage_module_set_enabled;
+	  semanage_module_install_info;
+	  semanage_module_upgrade_info;
+	  semanage_module_remove_key;
   local: *;
 };
diff --git a/libsemanage/src/module_internal.h b/libsemanage/src/module_internal.h
index f074a3a..7fe20be 100644
--- a/libsemanage/src/module_internal.h
+++ b/libsemanage/src/module_internal.h
@@ -2,10 +2,31 @@
 #define _SEMANAGE_MODULE_INTERNAL_H_
 
 #include <semanage/modules.h>
+#include <semanage/private/modules.h>
 #include "dso.h"
 
 hidden_proto(semanage_module_get_name)
     hidden_proto(semanage_module_get_version)
     hidden_proto(semanage_module_info_datum_destroy)
     hidden_proto(semanage_module_list_nth)
+    hidden_proto(semanage_module_info_create)
+    hidden_proto(semanage_module_info_destroy)
+    hidden_proto(semanage_module_info_get_priority)
+    hidden_proto(semanage_module_info_get_name)
+    hidden_proto(semanage_module_info_get_version)
+    hidden_proto(semanage_module_info_get_lang_ext)
+    hidden_proto(semanage_module_info_get_enabled)
+    hidden_proto(semanage_module_info_set_priority)
+    hidden_proto(semanage_module_info_set_name)
+    hidden_proto(semanage_module_info_set_version)
+    hidden_proto(semanage_module_info_set_lang_ext)
+    hidden_proto(semanage_module_info_set_enabled)
+    hidden_proto(semanage_module_key_create)
+    hidden_proto(semanage_module_key_destroy)
+    hidden_proto(semanage_module_key_get_priority)
+    hidden_proto(semanage_module_key_get_name)
+    hidden_proto(semanage_module_key_set_priority)
+    hidden_proto(semanage_module_key_set_name)
+    hidden_proto(semanage_module_get_enabled)
+    hidden_proto(semanage_module_set_enabled)
 #endif
diff --git a/libsemanage/src/modules.c b/libsemanage/src/modules.c
index 817da80..6f6f8b1 100644
--- a/libsemanage/src/modules.c
+++ b/libsemanage/src/modules.c
@@ -246,6 +246,8 @@ int semanage_module_info_create(semanage_handle_t *sh,
 	return semanage_module_info_init(sh, *modinfo);
 }
 
+hidden_def(semanage_module_info_create)
+
 int semanage_module_info_destroy(semanage_handle_t *sh,
 				 semanage_module_info_t *modinfo)
 {
@@ -262,6 +264,8 @@ int semanage_module_info_destroy(semanage_handle_t *sh,
 	return semanage_module_info_init(sh, modinfo);
 }
 
+hidden_def(semanage_module_info_destroy)
+
 int semanage_module_info_init(semanage_handle_t *sh,
 			      semanage_module_info_t *modinfo)
 {
@@ -342,6 +346,8 @@ int semanage_module_info_get_priority(semanage_handle_t *sh,
 	return 0;
 }
 
+hidden_def(semanage_module_info_get_priority)
+
 int semanage_module_info_get_name(semanage_handle_t *sh,
 				  semanage_module_info_t *modinfo,
 				  const char **name)
@@ -355,6 +361,8 @@ int semanage_module_info_get_name(semanage_handle_t *sh,
 	return 0;
 }
 
+hidden_def(semanage_module_info_get_name)
+
 int semanage_module_info_get_version(semanage_handle_t *sh,
 				     semanage_module_info_t *modinfo,
 				     const char **version)
@@ -368,6 +376,8 @@ int semanage_module_info_get_version(semanage_handle_t *sh,
 	return 0;
 }
 
+hidden_def(semanage_module_info_get_version)
+
 int semanage_module_info_get_lang_ext(semanage_handle_t *sh,
 				      semanage_module_info_t *modinfo,
 				      const char **lang_ext)
@@ -381,6 +391,8 @@ int semanage_module_info_get_lang_ext(semanage_handle_t *sh,
 	return 0;
 }
 
+hidden_def(semanage_module_info_get_lang_ext)
+
 int semanage_module_info_get_enabled(semanage_handle_t *sh,
 				     semanage_module_info_t *modinfo,
 				     int *enabled)
@@ -394,6 +406,8 @@ int semanage_module_info_get_enabled(semanage_handle_t *sh,
 	return 0;
 }
 
+hidden_def(semanage_module_info_get_enabled)
+
 int semanage_module_info_set_priority(semanage_handle_t *sh,
 				      semanage_module_info_t *modinfo,
 				      uint16_t priority)
@@ -413,6 +427,8 @@ int semanage_module_info_set_priority(semanage_handle_t *sh,
 	return 0;
 }
 
+hidden_def(semanage_module_info_set_priority)
+
 int semanage_module_info_set_name(semanage_handle_t *sh,
 				  semanage_module_info_t *modinfo,
 				  const char *name)
@@ -441,6 +457,8 @@ int semanage_module_info_set_name(semanage_handle_t *sh,
 	return 0;
 }
 
+hidden_def(semanage_module_info_set_name)
+
 int semanage_module_info_set_version(semanage_handle_t *sh,
 				     semanage_module_info_t *modinfo,
 				     const char *version)
@@ -469,6 +487,8 @@ int semanage_module_info_set_version(semanage_handle_t *sh,
 	return 0;
 }
 
+hidden_def(semanage_module_info_set_version)
+
 int semanage_module_info_set_lang_ext(semanage_handle_t *sh,
 				      semanage_module_info_t *modinfo,
 				      const char *lang_ext)
@@ -497,6 +517,8 @@ int semanage_module_info_set_lang_ext(semanage_handle_t *sh,
 	return 0;
 }
 
+hidden_def(semanage_module_info_set_lang_ext)
+
 int semanage_module_info_set_enabled(semanage_handle_t *sh,
 				     semanage_module_info_t *modinfo,
 				     int enabled)
@@ -516,6 +538,8 @@ int semanage_module_info_set_enabled(semanage_handle_t *sh,
 	return 0;
 }
 
+hidden_def(semanage_module_info_set_enabled)
+
 int semanage_module_get_path(semanage_handle_t *sh,
 			     const semanage_module_info_t *modinfo,
 			     enum semanage_module_path_type type,
@@ -721,6 +745,8 @@ int semanage_module_key_create(semanage_handle_t *sh,
 	return semanage_module_key_init(sh, *modkey);
 }
 
+hidden_def(semanage_module_key_create)
+
 int semanage_module_key_destroy(semanage_handle_t *sh,
 				semanage_module_key_t *modkey)
 {
@@ -733,6 +759,8 @@ int semanage_module_key_destroy(semanage_handle_t *sh,
 	return semanage_module_key_init(sh, modkey);
 }
 
+hidden_def(semanage_module_key_destroy)
+
 int semanage_module_key_init(semanage_handle_t *sh,
 			     semanage_module_key_t *modkey)
 {
@@ -758,6 +786,8 @@ int semanage_module_key_get_name(semanage_handle_t *sh,
 	return 0;
 }
 
+hidden_def(semanage_module_key_get_name)
+
 int semanage_module_key_get_priority(semanage_handle_t *sh,
 				     semanage_module_key_t *modkey,
 				     uint16_t *priority)
@@ -771,6 +801,8 @@ int semanage_module_key_get_priority(semanage_handle_t *sh,
 	return 0;
 }
 
+hidden_def(semanage_module_key_get_priority)
+
 int semanage_module_key_set_name(semanage_handle_t *sh,
 				 semanage_module_key_t *modkey,
 				 const char *name)
@@ -801,6 +833,8 @@ cleanup:
 	return status;
 }
 
+hidden_def(semanage_module_key_set_name)
+
 int semanage_module_key_set_priority(semanage_handle_t *sh,
 				     semanage_module_key_t *modkey,
 				     uint16_t priority)
@@ -819,6 +853,8 @@ int semanage_module_key_set_priority(semanage_handle_t *sh,
 	return 0;
 }
 
+hidden_def(semanage_module_key_set_priority)
+
 int semanage_module_get_enabled(semanage_handle_t *sh,
 				const semanage_module_key_t *modkey,
 				int *enabled)
@@ -839,6 +875,8 @@ int semanage_module_get_enabled(semanage_handle_t *sh,
 	return sh->funcs->get_enabled(sh, modkey, enabled);
 }
 
+hidden_def(semanage_module_get_enabled)
+
 int semanage_module_set_enabled(semanage_handle_t *sh,
 				const semanage_module_key_t *modkey,
 				int enabled)
@@ -863,6 +901,8 @@ int semanage_module_set_enabled(semanage_handle_t *sh,
 	return sh->funcs->set_enabled(sh, modkey, enabled);
 }
 
+hidden_def(semanage_module_set_enabled)
+
 /* Converts a string to a priority
  *
  * returns -1 if str is not a valid priority.
diff --git a/libsemanage/src/modules.h b/libsemanage/src/modules.h
index 7faead4..38e1e0c 100644
--- a/libsemanage/src/modules.h
+++ b/libsemanage/src/modules.h
@@ -35,25 +35,6 @@ struct semanage_module_info {
 	int enabled;		/* module enabled/disabled status */
 };
 
-/* Creates a module info struct.
- *
- * Returns 0 on success and -1 on failure.
- *
- * The @modinfo should be destroyed with semanage_module_info_destroy.
- * The caller should call free() on the struct.
- */
-int semanage_module_info_create(semanage_handle_t *sh,
-				semanage_module_info_t **modinfo);
-
-/* Frees the members of the module info struct.
- *
- * Returns 0 on success and -1 on failure.
- *
- * The caller should call free() on the struct.
- */
-int semanage_module_info_destroy(semanage_handle_t *handle,
-				 semanage_module_info_t *modinfo);
-
 /* Initializes a pre-allocated module info struct.
  *
  * Returns 0 on success and -1 on error.
@@ -69,90 +50,6 @@ int semanage_module_info_clone(semanage_handle_t *sh,
 			       const semanage_module_info_t *source,
 			       semanage_module_info_t *target);
 
-/* Module Info Getters */
-
-/* Get @priority from @modinfo.
- *
- * Returns 0 on success and -1 on error.
- */
-int semanage_module_info_get_priority(semanage_handle_t *sh,
-				      semanage_module_info_t *modinfo,
-				      uint16_t *priority);
-
-/* Get @name from @modinfo. Caller should not free @name.
- *
- * Returns 0 on success and -1 on error.
- */
-int semanage_module_info_get_name(semanage_handle_t *sh,
-				  semanage_module_info_t *modinfo,
-				  const char **name);
-
-/* Get @version from @modinfo. Caller should not free @version.
- *
- * Returns 0 on success and -1 on error.
- */
-int semanage_module_info_get_version(semanage_handle_t *sh,
-				     semanage_module_info_t *modinfo,
-				     const char **version);
-
-/* Get @lang_ext from @modinfo. Caller should not free @lang_ext.
- *
- * Returns 0 on success and -1 on error.
- */
-int semanage_module_info_get_lang_ext(semanage_handle_t *sh,
-				      semanage_module_info_t *modinfo,
-				      const char **lang_ext);
-
-/* Get @enabled from @modinfo.
- *
- * Returns 0 on success and -1 on error.
- */
-int semanage_module_info_get_enabled(semanage_handle_t *sh,
-				     semanage_module_info_t *modinfo,
-				     int *enabled);
-
-/* Module Info Setters */
-
-/* Set @priority in @modinfo.
- *
- * Returns 0 on success and -1 on error.
- */
-int semanage_module_info_set_priority(semanage_handle_t *sh,
-				      semanage_module_info_t *modinfo,
-				      uint16_t priority);
-
-/* Set @name in @modinfo.
- *
- * Returns 0 on success and -1 on error.
- */
-int semanage_module_info_set_name(semanage_handle_t *sh,
-				  semanage_module_info_t *modinfo,
-				  const char *name);
-
-/* Set @version in @modinfo.
- *
- * Returns 0 on success and -1 on error.
- */
-int semanage_module_info_set_version(semanage_handle_t *sh,
-				     semanage_module_info_t *modinfo,
-				     const char *version);
-
-/* Set @lang_ext in @modinfo.
- *
- * Returns 0 on success and -1 on error.
- */
-int semanage_module_info_set_lang_ext(semanage_handle_t *sh,
-				      semanage_module_info_t *modinfo,
-				      const char *lang_ext);
-
-/* Set @enabled in @modinfo.
- *
- * Returns 0 on success and -1 on error.
- */
-int semanage_module_info_set_enabled(semanage_handle_t *sh,
-				     semanage_module_info_t *modinfo,
-				     int enabled);
-
 /* Convert a cstring to a priority.
  *
  * Returns 0 on success and -1 on error.
@@ -167,28 +64,10 @@ int semanage_module_validate_lang_ext(const char *ext);
 int semanage_module_validate_version(const char *version);
 
 /* Module Key */
-typedef struct semanage_module_key {
+struct semanage_module_key {
 	uint16_t priority;	/* module priority */
 	char *name;		/* module name */
-} semanage_module_key_t;
-
-/* Creates a module key struct.
- *
- * Return 0 on success, and -1 on error.
- *
- * The @modkey should be destroyed with semanage_module_key_destroy.
- * The caller should call free() on the struct.
- */
-int semanage_module_key_create(semanage_handle_t *sh,
-			       semanage_module_key_t **modkey);
-
-/* Frees members of the @modkey, but not the struct. The caller should
- * call free() on struct.
- *
- * Returns 0 on success, and -1 on error.
- */
-int semanage_module_key_destroy(semanage_handle_t *sh,
-				semanage_module_key_t *modkey);
+};
 
 /* Initializes a pre-allocated module key struct.
  *
@@ -197,42 +76,6 @@ int semanage_module_key_destroy(semanage_handle_t *sh,
 int semanage_module_key_init(semanage_handle_t *sh,
 			     semanage_module_key_t *modkey);
 
-/* Module Key Getters */
-
-/* Get @name from @modkey. Caller should not free @name.
- *
- * Returns 0 on success and -1 on error.
- */
-int semanage_module_key_get_name(semanage_handle_t *sh,
-				 semanage_module_key_t *modkey,
-				 const char **name);
-
-/* Get @name from @modkey.
- *
- * Returns 0 on success and -1 on error.
- */
-int semanage_module_key_get_priority(semanage_handle_t *sh,
-				     semanage_module_key_t *modkey,
-				     uint16_t *priority);
-
-/* Module Key Setters */
-
-/* Set @name in @modkey.
- *
- * Returns 0 on success and -1 on error.
- */
-int semanage_module_key_set_name(semanage_handle_t *sh,
-				 semanage_module_key_t *modkey,
-				 const char *name);
-
-/* Set @priority in @modkey.
- *
- * Returns 0 on success and -1 on error.
- */
-int semanage_module_key_set_priority(semanage_handle_t *sh,
-				     semanage_module_key_t *modkey,
-				     uint16_t priority);
-
 /* Module Paths */
 
 enum semanage_module_path_type {
@@ -255,96 +98,4 @@ int semanage_module_get_path(semanage_handle_t *sh,
 			     char *path,
 			     size_t len);
 
-/* Module Enabled */
-
-/* Get module @enabled status from @modkey. Modules are enabled on a per
- * module name basis (across all priorities). @modkey only needs to have
- * name set (priority is ignored).
- *
- * Returns 0 on success and -1 on error.
- */
-int semanage_module_get_enabled(semanage_handle_t *sh,
-				const semanage_module_key_t *modkey,
-				int *enabled);
-
-/* Set module @enabled status from @modkey. Modules are enabled on a per
- * module name basis (across all priorities). @modkey only needs to have
- * name set (priority is ignored).
- *
- * Returns 0 on success and -1 on error.
- */
-int semanage_module_set_enabled(semanage_handle_t *sh,
-				const semanage_module_key_t *modkey,
-				int enabled);
-
-/* Lookup @modinfo by @modkey. Caller should use
- * semanage_module_info_destroy and free on @modinfo.
- * 
- * Returns 0 on success and -1 on error.
- */
-int semanage_module_get_module_info(semanage_handle_t *sh,
-				    const semanage_module_key_t *modkey,
-				    semanage_module_info_t **modinfo);
-
-/* Create a list of all modules in @modinfos of length @modinfos_len.
- * The list will be sorted from high priority to low and alphabetically
- * by module name within a priority.
- *
- * Caller should use semanage_module_info_destroy on each modinfo in
- * @modinfos and free on @modinfos.
- *
- * Returns 0 on success and -1 on error.
- */
-int semanage_module_list_all(semanage_handle_t *sh,
-			     semanage_module_info_t **modinfos,
-			     int *modinfos_len);
-
-/* Install the module indicated by @modinfo with input data from 
- * @module_data with length @data_len.
- *
- * @modinfo must have all values filled in.
- * @module_data may be bzip compressed.
- *
- * Returns:
- *	 0	success
- *	-1	failure, out of memory
- *	-2	failure, invalid @modinfo
- *	-3	failure, error writing file
- */
-int semanage_module_install_info(semanage_handle_t *sh,
-				 const semanage_module_info_t *modinfo,
-				 char *data,
-				 size_t data_len);
-
-/* Upgrade the module indicated by @modinfo with input data from
- * @module_data with length @data_len.
- *
- * If the module is not already installed, then this will install it.
- *
- * @modinfo must have all values filled in.
- * @module_data may be bzip compressed.
- *
- * Returns:
- *	 0	success
- *	-1	failure, out of memory
- *	-2	failure, invalid @modinfo
- *	-3	failure, error writing file
- *	-4	failure, same or newer version module exists
- */
-int semanage_module_upgrade_info(semanage_handle_t *sh,
-				 const semanage_module_info_t *modinfo,
-				 char *data,
-				 size_t data_len);
-
-/* Remove the module indicated by @modkey.
- * @modkey must have key values filled in.
- *
- * Returns:
- * 	 0	success
- *	-1	failure, out of memeory
- *	-2	failure, @module not found or couldn't be removed
- */
-int semanage_module_remove_key(semanage_handle_t *sh,
-			       const semanage_module_key_t *modkey);
-
 #endif
-- 
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@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

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

* [PATCH 12/13] semodule: add priority, enabled, and extended listing
  2009-12-23 23:25                     ` [PATCH 11/13] libsemanage: new private api for unstable functions Caleb Case
@ 2009-12-23 23:25                       ` Caleb Case
  2009-12-23 23:26                         ` [PATCH 13/13] semanage store migration script Caleb Case
  0 siblings, 1 reply; 39+ messages in thread
From: Caleb Case @ 2009-12-23 23:25 UTC (permalink / raw)
  To: selinux; +Cc: csellers, kmacmillan, jwcart2, jbrindle, sds, Caleb Case

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@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

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

* [PATCH 13/13] semanage store migration script
  2009-12-23 23:25                       ` [PATCH 12/13] semodule: add priority, enabled, and extended listing Caleb Case
@ 2009-12-23 23:26                         ` Caleb Case
  2010-01-08 15:34                           ` Stephen Smalley
  0 siblings, 1 reply; 39+ messages in thread
From: Caleb Case @ 2009-12-23 23:26 UTC (permalink / raw)
  To: selinux; +Cc: csellers, kmacmillan, jwcart2, jbrindle, sds, Caleb Case

We created a migration script to ease the burden of transition from the
old libsemanage store layout to the new. The script will detect all the
stores in /etc/selinux using the old layout and convert them to the new
layout in /var/lib/selinux. It also allows you to specify the default
priority to use with -p and store to operate on with -s. After migration
the script by default will leave the old store unchanged, but can be
told to remove the old modules directory with -c.

Examples:

# Migrate all stores to the new layout.
migrate.py

Migrating from /etc/selinux/targeted/modules/active to /var/lib/selinux/targeted/active
Attempting to rebuild policy from /var/lib/selinux

# Migrate only the targeted store.
migrate.py -s targeted

Migrating from /etc/selinux/targeted/modules/active to /var/lib/selinux/targeted/active
Attempting to rebuild policy from /var/lib/selinux

# Migrate all, but install to priority 150.
migrate.py -p 150

Migrating from /etc/selinux/targeted/modules/active to /var/lib/selinux/targeted/active
Attempting to rebuild policy from /var/lib/selinux
---
 libsemanage/utils/semanage_migrate_etc_to_var.py |  301 ++++++++++++++++++++++
 1 files changed, 301 insertions(+), 0 deletions(-)
 create mode 100755 libsemanage/utils/semanage_migrate_etc_to_var.py

diff --git a/libsemanage/utils/semanage_migrate_etc_to_var.py b/libsemanage/utils/semanage_migrate_etc_to_var.py
new file mode 100755
index 0000000..71dd6f5
--- /dev/null
+++ b/libsemanage/utils/semanage_migrate_etc_to_var.py
@@ -0,0 +1,301 @@
+#!/usr/bin/python -E
+
+
+import os
+import errno
+import shutil
+import sys
+from optparse import OptionParser
+
+import bz2
+import ctypes
+
+sepol = ctypes.cdll.LoadLibrary('libsepol.so')
+
+try:
+	import selinux
+	import semanage
+except:
+	print >> sys.stderr, "You must install libselinux-python and libsemanage-python before running this tool"
+	exit(1)
+
+
+
+
+# For some reason this function doesn't exist in libselinux :\
+def copy_with_context(src, dst):
+	if DEBUG:
+		print "copying %s to %s" % (src, dst)
+	try:
+		con = selinux.lgetfilecon_raw(src)[1]
+	except:
+		print >> sys.stderr, "Could not get file context of %s" % src
+		exit(1)
+
+	try:
+		selinux.setfscreatecon_raw(con)
+	except:
+		print >> sys.stderr, "Could not set fs create context: %s" %con
+		exit(1)
+
+	try:
+		shutil.copy2(src, dst)
+	except OSError as (err, strerr):
+		print >> sys.stderr, "Could not copy %s to %s, %s" %(src, dst, strerr)
+
+def create_dir_from(src, dst, mode):
+	if DEBUG: print "Making directory %s" % dst
+	try:
+		con = selinux.lgetfilecon_raw(src)[1]
+		selinux.setfscreatecon_raw(con)
+		os.mkdir(dst, mode)	
+	except OSError as (err, stderr):
+		if err == errno.EEXIST:
+			pass
+		else:
+			print >> sys.stderr, "Error creating %s" % dst
+			exit(1)
+	
+def copy_module(store, name, con, base):
+	if DEBUG: print "Install module %s" % name	
+	(file, ext) = os.path.splitext(name)
+	if ext != ".pp":
+		# Stray non-pp file in modules directory, skip
+		print >> sys.stderr, "warning: %s has invalid extension, skipping" % name
+		return
+	try:
+		selinux.setfscreatecon_raw(con)
+	
+		if base:
+			root = oldstore_path(store)
+		else:
+			root = oldmodules_path(store)
+
+		bottomdir = bottomdir_path(store)
+			
+		# Special case "base" since you can have modules named base 
+		if base:
+			file = "_base"
+
+		os.mkdir("%s/%s" % (bottomdir, file))
+
+		copy_with_context(os.path.join(root, name), "%s/%s/%s%s" % (bottomdir, file, file, ext))
+
+		# This is the ext file that will eventually be used to choose a compiler
+		efile = open("%s/%s/lang_ext" % (bottomdir, file), "w+", 0600)
+		efile.write("pp")
+		efile.close()
+
+		# This is the version file that stores the version of the module
+		version = "1.0.0"
+		if not base:
+			try:
+				pf = ctypes.c_void_p()
+				sepol.sepol_policy_file_create(ctypes.byref(pf))
+
+				pbuffer = None
+				try:
+					pbuffer = bz2.BZ2File(os.path.join(root, name)).read()
+				except:
+					pbuffer = open(os.path.join(root, name)).read()
+
+				if (pbuffer == None):
+					raise Exception("Unable read policy file into memory.")
+
+				cbuffer = ctypes.create_string_buffer(pbuffer)
+				sepol.sepol_policy_file_set_mem(pf, cbuffer, len(cbuffer))
+
+				header_file_type = ctypes.c_int()
+				header_name = ctypes.c_char_p()
+				header_version = ctypes.c_char_p()
+
+				ret = sepol.sepol_module_package_info(pf, ctypes.byref(header_file_type), ctypes.byref(header_name), ctypes.byref(header_version))
+				if (ret != 0):
+					raise Exception("Unable to parse package header.")
+
+				version = header_version.value
+
+				sepol.sepol_policy_file_free(pf)
+
+			except Exception as e:
+				print >> sys.stderr, e
+				print >> sys.stderr, "warning: unable to determine version, using default value"
+
+		efile = open("%s/%s/version" % (bottomdir, file), "w+", 0600)
+		efile.write(version)
+		efile.close()
+
+	except:
+		print >> sys.stderr, "Error installing module %s" % name
+
+def migrate_store(store):
+
+	oldstore = oldstore_path(store);
+	oldmodules = oldmodules_path(store);
+	newstore = newstore_path(store);
+	newmodules = newmodules_path(store);
+	bottomdir = bottomdir_path(store);
+
+	print "Migrating from %s to %s" % (oldstore, newstore)
+
+	# Build up new directory structure
+	create_dir_from(selinux.selinux_policy_root(), "%s/%s" % (newroot_path(), store), 0755)
+	create_dir_from(oldmodules, newstore, 0700)
+	create_dir_from(oldstore, newmodules, 0700)
+	create_dir_from(oldstore, bottomdir, 0700)
+
+	# use whatever the file context of bottomdir is for the module directories
+	con = selinux.lgetfilecon_raw(bottomdir)[1]
+
+	# Special case for base since it was in a different location
+	copy_module(store, "base.pp", con, 1)
+
+	# Dir structure built, start copying files
+	for root, dirs, files in os.walk(oldstore):
+		if root == oldstore:
+			# This is the top level directory, need to move 
+			for name in files:
+				# Check to see if it is in TOPPATHS and copy if so
+				if name in TOPPATHS:
+					copy_with_context(os.path.join(root, name), os.path.join(newstore, name))
+
+		elif root == oldmodules:
+			# This should be the modules directory
+			for name in files:
+				copy_module(store, name, con, 0)
+
+def rebuild_policy():
+	# Ok, the modules are loaded, lets try to rebuild the policy
+	print "Attempting to rebuild policy from %s" % newroot_path()
+
+	curstore = selinux.selinux_getpolicytype()[1]
+
+	handle = semanage.semanage_handle_create()
+	if not handle:
+		print >> sys.stderr, "Could not create semanage handle"
+		exit(1)
+
+	semanage.semanage_select_store(handle, curstore, semanage.SEMANAGE_CON_DIRECT)
+
+	if not semanage.semanage_is_managed(handle):
+		semanage.semanage_handle_destroy(handle)
+		print >> sys.stderr, "SELinux policy is not managed or store cannot be accessed."
+		exit(1)
+
+	rc = semanage.semanage_access_check(handle)
+	if rc < semanage.SEMANAGE_CAN_WRITE:
+		semanage.semanage_handle_destroy(handle)
+		print >> sys.stderr, "Cannot write to policy store."
+		exit(1)
+
+	rc = semanage.semanage_connect(handle)
+	if rc < 0:
+		semanage.semanage_handle_destroy(handle)
+		print >> sys.stderr, "Could not establish semanage connection"
+		exit(1)
+
+	semanage.semanage_set_rebuild(handle, 1)
+
+	rc = semanage.semanage_begin_transaction(handle)
+	if rc < 0:
+		semanage.semanage_handle_destroy(handle)
+		print >> sys.stderr, "Could not begin transaction"
+		exit(1)
+
+	rc = semanage.semanage_commit(handle)
+	if rc < 0:
+		print >> sys.stderr, "Could not commit transaction"
+
+	semanage.semanage_handle_destroy(handle)
+
+
+def oldroot_path():
+	return "/etc/selinux"
+
+def oldstore_path(store):
+	return "%s/%s/modules/active" % (oldroot_path(), store)
+
+def oldmodules_path(store):
+	return "%s/modules" % oldstore_path(store)
+
+def newroot_path():
+	return "/var/lib/selinux"
+
+def newstore_path(store):
+	return "%s/%s/active" % (newroot_path(), store)
+
+def newmodules_path(store):
+	return "%s/modules" % newstore_path(store)
+
+def bottomdir_path(store):
+	return "%s/%s" % (newmodules_path(store), PRIORITY)
+
+
+if __name__ == "__main__":
+
+	parser = OptionParser()
+	parser.add_option("-p", "--priority", dest="priority", default="100",
+			  help="Set priority of modules in new store (default: 100)")
+	parser.add_option("-s", "--store", dest="store", default=None,
+			  help="Store to read from and write to")
+	parser.add_option("-d", "--debug", dest="debug", action="store_true", default=False,
+			  help="Output debug information")
+	parser.add_option("-c", "--clean", dest="clean", action="store_true", default=False,
+			  help="Clean old modules directory after migrate (default: no)")
+
+	(options, args) = parser.parse_args()
+
+	DEBUG = options.debug
+	PRIORITY = options.priority
+	TYPE = options.store
+	CLEAN = options.clean
+
+	# List of paths that go in the active 'root'
+	TOPPATHS = [
+		"file_contexts",
+		"homedir_template",
+		"file_contexts.template",
+		"commit_num",
+		"ports.local",
+		"interfaces.local",
+		"nodes.local",
+		"booleans.local",
+		"file_contexts.local",
+		"seusers",
+		"users.local",
+		"users_extra.local",
+		"seusers.final",
+		"users_extra",
+		"netfilter_contexts",
+		"file_contexts.homedirs",
+		"disable_dontaudit" ]
+
+
+	create_dir_from(oldroot_path(), newroot_path(), 0755)
+
+	stores = None
+	if TYPE is not None:
+		stores = [TYPE]
+	else:
+		stores = os.listdir(oldroot_path())
+
+	# find stores in oldroot and migrate them to newroot if necessary
+	for store in stores:
+		if not os.path.isdir(oldmodules_path(store)):
+			# already migrated or not an selinux store
+			continue
+
+		if os.path.isdir(newstore_path(store)):
+			# store has already been migrated, but old modules dir still exits
+			print >> sys.stderr, "warning: Policy type %s has already been migrated, but modules still exist in the old store. Skipping store." % store
+			continue
+
+		migrate_store(store)
+
+		if CLEAN is True:
+			def remove_error(function, path, execinfo):
+				print >> sys.stderr, "warning: Unable to remove old store modules directory %s. Cleaning failed." % oldmodules_path(store)
+			shutil.rmtree(oldmodules_path(store), onerror=remove_error)
+
+	rebuild_policy()
+
-- 
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@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

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

* Re: [PATCH 00/13] RFC libsemanage move to var, enable/disable module, and priority support
  2009-12-23 23:25 [PATCH 00/13] RFC libsemanage move to var, enable/disable module, and priority support Caleb Case
  2009-12-23 23:25 ` [PATCH 01/13] libsemanage: fix typo in tests makefile -o -> -O Caleb Case
@ 2010-01-07 22:28 ` Chad Sellers
  2010-01-08 14:30   ` James Carter
  1 sibling, 1 reply; 39+ messages in thread
From: Chad Sellers @ 2010-01-07 22:28 UTC (permalink / raw)
  To: Caleb Case, selinux; +Cc: kmacmillan, jwcart2, jbrindle, Stephen Smalley

On 12/23/09 6:25 PM, "Caleb Case" <ccase@tresys.com> wrote:

> Our motivations for this patchset are to:
> 
> * Move the semanage store - the portion of the SELinux configuration
>   managed by libsemanage - to a more appropriate location in the
>   filesystem. The current location - in /etc - is designated for
>   administrator controlled configuration and is sometimes mounted
>   read-only. By storing binary, program managed data in /etc libsemanage
>   breaks administrator expectations.
> 
> * Enable the overriding of modules in the module store without require
>   the original modules to removed or modified. This allows
>   administrators to customize the policy more fully while allowing the
>   distribution provided policies to be left unmodified and continue to
>   be updated by the package manager.
> 
> * Provide the ability for an administrator to disable a module without
>   removing or overriding that module.
> 
> [Move to /var/lib/selinux]
> 
> Move the libsemanage private store
> from /etc/selinux/<policy type>/modules
> to   /var/lib/selinux/<policy type>
> 
> The benefits of this are:
> 
> * Permits the use of a read-only /etc.
> 
> * Conforms to the Filesystem Hierarchy Standard.
> 
> An additional change in layout structure moves the temporary space for
> the active policy to an external temporary space. This has the benefit
> of permitting source control management to be used on the private
> policy.
> 
> [Module Priorities]
> 
> Module priorities modify libsemanage and the module store to allow
> multiple modules with the same name to exist with different priorities.
> Only the highest priority module is used to create the final system
> policy. The addition of module priorities enables the modification of
> the system policy without modifying individual modules. For example, it
> allows an administrator to add his own policy module for apache,
> completely replacing the distribution provided module, without changing
> or removing the distribution policy. This has several benefits:
> 
> * Distribution provided policy package updates proceed normally - the
>   distribution policy is inserted but the administrator provided policy
>   remains active.
> 
> * Multiple levels allows distributors, 3rd party applications, system
>   management tools (e.g., puppet), and local administrators to all make
>   changes without conflicting.
> 
> * Semanage modifications of policy (e.g., port labeling) will be able to
>   use high priority modules in the future to override defaults (requires
>   the CIL[1] language changes).
> 
> [Enable/Disable Modules]
> 
> Modules gain an enabled / disabled status. Enabled modules are used by
> semanage when building the active policy, and disabled modules are
> ignored. The main benefit of this is that modules can be disabled
> without out removing them from the store.
> 
> [Patchset Breakdown]
> 
> The patchset is broken down as follows:
> 
> Bug fixes:
> 
> libsemanage: fix type in tests makefile -o -> -O
> 
> Move the libsemanage store to /var/lib/selinux:
> 
> semanage: move permissive module creation to /tmp
> libsemanage: move the module store to /var/lib/selinux
> libsemanage: split final files into /var/lib/selinux/tmp
> libsemanage: update unit tests for move to /var/lib/selinux
> 
> Implement support for the new libsemanage store layout:
> 
> libsemanage: add default priority to semanage_handle_t
> libsemanage: augment semanage_module_info_t and provide semanage_module_key_t
> libsemanage: get/set module info and enabled status
> libsemanage: provide function to get new base module path
> libsemanage: provide function to get new base module path
> libsemanage: installing/upgrading/removing modules via info and key
> 
> Provide private headers for upstream tools to use:
> 
> libsemanage: new private api for unstable functions
> 
> Extend semodule to support enable/disable, priorities, and detailed listings:
> 
> semodule: add priority, enabled, and extended listing
> 
> Migration script for moving the libsemanage store:
> 
> semanage store migration script
> 
> Thanks for you feedback!
> 
> Caleb
> 
> [1] CIL RFC: http://marc.info/?l=selinux&m=124759244409438&w=2
> 
> Caleb Case (13):
>   libsemanage: fix typo in tests makefile -o -> -O
>   semanage: move permissive module creation to /tmp
>   libsemanage: move the module store to /var/lib/selinux
>   libsemanage: split final files into /var/lib/selinux/tmp
>   libsemanage: update unit tests for move to /var/lib/selinux
>   libsemanage: add default priority to semanage_handle_t
>   libsemanage: augment semanage_module_info_t and provide
>     semanage_module_key_t
>   libsemanage: get/set module info and enabled status
>   libsemanage: provide function to get new base module path
>   libsemanage: installing/upgrading/removing modules via info and key
>   libsemanage: new private api for unstable functions
>   semodule: add priority, enabled, and extended listing
>   semanage store migration script
> 
>  libsemanage/include/Makefile                     |    3 +
>  libsemanage/include/semanage/private/handle.h    |   31 +
>  libsemanage/include/semanage/private/modules.h   |  281 ++++
>  libsemanage/include/semanage/private/semanage.h  |   26 +
>  libsemanage/src/boolean_internal.h               |    4 +-
>  libsemanage/src/booleans_file.c                  |    7 +-
>  libsemanage/src/booleans_policydb.c              |    6 +-
>  libsemanage/src/database_file.c                  |   45 +-
>  libsemanage/src/database_file.h                  |    3 +-
>  libsemanage/src/database_policydb.c              |   37 +-
>  libsemanage/src/database_policydb.h              |    3 +-
>  libsemanage/src/direct_api.c                     | 1652
> +++++++++++++++++++---
>  libsemanage/src/fcontext_internal.h              |    3 +-
>  libsemanage/src/fcontexts_file.c                 |    7 +-
>  libsemanage/src/genhomedircon.c                  |    3 +-
>  libsemanage/src/handle.c                         |   23 +
>  libsemanage/src/handle.h                         |    3 +
>  libsemanage/src/handle_internal.h                |    1 +
>  libsemanage/src/iface_internal.h                 |    4 +-
>  libsemanage/src/interfaces_file.c                |    7 +-
>  libsemanage/src/interfaces_policydb.c            |    6 +-
>  libsemanage/src/libsemanage.map                  |   26 +
>  libsemanage/src/module_internal.h                |   21 +
>  libsemanage/src/modules.c                        |  999 +++++++++++++-
>  libsemanage/src/modules.h                        |   76 +-
>  libsemanage/src/node_internal.h                  |    4 +-
>  libsemanage/src/nodes_file.c                     |    7 +-
>  libsemanage/src/nodes_policydb.c                 |    6 +-
>  libsemanage/src/policy.h                         |   36 +
>  libsemanage/src/port_internal.h                  |    4 +-
>  libsemanage/src/ports_file.c                     |    7 +-
>  libsemanage/src/ports_policydb.c                 |    6 +-
>  libsemanage/src/semanage_store.c                 |  794 ++++++++---
>  libsemanage/src/semanage_store.h                 |   47 +-
>  libsemanage/src/seuser_internal.h                |    4 +-
>  libsemanage/src/seusers_file.c                   |    7 +-
>  libsemanage/src/user_internal.h                  |    6 +-
>  libsemanage/src/users_base_file.c                |    7 +-
>  libsemanage/src/users_base_policydb.c            |    6 +-
>  libsemanage/src/users_extra_file.c               |    7 +-
>  libsemanage/tests/Makefile                       |    2 +-
>  libsemanage/tests/test_semanage_store.c          |   34 +-
>  libsemanage/utils/semanage_migrate_etc_to_var.py |  301 ++++
>  policycoreutils/semanage/seobject.py             |   15 +-
>  policycoreutils/semodule/semodule.8              |   25 +-
>  policycoreutils/semodule/semodule.c              |  242 +++-
>  46 files changed, 4267 insertions(+), 577 deletions(-)
>  create mode 100644 libsemanage/include/semanage/private/handle.h
>  create mode 100644 libsemanage/include/semanage/private/modules.h
>  create mode 100644 libsemanage/include/semanage/private/semanage.h
>  create mode 100755 libsemanage/utils/semanage_migrate_etc_to_var.py
> 
Well, there have been no comments on this patchset. I'm guessing that's
because:

1) We've talked to some of you face to face about it already.
2) It's a big patchset, and you'd want to try it out a bit before
commenting.

To address #2, I'd like to propose creating an upstream branch for these
changes. This patchset is actually just the first patchset in a larger
effort to improve policy infrastructure. I think an upstream branch will
make it easier for many people to track those changes and try out the new
features we're creating. Eventually that branch can be merged back into
master.

Thoughts?

Thanks,
Chad Sellers
 
Oh, and in case it wasn't implied:
Acked-by: Chad Sellers <csellers@tresys.com>


--
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] 39+ messages in thread

* Re: [PATCH 03/13] libsemanage: move the module store to /var/lib/selinux
  2009-12-23 23:25     ` [PATCH 03/13] libsemanage: move the module store to /var/lib/selinux Caleb Case
  2009-12-23 23:25       ` [PATCH 04/13] libsemanage: split final files into /var/lib/selinux/tmp Caleb Case
@ 2010-01-08 14:28       ` Stephen Smalley
  2010-01-08 14:50         ` James Carter
  1 sibling, 1 reply; 39+ messages in thread
From: Stephen Smalley @ 2010-01-08 14:28 UTC (permalink / raw)
  To: Caleb Case; +Cc: selinux, csellers, kmacmillan, jwcart2, jbrindle

On Wed, 2009-12-23 at 18:25 -0500, Caleb Case wrote:
> This patch moves the module store from /etc/selinux/<store>/modules to
> /var/lib/selinux/<store>.

Can the path prefix (i.e. /var/lib/selinux) be made configurable?

> This move will allow for the use of a read-only /etc/selinux. Currently
> that is not possible with semanage because of the lock files.
> 
> A consequence of this move is that packagers of libsemanage should
> create the /var/lib/selinux directory.
> ---
>  libsemanage/src/direct_api.c     |   20 ++----------------
>  libsemanage/src/semanage_store.c |   39 ++++++++++++++++++++++++-------------
>  libsemanage/src/semanage_store.h |    5 +++-
>  3 files changed, 32 insertions(+), 32 deletions(-)
> 
> diff --git a/libsemanage/src/direct_api.c b/libsemanage/src/direct_api.c
> index f09c7cf..5fb4523 100644
> --- a/libsemanage/src/direct_api.c
> +++ b/libsemanage/src/direct_api.c
> @@ -89,12 +89,7 @@ static struct semanage_policy_table direct_funcs = {
>  
>  int semanage_direct_is_managed(semanage_handle_t * sh)
>  {
> -	char polpath[PATH_MAX];
> -
> -	snprintf(polpath, PATH_MAX, "%s%s", selinux_path(),
> -		 sh->conf->store_path);
> -
> -	if (semanage_check_init(polpath))
> +	if (semanage_check_init(sh, semanage_root_path()))
>  		goto err;
>  
>  	if (semanage_access_check(sh) < 0)
> @@ -111,13 +106,9 @@ int semanage_direct_is_managed(semanage_handle_t * sh)
>   */
>  int semanage_direct_connect(semanage_handle_t * sh)
>  {
> -	char polpath[PATH_MAX];
>  	const char *path;
>  
> -	snprintf(polpath, PATH_MAX, "%s%s", selinux_path(),
> -		 sh->conf->store_path);
> -
> -	if (semanage_check_init(polpath))
> +	if (semanage_check_init(sh, semanage_root_path()))
>  		goto err;
>  
>  	if (sh->create_store)
> @@ -1416,12 +1407,7 @@ static int semanage_direct_list(semanage_handle_t * sh,
>  
>  int semanage_direct_access_check(semanage_handle_t * sh)
>  {
> -	char polpath[PATH_MAX];
> -
> -	snprintf(polpath, PATH_MAX, "%s%s", selinux_path(),
> -		 sh->conf->store_path);
> -
> -	if (semanage_check_init(polpath))
> +	if (semanage_check_init(sh, semanage_root_path()))
>  		return -1;
>  
>  	return semanage_store_access_check(sh);
> diff --git a/libsemanage/src/semanage_store.c b/libsemanage/src/semanage_store.c
> index 0a55ce0..049818a 100644
> --- a/libsemanage/src/semanage_store.c
> +++ b/libsemanage/src/semanage_store.c
> @@ -3,8 +3,9 @@
>   *	    Jason Tang <jtang@tresys.com>
>   *          Christopher Ashworth <cashworth@tresys.com>
>   *          Chris PeBenito <cpebenito@tresys.com>
> + *	    Caleb Case <ccase@tresys.com>
>   *
> - * Copyright (C) 2004-2006 Tresys Technology, LLC
> + * Copyright (C) 2004-2006,2009 Tresys Technology, LLC
>   * Copyright (C) 2005 Red Hat, Inc.
>   *
>   *  This library is free software; you can redistribute it and/or
> @@ -88,8 +89,6 @@ static const char *semanage_store_paths[SEMANAGE_NUM_STORES] = {
>  	"/tmp"
>  };
>  
> -/* this is the module store path relative to selinux_policy_root() */
> -#define SEMANAGE_MOD_DIR "/modules"
>  /* relative path names to enum sandbox_paths for special files within
>   * a sandbox */
>  static const char *semanage_sandbox_paths[SEMANAGE_STORE_NUM_PATHS] = {
> @@ -157,14 +156,14 @@ static int semanage_init_paths(const char *root)
>  	if (!root)
>  		return -1;
>  
> -	prefix_len = (strlen(root) + strlen(SEMANAGE_MOD_DIR));
> +	prefix_len = strlen(root);
>  
>  	for (i = 0; i < SEMANAGE_NUM_FILES; i++) {
>  		len = (strlen(semanage_relative_files[i]) + prefix_len);
>  		semanage_files[i] = calloc(len + 1, sizeof(char));
>  		if (!semanage_files[i])
>  			return -1;
> -		sprintf(semanage_files[i], "%s%s%s", root, SEMANAGE_MOD_DIR,
> +		sprintf(semanage_files[i], "%s%s", root,
>  			semanage_relative_files[i]);
>  	}
>  
> @@ -186,16 +185,11 @@ static int semanage_init_store_paths(const char *root)
>  	int i, j;
>  	size_t len;
>  	size_t prefix_len;
> -	char *prefix;
>  
>  	if (!root)
>  		return -1;
>  
> -	prefix_len = (strlen(root) + strlen(SEMANAGE_MOD_DIR));
> -	prefix = calloc(prefix_len + 1, sizeof(char));
> -	if (!prefix)
> -		return -1;
> -	sprintf(prefix, "%s%s", root, SEMANAGE_MOD_DIR);
> +	prefix_len = strlen(root);
>  
>  	for (i = 0; i < SEMANAGE_NUM_STORES; i++) {
>  		for (j = 0; j < SEMANAGE_STORE_NUM_PATHS; j++) {
> @@ -204,14 +198,13 @@ static int semanage_init_store_paths(const char *root)
>  			semanage_paths[i][j] = calloc(len + 1, sizeof(char));
>  			if (!semanage_paths[i][j])
>  				goto cleanup;
> -			sprintf(semanage_paths[i][j], "%s%s%s", prefix,
> +			sprintf(semanage_paths[i][j], "%s%s%s", root,
>  				semanage_store_paths[i],
>  				semanage_sandbox_paths[j]);
>  		}
>  	}
>  
>        cleanup:
> -	free(prefix);
>  	return 0;
>  }
>  
> @@ -223,16 +216,28 @@ static int semanage_init_store_paths(const char *root)
>   *
>   * Note that this function is NOT thread-safe.
>   */
> -int semanage_check_init(const char *root)
> +int semanage_check_init(semanage_handle_t *sh, const char *prefix)
>  {
>  	int rc;
>  	if (semanage_paths_initialized == 0) {
> +		char root[PATH_MAX];
> +
> +		rc = snprintf(root,
> +			      sizeof(root),
> +			      "%s/%s",
> +			      prefix,
> +			      sh->conf->store_path);
> +		if (rc < 0 || rc >= (int)sizeof(root))
> +			return -1;
> +
>  		rc = semanage_init_paths(root);
>  		if (rc)
>  			return rc;
> +
>  		rc = semanage_init_store_paths(root);
>  		if (rc)
>  			return rc;
> +
>  		semanage_paths_initialized = 1;
>  	}
>  	return 0;
> @@ -259,6 +264,12 @@ const char *semanage_path(enum semanage_store_defs store,
>  	return semanage_paths[store][path_name];
>  }
>  
> +/* Return the root of the semanage store. */
> +const char *semanage_root_path(void)
> +{
> +	return "/var/lib/selinux";
> +}
> +
>  /* Return a fully-qualified path + filename to the semanage
>   * configuration file.  The caller must not alter the string returned
>   * (and hence why this function return type is const).
> diff --git a/libsemanage/src/semanage_store.h b/libsemanage/src/semanage_store.h
> index 112edb6..c76ecfe 100644
> --- a/libsemanage/src/semanage_store.h
> +++ b/libsemanage/src/semanage_store.h
> @@ -62,11 +62,14 @@ enum semanage_sandbox_defs {
>  	SEMANAGE_STORE_NUM_PATHS
>  };
>  
> +const char *semanage_root_path(void);
> +
>  /* FIXME: this needs to be made a module store specific init and the
>   * global configuration moved to another file.
>   */
>  const char *semanage_conf_path(void);
> -int semanage_check_init(const char *root);
> +
> +int semanage_check_init(semanage_handle_t *sh, const char *prefix);
>  
>  extern const char *semanage_fname(enum semanage_sandbox_defs file_enum);
>  
-- 
Stephen Smalley
National Security Agency


--
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] 39+ messages in thread

* Re: [PATCH 00/13] RFC libsemanage move to var, enable/disable module, and priority support
  2010-01-07 22:28 ` [PATCH 00/13] RFC libsemanage move to var, enable/disable module, and priority support Chad Sellers
@ 2010-01-08 14:30   ` James Carter
  2010-01-21 21:06     ` Chad Sellers
  0 siblings, 1 reply; 39+ messages in thread
From: James Carter @ 2010-01-08 14:30 UTC (permalink / raw)
  To: Chad Sellers; +Cc: Caleb Case, selinux, kmacmillan, jbrindle, Stephen Smalley

On Thu, 2010-01-07 at 17:28 -0500, Chad Sellers wrote:
> On 12/23/09 6:25 PM, "Caleb Case" <ccase@tresys.com> wrote:
> 
> > Our motivations for this patchset are to:
> > 
> > * Move the semanage store - the portion of the SELinux configuration
> >   managed by libsemanage - to a more appropriate location in the
> >   filesystem. The current location - in /etc - is designated for
> >   administrator controlled configuration and is sometimes mounted
> >   read-only. By storing binary, program managed data in /etc libsemanage
> >   breaks administrator expectations.
> > 
> > * Enable the overriding of modules in the module store without require
> >   the original modules to removed or modified. This allows
> >   administrators to customize the policy more fully while allowing the
> >   distribution provided policies to be left unmodified and continue to
> >   be updated by the package manager.
> > 
> > * Provide the ability for an administrator to disable a module without
> >   removing or overriding that module.
> > 
> > [Move to /var/lib/selinux]
> > 
> > Move the libsemanage private store
> > from /etc/selinux/<policy type>/modules
> > to   /var/lib/selinux/<policy type>
> > 
> > The benefits of this are:
> > 
> > * Permits the use of a read-only /etc.
> > 
> > * Conforms to the Filesystem Hierarchy Standard.
> > 
> > An additional change in layout structure moves the temporary space for
> > the active policy to an external temporary space. This has the benefit
> > of permitting source control management to be used on the private
> > policy.
> > 
> > [Module Priorities]
> > 
> > Module priorities modify libsemanage and the module store to allow
> > multiple modules with the same name to exist with different priorities.
> > Only the highest priority module is used to create the final system
> > policy. The addition of module priorities enables the modification of
> > the system policy without modifying individual modules. For example, it
> > allows an administrator to add his own policy module for apache,
> > completely replacing the distribution provided module, without changing
> > or removing the distribution policy. This has several benefits:
> > 
> > * Distribution provided policy package updates proceed normally - the
> >   distribution policy is inserted but the administrator provided policy
> >   remains active.
> > 
> > * Multiple levels allows distributors, 3rd party applications, system
> >   management tools (e.g., puppet), and local administrators to all make
> >   changes without conflicting.
> > 
> > * Semanage modifications of policy (e.g., port labeling) will be able to
> >   use high priority modules in the future to override defaults (requires
> >   the CIL[1] language changes).
> > 
> > [Enable/Disable Modules]
> > 
> > Modules gain an enabled / disabled status. Enabled modules are used by
> > semanage when building the active policy, and disabled modules are
> > ignored. The main benefit of this is that modules can be disabled
> > without out removing them from the store.
> > 
> > [Patchset Breakdown]
> > 
> > The patchset is broken down as follows:
> > 
> > Bug fixes:
> > 
> > libsemanage: fix type in tests makefile -o -> -O
> > 
> > Move the libsemanage store to /var/lib/selinux:
> > 
> > semanage: move permissive module creation to /tmp
> > libsemanage: move the module store to /var/lib/selinux
> > libsemanage: split final files into /var/lib/selinux/tmp
> > libsemanage: update unit tests for move to /var/lib/selinux
> > 
> > Implement support for the new libsemanage store layout:
> > 
> > libsemanage: add default priority to semanage_handle_t
> > libsemanage: augment semanage_module_info_t and provide semanage_module_key_t
> > libsemanage: get/set module info and enabled status
> > libsemanage: provide function to get new base module path
> > libsemanage: provide function to get new base module path
> > libsemanage: installing/upgrading/removing modules via info and key
> > 
> > Provide private headers for upstream tools to use:
> > 
> > libsemanage: new private api for unstable functions
> > 
> > Extend semodule to support enable/disable, priorities, and detailed listings:
> > 
> > semodule: add priority, enabled, and extended listing
> > 
> > Migration script for moving the libsemanage store:
> > 
> > semanage store migration script
> > 
> > Thanks for you feedback!
> > 
> > Caleb
> > 
> > [1] CIL RFC: http://marc.info/?l=selinux&m=124759244409438&w=2
> > 
> > Caleb Case (13):
> >   libsemanage: fix typo in tests makefile -o -> -O
> >   semanage: move permissive module creation to /tmp
> >   libsemanage: move the module store to /var/lib/selinux
> >   libsemanage: split final files into /var/lib/selinux/tmp
> >   libsemanage: update unit tests for move to /var/lib/selinux
> >   libsemanage: add default priority to semanage_handle_t
> >   libsemanage: augment semanage_module_info_t and provide
> >     semanage_module_key_t
> >   libsemanage: get/set module info and enabled status
> >   libsemanage: provide function to get new base module path
> >   libsemanage: installing/upgrading/removing modules via info and key
> >   libsemanage: new private api for unstable functions
> >   semodule: add priority, enabled, and extended listing
> >   semanage store migration script
> > 
> >  libsemanage/include/Makefile                     |    3 +
> >  libsemanage/include/semanage/private/handle.h    |   31 +
> >  libsemanage/include/semanage/private/modules.h   |  281 ++++
> >  libsemanage/include/semanage/private/semanage.h  |   26 +
> >  libsemanage/src/boolean_internal.h               |    4 +-
> >  libsemanage/src/booleans_file.c                  |    7 +-
> >  libsemanage/src/booleans_policydb.c              |    6 +-
> >  libsemanage/src/database_file.c                  |   45 +-
> >  libsemanage/src/database_file.h                  |    3 +-
> >  libsemanage/src/database_policydb.c              |   37 +-
> >  libsemanage/src/database_policydb.h              |    3 +-
> >  libsemanage/src/direct_api.c                     | 1652
> > +++++++++++++++++++---
> >  libsemanage/src/fcontext_internal.h              |    3 +-
> >  libsemanage/src/fcontexts_file.c                 |    7 +-
> >  libsemanage/src/genhomedircon.c                  |    3 +-
> >  libsemanage/src/handle.c                         |   23 +
> >  libsemanage/src/handle.h                         |    3 +
> >  libsemanage/src/handle_internal.h                |    1 +
> >  libsemanage/src/iface_internal.h                 |    4 +-
> >  libsemanage/src/interfaces_file.c                |    7 +-
> >  libsemanage/src/interfaces_policydb.c            |    6 +-
> >  libsemanage/src/libsemanage.map                  |   26 +
> >  libsemanage/src/module_internal.h                |   21 +
> >  libsemanage/src/modules.c                        |  999 +++++++++++++-
> >  libsemanage/src/modules.h                        |   76 +-
> >  libsemanage/src/node_internal.h                  |    4 +-
> >  libsemanage/src/nodes_file.c                     |    7 +-
> >  libsemanage/src/nodes_policydb.c                 |    6 +-
> >  libsemanage/src/policy.h                         |   36 +
> >  libsemanage/src/port_internal.h                  |    4 +-
> >  libsemanage/src/ports_file.c                     |    7 +-
> >  libsemanage/src/ports_policydb.c                 |    6 +-
> >  libsemanage/src/semanage_store.c                 |  794 ++++++++---
> >  libsemanage/src/semanage_store.h                 |   47 +-
> >  libsemanage/src/seuser_internal.h                |    4 +-
> >  libsemanage/src/seusers_file.c                   |    7 +-
> >  libsemanage/src/user_internal.h                  |    6 +-
> >  libsemanage/src/users_base_file.c                |    7 +-
> >  libsemanage/src/users_base_policydb.c            |    6 +-
> >  libsemanage/src/users_extra_file.c               |    7 +-
> >  libsemanage/tests/Makefile                       |    2 +-
> >  libsemanage/tests/test_semanage_store.c          |   34 +-
> >  libsemanage/utils/semanage_migrate_etc_to_var.py |  301 ++++
> >  policycoreutils/semanage/seobject.py             |   15 +-
> >  policycoreutils/semodule/semodule.8              |   25 +-
> >  policycoreutils/semodule/semodule.c              |  242 +++-
> >  46 files changed, 4267 insertions(+), 577 deletions(-)
> >  create mode 100644 libsemanage/include/semanage/private/handle.h
> >  create mode 100644 libsemanage/include/semanage/private/modules.h
> >  create mode 100644 libsemanage/include/semanage/private/semanage.h
> >  create mode 100755 libsemanage/utils/semanage_migrate_etc_to_var.py
> > 
> Well, there have been no comments on this patchset. I'm guessing that's
> because:
> 
> 1) We've talked to some of you face to face about it already.
> 2) It's a big patchset, and you'd want to try it out a bit before
> commenting.
> 
I've been trying it out for the last few days.  I haven't had any
problems yet.

> To address #2, I'd like to propose creating an upstream branch for these
> changes. This patchset is actually just the first patchset in a larger
> effort to improve policy infrastructure. I think an upstream branch will
> make it easier for many people to track those changes and try out the new
> features we're creating. Eventually that branch can be merged back into
> master.
> 
> Thoughts?

I think that creating an upstream branch would be a good idea.

> 
> Thanks,
> Chad Sellers
>  
> Oh, and in case it wasn't implied:
> Acked-by: Chad Sellers <csellers@tresys.com>
> 
> 
> --
> 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.

-- 
James Carter <jwcart2@tycho.nsa.gov>
National Security Agency


--
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] 39+ messages in thread

* Re: [PATCH 04/13] libsemanage: split final files into /var/lib/selinux/tmp
  2009-12-23 23:25       ` [PATCH 04/13] libsemanage: split final files into /var/lib/selinux/tmp Caleb Case
  2009-12-23 23:25         ` [PATCH 05/13] libsemanage: update unit tests for move to /var/lib/selinux Caleb Case
@ 2010-01-08 14:30         ` Stephen Smalley
  2010-01-08 15:07           ` James Carter
  1 sibling, 1 reply; 39+ messages in thread
From: Stephen Smalley @ 2010-01-08 14:30 UTC (permalink / raw)
  To: Caleb Case; +Cc: selinux, csellers, kmacmillan, jwcart2, jbrindle

On Wed, 2009-12-23 at 18:25 -0500, Caleb Case wrote:
> This patch moves the final files from inside
> /var/lib/selinux/<store>/[active|previous|tmp] to
> /var/lib/selinux/tmp/<store>. The move is done to facilitate using
> source control management on the /var/lib/selinux/<store> directory. If
> these files remain in /var/lib/selinux/<store> they will pose a size
> problem if an SCM like git is used as we'd be storing lots of binary
> diffs. We are suggesting making this change now, rather than later when
> source policy, SCM, and CIL[1] support are available, to ease the
> migration burden.
> 
> These are the files that have been moved:
> 
> /var/lib/selinux/<store>/active/...	/var/lib/selinux/tmp/<store>/...
> 
> file_contexts				contexts/files/file_contexts
> file_contexts.homedirs			contexts/files/file_contexts.homedirs
> file_contexts.local			contexts/files/file_contexts.local
> netfilter_contexts			contexts/netfilter_contexts
> policy.kern				policy/policy.<policyversion>
> seusers.final				seusers
> 
> The layout of these files in /var/lib/selinux/tmp/<store> is designed to
> mirror their locations in /etc/selinux/<store>. This should help clarify
> the relationship between these final files and the files installed in
> etc.
> 
> One consequence of this move is that reverting to the previous policy
> version requires a policy rebuild. Currently you can revert without
> rebuilding.

That seems a little worrisome to me, as a rebuild might fail, e.g. what
happens if we abort a transaction due to a lack of disk space and then
try to revert, requiring a rebuild, only to run out of space during the
rebuild?

-- 
Stephen Smalley
National Security Agency


--
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] 39+ messages in thread

* Re: [PATCH 03/13] libsemanage: move the module store to /var/lib/selinux
  2010-01-08 14:28       ` [PATCH 03/13] libsemanage: move the module store to /var/lib/selinux Stephen Smalley
@ 2010-01-08 14:50         ` James Carter
  2010-01-08 15:19           ` Stephen Smalley
  0 siblings, 1 reply; 39+ messages in thread
From: James Carter @ 2010-01-08 14:50 UTC (permalink / raw)
  To: Stephen Smalley; +Cc: Caleb Case, selinux, csellers, kmacmillan, jbrindle

On Fri, 2010-01-08 at 09:28 -0500, Stephen Smalley wrote:
> On Wed, 2009-12-23 at 18:25 -0500, Caleb Case wrote:
> > This patch moves the module store from /etc/selinux/<store>/modules to
> > /var/lib/selinux/<store>.
> 
> Can the path prefix (i.e. /var/lib/selinux) be made configurable?
> 
There would be no other prefixes other than /var/lib/selinux
or /etc/selinux, or do you have something else in mind?

I guess that you are thinking of backwards compatibility, but you still
won't have it even if you change the prefix because the directory
structure is different (priority directories and such).  I don't see
what you would gain with changing the prefix.

> > This move will allow for the use of a read-only /etc/selinux. Currently
> > that is not possible with semanage because of the lock files.
> > 
> > A consequence of this move is that packagers of libsemanage should
> > create the /var/lib/selinux directory.
> > ---
> >  libsemanage/src/direct_api.c     |   20 ++----------------
> >  libsemanage/src/semanage_store.c |   39 ++++++++++++++++++++++++-------------
> >  libsemanage/src/semanage_store.h |    5 +++-
> >  3 files changed, 32 insertions(+), 32 deletions(-)
> > 
> > diff --git a/libsemanage/src/direct_api.c b/libsemanage/src/direct_api.c
> > index f09c7cf..5fb4523 100644
> > --- a/libsemanage/src/direct_api.c
> > +++ b/libsemanage/src/direct_api.c
> > @@ -89,12 +89,7 @@ static struct semanage_policy_table direct_funcs = {
> >  
> >  int semanage_direct_is_managed(semanage_handle_t * sh)
> >  {
> > -	char polpath[PATH_MAX];
> > -
> > -	snprintf(polpath, PATH_MAX, "%s%s", selinux_path(),
> > -		 sh->conf->store_path);
> > -
> > -	if (semanage_check_init(polpath))
> > +	if (semanage_check_init(sh, semanage_root_path()))
> >  		goto err;
> >  
> >  	if (semanage_access_check(sh) < 0)
> > @@ -111,13 +106,9 @@ int semanage_direct_is_managed(semanage_handle_t * sh)
> >   */
> >  int semanage_direct_connect(semanage_handle_t * sh)
> >  {
> > -	char polpath[PATH_MAX];
> >  	const char *path;
> >  
> > -	snprintf(polpath, PATH_MAX, "%s%s", selinux_path(),
> > -		 sh->conf->store_path);
> > -
> > -	if (semanage_check_init(polpath))
> > +	if (semanage_check_init(sh, semanage_root_path()))
> >  		goto err;
> >  
> >  	if (sh->create_store)
> > @@ -1416,12 +1407,7 @@ static int semanage_direct_list(semanage_handle_t * sh,
> >  
> >  int semanage_direct_access_check(semanage_handle_t * sh)
> >  {
> > -	char polpath[PATH_MAX];
> > -
> > -	snprintf(polpath, PATH_MAX, "%s%s", selinux_path(),
> > -		 sh->conf->store_path);
> > -
> > -	if (semanage_check_init(polpath))
> > +	if (semanage_check_init(sh, semanage_root_path()))
> >  		return -1;
> >  
> >  	return semanage_store_access_check(sh);
> > diff --git a/libsemanage/src/semanage_store.c b/libsemanage/src/semanage_store.c
> > index 0a55ce0..049818a 100644
> > --- a/libsemanage/src/semanage_store.c
> > +++ b/libsemanage/src/semanage_store.c
> > @@ -3,8 +3,9 @@
> >   *	    Jason Tang <jtang@tresys.com>
> >   *          Christopher Ashworth <cashworth@tresys.com>
> >   *          Chris PeBenito <cpebenito@tresys.com>
> > + *	    Caleb Case <ccase@tresys.com>
> >   *
> > - * Copyright (C) 2004-2006 Tresys Technology, LLC
> > + * Copyright (C) 2004-2006,2009 Tresys Technology, LLC
> >   * Copyright (C) 2005 Red Hat, Inc.
> >   *
> >   *  This library is free software; you can redistribute it and/or
> > @@ -88,8 +89,6 @@ static const char *semanage_store_paths[SEMANAGE_NUM_STORES] = {
> >  	"/tmp"
> >  };
> >  
> > -/* this is the module store path relative to selinux_policy_root() */
> > -#define SEMANAGE_MOD_DIR "/modules"
> >  /* relative path names to enum sandbox_paths for special files within
> >   * a sandbox */
> >  static const char *semanage_sandbox_paths[SEMANAGE_STORE_NUM_PATHS] = {
> > @@ -157,14 +156,14 @@ static int semanage_init_paths(const char *root)
> >  	if (!root)
> >  		return -1;
> >  
> > -	prefix_len = (strlen(root) + strlen(SEMANAGE_MOD_DIR));
> > +	prefix_len = strlen(root);
> >  
> >  	for (i = 0; i < SEMANAGE_NUM_FILES; i++) {
> >  		len = (strlen(semanage_relative_files[i]) + prefix_len);
> >  		semanage_files[i] = calloc(len + 1, sizeof(char));
> >  		if (!semanage_files[i])
> >  			return -1;
> > -		sprintf(semanage_files[i], "%s%s%s", root, SEMANAGE_MOD_DIR,
> > +		sprintf(semanage_files[i], "%s%s", root,
> >  			semanage_relative_files[i]);
> >  	}
> >  
> > @@ -186,16 +185,11 @@ static int semanage_init_store_paths(const char *root)
> >  	int i, j;
> >  	size_t len;
> >  	size_t prefix_len;
> > -	char *prefix;
> >  
> >  	if (!root)
> >  		return -1;
> >  
> > -	prefix_len = (strlen(root) + strlen(SEMANAGE_MOD_DIR));
> > -	prefix = calloc(prefix_len + 1, sizeof(char));
> > -	if (!prefix)
> > -		return -1;
> > -	sprintf(prefix, "%s%s", root, SEMANAGE_MOD_DIR);
> > +	prefix_len = strlen(root);
> >  
> >  	for (i = 0; i < SEMANAGE_NUM_STORES; i++) {
> >  		for (j = 0; j < SEMANAGE_STORE_NUM_PATHS; j++) {
> > @@ -204,14 +198,13 @@ static int semanage_init_store_paths(const char *root)
> >  			semanage_paths[i][j] = calloc(len + 1, sizeof(char));
> >  			if (!semanage_paths[i][j])
> >  				goto cleanup;
> > -			sprintf(semanage_paths[i][j], "%s%s%s", prefix,
> > +			sprintf(semanage_paths[i][j], "%s%s%s", root,
> >  				semanage_store_paths[i],
> >  				semanage_sandbox_paths[j]);
> >  		}
> >  	}
> >  
> >        cleanup:
> > -	free(prefix);
> >  	return 0;
> >  }
> >  
> > @@ -223,16 +216,28 @@ static int semanage_init_store_paths(const char *root)
> >   *
> >   * Note that this function is NOT thread-safe.
> >   */
> > -int semanage_check_init(const char *root)
> > +int semanage_check_init(semanage_handle_t *sh, const char *prefix)
> >  {
> >  	int rc;
> >  	if (semanage_paths_initialized == 0) {
> > +		char root[PATH_MAX];
> > +
> > +		rc = snprintf(root,
> > +			      sizeof(root),
> > +			      "%s/%s",
> > +			      prefix,
> > +			      sh->conf->store_path);
> > +		if (rc < 0 || rc >= (int)sizeof(root))
> > +			return -1;
> > +
> >  		rc = semanage_init_paths(root);
> >  		if (rc)
> >  			return rc;
> > +
> >  		rc = semanage_init_store_paths(root);
> >  		if (rc)
> >  			return rc;
> > +
> >  		semanage_paths_initialized = 1;
> >  	}
> >  	return 0;
> > @@ -259,6 +264,12 @@ const char *semanage_path(enum semanage_store_defs store,
> >  	return semanage_paths[store][path_name];
> >  }
> >  
> > +/* Return the root of the semanage store. */
> > +const char *semanage_root_path(void)
> > +{
> > +	return "/var/lib/selinux";
> > +}
> > +
> >  /* Return a fully-qualified path + filename to the semanage
> >   * configuration file.  The caller must not alter the string returned
> >   * (and hence why this function return type is const).
> > diff --git a/libsemanage/src/semanage_store.h b/libsemanage/src/semanage_store.h
> > index 112edb6..c76ecfe 100644
> > --- a/libsemanage/src/semanage_store.h
> > +++ b/libsemanage/src/semanage_store.h
> > @@ -62,11 +62,14 @@ enum semanage_sandbox_defs {
> >  	SEMANAGE_STORE_NUM_PATHS
> >  };
> >  
> > +const char *semanage_root_path(void);
> > +
> >  /* FIXME: this needs to be made a module store specific init and the
> >   * global configuration moved to another file.
> >   */
> >  const char *semanage_conf_path(void);
> > -int semanage_check_init(const char *root);
> > +
> > +int semanage_check_init(semanage_handle_t *sh, const char *prefix);
> >  
> >  extern const char *semanage_fname(enum semanage_sandbox_defs file_enum);
> >  

-- 
James Carter <jwcart2@tycho.nsa.gov>
National Security Agency


--
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] 39+ messages in thread

* Re: [PATCH 04/13] libsemanage: split final files into /var/lib/selinux/tmp
  2010-01-08 14:30         ` [PATCH 04/13] libsemanage: split final files into /var/lib/selinux/tmp Stephen Smalley
@ 2010-01-08 15:07           ` James Carter
  2010-01-08 15:28             ` Stephen Smalley
  0 siblings, 1 reply; 39+ messages in thread
From: James Carter @ 2010-01-08 15:07 UTC (permalink / raw)
  To: Stephen Smalley; +Cc: Caleb Case, selinux, csellers, kmacmillan, jbrindle

On Fri, 2010-01-08 at 09:30 -0500, Stephen Smalley wrote:
> On Wed, 2009-12-23 at 18:25 -0500, Caleb Case wrote:
> > This patch moves the final files from inside
> > /var/lib/selinux/<store>/[active|previous|tmp] to
> > /var/lib/selinux/tmp/<store>. The move is done to facilitate using
> > source control management on the /var/lib/selinux/<store> directory. If
> > these files remain in /var/lib/selinux/<store> they will pose a size
> > problem if an SCM like git is used as we'd be storing lots of binary
> > diffs. We are suggesting making this change now, rather than later when
> > source policy, SCM, and CIL[1] support are available, to ease the
> > migration burden.
> > 
> > These are the files that have been moved:
> > 
> > /var/lib/selinux/<store>/active/...	/var/lib/selinux/tmp/<store>/...
> > 
> > file_contexts				contexts/files/file_contexts
> > file_contexts.homedirs			contexts/files/file_contexts.homedirs
> > file_contexts.local			contexts/files/file_contexts.local
> > netfilter_contexts			contexts/netfilter_contexts
> > policy.kern				policy/policy.<policyversion>
> > seusers.final				seusers
> > 
> > The layout of these files in /var/lib/selinux/tmp/<store> is designed to
> > mirror their locations in /etc/selinux/<store>. This should help clarify
> > the relationship between these final files and the files installed in
> > etc.
> > 
> > One consequence of this move is that reverting to the previous policy
> > version requires a policy rebuild. Currently you can revert without
> > rebuilding.
> 
> That seems a little worrisome to me, as a rebuild might fail, e.g. what
> happens if we abort a transaction due to a lack of disk space and then
> try to revert, requiring a rebuild, only to run out of space during the
> rebuild?
> 
If the transaction is aborted then the policy hasn't actually been
changed, so I don't think that this example would be a problem.  It is
only after the transaction is complete that everything is written to the
final location.  Or am I missing something?

It would be a problem only if changes were made to the policy, that
policy loaded, there were problems, and then the rebuild of the previous
policy fails.

-- 
James Carter <jwcart2@tycho.nsa.gov>
National Security Agency


--
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] 39+ messages in thread

* Re: [PATCH 03/13] libsemanage: move the module store to /var/lib/selinux
  2010-01-08 14:50         ` James Carter
@ 2010-01-08 15:19           ` Stephen Smalley
  0 siblings, 0 replies; 39+ messages in thread
From: Stephen Smalley @ 2010-01-08 15:19 UTC (permalink / raw)
  To: jwcart2; +Cc: Caleb Case, selinux, csellers, kmacmillan, jbrindle

On Fri, 2010-01-08 at 09:50 -0500, James Carter wrote:
> On Fri, 2010-01-08 at 09:28 -0500, Stephen Smalley wrote:
> > On Wed, 2009-12-23 at 18:25 -0500, Caleb Case wrote:
> > > This patch moves the module store from /etc/selinux/<store>/modules to
> > > /var/lib/selinux/<store>.
> > 
> > Can the path prefix (i.e. /var/lib/selinux) be made configurable?
> > 
> There would be no other prefixes other than /var/lib/selinux
> or /etc/selinux, or do you have something else in mind?
> 
> I guess that you are thinking of backwards compatibility, but you still
> won't have it even if you change the prefix because the directory
> structure is different (priority directories and such).  I don't see
> what you would gain with changing the prefix.

I just dislike the notion that to change the location one would have to
recompile the library.  Even worse, one would have to modify the sources
versus just altering a -D flag in the Makefile specifying the path
prefix.  We already have one such case in libsemanage with a FIXME
comment next to it; I didn't want to extend the set of such cases.

-- 
Stephen Smalley
National Security Agency


--
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] 39+ messages in thread

* Re: [PATCH 04/13] libsemanage: split final files into /var/lib/selinux/tmp
  2010-01-08 15:07           ` James Carter
@ 2010-01-08 15:28             ` Stephen Smalley
  2010-01-08 18:25               ` Caleb Case
  2010-01-08 20:19               ` Joshua Brindle
  0 siblings, 2 replies; 39+ messages in thread
From: Stephen Smalley @ 2010-01-08 15:28 UTC (permalink / raw)
  To: jwcart2; +Cc: Caleb Case, selinux, csellers, kmacmillan, jbrindle

On Fri, 2010-01-08 at 10:07 -0500, James Carter wrote:
> On Fri, 2010-01-08 at 09:30 -0500, Stephen Smalley wrote:
> > On Wed, 2009-12-23 at 18:25 -0500, Caleb Case wrote:
> > > This patch moves the final files from inside
> > > /var/lib/selinux/<store>/[active|previous|tmp] to
> > > /var/lib/selinux/tmp/<store>. The move is done to facilitate using
> > > source control management on the /var/lib/selinux/<store> directory. If
> > > these files remain in /var/lib/selinux/<store> they will pose a size
> > > problem if an SCM like git is used as we'd be storing lots of binary
> > > diffs. We are suggesting making this change now, rather than later when
> > > source policy, SCM, and CIL[1] support are available, to ease the
> > > migration burden.
> > > 
> > > These are the files that have been moved:
> > > 
> > > /var/lib/selinux/<store>/active/...	/var/lib/selinux/tmp/<store>/...
> > > 
> > > file_contexts				contexts/files/file_contexts
> > > file_contexts.homedirs			contexts/files/file_contexts.homedirs
> > > file_contexts.local			contexts/files/file_contexts.local
> > > netfilter_contexts			contexts/netfilter_contexts
> > > policy.kern				policy/policy.<policyversion>
> > > seusers.final				seusers
> > > 
> > > The layout of these files in /var/lib/selinux/tmp/<store> is designed to
> > > mirror their locations in /etc/selinux/<store>. This should help clarify
> > > the relationship between these final files and the files installed in
> > > etc.
> > > 
> > > One consequence of this move is that reverting to the previous policy
> > > version requires a policy rebuild. Currently you can revert without
> > > rebuilding.
> > 
> > That seems a little worrisome to me, as a rebuild might fail, e.g. what
> > happens if we abort a transaction due to a lack of disk space and then
> > try to revert, requiring a rebuild, only to run out of space during the
> > rebuild?
> > 
> If the transaction is aborted then the policy hasn't actually been
> changed, so I don't think that this example would be a problem.  It is
> only after the transaction is complete that everything is written to the
> final location.  Or am I missing something?
> 
> It would be a problem only if changes were made to the policy, that
> policy loaded, there were problems, and then the rebuild of the previous
> policy fails.

I'm unclear on what state things would be left in.  I'm also unclear on
the implications of writing these files to a single tmp/ location rather
than having separate copies in active/, previous/, and tmp/ - I don't
want us to unwittingly clobber files or leave them in intermediate
states (as happened with the earlier attempt to hard link files among
active/, previous/ and tmp/).

I tried running the code but I seem to see these "final files" still
under the individual <store> directories in /var/lib/selinux rather than
under tmp/.

-- 
Stephen Smalley
National Security Agency


--
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] 39+ messages in thread

* Re: [PATCH 13/13] semanage store migration script
  2009-12-23 23:26                         ` [PATCH 13/13] semanage store migration script Caleb Case
@ 2010-01-08 15:34                           ` Stephen Smalley
  2010-01-08 20:59                             ` James Carter
  0 siblings, 1 reply; 39+ messages in thread
From: Stephen Smalley @ 2010-01-08 15:34 UTC (permalink / raw)
  To: Caleb Case; +Cc: selinux, csellers, kmacmillan, jwcart2, jbrindle

On Wed, 2009-12-23 at 18:26 -0500, Caleb Case wrote:
> We created a migration script to ease the burden of transition from the
> old libsemanage store layout to the new. The script will detect all the
> stores in /etc/selinux using the old layout and convert them to the new
> layout in /var/lib/selinux. It also allows you to specify the default
> priority to use with -p and store to operate on with -s. After migration
> the script by default will leave the old store unchanged, but can be
> told to remove the old modules directory with -c.
> 
> Examples:
> 
> # Migrate all stores to the new layout.
> migrate.py
> 
> Migrating from /etc/selinux/targeted/modules/active to /var/lib/selinux/targeted/active
> Attempting to rebuild policy from /var/lib/selinux
> 
> # Migrate only the targeted store.
> migrate.py -s targeted
> 
> Migrating from /etc/selinux/targeted/modules/active to /var/lib/selinux/targeted/active
> Attempting to rebuild policy from /var/lib/selinux
> 
> # Migrate all, but install to priority 150.
> migrate.py -p 150
> 
> Migrating from /etc/selinux/targeted/modules/active to /var/lib/selinux/targeted/active
> Attempting to rebuild policy from /var/lib/selinux

I tried the following:
semanage login -a -s user_u pi
cp -a /etc/selinux /etc/selinux.orig
install new userland
migrate.py
diff -ru /etc/selinux.orig /etc/selinux

The seusers entry for "pi" was dropped from the final seusers file in
the rebuilt policy.

-- 
Stephen Smalley
National Security Agency


--
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] 39+ messages in thread

* Re: [PATCH 04/13] libsemanage: split final files into /var/lib/selinux/tmp
  2010-01-08 15:28             ` Stephen Smalley
@ 2010-01-08 18:25               ` Caleb Case
  2010-01-08 20:19               ` Joshua Brindle
  1 sibling, 0 replies; 39+ messages in thread
From: Caleb Case @ 2010-01-08 18:25 UTC (permalink / raw)
  To: Stephen Smalley; +Cc: jwcart2, selinux, csellers, kmacmillan, jbrindle

On Fri, Jan 8, 2010 at 10:28 AM, Stephen Smalley <sds@tycho.nsa.gov> wrote:
> On Fri, 2010-01-08 at 10:07 -0500, James Carter wrote:
>> On Fri, 2010-01-08 at 09:30 -0500, Stephen Smalley wrote:
>> > On Wed, 2009-12-23 at 18:25 -0500, Caleb Case wrote:
>> > > This patch moves the final files from inside
>> > > /var/lib/selinux/<store>/[active|previous|tmp] to
>> > > /var/lib/selinux/tmp/<store>. The move is done to facilitate using
>> > > source control management on the /var/lib/selinux/<store> directory. If
>> > > these files remain in /var/lib/selinux/<store> they will pose a size
>> > > problem if an SCM like git is used as we'd be storing lots of binary
>> > > diffs. We are suggesting making this change now, rather than later when
>> > > source policy, SCM, and CIL[1] support are available, to ease the
>> > > migration burden.
>> > >
>> > > These are the files that have been moved:
>> > >
>> > > /var/lib/selinux/<store>/active/...       /var/lib/selinux/tmp/<store>/...
>> > >
>> > > file_contexts                             contexts/files/file_contexts
>> > > file_contexts.homedirs                    contexts/files/file_contexts.homedirs
>> > > file_contexts.local                       contexts/files/file_contexts.local
>> > > netfilter_contexts                        contexts/netfilter_contexts
>> > > policy.kern                               policy/policy.<policyversion>
>> > > seusers.final                             seusers
>> > >
>> > > The layout of these files in /var/lib/selinux/tmp/<store> is designed to
>> > > mirror their locations in /etc/selinux/<store>. This should help clarify
>> > > the relationship between these final files and the files installed in
>> > > etc.
>> > >
>> > > One consequence of this move is that reverting to the previous policy
>> > > version requires a policy rebuild. Currently you can revert without
>> > > rebuilding.
>> >
>> > That seems a little worrisome to me, as a rebuild might fail, e.g. what
>> > happens if we abort a transaction due to a lack of disk space and then
>> > try to revert, requiring a rebuild, only to run out of space during the
>> > rebuild?
>> >
>> If the transaction is aborted then the policy hasn't actually been
>> changed, so I don't think that this example would be a problem.  It is
>> only after the transaction is complete that everything is written to the
>> final location.  Or am I missing something?
>>
>> It would be a problem only if changes were made to the policy, that
>> policy loaded, there were problems, and then the rebuild of the previous
>> policy fails.
>
> I'm unclear on what state things would be left in.  I'm also unclear on
> the implications of writing these files to a single tmp/ location rather
> than having separate copies in active/, previous/, and tmp/ - I don't
> want us to unwittingly clobber files or leave them in intermediate
> states (as happened with the earlier attempt to hard link files among
> active/, previous/ and tmp/).

If there is an error and the transaction is aborted (for any reason),
then the effect is that nothing has changed. /etc/selinux/<store>
remains untouched. If this happens there shouldn't be any need to
revert. Since the tmp/<store> is emptied and then populated with
copies of the files from /etc/selinux/<store> when a transaction is
started there shouldn't be any files around to clobber. After a
transaction ends (successful or not), then tmp/<store> is emptied so
we shouldn't leave any files around in intermediate states. Only on a
successful transaction do we copy the files from tmp/<store> to
/etc/selinux/<store>.

>
> I tried running the code but I seem to see these "final files" still
> under the individual <store> directories in /var/lib/selinux rather than
> under tmp/.

I'm looking into this. After this patch the final files should all be
moved to tmp/.

>
> --
> Stephen Smalley
> National Security Agency
>
>
> --
> 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.
>


--
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] 39+ messages in thread

* Re: [PATCH 04/13] libsemanage: split final files into /var/lib/selinux/tmp
  2010-01-08 15:28             ` Stephen Smalley
  2010-01-08 18:25               ` Caleb Case
@ 2010-01-08 20:19               ` Joshua Brindle
  2010-01-08 20:25                 ` Stephen Smalley
  1 sibling, 1 reply; 39+ messages in thread
From: Joshua Brindle @ 2010-01-08 20:19 UTC (permalink / raw)
  To: Stephen Smalley
  Cc: jwcart2, Caleb Case, selinux, csellers, kmacmillan, jbrindle

Stephen Smalley wrote:
> On Fri, 2010-01-08 at 10:07 -0500, James Carter wrote:
<snip>

> I tried running the code but I seem to see these "final files" still
> under the individual<store>  directories in /var/lib/selinux rather than
> under tmp/.
>

I built patches 1-4 and made a fresh store from whatever was in 
/etc/selinux and I did not have any final files under 
/var/lib/selinux/targeted:

[root@F12 selinux]# pwd
/var/lib/selinux
[root@F12 selinux]# find
.
./targeted
./targeted/active
./targeted/active/modules
./targeted/active/modules/100
./targeted/active/modules/100/_base
./targeted/active/modules/100/_base/hll
./targeted/active/modules/100/_base/ext

...

./targeted/active/modules/100/milter
./targeted/active/modules/100/milter/hll
./targeted/active/modules/100/milter/ext
./targeted/active/modules/100/permissive_bin_t
./targeted/active/modules/100/permissive_bin_t/hll
./targeted/active/modules/100/permissive_bin_t/ext
./targeted/active/file_contexts.template
./targeted/active/file_contexts
./targeted/active/homedir_template
./targeted/active/seusers.final
./targeted/active/users_extra
./targeted/active/netfilter_contexts
./targeted/active/file_contexts.homedirs
./targeted/active/commit_num

--
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] 39+ messages in thread

* Re: [PATCH 04/13] libsemanage: split final files into /var/lib/selinux/tmp
  2010-01-08 20:19               ` Joshua Brindle
@ 2010-01-08 20:25                 ` Stephen Smalley
  2010-01-08 20:30                   ` Joshua Brindle
  0 siblings, 1 reply; 39+ messages in thread
From: Stephen Smalley @ 2010-01-08 20:25 UTC (permalink / raw)
  To: Joshua Brindle
  Cc: jwcart2, Caleb Case, selinux, csellers, kmacmillan, jbrindle

On Fri, 2010-01-08 at 15:19 -0500, Joshua Brindle wrote:
> Stephen Smalley wrote:
> > On Fri, 2010-01-08 at 10:07 -0500, James Carter wrote:
> <snip>
> 
> > I tried running the code but I seem to see these "final files" still
> > under the individual<store>  directories in /var/lib/selinux rather than
> > under tmp/.
> >
> 
> I built patches 1-4 and made a fresh store from whatever was in 
> /etc/selinux and I did not have any final files under 
> /var/lib/selinux/targeted:
> 
> [root@F12 selinux]# pwd
> /var/lib/selinux
> [root@F12 selinux]# find
> .
> ./targeted
> ./targeted/active
> ./targeted/active/modules
> ./targeted/active/modules/100
> ./targeted/active/modules/100/_base
> ./targeted/active/modules/100/_base/hll
> ./targeted/active/modules/100/_base/ext
> 
> ...
> 
> ./targeted/active/modules/100/milter
> ./targeted/active/modules/100/milter/hll
> ./targeted/active/modules/100/milter/ext
> ./targeted/active/modules/100/permissive_bin_t
> ./targeted/active/modules/100/permissive_bin_t/hll
> ./targeted/active/modules/100/permissive_bin_t/ext
> ./targeted/active/file_contexts.template
> ./targeted/active/file_contexts

That's a final file.

> ./targeted/active/homedir_template
> ./targeted/active/seusers.final

And there is one.

> ./targeted/active/users_extra
> ./targeted/active/netfilter_contexts

And another.

> ./targeted/active/file_contexts.homedirs
> ./targeted/active/commit_num
-- 
Stephen Smalley
National Security Agency


--
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] 39+ messages in thread

* Re: [PATCH 04/13] libsemanage: split final files into /var/lib/selinux/tmp
  2010-01-08 20:25                 ` Stephen Smalley
@ 2010-01-08 20:30                   ` Joshua Brindle
  2010-01-08 20:51                     ` Joshua Brindle
  0 siblings, 1 reply; 39+ messages in thread
From: Joshua Brindle @ 2010-01-08 20:30 UTC (permalink / raw)
  To: Stephen Smalley; +Cc: jwcart2, Caleb Case, selinux, csellers, kmacmillan



Stephen Smalley wrote:
> On Fri, 2010-01-08 at 15:19 -0500, Joshua Brindle wrote:
>> Stephen Smalley wrote:
>>> On Fri, 2010-01-08 at 10:07 -0500, James Carter wrote:
>> <snip>
>>
>>> I tried running the code but I seem to see these "final files" still
>>> under the individual<store>   directories in /var/lib/selinux rather than
>>> under tmp/.
>>>
>> I built patches 1-4 and made a fresh store from whatever was in
>> /etc/selinux and I did not have any final files under
>> /var/lib/selinux/targeted:
>>
>> [root@F12 selinux]# pwd
>> /var/lib/selinux
>> [root@F12 selinux]# find
>> .
>> ./targeted
>> ./targeted/active
>> ./targeted/active/modules
>> ./targeted/active/modules/100
>> ./targeted/active/modules/100/_base
>> ./targeted/active/modules/100/_base/hll
>> ./targeted/active/modules/100/_base/ext
>>
>> ...
>>
>> ./targeted/active/modules/100/milter
>> ./targeted/active/modules/100/milter/hll
>> ./targeted/active/modules/100/milter/ext
>> ./targeted/active/modules/100/permissive_bin_t
>> ./targeted/active/modules/100/permissive_bin_t/hll
>> ./targeted/active/modules/100/permissive_bin_t/ext
>> ./targeted/active/file_contexts.template
>> ./targeted/active/file_contexts
>
> That's a final file.
>
>> ./targeted/active/homedir_template
>> ./targeted/active/seusers.final
>
> And there is one.
>
>> ./targeted/active/users_extra
>> ./targeted/active/netfilter_contexts
>
> And another.
>
>> ./targeted/active/file_contexts.homedirs
>> ./targeted/active/commit_num

oops, I foolishly scanned looking for policy.kern.

--
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] 39+ messages in thread

* Re: [PATCH 04/13] libsemanage: split final files into /var/lib/selinux/tmp
  2010-01-08 20:30                   ` Joshua Brindle
@ 2010-01-08 20:51                     ` Joshua Brindle
  2010-01-08 20:58                       ` Stephen Smalley
  0 siblings, 1 reply; 39+ messages in thread
From: Joshua Brindle @ 2010-01-08 20:51 UTC (permalink / raw)
  To: Stephen Smalley; +Cc: jwcart2, Caleb Case, selinux, csellers, kmacmillan

Joshua Brindle wrote:
>
>
> Stephen Smalley wrote:
>> On Fri, 2010-01-08 at 15:19 -0500, Joshua Brindle wrote:
<snip>
> oops, I foolishly scanned looking for policy.kern.
>

No, it is worse than that, I wasn't actually running the code I was 
claiming to (as evidenced by the priority level and hll files)

Up to patch 4 my /var/lib/selinux now looks like this:

[root@F12 active]# find /var/lib/selinux/
/var/lib/selinux/
/var/lib/selinux/targeted
/var/lib/selinux/targeted/semanage.read.LOCK
/var/lib/selinux/targeted/semanage.trans.LOCK
/var/lib/selinux/targeted/active
/var/lib/selinux/targeted/active/modules
/var/lib/selinux/targeted/active/modules/abrt.pp
/var/lib/selinux/targeted/active/modules/ada.pp
...
/var/lib/selinux/targeted/active/modules/xguest.pp
/var/lib/selinux/targeted/active/modules/zabbix.pp
/var/lib/selinux/targeted/active/modules/zebra.pp
/var/lib/selinux/targeted/active/modules/zosremote.pp
/var/lib/selinux/targeted/active/base.pp
/var/lib/selinux/targeted/active/file_contexts.template
/var/lib/selinux/targeted/active/homedir_template
/var/lib/selinux/targeted/active/users_extra
/var/lib/selinux/targeted/active/commit_num
/var/lib/selinux/tmp


so I don't have any final files in targeted anymore, though I didn't try 
to stop semodule half-way and look in tmp.

--
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] 39+ messages in thread

* Re: [PATCH 04/13] libsemanage: split final files into /var/lib/selinux/tmp
  2010-01-08 20:51                     ` Joshua Brindle
@ 2010-01-08 20:58                       ` Stephen Smalley
  2010-01-08 21:02                         ` Joshua Brindle
  0 siblings, 1 reply; 39+ messages in thread
From: Stephen Smalley @ 2010-01-08 20:58 UTC (permalink / raw)
  To: Joshua Brindle; +Cc: jwcart2, Caleb Case, selinux, csellers, kmacmillan

On Fri, 2010-01-08 at 15:51 -0500, Joshua Brindle wrote:
> Joshua Brindle wrote:
> >
> >
> > Stephen Smalley wrote:
> >> On Fri, 2010-01-08 at 15:19 -0500, Joshua Brindle wrote:
> <snip>
> > oops, I foolishly scanned looking for policy.kern.
> >
> 
> No, it is worse than that, I wasn't actually running the code I was 
> claiming to (as evidenced by the priority level and hll files)
> 
> Up to patch 4 my /var/lib/selinux now looks like this:
> 
> [root@F12 active]# find /var/lib/selinux/
> /var/lib/selinux/
> /var/lib/selinux/targeted
> /var/lib/selinux/targeted/semanage.read.LOCK
> /var/lib/selinux/targeted/semanage.trans.LOCK
> /var/lib/selinux/targeted/active
> /var/lib/selinux/targeted/active/modules
> /var/lib/selinux/targeted/active/modules/abrt.pp
> /var/lib/selinux/targeted/active/modules/ada.pp
> ...
> /var/lib/selinux/targeted/active/modules/xguest.pp
> /var/lib/selinux/targeted/active/modules/zabbix.pp
> /var/lib/selinux/targeted/active/modules/zebra.pp
> /var/lib/selinux/targeted/active/modules/zosremote.pp
> /var/lib/selinux/targeted/active/base.pp
> /var/lib/selinux/targeted/active/file_contexts.template
> /var/lib/selinux/targeted/active/homedir_template
> /var/lib/selinux/targeted/active/users_extra
> /var/lib/selinux/targeted/active/commit_num
> /var/lib/selinux/tmp
> 
> 
> so I don't have any final files in targeted anymore, though I didn't try 
> to stop semodule half-way and look in tmp.

I haven't tried only up through patch 4, only with all 13 patches
applied.

Also, I have all Fedora policies installed (yum install
selinux-policy*), so I have mls, targeted, and minimum, although
targeted is the active one.

-- 
Stephen Smalley
National Security Agency


--
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] 39+ messages in thread

* Re: [PATCH 13/13] semanage store migration script
  2010-01-08 15:34                           ` Stephen Smalley
@ 2010-01-08 20:59                             ` James Carter
  2010-01-08 21:05                               ` Stephen Smalley
  2010-01-08 21:27                               ` Caleb Case
  0 siblings, 2 replies; 39+ messages in thread
From: James Carter @ 2010-01-08 20:59 UTC (permalink / raw)
  To: Stephen Smalley; +Cc: Caleb Case, selinux, csellers, kmacmillan, jbrindle

On Fri, 2010-01-08 at 10:34 -0500, Stephen Smalley wrote: 
> On Wed, 2009-12-23 at 18:26 -0500, Caleb Case wrote:
> > We created a migration script to ease the burden of transition from the
> > old libsemanage store layout to the new. The script will detect all the
> > stores in /etc/selinux using the old layout and convert them to the new
> > layout in /var/lib/selinux. It also allows you to specify the default
> > priority to use with -p and store to operate on with -s. After migration
> > the script by default will leave the old store unchanged, but can be
> > told to remove the old modules directory with -c.
> > 
> > Examples:
> > 
> > # Migrate all stores to the new layout.
> > migrate.py
> > 
> > Migrating from /etc/selinux/targeted/modules/active to /var/lib/selinux/targeted/active
> > Attempting to rebuild policy from /var/lib/selinux
> > 
> > # Migrate only the targeted store.
> > migrate.py -s targeted
> > 
> > Migrating from /etc/selinux/targeted/modules/active to /var/lib/selinux/targeted/active
> > Attempting to rebuild policy from /var/lib/selinux
> > 
> > # Migrate all, but install to priority 150.
> > migrate.py -p 150
> > 
> > Migrating from /etc/selinux/targeted/modules/active to /var/lib/selinux/targeted/active
> > Attempting to rebuild policy from /var/lib/selinux
> 
> I tried the following:
> semanage login -a -s user_u pi
> cp -a /etc/selinux /etc/selinux.orig
> install new userland
> migrate.py
> diff -ru /etc/selinux.orig /etc/selinux
> 
> The seusers entry for "pi" was dropped from the final seusers file in
> the rebuilt policy.
> 

I saw the same thing.  I added a new login, but it does not show up
after the migration with "semanage login -l" even though it is
in /var/lib/selinux/targeted/active/seusers and seusers.final.

booleans, ports, file contexts, and permissive domains all show up after
the migration, but there are some other issues.


1)  For booleans I am getting this error:

# semanage boolean --on git_system_use_cifs
Traceback (most recent call last):
  File "/usr/sbin/semanage", line 460, in <module>
    process_args(sys.argv[1:])
  File "/usr/sbin/semanage", line 407, in process_args
    raise ValueError(_("Invalid command") % " ".join(argv))
TypeError: not all arguments converted during string formatting



2)  Either the priority stuff doesn't work or I am doing something
wrong.  Shouldn't either of the following not display any modules since
they are all at priority 100?

"semodule -p 900 -l" or "semodule -p 900; semodule -l"

Both display all modules.


3)  I can't remove the permissive domain created before the migration
because the default priority level is 400, but the script put everything
at priority 100 and I don't know how to change the priority for
semanage.

# semanage permissive -d httpd_t
libsemanage.semanage_direct_remove_key: Unable to remove module
directory /var/lib/selinux/targeted/tmp/modules/400/permissive_httpd_t.
(No such file or directory).
/usr/sbin/semanage: Could not remove permissive domain httpd_t (remove
failed)


Ports and file contexts addition and removal seems to work fine.

-- 
James Carter <jwcart2@tycho.nsa.gov>
National Security Agency



--
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] 39+ messages in thread

* Re: [PATCH 04/13] libsemanage: split final files into /var/lib/selinux/tmp
  2010-01-08 20:58                       ` Stephen Smalley
@ 2010-01-08 21:02                         ` Joshua Brindle
  2010-01-08 21:04                           ` Stephen Smalley
  2010-01-08 21:12                           ` James Carter
  0 siblings, 2 replies; 39+ messages in thread
From: Joshua Brindle @ 2010-01-08 21:02 UTC (permalink / raw)
  To: Stephen Smalley; +Cc: jwcart2, Caleb Case, selinux, csellers, kmacmillan

Stephen Smalley wrote:
> On Fri, 2010-01-08 at 15:51 -0500, Joshua Brindle wrote:
>> Joshua Brindle wrote:
>>>
>>> Stephen Smalley wrote:
>>>> On Fri, 2010-01-08 at 15:19 -0500, Joshua Brindle wrote:
>> <snip>
>>> oops, I foolishly scanned looking for policy.kern.
>>>
>> No, it is worse than that, I wasn't actually running the code I was
>> claiming to (as evidenced by the priority level and hll files)
>>
>> Up to patch 4 my /var/lib/selinux now looks like this:
>>
>> [root@F12 active]# find /var/lib/selinux/
>> /var/lib/selinux/
>> /var/lib/selinux/targeted
>> /var/lib/selinux/targeted/semanage.read.LOCK
>> /var/lib/selinux/targeted/semanage.trans.LOCK
>> /var/lib/selinux/targeted/active
>> /var/lib/selinux/targeted/active/modules
>> /var/lib/selinux/targeted/active/modules/abrt.pp
>> /var/lib/selinux/targeted/active/modules/ada.pp
>> ...
>> /var/lib/selinux/targeted/active/modules/xguest.pp
>> /var/lib/selinux/targeted/active/modules/zabbix.pp
>> /var/lib/selinux/targeted/active/modules/zebra.pp
>> /var/lib/selinux/targeted/active/modules/zosremote.pp
>> /var/lib/selinux/targeted/active/base.pp
>> /var/lib/selinux/targeted/active/file_contexts.template
>> /var/lib/selinux/targeted/active/homedir_template
>> /var/lib/selinux/targeted/active/users_extra
>> /var/lib/selinux/targeted/active/commit_num
>> /var/lib/selinux/tmp
>>
>>
>> so I don't have any final files in targeted anymore, though I didn't try
>> to stop semodule half-way and look in tmp.
>
> I haven't tried only up through patch 4, only with all 13 patches
> applied.
>
> Also, I have all Fedora policies installed (yum install
> selinux-policy*), so I have mls, targeted, and minimum, although
> targeted is the active one.
>

Are you running the migrate script? I believe it is erroneously copying 
final files into the store:

+	# List of paths that go in the active 'root'
+	TOPPATHS = [
+		"file_contexts",
+		"homedir_template",
+		"file_contexts.template",
+		"commit_num",
+		"ports.local",
+		"interfaces.local",
+		"nodes.local",
+		"booleans.local",
+		"file_contexts.local",
+		"seusers",
+		"users.local",
+		"users_extra.local",
+		"seusers.final",
+		"users_extra",
+		"netfilter_contexts",
+		"file_contexts.homedirs",
+		"disable_dontaudit" ]
+

--
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] 39+ messages in thread

* Re: [PATCH 04/13] libsemanage: split final files into /var/lib/selinux/tmp
  2010-01-08 21:02                         ` Joshua Brindle
@ 2010-01-08 21:04                           ` Stephen Smalley
  2010-01-08 21:12                           ` James Carter
  1 sibling, 0 replies; 39+ messages in thread
From: Stephen Smalley @ 2010-01-08 21:04 UTC (permalink / raw)
  To: Joshua Brindle; +Cc: jwcart2, Caleb Case, selinux, csellers, kmacmillan

On Fri, 2010-01-08 at 16:02 -0500, Joshua Brindle wrote:
> Stephen Smalley wrote:
> > On Fri, 2010-01-08 at 15:51 -0500, Joshua Brindle wrote:
> >> Joshua Brindle wrote:
> >>>
> >>> Stephen Smalley wrote:
> >>>> On Fri, 2010-01-08 at 15:19 -0500, Joshua Brindle wrote:
> >> <snip>
> >>> oops, I foolishly scanned looking for policy.kern.
> >>>
> >> No, it is worse than that, I wasn't actually running the code I was
> >> claiming to (as evidenced by the priority level and hll files)
> >>
> >> Up to patch 4 my /var/lib/selinux now looks like this:
> >>
> >> [root@F12 active]# find /var/lib/selinux/
> >> /var/lib/selinux/
> >> /var/lib/selinux/targeted
> >> /var/lib/selinux/targeted/semanage.read.LOCK
> >> /var/lib/selinux/targeted/semanage.trans.LOCK
> >> /var/lib/selinux/targeted/active
> >> /var/lib/selinux/targeted/active/modules
> >> /var/lib/selinux/targeted/active/modules/abrt.pp
> >> /var/lib/selinux/targeted/active/modules/ada.pp
> >> ...
> >> /var/lib/selinux/targeted/active/modules/xguest.pp
> >> /var/lib/selinux/targeted/active/modules/zabbix.pp
> >> /var/lib/selinux/targeted/active/modules/zebra.pp
> >> /var/lib/selinux/targeted/active/modules/zosremote.pp
> >> /var/lib/selinux/targeted/active/base.pp
> >> /var/lib/selinux/targeted/active/file_contexts.template
> >> /var/lib/selinux/targeted/active/homedir_template
> >> /var/lib/selinux/targeted/active/users_extra
> >> /var/lib/selinux/targeted/active/commit_num
> >> /var/lib/selinux/tmp
> >>
> >>
> >> so I don't have any final files in targeted anymore, though I didn't try
> >> to stop semodule half-way and look in tmp.
> >
> > I haven't tried only up through patch 4, only with all 13 patches
> > applied.
> >
> > Also, I have all Fedora policies installed (yum install
> > selinux-policy*), so I have mls, targeted, and minimum, although
> > targeted is the active one.
> >
> 
> Are you running the migrate script?

Yes.  

>  I believe it is erroneously copying 
> final files into the store:
> 
> +	# List of paths that go in the active 'root'
> +	TOPPATHS = [
> +		"file_contexts",
> +		"homedir_template",
> +		"file_contexts.template",
> +		"commit_num",
> +		"ports.local",
> +		"interfaces.local",
> +		"nodes.local",
> +		"booleans.local",
> +		"file_contexts.local",
> +		"seusers",
> +		"users.local",
> +		"users_extra.local",
> +		"seusers.final",
> +		"users_extra",
> +		"netfilter_contexts",
> +		"file_contexts.homedirs",
> +		"disable_dontaudit" ]
> +

-- 
Stephen Smalley
National Security Agency


--
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] 39+ messages in thread

* Re: [PATCH 13/13] semanage store migration script
  2010-01-08 20:59                             ` James Carter
@ 2010-01-08 21:05                               ` Stephen Smalley
  2010-01-08 21:27                               ` Caleb Case
  1 sibling, 0 replies; 39+ messages in thread
From: Stephen Smalley @ 2010-01-08 21:05 UTC (permalink / raw)
  To: jwcart2; +Cc: Caleb Case, selinux, csellers, kmacmillan, jbrindle

On Fri, 2010-01-08 at 15:59 -0500, James Carter wrote:
> On Fri, 2010-01-08 at 10:34 -0500, Stephen Smalley wrote: 
> > On Wed, 2009-12-23 at 18:26 -0500, Caleb Case wrote:
> > > We created a migration script to ease the burden of transition from the
> > > old libsemanage store layout to the new. The script will detect all the
> > > stores in /etc/selinux using the old layout and convert them to the new
> > > layout in /var/lib/selinux. It also allows you to specify the default
> > > priority to use with -p and store to operate on with -s. After migration
> > > the script by default will leave the old store unchanged, but can be
> > > told to remove the old modules directory with -c.
> > > 
> > > Examples:
> > > 
> > > # Migrate all stores to the new layout.
> > > migrate.py
> > > 
> > > Migrating from /etc/selinux/targeted/modules/active to /var/lib/selinux/targeted/active
> > > Attempting to rebuild policy from /var/lib/selinux
> > > 
> > > # Migrate only the targeted store.
> > > migrate.py -s targeted
> > > 
> > > Migrating from /etc/selinux/targeted/modules/active to /var/lib/selinux/targeted/active
> > > Attempting to rebuild policy from /var/lib/selinux
> > > 
> > > # Migrate all, but install to priority 150.
> > > migrate.py -p 150
> > > 
> > > Migrating from /etc/selinux/targeted/modules/active to /var/lib/selinux/targeted/active
> > > Attempting to rebuild policy from /var/lib/selinux
> > 
> > I tried the following:
> > semanage login -a -s user_u pi
> > cp -a /etc/selinux /etc/selinux.orig
> > install new userland
> > migrate.py
> > diff -ru /etc/selinux.orig /etc/selinux
> > 
> > The seusers entry for "pi" was dropped from the final seusers file in
> > the rebuilt policy.
> > 
> 
> I saw the same thing.  I added a new login, but it does not show up
> after the migration with "semanage login -l" even though it is
> in /var/lib/selinux/targeted/active/seusers and seusers.final.

I also noticed that /etc/selinux/targeted/seusers lacks the header
comments (This file is auto-generated...).  Searching /var/lib/selinux
for a matching file, I find only one file - the seusers file in the
minimum policy tree.  How that ends up getting installed as the seusers
file for targeted is a mystery to me...

-- 
Stephen Smalley
National Security Agency


--
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] 39+ messages in thread

* Re: [PATCH 04/13] libsemanage: split final files into /var/lib/selinux/tmp
  2010-01-08 21:02                         ` Joshua Brindle
  2010-01-08 21:04                           ` Stephen Smalley
@ 2010-01-08 21:12                           ` James Carter
  1 sibling, 0 replies; 39+ messages in thread
From: James Carter @ 2010-01-08 21:12 UTC (permalink / raw)
  To: Joshua Brindle; +Cc: Stephen Smalley, Caleb Case, selinux, csellers, kmacmillan

On Fri, 2010-01-08 at 16:02 -0500, Joshua Brindle wrote:
> Stephen Smalley wrote:
> > On Fri, 2010-01-08 at 15:51 -0500, Joshua Brindle wrote:
> >> Joshua Brindle wrote:
> >>>
> >>> Stephen Smalley wrote:
> >>>> On Fri, 2010-01-08 at 15:19 -0500, Joshua Brindle wrote:
> >> <snip>
> >>> oops, I foolishly scanned looking for policy.kern.
> >>>
> >> No, it is worse than that, I wasn't actually running the code I was
> >> claiming to (as evidenced by the priority level and hll files)
> >>
> >> Up to patch 4 my /var/lib/selinux now looks like this:
> >>
> >> [root@F12 active]# find /var/lib/selinux/
> >> /var/lib/selinux/
> >> /var/lib/selinux/targeted
> >> /var/lib/selinux/targeted/semanage.read.LOCK
> >> /var/lib/selinux/targeted/semanage.trans.LOCK
> >> /var/lib/selinux/targeted/active
> >> /var/lib/selinux/targeted/active/modules
> >> /var/lib/selinux/targeted/active/modules/abrt.pp
> >> /var/lib/selinux/targeted/active/modules/ada.pp
> >> ...
> >> /var/lib/selinux/targeted/active/modules/xguest.pp
> >> /var/lib/selinux/targeted/active/modules/zabbix.pp
> >> /var/lib/selinux/targeted/active/modules/zebra.pp
> >> /var/lib/selinux/targeted/active/modules/zosremote.pp
> >> /var/lib/selinux/targeted/active/base.pp
> >> /var/lib/selinux/targeted/active/file_contexts.template
> >> /var/lib/selinux/targeted/active/homedir_template
> >> /var/lib/selinux/targeted/active/users_extra
> >> /var/lib/selinux/targeted/active/commit_num
> >> /var/lib/selinux/tmp
> >>
> >>
> >> so I don't have any final files in targeted anymore, though I didn't try
> >> to stop semodule half-way and look in tmp.
> >
> > I haven't tried only up through patch 4, only with all 13 patches
> > applied.
> >
> > Also, I have all Fedora policies installed (yum install
> > selinux-policy*), so I have mls, targeted, and minimum, although
> > targeted is the active one.
> >
> 
> Are you running the migrate script? I believe it is erroneously copying 
> final files into the store:
> 
> +	# List of paths that go in the active 'root'
> +	TOPPATHS = [
> +		"file_contexts",
> +		"homedir_template",
> +		"file_contexts.template",
> +		"commit_num",
> +		"ports.local",
> +		"interfaces.local",
> +		"nodes.local",
> +		"booleans.local",
> +		"file_contexts.local",
> +		"seusers",
> +		"users.local",
> +		"users_extra.local",
> +		"seusers.final",
> +		"users_extra",
> +		"netfilter_contexts",
> +		"file_contexts.homedirs",
> +		"disable_dontaudit" ]
> +
> 
That does appear to be the case.  When I remove the final files, they do
not reappear after I rebuild the policy.

> --
> 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.

-- 
James Carter <jwcart2@tycho.nsa.gov>
National Security Agency


--
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] 39+ messages in thread

* RE: [PATCH 13/13] semanage store migration script
  2010-01-08 20:59                             ` James Carter
  2010-01-08 21:05                               ` Stephen Smalley
@ 2010-01-08 21:27                               ` Caleb Case
  2010-01-11 19:53                                 ` James Carter
  1 sibling, 1 reply; 39+ messages in thread
From: Caleb Case @ 2010-01-08 21:27 UTC (permalink / raw)
  To: jwcart2, Stephen Smalley
  Cc: selinux, Chad Sellers, Karl MacMillan, Joshua Brindle

> -----Original Message-----
> From: James Carter [mailto:jwcart2@tycho.nsa.gov]
> Sent: Friday, January 08, 2010 4:00 PM
> To: Stephen Smalley
> Cc: Caleb Case; selinux@tycho.nsa.gov; Chad Sellers; Karl MacMillan;
> Joshua Brindle
> Subject: Re: [PATCH 13/13] semanage store migration script
> 
> On Fri, 2010-01-08 at 10:34 -0500, Stephen Smalley wrote:
> > On Wed, 2009-12-23 at 18:26 -0500, Caleb Case wrote:
> > > We created a migration script to ease the burden of transition
from
> the
> > > old libsemanage store layout to the new. The script will detect
all
> the
> > > stores in /etc/selinux using the old layout and convert them to
the
> new
> > > layout in /var/lib/selinux. It also allows you to specify the
default
> > > priority to use with -p and store to operate on with -s. After
> migration
> > > the script by default will leave the old store unchanged, but can
be
> > > told to remove the old modules directory with -c.
> > >
> > > Examples:
> > >
> > > # Migrate all stores to the new layout.
> > > migrate.py
> > >
> > > Migrating from /etc/selinux/targeted/modules/active to
> /var/lib/selinux/targeted/active
> > > Attempting to rebuild policy from /var/lib/selinux
> > >
> > > # Migrate only the targeted store.
> > > migrate.py -s targeted
> > >
> > > Migrating from /etc/selinux/targeted/modules/active to
> /var/lib/selinux/targeted/active
> > > Attempting to rebuild policy from /var/lib/selinux
> > >
> > > # Migrate all, but install to priority 150.
> > > migrate.py -p 150
> > >
> > > Migrating from /etc/selinux/targeted/modules/active to
> /var/lib/selinux/targeted/active
> > > Attempting to rebuild policy from /var/lib/selinux
> >
> > I tried the following:
> > semanage login -a -s user_u pi
> > cp -a /etc/selinux /etc/selinux.orig
> > install new userland
> > migrate.py
> > diff -ru /etc/selinux.orig /etc/selinux
> >
> > The seusers entry for "pi" was dropped from the final seusers file
in
> > the rebuilt policy.
> >
> 
> I saw the same thing.  I added a new login, but it does not show up
> after the migration with "semanage login -l" even though it is
> in /var/lib/selinux/targeted/active/seusers and seusers.final.
> 
> booleans, ports, file contexts, and permissive domains all show up
after
> the migration, but there are some other issues.
> 
> 
> 1)  For booleans I am getting this error:
> 
> # semanage boolean --on git_system_use_cifs
> Traceback (most recent call last):
>   File "/usr/sbin/semanage", line 460, in <module>
>     process_args(sys.argv[1:])
>   File "/usr/sbin/semanage", line 407, in process_args
>     raise ValueError(_("Invalid command") % " ".join(argv))
> TypeError: not all arguments converted during string formatting
> 
> 
> 
> 2)  Either the priority stuff doesn't work or I am doing something
> wrong.  Shouldn't either of the following not display any modules
since
> they are all at priority 100?
> 
> "semodule -p 900 -l" or "semodule -p 900; semodule -l"
> 
> Both display all modules.

The list command is not affected by the priority setting. Maybe it
should be? Currently the priority is defaulted to 400 in semodule, but
we could have it default to 0 and check in the -i/u/r cases for 0 and
set to 400 and then filter the modules in -l if priority != 0.

> 
> 
> 3)  I can't remove the permissive domain created before the migration
> because the default priority level is 400, but the script put
everything
> at priority 100 and I don't know how to change the priority for
> semanage.

semanage hasn't been updated yet to let you specify priorities.

> 
> # semanage permissive -d httpd_t
> libsemanage.semanage_direct_remove_key: Unable to remove module
> directory
/var/lib/selinux/targeted/tmp/modules/400/permissive_httpd_t.
> (No such file or directory).
> /usr/sbin/semanage: Could not remove permissive domain httpd_t (remove
> failed)
> 
> 
> Ports and file contexts addition and removal seems to work fine.
> 
> --
> James Carter <jwcart2@tycho.nsa.gov>
> National Security Agency
> 



--
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] 39+ messages in thread

* RE: [PATCH 13/13] semanage store migration script
  2010-01-08 21:27                               ` Caleb Case
@ 2010-01-11 19:53                                 ` James Carter
  2010-01-11 19:57                                   ` Joshua Brindle
  0 siblings, 1 reply; 39+ messages in thread
From: James Carter @ 2010-01-11 19:53 UTC (permalink / raw)
  To: Caleb Case
  Cc: Stephen Smalley, selinux, Chad Sellers, Karl MacMillan, Joshua Brindle

On Fri, 2010-01-08 at 16:27 -0500, Caleb Case wrote:
> > -----Original Message-----
> > From: James Carter [mailto:jwcart2@tycho.nsa.gov]
> > Sent: Friday, January 08, 2010 4:00 PM
> > To: Stephen Smalley
> > Cc: Caleb Case; selinux@tycho.nsa.gov; Chad Sellers; Karl MacMillan;
> > Joshua Brindle
> > Subject: Re: [PATCH 13/13] semanage store migration script
> > 
> > On Fri, 2010-01-08 at 10:34 -0500, Stephen Smalley wrote:
> > > On Wed, 2009-12-23 at 18:26 -0500, Caleb Case wrote:
> > > > We created a migration script to ease the burden of transition
> from
> > the
> > > > old libsemanage store layout to the new. The script will detect
> all
> > the
> > > > stores in /etc/selinux using the old layout and convert them to
> the
> > new
> > > > layout in /var/lib/selinux. It also allows you to specify the
> default
> > > > priority to use with -p and store to operate on with -s. After
> > migration
> > > > the script by default will leave the old store unchanged, but can
> be
> > > > told to remove the old modules directory with -c.
> > > >
> > > > Examples:
> > > >
> > > > # Migrate all stores to the new layout.
> > > > migrate.py
> > > >
> > > > Migrating from /etc/selinux/targeted/modules/active to
> > /var/lib/selinux/targeted/active
> > > > Attempting to rebuild policy from /var/lib/selinux
> > > >
> > > > # Migrate only the targeted store.
> > > > migrate.py -s targeted
> > > >
> > > > Migrating from /etc/selinux/targeted/modules/active to
> > /var/lib/selinux/targeted/active
> > > > Attempting to rebuild policy from /var/lib/selinux
> > > >
> > > > # Migrate all, but install to priority 150.
> > > > migrate.py -p 150
> > > >
> > > > Migrating from /etc/selinux/targeted/modules/active to
> > /var/lib/selinux/targeted/active
> > > > Attempting to rebuild policy from /var/lib/selinux
> > >
> > > I tried the following:
> > > semanage login -a -s user_u pi
> > > cp -a /etc/selinux /etc/selinux.orig
> > > install new userland
> > > migrate.py
> > > diff -ru /etc/selinux.orig /etc/selinux
> > >
> > > The seusers entry for "pi" was dropped from the final seusers file
> in
> > > the rebuilt policy.
> > >
> > 
> > I saw the same thing.  I added a new login, but it does not show up
> > after the migration with "semanage login -l" even though it is
> > in /var/lib/selinux/targeted/active/seusers and seusers.final.
> > 
> > booleans, ports, file contexts, and permissive domains all show up
> after
> > the migration, but there are some other issues.
> > 
> > 
> > 1)  For booleans I am getting this error:
> > 
> > # semanage boolean --on git_system_use_cifs
> > Traceback (most recent call last):
> >   File "/usr/sbin/semanage", line 460, in <module>
> >     process_args(sys.argv[1:])
> >   File "/usr/sbin/semanage", line 407, in process_args
> >     raise ValueError(_("Invalid command") % " ".join(argv))
> > TypeError: not all arguments converted during string formatting
> > 
> > 
> > 
> > 2)  Either the priority stuff doesn't work or I am doing something
> > wrong.  Shouldn't either of the following not display any modules
> since
> > they are all at priority 100?
> > 
> > "semodule -p 900 -l" or "semodule -p 900; semodule -l"
> > 
> > Both display all modules.
> 
> The list command is not affected by the priority setting. Maybe it
> should be? Currently the priority is defaulted to 400 in semodule, but
> we could have it default to 0 and check in the -i/u/r cases for 0 and
> set to 400 and then filter the modules in -l if priority != 0.
> 
It seems like most of the time a person will just want to see the
enabled modules.  At times, though, they might want to see which
priority each enabled module is at, or to see all the modules at a given
priority.

> > 
> > 
> > 3)  I can't remove the permissive domain created before the migration
> > because the default priority level is 400, but the script put
> everything
> > at priority 100 and I don't know how to change the priority for
> > semanage.
> 
> semanage hasn't been updated yet to let you specify priorities.
> 
I noticed. ;)
So why does the migration script put everything into priority 100
instead of the default priority?

> > 
> > # semanage permissive -d httpd_t
> > libsemanage.semanage_direct_remove_key: Unable to remove module
> > directory
> /var/lib/selinux/targeted/tmp/modules/400/permissive_httpd_t.
> > (No such file or directory).
> > /usr/sbin/semanage: Could not remove permissive domain httpd_t (remove
> > failed)
> > 
> > 
> > Ports and file contexts addition and removal seems to work fine.
> > 
> > --
> > James Carter <jwcart2@tycho.nsa.gov>
> > National Security Agency
> > 
> 
> 
> 
> --
> 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.

-- 
James Carter <jwcart2@tycho.nsa.gov>
National Security Agency


--
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] 39+ messages in thread

* RE: [PATCH 13/13] semanage store migration script
  2010-01-11 19:53                                 ` James Carter
@ 2010-01-11 19:57                                   ` Joshua Brindle
  2010-01-11 20:45                                     ` James Carter
  0 siblings, 1 reply; 39+ messages in thread
From: Joshua Brindle @ 2010-01-11 19:57 UTC (permalink / raw)
  To: jwcart2, Caleb Case
  Cc: Stephen Smalley, selinux, Chad Sellers, Karl MacMillan

On 2010-01-11 James Carter wrote:
> On Fri, 2010-01-08 at 16:27 -0500, Caleb Case wrote:
<snip>
>>> 
>>> 
>>> 3)  I can't remove the permissive domain created before the migration
>>> because the default priority level is 400, but the script put
>>> everything at priority 100 and I don't know how to change the priority
>>> for semanage.
>> 
>> semanage hasn't been updated yet to let you specify priorities.
>> 
> I noticed. ;)
> So why does the migration script put everything into priority 100
> instead of the default priority?
> 


priority 100 is for policies distributed by the distro, 400 is default for user actions (eg., running semodule without adding a priority)

I guess we could add some smarts to the migration script to put things like permissive modules and "local.pp" kinds of modules at 400.

or add a list of modules distributed by red hat *shrug*

I'm not sure any of these are good ideas, but they might soften the migration blow.


--
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] 39+ messages in thread

* RE: [PATCH 13/13] semanage store migration script
  2010-01-11 19:57                                   ` Joshua Brindle
@ 2010-01-11 20:45                                     ` James Carter
  0 siblings, 0 replies; 39+ messages in thread
From: James Carter @ 2010-01-11 20:45 UTC (permalink / raw)
  To: Joshua Brindle
  Cc: Caleb Case, Stephen Smalley, selinux, Chad Sellers, Karl MacMillan

On Mon, 2010-01-11 at 14:57 -0500, Joshua Brindle wrote:
> On 2010-01-11 James Carter wrote:
> > On Fri, 2010-01-08 at 16:27 -0500, Caleb Case wrote:
> <snip>
> >>> 
> >>> 
> >>> 3)  I can't remove the permissive domain created before the migration
> >>> because the default priority level is 400, but the script put
> >>> everything at priority 100 and I don't know how to change the priority
> >>> for semanage.
> >> 
> >> semanage hasn't been updated yet to let you specify priorities.
> >> 
> > I noticed. ;)
> > So why does the migration script put everything into priority 100
> > instead of the default priority?
> > 
> 
> 
> priority 100 is for policies distributed by the distro, 400 is default for user actions (eg., running semodule without adding a priority)
> 
> I guess we could add some smarts to the migration script to put things like permissive modules and "local.pp" kinds of modules at 400.
> 
> or add a list of modules distributed by red hat *shrug*
> 
> I'm not sure any of these are good ideas, but they might soften the migration blow.
> 
Oh wait.  I was thinking that 100 was a higher priority.  I couldn't
understand why everything was migrated into a higher priority than the
default.  Now it makes sense.

It still might make sense to put local.pp and permissive modules into
the default priority.  It could be very confusing to have these exist in
multiple priorities.

> 
> --
> 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.

-- 
James Carter <jwcart2@tycho.nsa.gov>
National Security Agency


--
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] 39+ messages in thread

* Re: [PATCH 00/13] RFC libsemanage move to var, enable/disable module, and priority support
  2010-01-08 14:30   ` James Carter
@ 2010-01-21 21:06     ` Chad Sellers
  0 siblings, 0 replies; 39+ messages in thread
From: Chad Sellers @ 2010-01-21 21:06 UTC (permalink / raw)
  To: jwcart2; +Cc: Caleb Case, selinux, kmacmillan, jbrindle, Stephen Smalley

On 1/8/10 9:30 AM, "James Carter" <jwcart2@tycho.nsa.gov> wrote:

> On Thu, 2010-01-07 at 17:28 -0500, Chad Sellers wrote:
>> On 12/23/09 6:25 PM, "Caleb Case" <ccase@tresys.com> wrote:
>> 
>>> Our motivations for this patchset are to:
>>> 
>>> * Move the semanage store - the portion of the SELinux configuration
>>>   managed by libsemanage - to a more appropriate location in the
>>>   filesystem. The current location - in /etc - is designated for
>>>   administrator controlled configuration and is sometimes mounted
>>>   read-only. By storing binary, program managed data in /etc libsemanage
>>>   breaks administrator expectations.
>>> 
>>> * Enable the overriding of modules in the module store without require
>>>   the original modules to removed or modified. This allows
>>>   administrators to customize the policy more fully while allowing the
>>>   distribution provided policies to be left unmodified and continue to
>>>   be updated by the package manager.
>>> 
>>> * Provide the ability for an administrator to disable a module without
>>>   removing or overriding that module.
>>> 
>>> [Move to /var/lib/selinux]
>>> 
>>> Move the libsemanage private store
>>> from /etc/selinux/<policy type>/modules
>>> to   /var/lib/selinux/<policy type>
>>> 
>>> The benefits of this are:
>>> 
>>> * Permits the use of a read-only /etc.
>>> 
>>> * Conforms to the Filesystem Hierarchy Standard.
>>> 
>>> An additional change in layout structure moves the temporary space for
>>> the active policy to an external temporary space. This has the benefit
>>> of permitting source control management to be used on the private
>>> policy.
>>> 
>>> [Module Priorities]
>>> 
>>> Module priorities modify libsemanage and the module store to allow
>>> multiple modules with the same name to exist with different priorities.
>>> Only the highest priority module is used to create the final system
>>> policy. The addition of module priorities enables the modification of
>>> the system policy without modifying individual modules. For example, it
>>> allows an administrator to add his own policy module for apache,
>>> completely replacing the distribution provided module, without changing
>>> or removing the distribution policy. This has several benefits:
>>> 
>>> * Distribution provided policy package updates proceed normally - the
>>>   distribution policy is inserted but the administrator provided policy
>>>   remains active.
>>> 
>>> * Multiple levels allows distributors, 3rd party applications, system
>>>   management tools (e.g., puppet), and local administrators to all make
>>>   changes without conflicting.
>>> 
>>> * Semanage modifications of policy (e.g., port labeling) will be able to
>>>   use high priority modules in the future to override defaults (requires
>>>   the CIL[1] language changes).
>>> 
>>> [Enable/Disable Modules]
>>> 
>>> Modules gain an enabled / disabled status. Enabled modules are used by
>>> semanage when building the active policy, and disabled modules are
>>> ignored. The main benefit of this is that modules can be disabled
>>> without out removing them from the store.
>>> 
>>> [Patchset Breakdown]
>>> 
>>> The patchset is broken down as follows:
>>> 
>>> Bug fixes:
>>> 
>>> libsemanage: fix type in tests makefile -o -> -O
>>> 
>>> Move the libsemanage store to /var/lib/selinux:
>>> 
>>> semanage: move permissive module creation to /tmp
>>> libsemanage: move the module store to /var/lib/selinux
>>> libsemanage: split final files into /var/lib/selinux/tmp
>>> libsemanage: update unit tests for move to /var/lib/selinux
>>> 
>>> Implement support for the new libsemanage store layout:
>>> 
>>> libsemanage: add default priority to semanage_handle_t
>>> libsemanage: augment semanage_module_info_t and provide
>>> semanage_module_key_t
>>> libsemanage: get/set module info and enabled status
>>> libsemanage: provide function to get new base module path
>>> libsemanage: provide function to get new base module path
>>> libsemanage: installing/upgrading/removing modules via info and key
>>> 
>>> Provide private headers for upstream tools to use:
>>> 
>>> libsemanage: new private api for unstable functions
>>> 
>>> Extend semodule to support enable/disable, priorities, and detailed
>>> listings:
>>> 
>>> semodule: add priority, enabled, and extended listing
>>> 
>>> Migration script for moving the libsemanage store:
>>> 
>>> semanage store migration script
>>> 
>>> Thanks for you feedback!
>>> 
>>> Caleb
>>> 
>>> [1] CIL RFC: http://marc.info/?l=selinux&m=124759244409438&w=2
>>> 
>>> Caleb Case (13):
>>>   libsemanage: fix typo in tests makefile -o -> -O
>>>   semanage: move permissive module creation to /tmp
>>>   libsemanage: move the module store to /var/lib/selinux
>>>   libsemanage: split final files into /var/lib/selinux/tmp
>>>   libsemanage: update unit tests for move to /var/lib/selinux
>>>   libsemanage: add default priority to semanage_handle_t
>>>   libsemanage: augment semanage_module_info_t and provide
>>>     semanage_module_key_t
>>>   libsemanage: get/set module info and enabled status
>>>   libsemanage: provide function to get new base module path
>>>   libsemanage: installing/upgrading/removing modules via info and key
>>>   libsemanage: new private api for unstable functions
>>>   semodule: add priority, enabled, and extended listing
>>>   semanage store migration script
>>> 
>>>  libsemanage/include/Makefile                     |    3 +
>>>  libsemanage/include/semanage/private/handle.h    |   31 +
>>>  libsemanage/include/semanage/private/modules.h   |  281 ++++
>>>  libsemanage/include/semanage/private/semanage.h  |   26 +
>>>  libsemanage/src/boolean_internal.h               |    4 +-
>>>  libsemanage/src/booleans_file.c                  |    7 +-
>>>  libsemanage/src/booleans_policydb.c              |    6 +-
>>>  libsemanage/src/database_file.c                  |   45 +-
>>>  libsemanage/src/database_file.h                  |    3 +-
>>>  libsemanage/src/database_policydb.c              |   37 +-
>>>  libsemanage/src/database_policydb.h              |    3 +-
>>>  libsemanage/src/direct_api.c                     | 1652
>>> +++++++++++++++++++---
>>>  libsemanage/src/fcontext_internal.h              |    3 +-
>>>  libsemanage/src/fcontexts_file.c                 |    7 +-
>>>  libsemanage/src/genhomedircon.c                  |    3 +-
>>>  libsemanage/src/handle.c                         |   23 +
>>>  libsemanage/src/handle.h                         |    3 +
>>>  libsemanage/src/handle_internal.h                |    1 +
>>>  libsemanage/src/iface_internal.h                 |    4 +-
>>>  libsemanage/src/interfaces_file.c                |    7 +-
>>>  libsemanage/src/interfaces_policydb.c            |    6 +-
>>>  libsemanage/src/libsemanage.map                  |   26 +
>>>  libsemanage/src/module_internal.h                |   21 +
>>>  libsemanage/src/modules.c                        |  999 +++++++++++++-
>>>  libsemanage/src/modules.h                        |   76 +-
>>>  libsemanage/src/node_internal.h                  |    4 +-
>>>  libsemanage/src/nodes_file.c                     |    7 +-
>>>  libsemanage/src/nodes_policydb.c                 |    6 +-
>>>  libsemanage/src/policy.h                         |   36 +
>>>  libsemanage/src/port_internal.h                  |    4 +-
>>>  libsemanage/src/ports_file.c                     |    7 +-
>>>  libsemanage/src/ports_policydb.c                 |    6 +-
>>>  libsemanage/src/semanage_store.c                 |  794 ++++++++---
>>>  libsemanage/src/semanage_store.h                 |   47 +-
>>>  libsemanage/src/seuser_internal.h                |    4 +-
>>>  libsemanage/src/seusers_file.c                   |    7 +-
>>>  libsemanage/src/user_internal.h                  |    6 +-
>>>  libsemanage/src/users_base_file.c                |    7 +-
>>>  libsemanage/src/users_base_policydb.c            |    6 +-
>>>  libsemanage/src/users_extra_file.c               |    7 +-
>>>  libsemanage/tests/Makefile                       |    2 +-
>>>  libsemanage/tests/test_semanage_store.c          |   34 +-
>>>  libsemanage/utils/semanage_migrate_etc_to_var.py |  301 ++++
>>>  policycoreutils/semanage/seobject.py             |   15 +-
>>>  policycoreutils/semodule/semodule.8              |   25 +-
>>>  policycoreutils/semodule/semodule.c              |  242 +++-
>>>  46 files changed, 4267 insertions(+), 577 deletions(-)
>>>  create mode 100644 libsemanage/include/semanage/private/handle.h
>>>  create mode 100644 libsemanage/include/semanage/private/modules.h
>>>  create mode 100644 libsemanage/include/semanage/private/semanage.h
>>>  create mode 100755 libsemanage/utils/semanage_migrate_etc_to_var.py
>>> 
>> Well, there have been no comments on this patchset. I'm guessing that's
>> because:
>> 
>> 1) We've talked to some of you face to face about it already.
>> 2) It's a big patchset, and you'd want to try it out a bit before
>> commenting.
>> 
> I've been trying it out for the last few days.  I haven't had any
> problems yet.
> 
>> To address #2, I'd like to propose creating an upstream branch for these
>> changes. This patchset is actually just the first patchset in a larger
>> effort to improve policy infrastructure. I think an upstream branch will
>> make it easier for many people to track those changes and try out the new
>> features we're creating. Eventually that branch can be merged back into
>> master.
>> 
>> Thoughts?
> 
> I think that creating an upstream branch would be a good idea.
> 
OK, I've created an upstream branch called src-policy and merged these
patches there. The name may seem odd right now, but the patchset we're about
to send (hopefully next week) will make it clear why it's named that. Anyone
that wants to play with this can check out that branch, and anyone who wants
to contribute can submit patches that apply to that branch. Note that all
patches will still flow through the list for this branch.

Thanks,
Chad

>> 
>> Thanks,
>> Chad Sellers
>>  
>> Oh, and in case it wasn't implied:
>> Acked-by: Chad Sellers <csellers@tresys.com>
>> 
>> 
>> --
>> 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.


--
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] 39+ messages in thread

end of thread, other threads:[~2010-01-21 21:06 UTC | newest]

Thread overview: 39+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-12-23 23:25 [PATCH 00/13] RFC libsemanage move to var, enable/disable module, and priority support Caleb Case
2009-12-23 23:25 ` [PATCH 01/13] libsemanage: fix typo in tests makefile -o -> -O Caleb Case
2009-12-23 23:25   ` [PATCH 02/13] semanage: move permissive module creation to /tmp Caleb Case
2009-12-23 23:25     ` [PATCH 03/13] libsemanage: move the module store to /var/lib/selinux Caleb Case
2009-12-23 23:25       ` [PATCH 04/13] libsemanage: split final files into /var/lib/selinux/tmp Caleb Case
2009-12-23 23:25         ` [PATCH 05/13] libsemanage: update unit tests for move to /var/lib/selinux Caleb Case
2009-12-23 23:25           ` [PATCH 06/13] libsemanage: add default priority to semanage_handle_t Caleb Case
2009-12-23 23:25             ` [PATCH 07/13] libsemanage: augment semanage_module_info_t and provide semanage_module_key_t Caleb Case
2009-12-23 23:25               ` [PATCH 08/13] libsemanage: get/set module info and enabled status Caleb Case
2009-12-23 23:25                 ` [PATCH 09/13] libsemanage: provide function to get new base module path Caleb Case
2009-12-23 23:25                   ` [PATCH 10/13] libsemanage: installing/upgrading/removing modules via info and key Caleb Case
2009-12-23 23:25                     ` [PATCH 11/13] libsemanage: new private api for unstable functions Caleb Case
2009-12-23 23:25                       ` [PATCH 12/13] semodule: add priority, enabled, and extended listing Caleb Case
2009-12-23 23:26                         ` [PATCH 13/13] semanage store migration script Caleb Case
2010-01-08 15:34                           ` Stephen Smalley
2010-01-08 20:59                             ` James Carter
2010-01-08 21:05                               ` Stephen Smalley
2010-01-08 21:27                               ` Caleb Case
2010-01-11 19:53                                 ` James Carter
2010-01-11 19:57                                   ` Joshua Brindle
2010-01-11 20:45                                     ` James Carter
2010-01-08 14:30         ` [PATCH 04/13] libsemanage: split final files into /var/lib/selinux/tmp Stephen Smalley
2010-01-08 15:07           ` James Carter
2010-01-08 15:28             ` Stephen Smalley
2010-01-08 18:25               ` Caleb Case
2010-01-08 20:19               ` Joshua Brindle
2010-01-08 20:25                 ` Stephen Smalley
2010-01-08 20:30                   ` Joshua Brindle
2010-01-08 20:51                     ` Joshua Brindle
2010-01-08 20:58                       ` Stephen Smalley
2010-01-08 21:02                         ` Joshua Brindle
2010-01-08 21:04                           ` Stephen Smalley
2010-01-08 21:12                           ` James Carter
2010-01-08 14:28       ` [PATCH 03/13] libsemanage: move the module store to /var/lib/selinux Stephen Smalley
2010-01-08 14:50         ` James Carter
2010-01-08 15:19           ` Stephen Smalley
2010-01-07 22:28 ` [PATCH 00/13] RFC libsemanage move to var, enable/disable module, and priority support Chad Sellers
2010-01-08 14:30   ` James Carter
2010-01-21 21:06     ` Chad Sellers

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.