diff --git a/.gitignore b/.gitignore index db91e67..9ce7e1d 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.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 -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/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 -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 - fix it. - -Signed-off-by: Ondrej Mosnacek -Acked-by: James Carter ---- - 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 -+#include -+#include -+ - #include - - 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 - #include - - /* 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 -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 ---- - 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 - #include - #include -+#include - #include - #include - - #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 -+ -+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -+// 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 -+#include -+ -+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 -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 ---- - 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 -+ * Christopher Ashworth -+ * Ondrej Mosnacek -+ * -+ * 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 -+#include -+#include -+ -+#include -+#include -+ -+#include -+ -+#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 -+ * Christopher Ashworth -+ * Ondrej Mosnacek -+ * -+ * 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 -+#include -+ -+#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 --#include --#include --#include -- --/* 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 --#include --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 -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 ---- - 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 -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 ---- - 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 - #include - #include -+#include -+#include - #include - #include - #include -@@ -56,8 +58,7 @@ - #include "semanage_store.h" - #include "database_policydb.h" - #include "policy.h" --#include --#include -+#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/0007-libsemanage-allow-spaces-in-user-group-names.patch b/0007-libsemanage-allow-spaces-in-user-group-names.patch deleted file mode 100644 index 856f015..0000000 --- a/0007-libsemanage-allow-spaces-in-user-group-names.patch +++ /dev/null @@ -1,362 +0,0 @@ -From 898d1e720a4cf1e0dfdb76e0c4b11d92031a8e1a Mon Sep 17 00:00:00 2001 -From: Vit Mojzis -Date: Thu, 17 Feb 2022 13:49:23 +0100 -Subject: [PATCH] libsemanage: allow spaces in user/group names -Content-type: text/plain - -"semanage login -a" accepts whitespaces in user/group name -(e.g. users/groups from Active Directory), which may lead to issues down -the line since libsemanage doesn't expect whitespaces in -/var/lib/selinux/targeted/active/seusers and other config files. - -Fixes: - Artificial but simple reproducer - # groupadd server_admins - # sed -i "s/^server_admins/server admins/" /etc/group - # semanage login -a -s staff_u %server\ admins - # semanage login -l (or "semodule -B") - libsemanage.parse_assert_ch: expected character ':', but found 'a' (/var/lib/selinux/targeted/active/seusers: 6): - %server admins:staff_u:s0-s0:c0.c1023 (No such file or directory). - libsemanage.seuser_parse: could not parse seuser record (No such file or directory). - libsemanage.dbase_file_cache: could not cache file database (No such file or directory). - libsemanage.enter_ro: could not enter read-only section (No such file or directory). - FileNotFoundError: [Errno 2] No such file or directory - -Signed-off-by: Vit Mojzis ---- - libsemanage/src/booleans_file.c | 2 +- - libsemanage/src/fcontexts_file.c | 6 +++--- - libsemanage/src/ibendports_file.c | 4 ++-- - libsemanage/src/ibpkeys_file.c | 4 ++-- - libsemanage/src/interfaces_file.c | 6 +++--- - libsemanage/src/nodes_file.c | 8 ++++---- - libsemanage/src/parse_utils.c | 6 +++--- - libsemanage/src/parse_utils.h | 11 +++++------ - libsemanage/src/ports_file.c | 4 ++-- - libsemanage/src/seusers_file.c | 6 +++--- - libsemanage/src/users_base_file.c | 7 +++---- - libsemanage/src/users_extra_file.c | 4 ++-- - 12 files changed, 33 insertions(+), 35 deletions(-) - -diff --git a/libsemanage/src/booleans_file.c b/libsemanage/src/booleans_file.c -index f79d0b44eb16..6d600bbc9421 100644 ---- a/libsemanage/src/booleans_file.c -+++ b/libsemanage/src/booleans_file.c -@@ -48,7 +48,7 @@ static int bool_parse(semanage_handle_t * handle, - goto last; - - /* Extract name */ -- if (parse_fetch_string(handle, info, &str, '=') < 0) -+ if (parse_fetch_string(handle, info, &str, '=', 0) < 0) - goto err; - - if (semanage_bool_set_name(handle, boolean, str) < 0) -diff --git a/libsemanage/src/fcontexts_file.c b/libsemanage/src/fcontexts_file.c -index 04cd365aa2df..f35794103a50 100644 ---- a/libsemanage/src/fcontexts_file.c -+++ b/libsemanage/src/fcontexts_file.c -@@ -90,7 +90,7 @@ static int fcontext_parse(semanage_handle_t * handle, - goto last; - - /* Regexp */ -- if (parse_fetch_string(handle, info, &str, ' ') < 0) -+ if (parse_fetch_string(handle, info, &str, ' ', 0) < 0) - goto err; - if (semanage_fcontext_set_expr(handle, fcontext, str) < 0) - goto err; -@@ -100,7 +100,7 @@ static int fcontext_parse(semanage_handle_t * handle, - /* Type */ - if (parse_assert_space(handle, info) < 0) - goto err; -- if (parse_fetch_string(handle, info, &str, ' ') < 0) -+ if (parse_fetch_string(handle, info, &str, ' ', 0) < 0) - goto err; - if (!strcasecmp(str, "-s")) - semanage_fcontext_set_type(fcontext, SEMANAGE_FCONTEXT_SOCK); -@@ -124,7 +124,7 @@ static int fcontext_parse(semanage_handle_t * handle, - /* Context */ - if (parse_assert_space(handle, info) < 0) - goto err; -- if (parse_fetch_string(handle, info, &str, ' ') < 0) -+ if (parse_fetch_string(handle, info, &str, ' ', 0) < 0) - goto err; - - process_context: -diff --git a/libsemanage/src/ibendports_file.c b/libsemanage/src/ibendports_file.c -index bafa8c1d65bf..2fa2a67c5b40 100644 ---- a/libsemanage/src/ibendports_file.c -+++ b/libsemanage/src/ibendports_file.c -@@ -75,7 +75,7 @@ static int ibendport_parse(semanage_handle_t *handle, - goto err; - - /* IB Device Name */ -- if (parse_fetch_string(handle, info, &str, ' ') < 0) -+ if (parse_fetch_string(handle, info, &str, ' ', 0) < 0) - goto err; - if (semanage_ibendport_set_ibdev_name(handle, ibendport, str) < 0) - goto err; -@@ -92,7 +92,7 @@ static int ibendport_parse(semanage_handle_t *handle, - /* context */ - if (parse_assert_space(handle, info) < 0) - goto err; -- if (parse_fetch_string(handle, info, &str, ' ') < 0) -+ if (parse_fetch_string(handle, info, &str, ' ', 0) < 0) - goto err; - if (semanage_context_from_string(handle, str, &con) < 0) { - ERR(handle, "invalid security context \"%s\" (%s: %u)\n%s", -diff --git a/libsemanage/src/ibpkeys_file.c b/libsemanage/src/ibpkeys_file.c -index 929bc31e612e..edde69f09f70 100644 ---- a/libsemanage/src/ibpkeys_file.c -+++ b/libsemanage/src/ibpkeys_file.c -@@ -80,7 +80,7 @@ static int ibpkey_parse(semanage_handle_t *handle, - goto err; - - /* Subnet Prefix */ -- if (parse_fetch_string(handle, info, &str, ' ') < 0) -+ if (parse_fetch_string(handle, info, &str, ' ', 0) < 0) - goto err; - if (semanage_ibpkey_set_subnet_prefix(handle, ibpkey, str) < 0) - goto err; -@@ -115,7 +115,7 @@ static int ibpkey_parse(semanage_handle_t *handle, - semanage_ibpkey_set_pkey(ibpkey, low); - } - /* Pkey context */ -- if (parse_fetch_string(handle, info, &str, ' ') < 0) -+ if (parse_fetch_string(handle, info, &str, ' ', 0) < 0) - goto err; - if (semanage_context_from_string(handle, str, &con) < 0) { - ERR(handle, "invalid security context \"%s\" (%s: %u)\n%s", -diff --git a/libsemanage/src/interfaces_file.c b/libsemanage/src/interfaces_file.c -index c19c8f949c91..244f0ae51eca 100644 ---- a/libsemanage/src/interfaces_file.c -+++ b/libsemanage/src/interfaces_file.c -@@ -72,7 +72,7 @@ static int iface_parse(semanage_handle_t * handle, - goto err; - - /* Name */ -- if (parse_fetch_string(handle, info, &str, ' ') < 0) -+ if (parse_fetch_string(handle, info, &str, ' ', 0) < 0) - goto err; - if (semanage_iface_set_name(handle, iface, str) < 0) - goto err; -@@ -82,7 +82,7 @@ static int iface_parse(semanage_handle_t * handle, - /* Interface context */ - if (parse_assert_space(handle, info) < 0) - goto err; -- if (parse_fetch_string(handle, info, &str, ' ') < 0) -+ if (parse_fetch_string(handle, info, &str, ' ', 0) < 0) - goto err; - if (semanage_context_from_string(handle, str, &con) < 0) { - ERR(handle, "invalid security context \"%s\" (%s: %u)\n%s", -@@ -106,7 +106,7 @@ static int iface_parse(semanage_handle_t * handle, - /* Message context */ - if (parse_assert_space(handle, info) < 0) - goto err; -- if (parse_fetch_string(handle, info, &str, ' ') < 0) -+ if (parse_fetch_string(handle, info, &str, ' ', 0) < 0) - goto err; - if (semanage_context_from_string(handle, str, &con) < 0) { - ERR(handle, "invalid security context \"%s\" (%s: %u)\n%s", -diff --git a/libsemanage/src/nodes_file.c b/libsemanage/src/nodes_file.c -index c3647f2ad622..2d2b7fe023f5 100644 ---- a/libsemanage/src/nodes_file.c -+++ b/libsemanage/src/nodes_file.c -@@ -77,7 +77,7 @@ static int node_parse(semanage_handle_t * handle, - goto err; - - /* Protocol */ -- if (parse_fetch_string(handle, info, &str, ' ') < 0) -+ if (parse_fetch_string(handle, info, &str, ' ', 0) < 0) - goto err; - if (!strcasecmp(str, "ipv4")) - proto = SEMANAGE_PROTO_IP4; -@@ -96,7 +96,7 @@ static int node_parse(semanage_handle_t * handle, - /* Address */ - if (parse_assert_space(handle, info) < 0) - goto err; -- if (parse_fetch_string(handle, info, &str, ' ') < 0) -+ if (parse_fetch_string(handle, info, &str, ' ', 0) < 0) - goto err; - if (semanage_node_set_addr(handle, node, proto, str) < 0) - goto err; -@@ -106,7 +106,7 @@ static int node_parse(semanage_handle_t * handle, - str = NULL; - - /* Netmask */ -- if (parse_fetch_string(handle, info, &str, ' ') < 0) -+ if (parse_fetch_string(handle, info, &str, ' ', 0) < 0) - goto err; - if (semanage_node_set_mask(handle, node, proto, str) < 0) - goto err; -@@ -116,7 +116,7 @@ static int node_parse(semanage_handle_t * handle, - str = NULL; - - /* Port context */ -- if (parse_fetch_string(handle, info, &str, ' ') < 0) -+ if (parse_fetch_string(handle, info, &str, ' ', 0) < 0) - goto err; - if (semanage_context_from_string(handle, str, &con) < 0) { - ERR(handle, "invalid security context \"%s\" (%s: %u)\n%s", -diff --git a/libsemanage/src/parse_utils.c b/libsemanage/src/parse_utils.c -index 4fb54fc3d831..918dee439582 100644 ---- a/libsemanage/src/parse_utils.c -+++ b/libsemanage/src/parse_utils.c -@@ -239,7 +239,7 @@ int parse_fetch_int(semanage_handle_t * handle, - char *test = NULL; - int value = 0; - -- if (parse_fetch_string(handle, info, &str, delim) < 0) -+ if (parse_fetch_string(handle, info, &str, delim, 0) < 0) - goto err; - - if (!isdigit((int)*str)) { -@@ -267,7 +267,7 @@ int parse_fetch_int(semanage_handle_t * handle, - } - - int parse_fetch_string(semanage_handle_t * handle, -- parse_info_t * info, char **str, char delim) -+ parse_info_t * info, char **str, char delim, int allow_spaces) - { - - char *start = info->ptr; -@@ -277,7 +277,7 @@ int parse_fetch_string(semanage_handle_t * handle, - if (parse_assert_noeof(handle, info) < 0) - goto err; - -- while (*(info->ptr) && !isspace(*(info->ptr)) && -+ while (*(info->ptr) && (allow_spaces || !isspace(*(info->ptr))) && - (*(info->ptr) != delim)) { - info->ptr++; - len++; -diff --git a/libsemanage/src/parse_utils.h b/libsemanage/src/parse_utils.h -index 0f3348601828..3e44aca10d1c 100644 ---- a/libsemanage/src/parse_utils.h -+++ b/libsemanage/src/parse_utils.h -@@ -71,12 +71,11 @@ extern int parse_optional_str(parse_info_t * info, const char *str); - int parse_fetch_int(semanage_handle_t * hgandle, - parse_info_t * info, int *num, char delim); - --/* Extract the next string (delimited by -- * whitespace), and move the read pointer past it. -- * Stop of the optional character delim is encountered, -- * or if whitespace/eof is encountered. Fail if the -- * string is of length 0. */ -+/* Extract the next string and move the read pointer past it. -+ * Stop if the optional character delim (or eof) is encountered, -+ * or if whitespace is encountered and allow_spaces is 0. -+ * Fail if the string is of length 0. */ - extern int parse_fetch_string(semanage_handle_t * handle, -- parse_info_t * info, char **str_ptr, char delim); -+ parse_info_t * info, char **str_ptr, char delim, int allow_spaces); - - #endif -diff --git a/libsemanage/src/ports_file.c b/libsemanage/src/ports_file.c -index ade4102f0e0d..1356021aaaac 100644 ---- a/libsemanage/src/ports_file.c -+++ b/libsemanage/src/ports_file.c -@@ -77,7 +77,7 @@ static int port_parse(semanage_handle_t * handle, - goto err; - - /* Protocol */ -- if (parse_fetch_string(handle, info, &str, ' ') < 0) -+ if (parse_fetch_string(handle, info, &str, ' ', 0) < 0) - goto err; - if (!strcasecmp(str, "tcp")) - semanage_port_set_proto(port, SEMANAGE_PROTO_TCP); -@@ -123,7 +123,7 @@ static int port_parse(semanage_handle_t * handle, - semanage_port_set_port(port, low); - - /* Port context */ -- if (parse_fetch_string(handle, info, &str, ' ') < 0) -+ if (parse_fetch_string(handle, info, &str, ' ', 0) < 0) - goto err; - if (semanage_context_from_string(handle, str, &con) < 0) { - ERR(handle, "invalid security context \"%s\" (%s: %u)\n%s", -diff --git a/libsemanage/src/seusers_file.c b/libsemanage/src/seusers_file.c -index 910bedf47a81..21b970acd417 100644 ---- a/libsemanage/src/seusers_file.c -+++ b/libsemanage/src/seusers_file.c -@@ -53,7 +53,7 @@ static int seuser_parse(semanage_handle_t * handle, - goto last; - - /* Extract name */ -- if (parse_fetch_string(handle, info, &str, ':') < 0) -+ if (parse_fetch_string(handle, info, &str, ':', 1) < 0) - goto err; - if (semanage_seuser_set_name(handle, seuser, str) < 0) - goto err; -@@ -68,7 +68,7 @@ static int seuser_parse(semanage_handle_t * handle, - goto err; - - /* Extract sename */ -- if (parse_fetch_string(handle, info, &str, ':') < 0) -+ if (parse_fetch_string(handle, info, &str, ':', 1) < 0) - goto err; - if (semanage_seuser_set_sename(handle, seuser, str) < 0) - goto err; -@@ -83,7 +83,7 @@ static int seuser_parse(semanage_handle_t * handle, - goto err; - - /* NOTE: does not allow spaces/multiline */ -- if (parse_fetch_string(handle, info, &str, ' ') < 0) -+ if (parse_fetch_string(handle, info, &str, ' ', 0) < 0) - goto err; - - if (semanage_seuser_set_mlsrange(handle, seuser, str) < 0) -diff --git a/libsemanage/src/users_base_file.c b/libsemanage/src/users_base_file.c -index 0f0a8fdb7973..a0f8cd7e1c5b 100644 ---- a/libsemanage/src/users_base_file.c -+++ b/libsemanage/src/users_base_file.c -@@ -83,7 +83,7 @@ static int user_base_parse(semanage_handle_t * handle, - goto err; - - /* Parse user name */ -- if (parse_fetch_string(handle, info, &name_str, ' ') < 0) -+ if (parse_fetch_string(handle, info, &name_str, ' ', 0) < 0) - goto err; - - if (semanage_user_base_set_name(handle, user, name_str) < 0) { -@@ -150,7 +150,7 @@ static int user_base_parse(semanage_handle_t * handle, - goto err; - - /* NOTE: does not allow spaces/multiline */ -- if (parse_fetch_string(handle, info, &str, ' ') < 0) -+ if (parse_fetch_string(handle, info, &str, ' ', 0) < 0) - goto err; - if (semanage_user_base_set_mlslevel(handle, user, str) < 0) - goto err; -@@ -165,8 +165,7 @@ static int user_base_parse(semanage_handle_t * handle, - if (parse_assert_space(handle, info) < 0) - goto err; - -- /* NOTE: does not allow spaces/multiline */ -- if (parse_fetch_string(handle, info, &str, ';') < 0) -+ if (parse_fetch_string(handle, info, &str, ';', 1) < 0) - goto err; - if (semanage_user_base_set_mlsrange(handle, user, str) < 0) - goto err; -diff --git a/libsemanage/src/users_extra_file.c b/libsemanage/src/users_extra_file.c -index 8f2bebd687b9..7aa9df3c6ba6 100644 ---- a/libsemanage/src/users_extra_file.c -+++ b/libsemanage/src/users_extra_file.c -@@ -57,7 +57,7 @@ static int user_extra_parse(semanage_handle_t * handle, - goto err; - - /* Extract name */ -- if (parse_fetch_string(handle, info, &str, ' ') < 0) -+ if (parse_fetch_string(handle, info, &str, ' ', 0) < 0) - goto err; - if (semanage_user_extra_set_name(handle, user_extra, str) < 0) - goto err; -@@ -73,7 +73,7 @@ static int user_extra_parse(semanage_handle_t * handle, - goto err; - - /* Extract prefix */ -- if (parse_fetch_string(handle, info, &str, ';') < 0) -+ if (parse_fetch_string(handle, info, &str, ';', 1) < 0) - goto err; - if (semanage_user_extra_set_prefix(handle, user_extra, str) < 0) - goto err; --- -2.36.0 - diff --git a/0008-libsemanage-Fall-back-to-semanage_copy_dir-when-rena.patch b/0008-libsemanage-Fall-back-to-semanage_copy_dir-when-rena.patch deleted file mode 100644 index 6e497d3..0000000 --- a/0008-libsemanage-Fall-back-to-semanage_copy_dir-when-rena.patch +++ /dev/null @@ -1,135 +0,0 @@ -From b05fd4edd27fae3d00cc31e9d24910ef4925f8c1 Mon Sep 17 00:00:00 2001 -From: Petr Lautrbach -Date: Thu, 24 Mar 2022 13:00:34 +0100 -Subject: [PATCH] libsemanage: Fall back to semanage_copy_dir when rename() - fails -Content-type: text/plain - -In some circumstances, like semanage-store being on overlayfs, rename() -could fail with EXDEV - Invalid cross-device link. This is due to the -fact that overlays doesn't support rename() if source and target are not -on the same layer, e.g. in containers built from several layers. Even -though it's not atomic operation, it's better to try to copy files from -src to dst on our own in this case. Next rebuild will probably not fail -as the new directories will be on the same layer. - -Fixes: https://github.com/SELinuxProject/selinux/issues/343 - -Reproducer: - - $ cd selinux1 - - $ cat Dockerfile - FROM fedora:35 - RUN dnf install -y selinux-policy selinux-policy-targeted - - $ podman build -t localhost/selinux . --no-cache - - $ cd ../selinux2 - - $ cat Dockerfile - FROM localhost/selinux - RUN semodule -B - - $ podman build -t localhost/selinux2 . --no-cache - STEP 2/2: RUN semodule -B - libsemanage.semanage_commit_sandbox: Error while renaming /var/lib/selinux/targeted/active to /var/lib/selinux/targeted/previous. (Invalid cross-device link). - semodule: Failed! - Error: error building at STEP "RUN semodule -B": error while running runtime: exit status 1 - -With the fix: - - $ podman build -t localhost/selinux2 . --no-cache - STEP 2/2: RUN semodule -B - libsemanage.semanage_rename: Warning: rename(/var/lib/selinux/targeted/active, /var/lib/selinux/targeted/previous) failed: Invalid cross-device link, fall back to non-atomic semanage_copy_dir_flags() - - COMMIT localhost/selinux2 - --> d2cfcebc1a1 - Successfully tagged localhost/selinux2:latest - d2cfcebc1a1b34f1c2cd661ac18292b0612c3e5fa71d6fa1441be244da91b1af - -Reported-by: Joseph Marrero Corchado -Signed-off-by: Petr Lautrbach -Acked-by: Ondrej Mosnacek ---- - libsemanage/src/semanage_store.c | 30 ++++++++++++++++++++++++------ - 1 file changed, 24 insertions(+), 6 deletions(-) - -diff --git a/libsemanage/src/semanage_store.c b/libsemanage/src/semanage_store.c -index 767f05cb2853..c6d2c5e72709 100644 ---- a/libsemanage/src/semanage_store.c -+++ b/libsemanage/src/semanage_store.c -@@ -697,6 +697,10 @@ int semanage_store_access_check(void) - - /********************* other I/O functions *********************/ - -+static int semanage_rename(semanage_handle_t * sh, const char *tmp, const char *dst); -+int semanage_remove_directory(const char *path); -+static int semanage_copy_dir_flags(const char *src, const char *dst, int flag); -+ - /* Callback used by scandir() to select files. */ - static int semanage_filename_select(const struct dirent *d) - { -@@ -768,7 +772,21 @@ out: - return retval; - } - --static int semanage_copy_dir_flags(const char *src, const char *dst, int flag); -+static int semanage_rename(semanage_handle_t * sh, const char *src, const char *dst) { -+ int retval; -+ -+ retval = rename(src, dst); -+ if (retval == 0 || errno != EXDEV) -+ return retval; -+ -+ /* we can't use rename() due to filesystem limitation, lets try to copy files manually */ -+ WARN(sh, "WARNING: rename(%s, %s) failed: %s, fall back to non-atomic semanage_copy_dir_flags()", -+ src, dst, strerror(errno)); -+ if (semanage_copy_dir_flags(src, dst, 1) == -1) { -+ return -1; -+ } -+ return semanage_remove_directory(src); -+} - - /* Copies all of the files from src to dst, recursing into - * subdirectories. Returns 0 on success, -1 on error. */ -@@ -1770,7 +1788,7 @@ static int semanage_commit_sandbox(semanage_handle_t * sh) - goto cleanup; - } - -- if (rename(active, backup) == -1) { -+ if (semanage_rename(sh, active, backup) == -1) { - ERR(sh, "Error while renaming %s to %s.", active, backup); - retval = -1; - goto cleanup; -@@ -1779,12 +1797,12 @@ static int semanage_commit_sandbox(semanage_handle_t * sh) - /* clean up some files from the sandbox before install */ - /* remove homedir_template from sandbox */ - -- if (rename(sandbox, active) == -1) { -+ if (semanage_rename(sh, sandbox, active) == -1) { - ERR(sh, "Error while renaming %s to %s.", sandbox, active); - /* note that if an error occurs during the next - * function then the store will be left in an - * inconsistent state */ -- if (rename(backup, active) < 0) -+ if (semanage_rename(sh, backup, active) < 0) - ERR(sh, "Error while renaming %s back to %s.", backup, - active); - retval = -1; -@@ -1795,10 +1813,10 @@ static int semanage_commit_sandbox(semanage_handle_t * sh) - * function then the store will be left in an - * inconsistent state */ - int errsv = errno; -- if (rename(active, sandbox) < 0) -+ if (semanage_rename(sh, active, sandbox) < 0) - ERR(sh, "Error while renaming %s back to %s.", active, - sandbox); -- else if (rename(backup, active) < 0) -+ else if (semanage_rename(sh, backup, active) < 0) - ERR(sh, "Error while renaming %s back to %s.", backup, - active); - else --- -2.36.0 - diff --git a/libsemanage.spec b/libsemanage.spec index 162241c..d26cf17 100644 --- a/libsemanage.spec +++ b/libsemanage.spec @@ -1,23 +1,15 @@ -%define libsepolver 3.3-1 -%define libselinuxver 3.3-1 +%define libsepolver 3.4-1 +%define libselinuxver 3.4-1 Summary: SELinux binary policy manipulation library Name: libsemanage -Version: 3.3 -Release: 3%{?dist} +Version: 3.4 +Release: 1%{?dist} License: LGPLv2+ -Source0: https://github.com/SELinuxProject/selinux/releases/download/3.3/libsemanage-3.3.tar.gz -# fedora-selinux/selinux: git checkout c9s; git format-patch -N 3.3 -- libsemanage +Source0: https://github.com/SELinuxProject/selinux/releases/download/3.4/libsemanage-3.4.tar.gz +# fedora-selinux/selinux: git checkout c9s; git format-patch -N 3.4 -- 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 -Patch0007: 0007-libsemanage-allow-spaces-in-user-group-names.patch -Patch0008: 0008-libsemanage-Fall-back-to-semanage_copy_dir-when-rena.patch # Patch list end URL: https://github.com/SELinuxProject/selinux/wiki Source1: semanage.conf @@ -161,6 +153,9 @@ cp %{SOURCE1} ${RPM_BUILD_ROOT}%{_sysconfdir}/selinux/semanage.conf %{_libexecdir}/selinux/semanage_migrate_store %changelog +* Thu May 19 2022 Petr Lautrbach - 3.4-1 +- SELinux userspace 3.4 release + * Wed Apr 27 2022 Petr Lautrbach - 3.3-3 - allow spaces in user/group names (#2049665) - Fall back to semanage_copy_dir when rename() fails (#2068085) diff --git a/sources b/sources index e3232de..57839a9 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -SHA512 (libsemanage-3.3.tar.gz) = 6026d9773c0886436ad801bc0c8beac888b6fb62034edeb863192dea4b6ef34a88e080758820fe635a20e048ac666beee505a0f946258f18571709cca5228aad +SHA512 (libsemanage-3.4.tar.gz) = 831dc789545bb9a0b009bdb4f7fe52f6197ad8325946640f886a960d08e40b8a69eccd5a70cce51466bb5cb7f742feb78d19a9ec63383fbd03aa451508677e73