diff mbox series

[RFC,1/2] libsemanage: support changing policy version via API

Message ID 20200206131253.535302-2-omosnace@redhat.com (mailing list archive)
State Rejected
Headers show
Series userspace: Allow changing version of kernel policy built by semodule | expand

Commit Message

Ondrej Mosnacek Feb. 6, 2020, 1:12 p.m. UTC
This change will be needed to support explicly specifying the policy
version in semodule (in a subsequent patch).

Signed-off-by: Ondrej Mosnacek <omosnace@redhat.com>
---
 libsemanage/include/semanage/handle.h |  6 +++
 libsemanage/src/direct_api.c          |  9 ++++-
 libsemanage/src/handle.c              | 24 ++++++++++++
 libsemanage/src/handle.h              |  1 +
 libsemanage/src/libsemanage.map       |  6 +++
 libsemanage/src/semanage_store.c      | 54 ++++++++++++++++-----------
 libsemanage/src/semanage_store.h      |  6 ++-
 7 files changed, 81 insertions(+), 25 deletions(-)
diff mbox series

Patch

diff --git a/libsemanage/include/semanage/handle.h b/libsemanage/include/semanage/handle.h
index 946d69bc..70b37863 100644
--- a/libsemanage/include/semanage/handle.h
+++ b/libsemanage/include/semanage/handle.h
@@ -85,6 +85,12 @@  extern void semanage_set_disable_dontaudit(semanage_handle_t * handle, int disab
 /* Set whether or not to execute setfiles to check file contexts upon commit */
 extern void semanage_set_check_contexts(semanage_handle_t * sh, int do_check_contexts);
 
+/* Get the kernel policy version. */
+extern unsigned semanage_get_policyvers(semanage_handle_t *sh);
+
+/* Set the kernel policy version. */
+extern int semanage_set_policyvers(semanage_handle_t *sh, unsigned policyvers);
+
 /* Get the default priority. */
 extern uint16_t semanage_get_default_priority(semanage_handle_t *sh);
 
diff --git a/libsemanage/src/direct_api.c b/libsemanage/src/direct_api.c
index 1088a0ac..78c40018 100644
--- a/libsemanage/src/direct_api.c
+++ b/libsemanage/src/direct_api.c
@@ -1204,6 +1204,7 @@  static int semanage_direct_commit(semanage_handle_t * sh)
 	size_t fc_buffer_len = 0;
 	const char *ofilename = NULL;
 	const char *path;
+	char kernel_path[PATH_MAX];
 	int retval = -1, num_modinfos = 0, i;
 	sepol_policydb_t *out = NULL;
 	struct cil_db *cildb = NULL;
@@ -1593,9 +1594,13 @@  rebuild:
 	if (retval < 0)
 		goto cleanup;
 
+	if (semanage_get_full_kernel_path(sh, SEMANAGE_FINAL_TMP, kernel_path)) {
+		ERR(sh, "Unable to build path to kernel policy.");
+		goto cleanup;
+	}
+
 	retval = semanage_copy_file(semanage_path(SEMANAGE_TMP, SEMANAGE_STORE_KERNEL),
-			semanage_final_path(SEMANAGE_FINAL_TMP, SEMANAGE_KERNEL),
-			sh->conf->file_mode);
+			kernel_path, sh->conf->file_mode);
 	if (retval < 0) {
 		goto cleanup;
 	}
diff --git a/libsemanage/src/handle.c b/libsemanage/src/handle.c
index 5e59aef7..78818930 100644
--- a/libsemanage/src/handle.c
+++ b/libsemanage/src/handle.c
@@ -81,6 +81,9 @@  semanage_handle_t *semanage_handle_create(void)
 		goto err;
 	sepol_msg_set_callback(sh->sepolh, semanage_msg_relay_handler, sh);
 
+	/* Default policy version is taken from config */
+	sh->policyvers = sh->conf->policyvers;
+
 	/* Default priority is 400 */
 	sh->priority = 400;
 
@@ -246,6 +249,27 @@  void semanage_set_check_contexts(semanage_handle_t * sh, int do_check_contexts)
 	return;
 }
 
