diff --git a/.gitignore b/.gitignore
index db91e67..9e469e0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -152,3 +152,4 @@ libsemanage-2.0.45.tgz
 /libsemanage-3.3-rc2.tar.gz
 /libsemanage-3.3-rc3.tar.gz
 /libsemanage-3.3.tar.gz
+/libsemanage-3.4-rc1.tar.gz
diff --git a/0001-libsemanage-Fix-RESOURCE_LEAK-and-USE_AFTER_FREE-cov.patch b/0001-libsemanage-Fix-RESOURCE_LEAK-and-USE_AFTER_FREE-cov.patch
deleted file mode 100644
index 4dc4ca8..0000000
--- a/0001-libsemanage-Fix-RESOURCE_LEAK-and-USE_AFTER_FREE-cov.patch
+++ /dev/null
@@ -1,66 +0,0 @@
-From 05bc0fe72b53476a9d4da3957c6d6cba00c76eea Mon Sep 17 00:00:00 2001
-From: Petr Lautrbach <plautrba@redhat.com>
-Date: Wed, 7 Nov 2018 18:17:34 +0100
-Subject: [PATCH] libsemanage: Fix RESOURCE_LEAK and USE_AFTER_FREE coverity
- scan defects
-
----
- libsemanage/src/direct_api.c | 21 ++++++++-------------
- 1 file changed, 8 insertions(+), 13 deletions(-)
-
-diff --git a/libsemanage/src/direct_api.c b/libsemanage/src/direct_api.c
-index f0e2300a2f58..b7a3e0f17cc1 100644
---- a/libsemanage/src/direct_api.c
-+++ b/libsemanage/src/direct_api.c
-@@ -1029,7 +1029,7 @@ static int semanage_direct_write_langext(semanage_handle_t *sh,
- 
- 	fp = NULL;
- 
--	ret = 0;
-+	return 0;
- 
- cleanup:
- 	if (fp != NULL) fclose(fp);
-@@ -2186,7 +2186,6 @@ cleanup:
- 	semanage_module_info_destroy(sh, modinfo);
- 	free(modinfo);
- 
--	if (fp != NULL) fclose(fp);
- 	return status;
- }
- 
-@@ -2351,16 +2350,6 @@ static int semanage_direct_get_module_info(semanage_handle_t *sh,
- 	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 enabled/disabled status */
- 	ret = semanage_module_get_path(sh,
- 				       *modinfo,
-@@ -2404,7 +2393,13 @@ cleanup:
- 		free(modinfos);
- 	}
- 
--	if (fp != NULL) fclose(fp);
-+	if (fp != NULL && fclose(fp) != 0) {
-+		ERR(sh,
-+		    "Unable to close %s module lang ext file.",
-+		    (*modinfo)->name);
-+		status = -1;
-+	}
-+
- 	return status;
- }
- 
--- 
-2.32.0
-
diff --git a/0001-libsemanage-avoid-double-fclose.patch b/0001-libsemanage-avoid-double-fclose.patch
new file mode 100644
index 0000000..456e659
--- /dev/null
+++ b/0001-libsemanage-avoid-double-fclose.patch
@@ -0,0 +1,53 @@
+From 966cda1fccc78c4c3d4f23bb4c211a09393f30fb Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= <cgzones@googlemail.com>
+Date: Fri, 8 Apr 2022 15:10:54 +0200
+Subject: [PATCH] libsemanage: avoid double fclose
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+Content-type: text/plain
+
+The cleanup goto block in `semanage_direct_set_enabled()` closes the
+file stream pointer fp if not NULL.  Set the stream to NULL after a
+manual fclose(3), even on failure.
+
+    direct_api.c: In function ‘semanage_direct_set_enabled’:
+    direct_api.c:2130:25: error: pointer ‘fp’ may be used after ‘fclose’ [-Werror=use-after-free]
+     2130 |         if (fp != NULL) fclose(fp);
+          |                         ^~~~~~~~~~
+    direct_api.c:2092:29: note: call to ‘fclose’ here
+     2092 |                         if (fclose(fp) != 0) {
+          |                             ^~~~~~~~~~
+
+Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
+---
+ libsemanage/src/direct_api.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/libsemanage/src/direct_api.c b/libsemanage/src/direct_api.c
+index d5716ce579e9..7206483a3ebb 100644
+--- a/libsemanage/src/direct_api.c
++++ b/libsemanage/src/direct_api.c
+@@ -2089,7 +2089,9 @@ static int semanage_direct_set_enabled(semanage_handle_t *sh,
+ 				goto cleanup;
+ 			}
+ 
+-			if (fclose(fp) != 0) {
++			ret = fclose(fp);
++			fp = NULL;
++			if (ret != 0) {
+ 				ERR(sh,
+ 				    "Unable to close disabled file for module %s",
+ 				    modkey->name);
+@@ -2097,8 +2099,6 @@ static int semanage_direct_set_enabled(semanage_handle_t *sh,
+ 				goto cleanup;
+ 			}
+ 
+-			fp = NULL;
+-
+ 			break;
+ 		case 1: /* enable the module */
+ 			if (unlink(fn) < 0) {
+-- 
+2.35.1
+
diff --git a/0002-libsemanage-add-missing-include-to-boolean_record.c.patch b/0002-libsemanage-add-missing-include-to-boolean_record.c.patch
deleted file mode 100644
index ec8fa2c..0000000
--- a/0002-libsemanage-add-missing-include-to-boolean_record.c.patch
+++ /dev/null
@@ -1,38 +0,0 @@
-From 5bf29afd8591d93aa6052254855b2ff5c9b38ec6 Mon Sep 17 00:00:00 2001
-From: Ondrej Mosnacek <omosnace@redhat.com>
-Date: Thu, 3 Feb 2022 17:53:22 +0100
-Subject: [PATCH] libsemanage: add missing include to boolean_record.c
-
-It uses asprintf(3), but doesn't directly include <stdio.h> - fix it.
-
-Signed-off-by: Ondrej Mosnacek <omosnace@redhat.com>
-Acked-by: James Carter <jwcart2@gmail.com>
----
- libsemanage/src/boolean_record.c | 4 +++-
- 1 file changed, 3 insertions(+), 1 deletion(-)
-
-diff --git a/libsemanage/src/boolean_record.c b/libsemanage/src/boolean_record.c
-index 95f3a8620ead..40dc6545fbdb 100644
---- a/libsemanage/src/boolean_record.c
-+++ b/libsemanage/src/boolean_record.c
-@@ -7,6 +7,9 @@
-  */
- 
- #include <string.h>
-+#include <stdio.h>
-+#include <stdlib.h>
-+
- #include <sepol/boolean_record.h>
- 
- typedef sepol_bool_t semanage_bool_t;
-@@ -20,7 +23,6 @@ typedef semanage_bool_key_t record_key_t;
- #include "boolean_internal.h"
- #include "handle.h"
- #include "database.h"
--#include <stdlib.h>
- #include <selinux/selinux.h>
- 
- /* Key */
--- 
-2.34.1
-
diff --git a/0003-semodule-libsemanage-move-module-hashing-into-libsem.patch b/0003-semodule-libsemanage-move-module-hashing-into-libsem.patch
deleted file mode 100644
index d17439e..0000000
--- a/0003-semodule-libsemanage-move-module-hashing-into-libsem.patch
+++ /dev/null
@@ -1,575 +0,0 @@
-From f77f2b70930c628b362320cbfe07833032ae9b0f Mon Sep 17 00:00:00 2001
-From: Ondrej Mosnacek <omosnace@redhat.com>
-Date: Thu, 3 Feb 2022 17:53:23 +0100
-Subject: [PATCH] semodule,libsemanage: move module hashing into libsemanage
-
-The main goal of this move is to have the SHA-256 implementation under
-libsemanage, since upcoming patches will make use of SHA-256 for a
-different (but similar) purpose in libsemanage. Having the hashing code
-in libsemanage will reduce code duplication and allow for easier hash
-algorithm upgrade in the future.
-
-Note that libselinux currently also contains a hash function
-implementation (for yet another different purpose). This patch doesn't
-make any effort to address that duplicity yet.
-
-This patch also changes the format of the hash string printed by
-semodule to include the name of the hash. The intent is to avoid
-ambiguity and potential collisions when the algorithm is potentially
-changed in the future.
-
-Signed-off-by: Ondrej Mosnacek <omosnace@redhat.com>
----
- libsemanage/include/semanage/modules.h        |  26 ++
- libsemanage/src/libsemanage.map               |   4 +
- libsemanage/src/modules.c                     |  59 ++++
- .../src/semanageswig_python_exception.i       |   8 +
- libsemanage/src/sha256.c                      | 294 ++++++++++++++++++
- libsemanage/src/sha256.h                      |  89 ++++++
- 6 files changed, 480 insertions(+)
- create mode 100644 libsemanage/src/sha256.c
- create mode 100644 libsemanage/src/sha256.h
-
-diff --git a/libsemanage/include/semanage/modules.h b/libsemanage/include/semanage/modules.h
-index b51f61f033d5..14666f6dbe00 100644
---- a/libsemanage/include/semanage/modules.h
-+++ b/libsemanage/include/semanage/modules.h
-@@ -282,4 +282,30 @@ extern int semanage_module_get_enabled(semanage_handle_t *sh,
- 				       const semanage_module_key_t *modkey,
- 				       int *enabled);
- 
-+/* Compute checksum for @modkey module contents.
-+ *
-+ * If @checksum is NULL, the function will just return the length of the
-+ * checksum string in @checksum_len (checksum strings are guaranteed to
-+ * have a fixed length for a given libsemanage binary). @modkey and @cil
-+ * are ignored in this case and should be set to NULL and 0 (respectively).
-+ *
-+ * If @checksum is non-NULL, on success, @checksum will point to a buffer
-+ * containing the checksum string and @checksum_len will point to the
-+ * length of the string (without the null terminator). The semantics of
-+ * @cil are the same as for @extract_cil in semanage_module_extract().
-+ *
-+ * The caller is responsible to free the buffer returned in @checksum (using
-+ * free(3)).
-+ *
-+ * Callers may assume that if the checksum strings for two modules match,
-+ * the module content is the same (collisions are theoretically possible,
-+ * yet extremely unlikely).
-+ *
-+ * Returns 0 on success and -1 on error.
-+ */
-+extern int semanage_module_compute_checksum(semanage_handle_t *sh,
-+					    semanage_module_key_t *modkey,
-+					    int cil, char **checksum,
-+					    size_t *checksum_len);
-+
- #endif
-diff --git a/libsemanage/src/libsemanage.map b/libsemanage/src/libsemanage.map
-index 3ea7b60f97bb..00259fc817f5 100644
---- a/libsemanage/src/libsemanage.map
-+++ b/libsemanage/src/libsemanage.map
-@@ -345,3 +345,7 @@ LIBSEMANAGE_1.1 {
-     semanage_module_remove_key;
-     semanage_set_store_root;
- } LIBSEMANAGE_1.0;
-+
-+LIBSEMANAGE_3.4 {
-+    semanage_module_compute_checksum;
-+} LIBSEMANAGE_1.1;
-diff --git a/libsemanage/src/modules.c b/libsemanage/src/modules.c
-index b6dd456cac32..5dbb28fdbaa5 100644
---- a/libsemanage/src/modules.c
-+++ b/libsemanage/src/modules.c
-@@ -35,11 +35,13 @@
- #include <fcntl.h>
- #include <sys/types.h>
- #include <sys/stat.h>
-+#include <sys/mman.h>
- #include <errno.h>
- #include <ctype.h>
- 
- #include "handle.h"
- #include "modules.h"
-+#include "sha256.h"
- #include "debug.h"
- 
- int semanage_module_install(semanage_handle_t * sh,
-@@ -975,3 +977,60 @@ int semanage_module_remove_key(semanage_handle_t *sh,
- 	return sh->funcs->remove_key(sh, modkey);
- }
- 
-+static const char CHECKSUM_TYPE[] = "sha256";
-+static const size_t CHECKSUM_CONTENT_SIZE = sizeof(CHECKSUM_TYPE) + 1 + 2 * SHA256_HASH_SIZE;
-+
-+static void semanage_hash_to_checksum_string(const uint8_t *hash, char *checksum)
-+{
-+	size_t i;
-+
-+	checksum += sprintf(checksum, "%s:", CHECKSUM_TYPE);
-+	for (i = 0; i < SHA256_HASH_SIZE; i++) {
-+		checksum += sprintf(checksum, "%02x", (unsigned)hash[i]);
-+	}
-+}
-+
-+int semanage_module_compute_checksum(semanage_handle_t *sh,
-+				     semanage_module_key_t *modkey,
-+				     int cil, char **checksum,
-+				     size_t *checksum_len)
-+{
-+	semanage_module_info_t *extract_info = NULL;
-+	Sha256Context context;
-+	SHA256_HASH sha256_hash;
-+	char *checksum_str;
-+	void *data;
-+	size_t data_len = 0;
-+	int result;
-+
-+	if (!checksum_len)
-+		return -1;
-+
-+	if (!checksum) {
-+		*checksum_len = CHECKSUM_CONTENT_SIZE;
-+		return 0;
-+	}
-+
-+	result = semanage_module_extract(sh, modkey, cil, &data, &data_len, &extract_info);
-+	if (result != 0)
-+		return -1;
-+
-+	semanage_module_info_destroy(sh, extract_info);
-+	free(extract_info);
-+
-+	Sha256Initialise(&context);
-+	Sha256Update(&context, data, data_len);
-+	Sha256Finalise(&context, &sha256_hash);
-+
-+	munmap(data, data_len);
-+
-+	checksum_str = malloc(CHECKSUM_CONTENT_SIZE + 1 /* '\0' */);
-+	if (!checksum_str)
-+		return -1;
-+
-+	semanage_hash_to_checksum_string(sha256_hash.bytes, checksum_str);
-+
-+	*checksum = checksum_str;
-+	*checksum_len = CHECKSUM_CONTENT_SIZE;
-+	return 0;
-+}
-diff --git a/libsemanage/src/semanageswig_python_exception.i b/libsemanage/src/semanageswig_python_exception.i
-index 372ec948866a..0df8bbc350e2 100644
---- a/libsemanage/src/semanageswig_python_exception.i
-+++ b/libsemanage/src/semanageswig_python_exception.i
-@@ -351,6 +351,14 @@
-   }
- }
- 
-+%exception semanage_module_compute_checksum {
-+  $action
-+  if (result < 0) {
-+     PyErr_SetFromErrno(PyExc_OSError);
-+     SWIG_fail;
-+  }
-+}
-+
- %exception semanage_msg_get_level {
-   $action
-   if (result < 0) {
-diff --git a/libsemanage/src/sha256.c b/libsemanage/src/sha256.c
-new file mode 100644
-index 000000000000..fe2aeef07f53
---- /dev/null
-+++ b/libsemanage/src/sha256.c
-@@ -0,0 +1,294 @@
-+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-+//  WjCryptLib_Sha256
-+//
-+//  Implementation of SHA256 hash function.
-+//  Original author: Tom St Denis, tomstdenis@gmail.com, http://libtom.org
-+//  Modified by WaterJuice retaining Public Domain license.
-+//
-+//  This is free and unencumbered software released into the public domain - June 2013 waterjuice.org
-+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-+
-+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-+//  IMPORTS
-+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-+
-+#include "sha256.h"
-+#include <memory.h>
-+
-+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-+//  MACROS
-+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-+
-+#define ror(value, bits) (((value) >> (bits)) | ((value) << (32 - (bits))))
-+
-+#define MIN(x, y) ( ((x)<(y))?(x):(y) )
-+
-+#define STORE32H(x, y)                                                                     \
-+     { (y)[0] = (uint8_t)(((x)>>24)&255); (y)[1] = (uint8_t)(((x)>>16)&255);   \
-+       (y)[2] = (uint8_t)(((x)>>8)&255); (y)[3] = (uint8_t)((x)&255); }
-+
-+#define LOAD32H(x, y)                            \
-+     { x = ((uint32_t)((y)[0] & 255)<<24) | \
-+           ((uint32_t)((y)[1] & 255)<<16) | \
-+           ((uint32_t)((y)[2] & 255)<<8)  | \
-+           ((uint32_t)((y)[3] & 255)); }
-+
-+#define STORE64H(x, y)                                                                     \
-+   { (y)[0] = (uint8_t)(((x)>>56)&255); (y)[1] = (uint8_t)(((x)>>48)&255);     \
-+     (y)[2] = (uint8_t)(((x)>>40)&255); (y)[3] = (uint8_t)(((x)>>32)&255);     \
-+     (y)[4] = (uint8_t)(((x)>>24)&255); (y)[5] = (uint8_t)(((x)>>16)&255);     \
-+     (y)[6] = (uint8_t)(((x)>>8)&255); (y)[7] = (uint8_t)((x)&255); }
-+
-+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-+//  CONSTANTS
-+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-+
-+// The K array
-+static const uint32_t K[64] = {
-+    0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL, 0x3956c25bUL,
-+    0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL, 0xd807aa98UL, 0x12835b01UL,
-+    0x243185beUL, 0x550c7dc3UL, 0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL,
-+    0xc19bf174UL, 0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL,
-+    0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL, 0x983e5152UL,
-+    0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL, 0xc6e00bf3UL, 0xd5a79147UL,
-+    0x06ca6351UL, 0x14292967UL, 0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL,
-+    0x53380d13UL, 0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL,
-+    0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL, 0xd192e819UL,
-+    0xd6990624UL, 0xf40e3585UL, 0x106aa070UL, 0x19a4c116UL, 0x1e376c08UL,
-+    0x2748774cUL, 0x34b0bcb5UL, 0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL,
-+    0x682e6ff3UL, 0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL,
-+    0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL
-+};
-+
-+#define BLOCK_SIZE          64
-+
-+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-+//  INTERNAL FUNCTIONS
-+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-+
-+// Various logical functions
-+#define Ch( x, y, z )     (z ^ (x & (y ^ z)))
-+#define Maj( x, y, z )    (((x | y) & z) | (x & y))
-+#define S( x, n )         ror((x),(n))
-+#define R( x, n )         (((x)&0xFFFFFFFFUL)>>(n))
-+#define Sigma0( x )       (S(x, 2) ^ S(x, 13) ^ S(x, 22))
-+#define Sigma1( x )       (S(x, 6) ^ S(x, 11) ^ S(x, 25))
-+#define Gamma0( x )       (S(x, 7) ^ S(x, 18) ^ R(x, 3))
-+#define Gamma1( x )       (S(x, 17) ^ S(x, 19) ^ R(x, 10))
-+
-+#define Sha256Round( a, b, c, d, e, f, g, h, i )       \
-+     t0 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i];   \
-+     t1 = Sigma0(a) + Maj(a, b, c);                    \
-+     d += t0;                                          \
-+     h  = t0 + t1;
-+
-+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-+//  TransformFunction
-+//
-+//  Compress 512-bits
-+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-+static
-+void
-+    TransformFunction
-+    (
-+        Sha256Context*      Context,
-+        uint8_t const*      Buffer
-+    )
-+{
-+    uint32_t    S[8];
-+    uint32_t    W[64];
-+    uint32_t    t0;
-+    uint32_t    t1;
-+    uint32_t    t;
-+    int         i;
-+
-+    // Copy state into S
-+    for( i=0; i<8; i++ )
-+    {
-+        S[i] = Context->state[i];
-+    }
-+
-+    // Copy the state into 512-bits into W[0..15]
-+    for( i=0; i<16; i++ )
-+    {
-+        LOAD32H( W[i], Buffer + (4*i) );
-+    }
-+
-+    // Fill W[16..63]
-+    for( i=16; i<64; i++ )
-+    {
-+        W[i] = Gamma1( W[i-2]) + W[i-7] + Gamma0( W[i-15] ) + W[i-16];
-+    }
-+
-+    // Compress
-+    for( i=0; i<64; i++ )
-+    {
-+        Sha256Round( S[0], S[1], S[2], S[3], S[4], S[5], S[6], S[7], i );
-+        t = S[7];
-+        S[7] = S[6];
-+        S[6] = S[5];
-+        S[5] = S[4];
-+        S[4] = S[3];
-+        S[3] = S[2];
-+        S[2] = S[1];
-+        S[1] = S[0];
-+        S[0] = t;
-+    }
-+
-+    // Feedback
-+    for( i=0; i<8; i++ )
-+    {
-+        Context->state[i] = Context->state[i] + S[i];
-+    }
-+}
-+
-+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-+//  PUBLIC FUNCTIONS
-+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-+
-+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-+//  Sha256Initialise
-+//
-+//  Initialises a SHA256 Context. Use this to initialise/reset a context.
-+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-+void
-+    Sha256Initialise
-+    (
-+        Sha256Context*      Context         // [out]
-+    )
-+{
-+    Context->curlen = 0;
-+    Context->length = 0;
-+    Context->state[0] = 0x6A09E667UL;
-+    Context->state[1] = 0xBB67AE85UL;
-+    Context->state[2] = 0x3C6EF372UL;
-+    Context->state[3] = 0xA54FF53AUL;
-+    Context->state[4] = 0x510E527FUL;
-+    Context->state[5] = 0x9B05688CUL;
-+    Context->state[6] = 0x1F83D9ABUL;
-+    Context->state[7] = 0x5BE0CD19UL;
-+}
-+
-+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-+//  Sha256Update
-+//
-+//  Adds data to the SHA256 context. This will process the data and update the internal state of the context. Keep on
-+//  calling this function until all the data has been added. Then call Sha256Finalise to calculate the hash.
-+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-+void
-+    Sha256Update
-+    (
-+        Sha256Context*      Context,        // [in out]
-+        void const*         Buffer,         // [in]
-+        uint32_t            BufferSize      // [in]
-+    )
-+{
-+    uint32_t n;
-+
-+    if( Context->curlen > sizeof(Context->buf) )
-+    {
-+       return;
-+    }
-+
-+    while( BufferSize > 0 )
-+    {
-+        if( Context->curlen == 0 && BufferSize >= BLOCK_SIZE )
-+        {
-+           TransformFunction( Context, (uint8_t*)Buffer );
-+           Context->length += BLOCK_SIZE * 8;
-+           Buffer = (uint8_t*)Buffer + BLOCK_SIZE;
-+           BufferSize -= BLOCK_SIZE;
-+        }
-+        else
-+        {
-+           n = MIN( BufferSize, (BLOCK_SIZE - Context->curlen) );
-+           memcpy( Context->buf + Context->curlen, Buffer, (size_t)n );
-+           Context->curlen += n;
-+           Buffer = (uint8_t*)Buffer + n;
-+           BufferSize -= n;
-+           if( Context->curlen == BLOCK_SIZE )
-+           {
-+              TransformFunction( Context, Context->buf );
-+              Context->length += 8*BLOCK_SIZE;
-+              Context->curlen = 0;
-+           }
-+       }
-+    }
-+}
-+
-+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-+//  Sha256Finalise
-+//
-+//  Performs the final calculation of the hash and returns the digest (32 byte buffer containing 256bit hash). After
-+//  calling this, Sha256Initialised must be used to reuse the context.
-+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-+void
-+    Sha256Finalise
-+    (
-+        Sha256Context*      Context,        // [in out]
-+        SHA256_HASH*        Digest          // [out]
-+    )
-+{
-+    int i;
-+
-+    if( Context->curlen >= sizeof(Context->buf) )
-+    {
-+       return;
-+    }
-+
-+    // Increase the length of the message
-+    Context->length += Context->curlen * 8;
-+
-+    // Append the '1' bit
-+    Context->buf[Context->curlen++] = (uint8_t)0x80;
-+
-+    // if the length is currently above 56 bytes we append zeros
-+    // then compress.  Then we can fall back to padding zeros and length
-+    // encoding like normal.
-+    if( Context->curlen > 56 )
-+    {
-+        while( Context->curlen < 64 )
-+        {
-+            Context->buf[Context->curlen++] = (uint8_t)0;
-+        }
-+        TransformFunction(Context, Context->buf);
-+        Context->curlen = 0;
-+    }
-+
-+    // Pad up to 56 bytes of zeroes
-+    while( Context->curlen < 56 )
-+    {
-+        Context->buf[Context->curlen++] = (uint8_t)0;
-+    }
-+
-+    // Store length
-+    STORE64H( Context->length, Context->buf+56 );
-+    TransformFunction( Context, Context->buf );
-+
-+    // Copy output
-+    for( i=0; i<8; i++ )
-+    {
-+        STORE32H( Context->state[i], Digest->bytes+(4*i) );
-+    }
-+}
-+
-+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-+//  Sha256Calculate
-+//
-+//  Combines Sha256Initialise, Sha256Update, and Sha256Finalise into one function. Calculates the SHA256 hash of the
-+//  buffer.
-+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-+void
-+    Sha256Calculate
-+    (
-+        void  const*        Buffer,         // [in]
-+        uint32_t            BufferSize,     // [in]
-+        SHA256_HASH*        Digest          // [in]
-+    )
-+{
-+    Sha256Context context;
-+
-+    Sha256Initialise( &context );
-+    Sha256Update( &context, Buffer, BufferSize );
-+    Sha256Finalise( &context, Digest );
-+}
-diff --git a/libsemanage/src/sha256.h b/libsemanage/src/sha256.h
-new file mode 100644
-index 000000000000..406ed869cd82
---- /dev/null
-+++ b/libsemanage/src/sha256.h
-@@ -0,0 +1,89 @@
-+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-+//  WjCryptLib_Sha256
-+//
-+//  Implementation of SHA256 hash function.
-+//  Original author: Tom St Denis, tomstdenis@gmail.com, http://libtom.org
-+//  Modified by WaterJuice retaining Public Domain license.
-+//
-+//  This is free and unencumbered software released into the public domain - June 2013 waterjuice.org
-+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-+
-+#pragma once
-+
-+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-+//  IMPORTS
-+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-+
-+#include <stdint.h>
-+#include <stdio.h>
-+
-+typedef struct
-+{
-+    uint64_t    length;
-+    uint32_t    state[8];
-+    uint32_t    curlen;
-+    uint8_t     buf[64];
-+} Sha256Context;
-+
-+#define SHA256_HASH_SIZE           ( 256 / 8 )
-+
-+typedef struct
-+{
-+    uint8_t      bytes [SHA256_HASH_SIZE];
-+} SHA256_HASH;
-+
-+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-+//  PUBLIC FUNCTIONS
-+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-+
-+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-+//  Sha256Initialise
-+//
-+//  Initialises a SHA256 Context. Use this to initialise/reset a context.
-+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-+void
-+    Sha256Initialise
-+    (
-+        Sha256Context*      Context         // [out]
-+    );
-+
-+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-+//  Sha256Update
-+//
-+//  Adds data to the SHA256 context. This will process the data and update the internal state of the context. Keep on
-+//  calling this function until all the data has been added. Then call Sha256Finalise to calculate the hash.
-+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-+void
-+    Sha256Update
-+    (
-+        Sha256Context*      Context,        // [in out]
-+        void const*         Buffer,         // [in]
-+        uint32_t            BufferSize      // [in]
-+    );
-+
-+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-+//  Sha256Finalise
-+//
-+//  Performs the final calculation of the hash and returns the digest (32 byte buffer containing 256bit hash). After
-+//  calling this, Sha256Initialised must be used to reuse the context.
-+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-+void
-+    Sha256Finalise
-+    (
-+        Sha256Context*      Context,        // [in out]
-+        SHA256_HASH*        Digest          // [out]
-+    );
-+
-+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-+//  Sha256Calculate
-+//
-+//  Combines Sha256Initialise, Sha256Update, and Sha256Finalise into one function. Calculates the SHA256 hash of the
-+//  buffer.
-+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-+void
-+    Sha256Calculate
-+    (
-+        void  const*        Buffer,         // [in]
-+        uint32_t            BufferSize,     // [in]
-+        SHA256_HASH*        Digest          // [in]
-+    );
--- 
-2.34.1
-
diff --git a/0004-libsemanage-move-compressed-file-handling-into-a-sep.patch b/0004-libsemanage-move-compressed-file-handling-into-a-sep.patch
deleted file mode 100644
index 0714895..0000000
--- a/0004-libsemanage-move-compressed-file-handling-into-a-sep.patch
+++ /dev/null
@@ -1,824 +0,0 @@
-From 7b059d3ca56dbe7003cec921c13be70f9fa1a0f7 Mon Sep 17 00:00:00 2001
-From: Ondrej Mosnacek <omosnace@redhat.com>
-Date: Thu, 3 Feb 2022 17:53:24 +0100
-Subject: [PATCH] libsemanage: move compressed file handling into a separate
- object
-
-In order to reduce exisiting and future code duplication and to avoid
-some unnecessary allocations and copying, factor the compressed file
-utility functions out into a separate C/header file and refactor their
-interface.
-
-Note that this change effectively removes the __fsetlocking(3) call from
-semanage_load_files() - I haven't been able to figure out what purpose
-it serves, but it seems pointless...
-
-Signed-off-by: Ondrej Mosnacek <omosnace@redhat.com>
----
- libsemanage/src/compressed_file.c | 224 +++++++++++++++++++++++++
- libsemanage/src/compressed_file.h |  78 +++++++++
- libsemanage/src/direct_api.c      | 263 +++++-------------------------
- libsemanage/src/direct_api.h      |   4 -
- libsemanage/src/semanage_store.c  |  52 ++----
- 5 files changed, 354 insertions(+), 267 deletions(-)
- create mode 100644 libsemanage/src/compressed_file.c
- create mode 100644 libsemanage/src/compressed_file.h
-
-diff --git a/libsemanage/src/compressed_file.c b/libsemanage/src/compressed_file.c
-new file mode 100644
-index 000000000000..5546b83074d5
---- /dev/null
-+++ b/libsemanage/src/compressed_file.c
-@@ -0,0 +1,224 @@
-+/* Author: Jason Tang	  <jtang@tresys.com>
-+ *         Christopher Ashworth <cashworth@tresys.com>
-+ *         Ondrej Mosnacek <omosnacek@gmail.com>
-+ *
-+ * Copyright (C) 2004-2006 Tresys Technology, LLC
-+ * Copyright (C) 2005-2021 Red Hat, Inc.
-+ *
-+ *  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
-+ */
-+
-+#include <stdlib.h>
-+#include <string.h>
-+#include <stdint.h>
-+
-+#include <unistd.h>
-+#include <fcntl.h>
-+
-+#include <bzlib.h>
-+
-+#include "compressed_file.h"
-+
-+#include "debug.h"
-+
-+#define BZ2_MAGICSTR "BZh"
-+#define BZ2_MAGICLEN (sizeof(BZ2_MAGICSTR)-1)
-+
-+/* bzip() a data to a file, returning the total number of compressed bytes
-+ * in the file.  Returns -1 if file could not be compressed. */
-+static int bzip(semanage_handle_t *sh, const char *filename, void *data,
-+		size_t num_bytes)
-+{
-+	BZFILE* b;
-+	size_t  size = 1<<16;
-+	int     bzerror;
-+	size_t  total = 0;
-+	size_t len = 0;
-+	FILE *f;
-+
-+	if ((f = fopen(filename, "wb")) == NULL) {
-+		return -1;
-+	}
-+
-+	if (!sh->conf->bzip_blocksize) {
-+		if (fwrite(data, 1, num_bytes, f) < num_bytes) {
-+			fclose(f);
-+			return -1;
-+		}
-+		fclose(f);
-+		return 0;
-+	}
-+
-+	b = BZ2_bzWriteOpen( &bzerror, f, sh->conf->bzip_blocksize, 0, 0);
-+	if (bzerror != BZ_OK) {
-+		BZ2_bzWriteClose ( &bzerror, b, 1, 0, 0 );
-+		fclose(f);
-+		return -1;
-+	}
-+
-+	while ( num_bytes > total ) {
-+		if (num_bytes - total > size) {
-+			len = size;
-+		} else {
-+			len = num_bytes - total;
-+		}
-+		BZ2_bzWrite ( &bzerror, b, (uint8_t *)data + total, len );
-+		if (bzerror == BZ_IO_ERROR) {
-+			BZ2_bzWriteClose ( &bzerror, b, 1, 0, 0 );
-+			fclose(f);
-+			return -1;
-+		}
-+		total += len;
-+	}
-+
-+	BZ2_bzWriteClose ( &bzerror, b, 0, 0, 0 );
-+	fclose(f);
-+	if (bzerror == BZ_IO_ERROR) {
-+		return -1;
-+	}
-+	return 0;
-+}
-+
-+/* bunzip() a file to '*data', returning the total number of uncompressed bytes
-+ * in the file.  Returns -1 if file could not be decompressed. */
-+static ssize_t bunzip(semanage_handle_t *sh, FILE *f, void **data)
-+{
-+	BZFILE*  b = NULL;
-+	size_t   nBuf;
-+	uint8_t* buf = NULL;
-+	size_t   size = 1<<18;
-+	size_t   bufsize = size;
-+	int      bzerror;
-+	size_t   total = 0;
-+	uint8_t* uncompress = NULL;
-+	uint8_t* tmpalloc = NULL;
-+	int      ret = -1;
-+
-+	buf = malloc(bufsize);
-+	if (buf == NULL) {
-+		ERR(sh, "Failure allocating memory.");
-+		goto exit;
-+	}
-+
-+	/* Check if the file is bzipped */
-+	bzerror = fread(buf, 1, BZ2_MAGICLEN, f);
-+	rewind(f);
-+	if ((bzerror != BZ2_MAGICLEN) || memcmp(buf, BZ2_MAGICSTR, BZ2_MAGICLEN)) {
-+		goto exit;
-+	}
-+
-+	b = BZ2_bzReadOpen ( &bzerror, f, 0, sh->conf->bzip_small, NULL, 0 );
-+	if ( bzerror != BZ_OK ) {
-+		ERR(sh, "Failure opening bz2 archive.");
-+		goto exit;
-+	}
-+
-+	uncompress = malloc(size);
-+	if (uncompress == NULL) {
-+		ERR(sh, "Failure allocating memory.");
-+		goto exit;
-+	}
-+
-+	while ( bzerror == BZ_OK) {
-+		nBuf = BZ2_bzRead ( &bzerror, b, buf, bufsize);
-+		if (( bzerror == BZ_OK ) || ( bzerror == BZ_STREAM_END )) {
-+			if (total + nBuf > size) {
-+				size *= 2;
-+				tmpalloc = realloc(uncompress, size);
-+				if (tmpalloc == NULL) {
-+					ERR(sh, "Failure allocating memory.");
-+					goto exit;
-+				}
-+				uncompress = tmpalloc;
-+			}
-+			memcpy(&uncompress[total], buf, nBuf);
-+			total += nBuf;
-+		}
-+	}
-+	if ( bzerror != BZ_STREAM_END ) {
-+		ERR(sh, "Failure reading bz2 archive.");
-+		goto exit;
-+	}
-+
-+	ret = total;
-+	*data = uncompress;
-+
-+exit:
-+	BZ2_bzReadClose ( &bzerror, b );
-+	free(buf);
-+	if ( ret < 0 ) {
-+		free(uncompress);
-+	}
-+	return ret;
-+}
-+
-+int map_compressed_file(semanage_handle_t *sh, const char *path,
-+			struct file_contents *contents)
-+{
-+	ssize_t size = -1;
-+	void *uncompress;
-+	int ret = 0, fd = -1;
-+	FILE *file = NULL;
-+
-+	fd = open(path, O_RDONLY);
-+	if (fd == -1) {
-+		ERR(sh, "Unable to open %s\n", path);
-+		return -1;
-+	}
-+
-+	file = fdopen(fd, "r");
-+	if (file == NULL) {
-+		ERR(sh, "Unable to open %s\n", path);
-+		close(fd);
-+		return -1;
-+	}
-+
-+	if ((size = bunzip(sh, file, &uncompress)) >= 0) {
-+		contents->data = uncompress;
-+		contents->len = size;
-+		contents->compressed = 1;
-+	} else {
-+		struct stat sb;
-+		if (fstat(fd, &sb) == -1 ||
-+		    (uncompress = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0)) ==
-+		    MAP_FAILED) {
-+			ret = -1;
-+		} else {
-+			contents->data = uncompress;
-+			contents->len = sb.st_size;
-+			contents->compressed = 0;
-+		}
-+	}
-+	fclose(file);
-+	return ret;
-+}
-+
-+void unmap_compressed_file(struct file_contents *contents)
-+{
-+	if (!contents->data)
-+		return;
-+
-+	if (contents->compressed) {
-+		free(contents->data);
-+	} else {
-+		munmap(contents->data, contents->len);
-+	}
-+}
-+
-+int write_compressed_file(semanage_handle_t *sh, const char *path,
-+			  void *data, size_t len)
-+{
-+	return bzip(sh, path, data, len);
-+}
-diff --git a/libsemanage/src/compressed_file.h b/libsemanage/src/compressed_file.h
-new file mode 100644
-index 000000000000..96cfb4b6304a
---- /dev/null
-+++ b/libsemanage/src/compressed_file.h
-@@ -0,0 +1,78 @@
-+/* Author: Jason Tang	  <jtang@tresys.com>
-+ *         Christopher Ashworth <cashworth@tresys.com>
-+ *         Ondrej Mosnacek <omosnacek@gmail.com>
-+ *
-+ * Copyright (C) 2004-2006 Tresys Technology, LLC
-+ * Copyright (C) 2005-2021 Red Hat, Inc.
-+ *
-+ *  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_CIL_FILE_H_
-+#define _SEMANAGE_CIL_FILE_H_
-+
-+#include <sys/mman.h>
-+#include <sys/types.h>
-+
-+#include "handle.h"
-+
-+struct file_contents {
-+	void *data; /** file contents (uncompressed) */
-+	size_t len; /** length of contents */
-+	int compressed; /** whether file was compressed */
-+};
-+
-+/**
-+ * Map/read a possibly-compressed file into memory.
-+ *
-+ * If the file is bzip compressed map_file will uncompress the file into
-+ * @p contents. The caller is responsible for calling
-+ * @ref unmap_compressed_file on @p contents on success.
-+ *
-+ * @param sh        semanage handle
-+ * @param path      path to the file
-+ * @param contents  pointer to struct file_contents, which will be
-+ *   populated with data pointer, size, and an indication whether
-+ *   the file was compressed or not
-+ *
-+ * @return 0 on success, -1 otherwise.
-+ */
-+int map_compressed_file(semanage_handle_t *sh, const char *path,
-+			struct file_contents *contents);
-+
-+/**
-+ * Destroy a previously mapped possibly-compressed file.
-+ *
-+ * If all fields of @p contents are zero/NULL, the function is
-+ * guaranteed to do nothing.
-+ *
-+ * @param contents  pointer to struct file_contents to destroy
-+ */
-+void unmap_compressed_file(struct file_contents *contents);
-+
-+/**
-+ * Write bytes into a file, using compression if configured.
-+ *
-+ * @param sh    semanage handle
-+ * @param path  path to the file
-+ * @param data  pointer to the data
-+ * @param len   length of the data
-+ *
-+ * @return 0 on success, -1 otherwise.
-+ */
-+int write_compressed_file(semanage_handle_t *sh, const char *path,
-+			  void *data, size_t len);
-+
-+#endif
-diff --git a/libsemanage/src/direct_api.c b/libsemanage/src/direct_api.c
-index b7a3e0f17cc1..aa2bfcf35016 100644
---- a/libsemanage/src/direct_api.c
-+++ b/libsemanage/src/direct_api.c
-@@ -50,6 +50,7 @@
- 
- #include "debug.h"
- #include "handle.h"
-+#include "compressed_file.h"
- #include "modules.h"
- #include "direct_api.h"
- #include "semanage_store.h"
-@@ -446,194 +447,6 @@ static int parse_module_headers(semanage_handle_t * sh, char *module_data,
-        return 0;
- }
- 
--#include <stdlib.h>
--#include <bzlib.h>
--#include <string.h>
--#include <sys/sendfile.h>
--
--/* bzip() a data to a file, returning the total number of compressed bytes
-- * in the file.  Returns -1 if file could not be compressed. */
--static ssize_t bzip(semanage_handle_t *sh, const char *filename, char *data,
--			size_t num_bytes)
--{
--	BZFILE* b;
--	size_t  size = 1<<16;
--	int     bzerror;
--	size_t  total = 0;
--	size_t len = 0;
--	FILE *f;
--
--	if ((f = fopen(filename, "wb")) == NULL) {
--		return -1;
--	}
--
--	if (!sh->conf->bzip_blocksize) {
--		if (fwrite(data, 1, num_bytes, f) < num_bytes) {
--			fclose(f);
--			return -1;
--		}
--		fclose(f);
--		return num_bytes;
--	}
--
--	b = BZ2_bzWriteOpen( &bzerror, f, sh->conf->bzip_blocksize, 0, 0);
--	if (bzerror != BZ_OK) {
--		BZ2_bzWriteClose ( &bzerror, b, 1, 0, 0 );
--		return -1;
--	}
--	
--	while ( num_bytes > total ) {
--		if (num_bytes - total > size) {
--			len = size;
--		} else {
--			len = num_bytes - total;
--		}
--		BZ2_bzWrite ( &bzerror, b, &data[total], len );
--		if (bzerror == BZ_IO_ERROR) { 
--			BZ2_bzWriteClose ( &bzerror, b, 1, 0, 0 );
--			return -1;
--		}
--		total += len;
--	}
--
--	BZ2_bzWriteClose ( &bzerror, b, 0, 0, 0 );
--	fclose(f);
--	if (bzerror == BZ_IO_ERROR) {
--		return -1;
--	}
--	return total;
--}
--
--#define BZ2_MAGICSTR "BZh"
--#define BZ2_MAGICLEN (sizeof(BZ2_MAGICSTR)-1)
--
--/* bunzip() a file to '*data', returning the total number of uncompressed bytes
-- * in the file.  Returns -1 if file could not be decompressed. */
--ssize_t bunzip(semanage_handle_t *sh, FILE *f, char **data)
--{
--	BZFILE* b = NULL;
--	size_t  nBuf;
--	char*   buf = NULL;
--	size_t  size = 1<<18;
--	size_t  bufsize = size;
--	int     bzerror;
--	size_t  total = 0;
--	char*   uncompress = NULL;
--	char*   tmpalloc = NULL;
--	int     ret = -1;
--
--	buf = malloc(bufsize);
--	if (buf == NULL) {
--		ERR(sh, "Failure allocating memory.");
--		goto exit;
--	}
--
--	/* Check if the file is bzipped */
--	bzerror = fread(buf, 1, BZ2_MAGICLEN, f);
--	rewind(f);
--	if ((bzerror != BZ2_MAGICLEN) || memcmp(buf, BZ2_MAGICSTR, BZ2_MAGICLEN)) {
--		goto exit;
--	}
--
--	b = BZ2_bzReadOpen ( &bzerror, f, 0, sh->conf->bzip_small, NULL, 0 );
--	if ( bzerror != BZ_OK ) {
--		ERR(sh, "Failure opening bz2 archive.");
--		goto exit;
--	}
--
--	uncompress = malloc(size);
--	if (uncompress == NULL) {
--		ERR(sh, "Failure allocating memory.");
--		goto exit;
--	}
--
--	while ( bzerror == BZ_OK) {
--		nBuf = BZ2_bzRead ( &bzerror, b, buf, bufsize);
--		if (( bzerror == BZ_OK ) || ( bzerror == BZ_STREAM_END )) {
--			if (total + nBuf > size) {
--				size *= 2;
--				tmpalloc = realloc(uncompress, size);
--				if (tmpalloc == NULL) {
--					ERR(sh, "Failure allocating memory.");
--					goto exit;
--				}
--				uncompress = tmpalloc;
--			}
--			memcpy(&uncompress[total], buf, nBuf);
--			total += nBuf;
--		}
--	}
--	if ( bzerror != BZ_STREAM_END ) {
--		ERR(sh, "Failure reading bz2 archive.");
--		goto exit;
--	}
--
--	ret = total;
--	*data = uncompress;
--
--exit:
--	BZ2_bzReadClose ( &bzerror, b );
--	free(buf);
--	if ( ret < 0 ) {
--		free(uncompress);
--	}
--	return ret;
--}
--
--/* mmap() a file to '*data',
-- *  If the file is bzip compressed map_file will uncompress 
-- * the file into '*data'.
-- * Returns the total number of bytes in memory .
-- * Returns -1 if file could not be opened or mapped. */
--static ssize_t map_file(semanage_handle_t *sh, const char *path, char **data,
--			int *compressed)
--{
--	ssize_t size = -1;
--	char *uncompress;
--	int fd = -1;
--	FILE *file = NULL;
--
--	fd = open(path, O_RDONLY);
--	if (fd == -1) {
--		ERR(sh, "Unable to open %s\n", path);
--		return -1;
--	}
--
--	file = fdopen(fd, "r");
--	if (file == NULL) {
--		ERR(sh, "Unable to open %s\n", path);
--		close(fd);
--		return -1;
--	}
--
--	if ((size = bunzip(sh, file, &uncompress)) > 0) {
--		*data = mmap(0, size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, 0, 0);
--		if (*data == MAP_FAILED) {
--			free(uncompress);
--			fclose(file);
--			return -1;
--		} else {
--			memcpy(*data, uncompress, size);
--		}
--		free(uncompress);
--		*compressed = 1;
--	} else {
--		struct stat sb;
--		if (fstat(fd, &sb) == -1 ||
--		    (*data = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0)) ==
--		    MAP_FAILED) {
--			size = -1;
--		} else {
--			size = sb.st_size;
--		}
--		*compressed = 0;
--	} 
--
--	fclose(file);
--
--	return size;
--}
--
- /* Writes a block of data to a file.  Returns 0 on success, -1 on
-  * error. */
- static int write_file(semanage_handle_t * sh,
-@@ -1045,15 +858,12 @@ static int semanage_compile_module(semanage_handle_t *sh,
- 	char *compiler_path = NULL;
- 	char *cil_data = NULL;
- 	char *err_data = NULL;
--	char *hll_data = NULL;
- 	char *start = NULL;
- 	char *end = NULL;
--	ssize_t hll_data_len = 0;
--	ssize_t bzip_status;
- 	int status = 0;
--	int compressed;
- 	size_t cil_data_len = 0;
- 	size_t err_data_len = 0;
-+	struct file_contents hll_contents = {};
- 
- 	if (!strcasecmp(modinfo->lang_ext, "cil")) {
- 		goto cleanup;
-@@ -1084,13 +894,15 @@ static int semanage_compile_module(semanage_handle_t *sh,
- 		goto cleanup;
- 	}
- 
--	if ((hll_data_len = map_file(sh, hll_path, &hll_data, &compressed)) <= 0) {
-+	status = map_compressed_file(sh, hll_path, &hll_contents);
-+	if (status < 0) {
- 		ERR(sh, "Unable to read file %s\n", hll_path);
--		status = -1;
- 		goto cleanup;
- 	}
- 
--	status = semanage_pipe_data(sh, compiler_path, hll_data, (size_t)hll_data_len, &cil_data, &cil_data_len, &err_data, &err_data_len);
-+	status = semanage_pipe_data(sh, compiler_path, hll_contents.data,
-+				    hll_contents.len, &cil_data, &cil_data_len,
-+				    &err_data, &err_data_len);
- 	if (err_data_len > 0) {
- 		for (start = end = err_data; end < err_data + err_data_len; end++) {
- 			if (*end == '\n') {
-@@ -1110,10 +922,9 @@ static int semanage_compile_module(semanage_handle_t *sh,
- 		goto cleanup;
- 	}
- 
--	bzip_status = bzip(sh, cil_path, cil_data, cil_data_len);
--	if (bzip_status == -1) {
--		ERR(sh, "Failed to bzip %s\n", cil_path);
--		status = -1;
-+	status = write_compressed_file(sh, cil_path, cil_data, cil_data_len);
-+	if (status == -1) {
-+		ERR(sh, "Failed to write %s\n", cil_path);
- 		goto cleanup;
- 	}
- 
-@@ -1131,9 +942,7 @@ static int semanage_compile_module(semanage_handle_t *sh,
- 	}
- 
- cleanup:
--	if (hll_data_len > 0) {
--		munmap(hll_data, hll_data_len);
--	}
-+	unmap_compressed_file(&hll_contents);
- 	free(cil_data);
- 	free(err_data);
- 	free(compiler_path);
-@@ -1756,19 +1565,17 @@ static int semanage_direct_install_file(semanage_handle_t * sh,
- {
- 
- 	int retval = -1;
--	char *data = NULL;
--	ssize_t data_len = 0;
--	int compressed = 0;
- 	char *path = NULL;
- 	char *filename;
- 	char *lang_ext = NULL;
- 	char *module_name = NULL;
- 	char *separator;
- 	char *version = NULL;
-+	struct file_contents contents = {};
- 
--	if ((data_len = map_file(sh, install_filename, &data, &compressed)) <= 0) {
-+	retval = map_compressed_file(sh, install_filename, &contents);
-+	if (retval < 0) {
- 		ERR(sh, "Unable to read file %s\n", install_filename);
--		retval = -1;
- 		goto cleanup;
- 	}
- 
-@@ -1781,7 +1588,7 @@ static int semanage_direct_install_file(semanage_handle_t * sh,
- 
- 	filename = basename(path);
- 
--	if (compressed) {
-+	if (contents.compressed) {
- 		separator = strrchr(filename, '.');
- 		if (separator == NULL) {
- 			ERR(sh, "Compressed module does not have a valid extension.");
-@@ -1805,7 +1612,8 @@ static int semanage_direct_install_file(semanage_handle_t * sh,
- 	}
- 
- 	if (strcmp(lang_ext, "pp") == 0) {
--		retval = parse_module_headers(sh, data, data_len, &module_name, &version);
-+		retval = parse_module_headers(sh, contents.data, contents.len,
-+					      &module_name, &version);
- 		free(version);
- 		if (retval != 0)
- 			goto cleanup;
-@@ -1822,10 +1630,11 @@ static int semanage_direct_install_file(semanage_handle_t * sh,
- 		fprintf(stderr, "Warning: SELinux userspace will refer to the module from %s as %s rather than %s\n", install_filename, module_name, filename);
- 	}
- 
--	retval = semanage_direct_install(sh, data, data_len, module_name, lang_ext);
-+	retval = semanage_direct_install(sh, contents.data, contents.len,
-+					 module_name, lang_ext);
- 
- cleanup:
--	if (data_len > 0) munmap(data, data_len);
-+	unmap_compressed_file(&contents);
- 	free(module_name);
- 	free(path);
- 
-@@ -1844,10 +1653,8 @@ static int semanage_direct_extract(semanage_handle_t * sh,
- 	enum semanage_module_path_type file_type;
- 	int rc = -1;
- 	semanage_module_info_t *_modinfo = NULL;
--	ssize_t _data_len;
--	char *_data;
--	int compressed;
- 	struct stat sb;
-+	struct file_contents contents = {};
- 
- 	/* get path of module */
- 	rc = semanage_module_get_path(
-@@ -1903,19 +1710,33 @@ static int semanage_direct_extract(semanage_handle_t * sh,
- 		}
- 	}
- 
--	_data_len = map_file(sh, input_file, &_data, &compressed);
--	if (_data_len <= 0) {
-+	rc = map_compressed_file(sh, input_file, &contents);
-+	if (rc < 0) {
- 		ERR(sh, "Error mapping file: %s", input_file);
--		rc = -1;
- 		goto cleanup;
- 	}
- 
-+	/* The API promises an mmap'ed pointer */
-+	if (contents.compressed) {
-+		*mapped_data = mmap(NULL, contents.len, PROT_READ|PROT_WRITE,
-+				    MAP_PRIVATE|MAP_ANONYMOUS, 0, 0);
-+		if (*mapped_data == MAP_FAILED) {
-+			ERR(sh, "Unable to map memory");
-+			rc = -1;
-+			goto cleanup;
-+		}
-+		memcpy(*mapped_data, contents.data, contents.len);
-+		free(contents.data);
-+	} else {
-+		*mapped_data = contents.data;
-+	}
-+
- 	*modinfo = _modinfo;
--	*data_len = (size_t)_data_len;
--	*mapped_data = _data;
-+	*data_len = contents.len;
- 
- cleanup:
- 	if (rc != 0) {
-+		unmap_compressed_file(&contents);
- 		semanage_module_info_destroy(sh, _modinfo);
- 		free(_modinfo);
- 	}
-@@ -2864,8 +2685,8 @@ static int semanage_direct_install_info(semanage_handle_t *sh,
- 		goto cleanup;
- 	}
- 
--	ret = bzip(sh, path, data, data_len);
--	if (ret <= 0) {
-+	ret = write_compressed_file(sh, path, data, data_len);
-+	if (ret < 0) {
- 		ERR(sh, "Error while writing to %s.", path);
- 		status = -3;
- 		goto cleanup;
-diff --git a/libsemanage/src/direct_api.h b/libsemanage/src/direct_api.h
-index e56107b27573..ffd428eb82ba 100644
---- a/libsemanage/src/direct_api.h
-+++ b/libsemanage/src/direct_api.h
-@@ -39,8 +39,4 @@ int semanage_direct_access_check(struct semanage_handle *sh);
- 
- int semanage_direct_mls_enabled(struct semanage_handle *sh);
- 
--#include <stdio.h>
--#include <unistd.h>
--ssize_t bunzip(struct semanage_handle *sh, FILE *f, char **data);
--
- #endif
-diff --git a/libsemanage/src/semanage_store.c b/libsemanage/src/semanage_store.c
-index c6a736fe2d26..633ee73165fb 100644
---- a/libsemanage/src/semanage_store.c
-+++ b/libsemanage/src/semanage_store.c
-@@ -59,6 +59,7 @@ typedef struct dbase_policydb dbase_t;
- 
- #include "debug.h"
- #include "utilities.h"
-+#include "compressed_file.h"
- 
- #define SEMANAGE_CONF_FILE "semanage.conf"
- /* relative path names to enum semanage_paths to special files and
-@@ -2054,60 +2055,27 @@ int semanage_direct_get_serial(semanage_handle_t * sh)
- 
- int semanage_load_files(semanage_handle_t * sh, cil_db_t *cildb, char **filenames, int numfiles)
- {
--	int retval = 0;
--	FILE *fp;
--	ssize_t size;
--	char *data = NULL;
-+	int i, retval = 0;
- 	char *filename;
--	int i;
-+	struct file_contents contents = {};
- 
- 	for (i = 0; i < numfiles; i++) {
- 		filename = filenames[i];
- 
--		if ((fp = fopen(filename, "rb")) == NULL) {
--			ERR(sh, "Could not open module file %s for reading.", filename);
--			goto cleanup;
--		}
--
--		if ((size = bunzip(sh, fp, &data)) <= 0) {
--			rewind(fp);
--			__fsetlocking(fp, FSETLOCKING_BYCALLER);
--
--			if (fseek(fp, 0, SEEK_END) != 0) {
--				ERR(sh, "Failed to determine size of file %s.", filename);
--				goto cleanup;
--			}
--			size = ftell(fp);
--			rewind(fp);
--
--			data = malloc(size);
--			if (fread(data, size, 1, fp) != 1) {
--				ERR(sh, "Failed to read file %s.", filename);
--				goto cleanup;
--			}
--		}
-+		retval = map_compressed_file(sh, filename, &contents);
-+		if (retval < 0)
-+			return -1;
- 
--		fclose(fp);
--		fp = NULL;
-+		retval = cil_add_file(cildb, filename, contents.data, contents.len);
-+		unmap_compressed_file(&contents);
- 
--		retval = cil_add_file(cildb, filename, data, size);
- 		if (retval != SEPOL_OK) {
- 			ERR(sh, "Error while reading from file %s.", filename);
--			goto cleanup;
-+			return -1;
- 		}
--	
--		free(data);
--		data = NULL;
- 	}
- 
--	return retval;
--
--      cleanup:
--	if (fp != NULL) {
--		fclose(fp);
--	}
--	free(data);
--	return -1;
-+	return 0;
- }
- 
- /* 
--- 
-2.34.1
-
diff --git a/0005-libsemanage-clean-up-semanage_direct_commit-a-bit.patch b/0005-libsemanage-clean-up-semanage_direct_commit-a-bit.patch
deleted file mode 100644
index 8a05532..0000000
--- a/0005-libsemanage-clean-up-semanage_direct_commit-a-bit.patch
+++ /dev/null
@@ -1,150 +0,0 @@
-From b3c63ad0f9c5c35d80fabeb0ca7abd86f34aad0e Mon Sep 17 00:00:00 2001
-From: Ondrej Mosnacek <omosnace@redhat.com>
-Date: Thu, 3 Feb 2022 17:53:25 +0100
-Subject: [PATCH] libsemanage: clean up semanage_direct_commit() a bit
-
-Do some minor cosmetic cleanup, mainly to eliminate the 'rebuilt' goto
-label.
-
-Signed-off-by: Ondrej Mosnacek <omosnace@redhat.com>
----
- libsemanage/src/direct_api.c | 91 ++++++++++++++++++------------------
- 1 file changed, 45 insertions(+), 46 deletions(-)
-
-diff --git a/libsemanage/src/direct_api.c b/libsemanage/src/direct_api.c
-index aa2bfcf35016..bed1e1eda78f 100644
---- a/libsemanage/src/direct_api.c
-+++ b/libsemanage/src/direct_api.c
-@@ -994,6 +994,16 @@ cleanup:
- 	return status;
- }
- 
-+/* Files that must exist in order to skip policy rebuild. */
-+static const int semanage_computed_files[] = {
-+	SEMANAGE_STORE_KERNEL,
-+	SEMANAGE_STORE_FC,
-+	SEMANAGE_STORE_SEUSERS,
-+	SEMANAGE_LINKED,
-+	SEMANAGE_SEUSERS_LINKED,
-+	SEMANAGE_USERS_EXTRA_LINKED
-+};
-+
- /* Copies a file from src to dst. If dst already exists then
-  * overwrite it. If source doesn't exist then return success.
-  * Returns 0 on success, -1 on error. */
-@@ -1053,6 +1063,14 @@ static int semanage_direct_commit(semanage_handle_t * sh)
- 	seusers_modified = seusers->dtable->is_modified(seusers->dbase);
- 	fcontexts_modified = fcontexts->dtable->is_modified(fcontexts->dbase);
- 
-+	/* Before we do anything else, flush the join to its component parts.
-+	 * This *does not* flush to disk automatically */
-+	if (users->dtable->is_modified(users->dbase)) {
-+		retval = users->dtable->flush(sh, users->dbase);
-+		if (retval < 0)
-+			goto cleanup;
-+	}
-+
- 	/* Rebuild if explicitly requested or any module changes occurred. */
- 	do_rebuild = sh->do_rebuild | sh->modules_modified;
- 
-@@ -1119,14 +1137,6 @@ static int semanage_direct_commit(semanage_handle_t * sh)
- 		}
- 	}
- 
--	/* Before we do anything else, flush the join to its component parts.
--	 * This *does not* flush to disk automatically */
--	if (users->dtable->is_modified(users->dbase)) {
--		retval = users->dtable->flush(sh, users->dbase);
--		if (retval < 0)
--			goto cleanup;
--	}
--
- 	/*
- 	 * This is for systems that have already migrated with an older version
- 	 * of semanage_migrate_store. The older version did not copy
-@@ -1135,48 +1145,20 @@ static int semanage_direct_commit(semanage_handle_t * sh)
- 	 * in order to skip re-linking are present; otherwise, we force
- 	 * a rebuild.
- 	 */
--	if (!do_rebuild) {
--		int files[] = {SEMANAGE_STORE_KERNEL,
--					   SEMANAGE_STORE_FC,
--					   SEMANAGE_STORE_SEUSERS,
--					   SEMANAGE_LINKED,
--					   SEMANAGE_SEUSERS_LINKED,
--					   SEMANAGE_USERS_EXTRA_LINKED};
--
--		for (i = 0; i < (int) ARRAY_SIZE(files); i++) {
--			path = semanage_path(SEMANAGE_TMP, files[i]);
--			if (stat(path, &sb) != 0) {
--				if (errno != ENOENT) {
--					ERR(sh, "Unable to access %s: %s\n", path, strerror(errno));
--					retval = -1;
--					goto cleanup;
--				}
--
--				do_rebuild = 1;
--				goto rebuild;
-+	for (i = 0; !do_rebuild && i < (int)ARRAY_SIZE(semanage_computed_files); i++) {
-+		path = semanage_path(SEMANAGE_TMP, semanage_computed_files[i]);
-+		if (stat(path, &sb) != 0) {
-+			if (errno != ENOENT) {
-+				ERR(sh, "Unable to access %s: %s\n", path, strerror(errno));
-+				retval = -1;
-+				goto cleanup;
- 			}
-+
-+			do_rebuild = 1;
-+			break;
- 		}
- 	}
- 
--rebuild:
--	/*
--	 * Now that we know whether or not a rebuild is required,
--	 * we can determine what else needs to be done.
--	 * We need to write the kernel policy if we are rebuilding
--	 * or if any other policy component that lives in the kernel
--	 * policy has been modified.
--	 * We need to install the policy files if any of the managed files
--	 * that live under /etc/selinux (kernel policy, seusers, file contexts)
--	 * will be modified.
--	 */
--	do_write_kernel = do_rebuild | ports_modified | ibpkeys_modified |
--		ibendports_modified |
--		bools->dtable->is_modified(bools->dbase) |
--		ifaces->dtable->is_modified(ifaces->dbase) |
--		nodes->dtable->is_modified(nodes->dbase) |
--		users->dtable->is_modified(users_base->dbase);
--	do_install = do_write_kernel | seusers_modified | fcontexts_modified;
--
- 	/*
- 	 * If there were policy changes, or explicitly requested, or
- 	 * any required files are missing, rebuild the policy.
-@@ -1330,6 +1312,23 @@ rebuild:
- 		}
- 	}
- 
-+	/*
-+	 * Determine what else needs to be done.
-+	 * We need to write the kernel policy if we are rebuilding
-+	 * or if any other policy component that lives in the kernel
-+	 * policy has been modified.
-+	 * We need to install the policy files if any of the managed files
-+	 * that live under /etc/selinux (kernel policy, seusers, file contexts)
-+	 * will be modified.
-+	 */
-+	do_write_kernel = do_rebuild | ports_modified | ibpkeys_modified |
-+		ibendports_modified |
-+		bools->dtable->is_modified(bools->dbase) |
-+		ifaces->dtable->is_modified(ifaces->dbase) |
-+		nodes->dtable->is_modified(nodes->dbase) |
-+		users->dtable->is_modified(users_base->dbase);
-+	do_install = do_write_kernel | seusers_modified | fcontexts_modified;
-+
- 	/* Attach our databases to the policydb we just created or loaded. */
- 	dbase_policydb_attach((dbase_policydb_t *) pusers_base->dbase, out);
- 	dbase_policydb_attach((dbase_policydb_t *) pports->dbase, out);
--- 
-2.34.1
-
diff --git a/0006-libsemanage-optionally-rebuild-policy-when-modules-a.patch b/0006-libsemanage-optionally-rebuild-policy-when-modules-a.patch
deleted file mode 100644
index 6cada7b..0000000
--- a/0006-libsemanage-optionally-rebuild-policy-when-modules-a.patch
+++ /dev/null
@@ -1,492 +0,0 @@
-From e8251a69e9f8386a232c999c068ed2daf02a8370 Mon Sep 17 00:00:00 2001
-From: Ondrej Mosnacek <omosnace@redhat.com>
-Date: Thu, 3 Feb 2022 17:53:26 +0100
-Subject: [PATCH] libsemanage: optionally rebuild policy when modules are
- changed externally
-
-In Fedora/RHEL's selinux-policy package we ship a pre-built SELinux
-policy store in the RPMs. When updating the main policy RPM, care must
-be taken to rebuild the policy using `semodule -B` if there are any
-other SELinux modules installed (whether shipped via another RPM or
-manually installed locally).
-
-However, this way of shipping/managing the policy creates complications
-on systems, where system files are managed by rpm-ostree (such as Fedora
-CoreOS or Red Hat CoreOS), where the "package update" process is more
-sophisticated.
-
-(Disclaimer: The following is written according to my current limited
-understanding of rpm-ostree and may not be entirely accurate, but the
-gist of it should match the reality.)
-
-Basically, one can think of rpm-ostree as a kind of Git for system
-files. The package content is provided on a "branch", where each
-"commit" represents a set of package updates layered on top of the
-previous commit (i.e. it is a rolling release with some defined
-package content snapshots). The user can then maintain their own branch
-with additional package updates/installations/... and "rebase" it on top
-of the main branch as needed. On top of that, the user can also have
-additional configuration files (or modifications to existing files) in
-/etc, which represent an additional layer on top of the package content.
-
-When updating the system (i.e. rebasing on a new "commit" of the "main
-branch"), the files on the running system are not touched and the new
-system state is prepared under a new root directory, which is chrooted
-into on the next reboot.
-
-When an rpm-ostree system is updated, there are three moments when the
-SELinux module store needs to be rebuilt to ensure that all modules are
-included in the binary policy:
-1. When the local RPM installations are applied on top of the base
-   system snapshot.
-2. When local user configuartion is applied on top of that.
-3. On system shutdown, to ensure that any changes in local configuration
-   performed since (2.) are reflected in the final new system image.
-
-Forcing a full rebuild at each step is not optimal and in many cases is
-not necessary, as the user may not have any custom modules installed.
-
-Thus, this patch extends libsemanage to compute a checksum of the
-content of all enabled modules, which is stored in the store, and adds a
-flag to the libsemanage handle that instructs it to check the module
-content checksum against the one from the last successful transaction
-and force a full policy rebuild if they don't match.
-
-This will allow rpm-ostree systems to potentially reduce delays when
-reconciling the module store when applying updates.
-
-I wasn't able to measure any noticeable overhead of the hash
-computation, which is now added for every transaction (both before and
-after this change a full policy rebuild took about 7 seconds on my test
-x86 VM). With the new option check_ext_changes enabled, rebuilding a
-policy store with unchanged modules took only about 0.96 seconds.
-
-Signed-off-by: Ondrej Mosnacek <omosnace@redhat.com>
----
- libsemanage/include/semanage/handle.h |   5 +
- libsemanage/src/direct_api.c          | 187 +++++++++++++++++++++-----
- libsemanage/src/handle.c              |  11 +-
- libsemanage/src/handle.h              |   1 +
- libsemanage/src/libsemanage.map       |   1 +
- libsemanage/src/modules.c             |   4 +-
- libsemanage/src/modules.h             |   3 +
- libsemanage/src/semanage_store.c      |   1 +
- libsemanage/src/semanage_store.h      |   1 +
- 9 files changed, 175 insertions(+), 39 deletions(-)
-
-diff --git a/libsemanage/include/semanage/handle.h b/libsemanage/include/semanage/handle.h
-index 946d69bc91fe..0157be4fbc46 100644
---- a/libsemanage/include/semanage/handle.h
-+++ b/libsemanage/include/semanage/handle.h
-@@ -66,6 +66,11 @@ extern void semanage_set_reload(semanage_handle_t * handle, int do_reload);
-  * 1 for yes, 0 for no (default) */
- extern void semanage_set_rebuild(semanage_handle_t * handle, int do_rebuild);
- 
-+/* set whether to rebuild the policy on commit when potential changes
-+ * to module files since last rebuild are detected,
-+ * 1 for yes (default), 0 for no */
-+extern void semanage_set_check_ext_changes(semanage_handle_t * handle, int do_check);
-+
- /* Fills *compiler_path with the location of the hll compiler sh->conf->compiler_directory_path
-  * corresponding to lang_ext.
-  * Upon success returns 0, -1 on error. */
-diff --git a/libsemanage/src/direct_api.c b/libsemanage/src/direct_api.c
-index bed1e1eda78f..e0255310395b 100644
---- a/libsemanage/src/direct_api.c
-+++ b/libsemanage/src/direct_api.c
-@@ -33,6 +33,8 @@
- #include <unistd.h>
- #include <sys/stat.h>
- #include <sys/types.h>
-+#include <sys/mman.h>
-+#include <sys/wait.h>
- #include <limits.h>
- #include <errno.h>
- #include <dirent.h>
-@@ -56,8 +58,7 @@
- #include "semanage_store.h"
- #include "database_policydb.h"
- #include "policy.h"
--#include <sys/mman.h>
--#include <sys/wait.h>
-+#include "sha256.h"
- 
- #define PIPE_READ 0
- #define PIPE_WRITE 1
-@@ -450,7 +451,7 @@ static int parse_module_headers(semanage_handle_t * sh, char *module_data,
- /* Writes a block of data to a file.  Returns 0 on success, -1 on
-  * error. */
- static int write_file(semanage_handle_t * sh,
--		      const char *filename, char *data, size_t num_bytes)
-+		      const char *filename, const char *data, size_t num_bytes)
- {
- 	int out;
- 
-@@ -850,8 +851,21 @@ cleanup:
- 	return ret;
- }
- 
-+static void update_checksum_with_len(Sha256Context *context, size_t s)
-+{
-+	int i;
-+	uint8_t buffer[8];
-+
-+	for (i = 0; i < 8; i++) {
-+		buffer[i] = s & 0xff;
-+		s >>= 8;
-+	}
-+	Sha256Update(context, buffer, 8);
-+}
-+
- static int semanage_compile_module(semanage_handle_t *sh,
--				semanage_module_info_t *modinfo)
-+				   semanage_module_info_t *modinfo,
-+				   Sha256Context *context)
- {
- 	char cil_path[PATH_MAX];
- 	char hll_path[PATH_MAX];
-@@ -922,6 +936,11 @@ static int semanage_compile_module(semanage_handle_t *sh,
- 		goto cleanup;
- 	}
- 
-+	if (context) {
-+		update_checksum_with_len(context, cil_data_len);
-+		Sha256Update(context, cil_data, cil_data_len);
-+	}
-+
- 	status = write_compressed_file(sh, cil_path, cil_data, cil_data_len);
- 	if (status == -1) {
- 		ERR(sh, "Failed to write %s\n", cil_path);
-@@ -950,18 +969,40 @@ cleanup:
- 	return status;
- }
- 
-+static int modinfo_cmp(const void *a, const void *b)
-+{
-+	const semanage_module_info_t *ma = a;
-+	const semanage_module_info_t *mb = b;
-+
-+	return strcmp(ma->name, mb->name);
-+}
-+
- static int semanage_compile_hll_modules(semanage_handle_t *sh,
--				semanage_module_info_t *modinfos,
--				int num_modinfos)
-+					semanage_module_info_t *modinfos,
-+					int num_modinfos,
-+					char *cil_checksum)
- {
--	int status = 0;
--	int i;
-+	/* to be incremented when checksum input data format changes */
-+	static const size_t CHECKSUM_EPOCH = 1;
-+
-+	int i, status = 0;
- 	char cil_path[PATH_MAX];
- 	struct stat sb;
-+	Sha256Context context;
-+	SHA256_HASH hash;
-+	struct file_contents contents = {};
- 
- 	assert(sh);
- 	assert(modinfos);
- 
-+	/* Sort modules by name to get consistent ordering. */
-+	qsort(modinfos, num_modinfos, sizeof(*modinfos), &modinfo_cmp);
-+
-+	Sha256Initialise(&context);
-+	update_checksum_with_len(&context, CHECKSUM_EPOCH);
-+
-+	/* prefix with module count to avoid collisions */
-+	update_checksum_with_len(&context, num_modinfos);
- 	for (i = 0; i < num_modinfos; i++) {
- 		status = semanage_module_get_path(
- 				sh,
-@@ -969,29 +1010,91 @@ static int semanage_compile_hll_modules(semanage_handle_t *sh,
- 				SEMANAGE_MODULE_PATH_CIL,
- 				cil_path,
- 				sizeof(cil_path));
--		if (status != 0) {
--			goto cleanup;
--		}
-+		if (status != 0)
-+			return -1;
- 
--		if (semanage_get_ignore_module_cache(sh) == 0 &&
--				(status = stat(cil_path, &sb)) == 0) {
--			continue;
--		}
--		if (status != 0 && errno != ENOENT) {
--			ERR(sh, "Unable to access %s: %s\n", cil_path, strerror(errno));
--			goto cleanup; //an error in the "stat" call
-+		if (!semanage_get_ignore_module_cache(sh)) {
-+			status = stat(cil_path, &sb);
-+			if (status == 0) {
-+				status = map_compressed_file(sh, cil_path, &contents);
-+				if (status < 0) {
-+					ERR(sh, "Error mapping file: %s", cil_path);
-+					return -1;
-+				}
-+
-+				/* prefix with length to avoid collisions */
-+				update_checksum_with_len(&context, contents.len);
-+				Sha256Update(&context, contents.data, contents.len);
-+
-+				unmap_compressed_file(&contents);
-+				continue;
-+			} else if (errno != ENOENT) {
-+				ERR(sh, "Unable to access %s: %s\n", cil_path,
-+				    strerror(errno));
-+				return -1; //an error in the "stat" call
-+			}
- 		}
- 
--		status = semanage_compile_module(sh, &modinfos[i]);
--		if (status < 0) {
--			goto cleanup;
-+		status = semanage_compile_module(sh, &modinfos[i], &context);
-+		if (status < 0)
-+			return -1;
-+	}
-+	Sha256Finalise(&context, &hash);
-+
-+	semanage_hash_to_checksum_string(hash.bytes, cil_checksum);
-+	return 0;
-+}
-+
-+static int semanage_compare_checksum(semanage_handle_t *sh, const char *reference)
-+{
-+	const char *path = semanage_path(SEMANAGE_TMP, SEMANAGE_MODULES_CHECKSUM);
-+	struct stat sb;
-+	int fd, retval;
-+	char *data;
-+
-+	fd = open(path, O_RDONLY);
-+	if (fd == -1) {
-+		if (errno != ENOENT) {
-+			ERR(sh, "Unable to open %s: %s\n", path, strerror(errno));
-+			return -1;
- 		}
-+		/* Checksum file not present - force a rebuild. */
-+		return 1;
-+	}
-+
-+	if (fstat(fd, &sb) == -1) {
-+		ERR(sh, "Unable to stat %s\n", path);
-+		retval = -1;
-+		goto out_close;
- 	}
- 
--	status = 0;
-+	if (sb.st_size != (off_t)CHECKSUM_CONTENT_SIZE) {
-+		/* Incompatible/invalid hash type - just force a rebuild. */
-+		WARN(sh, "Module checksum invalid - forcing a rebuild\n");
-+		retval = 1;
-+		goto out_close;
-+	}
- 
--cleanup:
--	return status;
-+	data = mmap(NULL, CHECKSUM_CONTENT_SIZE, PROT_READ, MAP_PRIVATE, fd, 0);
-+	if (data == MAP_FAILED) {
-+		ERR(sh, "Unable to mmap %s\n", path);
-+		retval = -1;
-+		goto out_close;
-+	}
-+
-+	retval = memcmp(data, reference, CHECKSUM_CONTENT_SIZE) != 0;
-+	munmap(data, sb.st_size);
-+out_close:
-+	close(fd);
-+	return retval;
-+}
-+
-+static int semanage_write_modules_checksum(semanage_handle_t *sh,
-+					   const char *checksum)
-+{
-+	const char *path = semanage_path(SEMANAGE_TMP, SEMANAGE_MODULES_CHECKSUM);
-+
-+	return write_file(sh, path, checksum, CHECKSUM_CONTENT_SIZE);
- }
- 
- /* Files that must exist in order to skip policy rebuild. */
-@@ -1030,6 +1133,7 @@ static int semanage_direct_commit(semanage_handle_t * sh)
- 	semanage_module_info_t *modinfos = NULL;
- 	mode_t mask = umask(0077);
- 	struct stat sb;
-+	char modules_checksum[CHECKSUM_CONTENT_SIZE + 1 /* '\0' */];
- 
- 	int do_rebuild, do_write_kernel, do_install;
- 	int fcontexts_modified, ports_modified, seusers_modified,
-@@ -1159,28 +1263,45 @@ static int semanage_direct_commit(semanage_handle_t * sh)
- 		}
- 	}
- 
--	/*
--	 * If there were policy changes, or explicitly requested, or
--	 * any required files are missing, rebuild the policy.
--	 */
--	if (do_rebuild) {
--		/* =================== Module expansion =============== */
--
-+	if (do_rebuild || sh->check_ext_changes) {
- 		retval = semanage_get_active_modules(sh, &modinfos, &num_modinfos);
- 		if (retval < 0) {
- 			goto cleanup;
- 		}
- 
-+		/* No modules - nothing to rebuild. */
- 		if (num_modinfos == 0) {
- 			goto cleanup;
- 		}
- 
--		retval = semanage_compile_hll_modules(sh, modinfos, num_modinfos);
-+		retval = semanage_compile_hll_modules(sh, modinfos, num_modinfos,
-+						      modules_checksum);
- 		if (retval < 0) {
- 			ERR(sh, "Failed to compile hll files into cil files.\n");
- 			goto cleanup;
- 		}
- 
-+		if (!do_rebuild && sh->check_ext_changes) {
-+			retval = semanage_compare_checksum(sh, modules_checksum);
-+			if (retval < 0)
-+				goto cleanup;
-+			do_rebuild = retval;
-+		}
-+
-+		retval = semanage_write_modules_checksum(sh, modules_checksum);
-+		if (retval < 0) {
-+			ERR(sh, "Failed to write module checksum file.\n");
-+			goto cleanup;
-+		}
-+	}
-+
-+	/*
-+	 * If there were policy changes, or explicitly requested, or
-+	 * any required files are missing, rebuild the policy.
-+	 */
-+	if (do_rebuild) {
-+		/* =================== Module expansion =============== */
-+
- 		retval = semanage_get_cil_paths(sh, modinfos, num_modinfos, &mod_filenames);
- 		if (retval < 0)
- 			goto cleanup;
-@@ -1703,7 +1824,7 @@ static int semanage_direct_extract(semanage_handle_t * sh,
- 			goto cleanup;
- 		}
- 
--		rc = semanage_compile_module(sh, _modinfo);
-+		rc = semanage_compile_module(sh, _modinfo, NULL);
- 		if (rc < 0) {
- 			goto cleanup;
- 		}
-diff --git a/libsemanage/src/handle.c b/libsemanage/src/handle.c
-index bb1e61400760..b2201ee346dc 100644
---- a/libsemanage/src/handle.c
-+++ b/libsemanage/src/handle.c
-@@ -116,20 +116,23 @@ semanage_handle_t *semanage_handle_create(void)
- 
- void semanage_set_rebuild(semanage_handle_t * sh, int do_rebuild)
- {
--
- 	assert(sh != NULL);
- 
- 	sh->do_rebuild = do_rebuild;
--	return;
- }
- 
- void semanage_set_reload(semanage_handle_t * sh, int do_reload)
- {
--
- 	assert(sh != NULL);
- 
- 	sh->do_reload = do_reload;
--	return;
-+}
-+
-+void semanage_set_check_ext_changes(semanage_handle_t * sh, int do_check)
-+{
-+	assert(sh != NULL);
-+
-+	sh->check_ext_changes = do_check;
- }
- 
- int semanage_get_hll_compiler_path(semanage_handle_t *sh,
-diff --git a/libsemanage/src/handle.h b/libsemanage/src/handle.h
-index e1ce83ba2d08..4d2aae8f69cc 100644
---- a/libsemanage/src/handle.h
-+++ b/libsemanage/src/handle.h
-@@ -61,6 +61,7 @@ struct semanage_handle {
- 	int is_in_transaction;
- 	int do_reload;		/* whether to reload policy after commit */
- 	int do_rebuild;		/* whether to rebuild policy if there were no changes */
-+	int check_ext_changes;	/* whether to rebuild if external changes are detected via checksum */
- 	int commit_err;		/* set by semanage_direct_commit() if there are
- 				 * any errors when building or committing the
- 				 * sandbox to kernel policy at /etc/selinux
-diff --git a/libsemanage/src/libsemanage.map b/libsemanage/src/libsemanage.map
-index 00259fc817f5..c8214b26fc03 100644
---- a/libsemanage/src/libsemanage.map
-+++ b/libsemanage/src/libsemanage.map
-@@ -348,4 +348,5 @@ LIBSEMANAGE_1.1 {
- 
- LIBSEMANAGE_3.4 {
-     semanage_module_compute_checksum;
-+    semanage_set_check_ext_changes;
- } LIBSEMANAGE_1.1;
-diff --git a/libsemanage/src/modules.c b/libsemanage/src/modules.c
-index 5dbb28fdbaa5..94bf884bf45d 100644
---- a/libsemanage/src/modules.c
-+++ b/libsemanage/src/modules.c
-@@ -978,9 +978,9 @@ int semanage_module_remove_key(semanage_handle_t *sh,
- }
- 
- static const char CHECKSUM_TYPE[] = "sha256";
--static const size_t CHECKSUM_CONTENT_SIZE = sizeof(CHECKSUM_TYPE) + 1 + 2 * SHA256_HASH_SIZE;
-+const size_t CHECKSUM_CONTENT_SIZE = sizeof(CHECKSUM_TYPE) + 1 + 2 * SHA256_HASH_SIZE;
- 
--static void semanage_hash_to_checksum_string(const uint8_t *hash, char *checksum)
-+void semanage_hash_to_checksum_string(const uint8_t *hash, char *checksum)
- {
- 	size_t i;
- 
-diff --git a/libsemanage/src/modules.h b/libsemanage/src/modules.h
-index 64d4a157f5ca..cf2432c5b64d 100644
---- a/libsemanage/src/modules.h
-+++ b/libsemanage/src/modules.h
-@@ -102,4 +102,7 @@ int semanage_module_get_path(semanage_handle_t *sh,
- 			     char *path,
- 			     size_t len);
- 
-+extern const size_t CHECKSUM_CONTENT_SIZE;
-+void semanage_hash_to_checksum_string(const uint8_t *hash, char *checksum);
-+
- #endif
-diff --git a/libsemanage/src/semanage_store.c b/libsemanage/src/semanage_store.c
-index 633ee73165fb..767f05cb2853 100644
---- a/libsemanage/src/semanage_store.c
-+++ b/libsemanage/src/semanage_store.c
-@@ -115,6 +115,7 @@ static const char *semanage_sandbox_paths[SEMANAGE_STORE_NUM_PATHS] = {
- 	"/disable_dontaudit",
- 	"/preserve_tunables",
- 	"/modules/disabled",
-+	"/modules_checksum",
- 	"/policy.kern",
- 	"/file_contexts.local",
- 	"/file_contexts.homedirs",
-diff --git a/libsemanage/src/semanage_store.h b/libsemanage/src/semanage_store.h
-index b9ec566427a4..1fc77da83df0 100644
---- a/libsemanage/src/semanage_store.h
-+++ b/libsemanage/src/semanage_store.h
-@@ -60,6 +60,7 @@ enum semanage_sandbox_defs {
- 	SEMANAGE_DISABLE_DONTAUDIT,
- 	SEMANAGE_PRESERVE_TUNABLES,
- 	SEMANAGE_MODULES_DISABLED,
-+	SEMANAGE_MODULES_CHECKSUM,
- 	SEMANAGE_STORE_KERNEL,
- 	SEMANAGE_STORE_FC_LOCAL,
- 	SEMANAGE_STORE_FC_HOMEDIRS,
--- 
-2.34.1
-
diff --git a/libsemanage.spec b/libsemanage.spec
index 466423c..0ad7acf 100644
--- a/libsemanage.spec
+++ b/libsemanage.spec
@@ -1,21 +1,16 @@
-%define libsepolver 3.3-1
-%define libselinuxver 3.3-1
+%define libsepolver 3.4-0
+%define libselinuxver 3.4-0
 
 Summary: SELinux binary policy manipulation library
 Name: libsemanage
-Version: 3.3
-Release: 3%{?dist}
+Version: 3.4
+Release: 0.rc1.1%{?dist}
 License: LGPLv2+
-Source0: https://github.com/SELinuxProject/selinux/releases/download/3.3/libsemanage-3.3.tar.gz
-# fedora-selinux/selinux: git format-patch -N 3.3 -- libsemanage
+Source0: https://github.com/SELinuxProject/selinux/releases/download/3.4-rc1/libsemanage-3.4-rc1.tar.gz
+# fedora-selinux/selinux: git format-patch -N 3.4-rc1 -- libsemanage
 # i=1; for j in 00*patch; do printf "Patch%04d: %s\n" $i $j; i=$((i+1));done
 # Patch list start
-Patch0001: 0001-libsemanage-Fix-RESOURCE_LEAK-and-USE_AFTER_FREE-cov.patch
-Patch0002: 0002-libsemanage-add-missing-include-to-boolean_record.c.patch
-Patch0003: 0003-semodule-libsemanage-move-module-hashing-into-libsem.patch
-Patch0004: 0004-libsemanage-move-compressed-file-handling-into-a-sep.patch
-Patch0005: 0005-libsemanage-clean-up-semanage_direct_commit-a-bit.patch
-Patch0006: 0006-libsemanage-optionally-rebuild-policy-when-modules-a.patch
+Patch0001: 0001-libsemanage-avoid-double-fclose.patch
 # Patch list end
 URL: https://github.com/SELinuxProject/selinux/wiki
 Source1: semanage.conf
@@ -80,7 +75,7 @@ The libsemanage-python3 package contains the python 3 bindings for developing
 SELinux management applications.
 
 %prep
-%autosetup -n libsemanage-%{version} -p 2
+%autosetup -n libsemanage-%{version}-rc1 -p 2
 
 
 %build
@@ -159,6 +154,9 @@ cp %{SOURCE1} ${RPM_BUILD_ROOT}%{_sysconfdir}/selinux/semanage.conf
 %{_libexecdir}/selinux/semanage_migrate_store
 
 %changelog
+* Wed Apr 13 2022 Petr Lautrbach <plautrba@redhat.com> - 3.4-0.rc1.1
+- SELinux userspace 3.4-rc1 release
+
 * Tue Feb 15 2022 Petr Lautrbach <plautrba@redhat.com> - 3.3-3
 - optionally rebuild policy when modules are changed externally
 
diff --git a/sources b/sources
index e3232de..60c09b6 100644
--- a/sources
+++ b/sources
@@ -1 +1 @@
-SHA512 (libsemanage-3.3.tar.gz) = 6026d9773c0886436ad801bc0c8beac888b6fb62034edeb863192dea4b6ef34a88e080758820fe635a20e048ac666beee505a0f946258f18571709cca5228aad
+SHA512 (libsemanage-3.4-rc1.tar.gz) = 65bcb569981bc45b5520829e7df79bd6de75cd1877b75233727aa89484b123c730fd4dca4f297cf85616597632ec3c4be36b6cca1178811ac8cc0d45465954ca