+unsigned semanage_get_policyvers(semanage_handle_t *sh)
+{
+	assert(sh != NULL);
+	return sh->policyvers;
+}
+
+int semanage_set_policyvers(semanage_handle_t *sh, unsigned policyvers)
+{
+	assert(sh != NULL);
+
+	/* Verify policy version */
+	if (   policyvers < POLICYDB_VERSION_MIN
+	    || policyvers > POLICYDB_VERSION_MAX) {
+		ERR(sh, "Policy version %u is invalid.", policyvers);
+		return -1;
+	}
+
+	sh->policyvers = policyvers;
+	return 0;
+}
+
 uint16_t semanage_get_default_priority(semanage_handle_t *sh)
 {
 	assert(sh != NULL);
diff --git a/libsemanage/src/handle.h b/libsemanage/src/handle.h
index a91907b0..ee389226 100644
--- a/libsemanage/src/handle.h
+++ b/libsemanage/src/handle.h
@@ -57,6 +57,7 @@  struct semanage_handle {
 
 	semanage_conf_t *conf;
 
+	unsigned policyvers;
 	uint16_t priority;
 	int is_connected;
 	int is_in_transaction;
diff --git a/libsemanage/src/libsemanage.map b/libsemanage/src/libsemanage.map
index 02036696..8c05b9ad 100644
--- a/libsemanage/src/libsemanage.map
+++ b/libsemanage/src/libsemanage.map
@@ -63,3 +63,9 @@  LIBSEMANAGE_1.1 {
 	  semanage_module_remove_key;
 	  semanage_set_store_root;
 } LIBSEMANAGE_1.0;
+
+LIBSEMANAGE_1.2 {
+  global:
+	  semanage_get_policyvers;
+	  semanage_set_policyvers;
+} LIBSEMANAGE_1.1;
diff --git a/libsemanage/src/semanage_store.c b/libsemanage/src/semanage_store.c
index 58dded6e..52217be7 100644
--- a/libsemanage/src/semanage_store.c
+++ b/libsemanage/src/semanage_store.c
@@ -277,9 +277,7 @@  cleanup:
 
 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("");
@@ -350,19 +348,9 @@  static int semanage_init_final_suffix(semanage_handle_t *sh)
 		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) {
+	semanage_final_suffix[SEMANAGE_KERNEL_PREFIX] =
+		strdup(selinux_binary_policy_path() + offset);
+	if (semanage_final_suffix[SEMANAGE_KERNEL_PREFIX] == NULL) {
 		ERR(sh, "Unable to allocate space for policy binary path.");
 		status = -1;
 		goto cleanup;
@@ -503,6 +491,20 @@  const char *semanage_final_path(enum semanage_final_defs store,
 	return semanage_final_paths[store][path_name];
 }
 
+/* Return a fully-qualified path + filename to kernel policy for the given
+ * semanage store.
+ */
+int semanage_get_full_kernel_path(semanage_handle_t * sh,
+				  enum semanage_final_defs root,
+				  char out[PATH_MAX])
+{
+	int ret = snprintf(out, PATH_MAX, "%s.%u",
+			   semanage_final_path(root, SEMANAGE_KERNEL_PREFIX),
+			   sh->policyvers);
+
+	return ret < 0 || ret >= PATH_MAX ? -1 : 0;
+}
+
 /* Return a fully-qualified path + filename to the semanage
  * configuration file. If semanage.conf file in the semanage
  * root is cannot be read, use the default semanage.conf as a
@@ -1568,12 +1570,16 @@  static int semanage_validate_and_compile_fcontexts(semanage_handle_t * sh)
 	int status = -1;
 
 	if (sh->do_check_contexts) {
+		char path[PATH_MAX];
 		int ret;
+
+		if (semanage_get_full_kernel_path(sh, SEMANAGE_FINAL_TMP, path)) {
+			ERR(sh, "Unable to build path to kernel policy.");
+			goto cleanup;
+		}
+
 		ret = semanage_exec_prog(
-			sh,
-			sh->conf->setfiles,
-			semanage_final_path(SEMANAGE_FINAL_TMP,
-					    SEMANAGE_KERNEL),
+			sh, sh->conf->setfiles, path,
 			semanage_final_path(SEMANAGE_FINAL_TMP,
 					    SEMANAGE_FC));
 		if (ret != 0) {
@@ -2233,15 +2239,19 @@  int semanage_verify_linked(semanage_handle_t * sh)
 int semanage_verify_kernel(semanage_handle_t * sh)
 {
 	int retval = -1;
-	const char *kernel_filename =
-	    semanage_final_path(SEMANAGE_FINAL_TMP, SEMANAGE_KERNEL);
+	char path[PATH_MAX];
 	semanage_conf_t *conf = sh->conf;
 	external_prog_t *e;
+
 	if (conf->kernel_prog == NULL) {
 		return 0;
 	}
+	if (semanage_get_full_kernel_path(sh, SEMANAGE_FINAL_TMP, path)) {
+		ERR(sh, "Unable to build path to kernel policy.");
+		goto cleanup;
+	}
 	for (e = conf->kernel_prog; e != NULL; e = e->next) {
-		if (semanage_exec_prog(sh, e, kernel_filename, "$<") != 0) {
+		if (semanage_exec_prog(sh, e, path, "$<") != 0) {
 			goto cleanup;
 		}
 	}
diff --git a/libsemanage/src/semanage_store.h b/libsemanage/src/semanage_store.h
index 34bf8523..d5567782 100644
--- a/libsemanage/src/semanage_store.h
+++ b/libsemanage/src/semanage_store.h
@@ -81,7 +81,7 @@  enum semanage_final_path_defs {
 	SEMANAGE_FC_HOMEDIRS_BIN,
 	SEMANAGE_FC_LOCAL,
 	SEMANAGE_FC_LOCAL_BIN,
-	SEMANAGE_KERNEL,
+	SEMANAGE_KERNEL_PREFIX,
 	SEMANAGE_NC,
 	SEMANAGE_SEUSERS,
 	SEMANAGE_FINAL_PATH_NUM
@@ -102,6 +102,10 @@  extern const char *semanage_path(enum semanage_store_defs store,
 extern const char *semanage_final_path(enum semanage_final_defs root,
 				       enum semanage_final_path_defs suffix);
 
+int semanage_get_full_kernel_path(semanage_handle_t * sh,
+				  enum semanage_final_defs root,
+				  char out[PATH_MAX]);
+
 int semanage_create_store(semanage_handle_t * sh, int create);
 
 int semanage_store_access_check(void);