SELinux userspace 3.4 release
Resolves: rhbz#2079285
This commit is contained in:
parent
739e7477f9
commit
26530a8209
1
.gitignore
vendored
1
.gitignore
vendored
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -1,362 +0,0 @@
|
||||
From 898d1e720a4cf1e0dfdb76e0c4b11d92031a8e1a Mon Sep 17 00:00:00 2001
|
||||
From: Vit Mojzis <vmojzis@redhat.com>
|
||||
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 <vmojzis@redhat.com>
|
||||
---
|
||||
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
|
||||
|
@ -1,135 +0,0 @@
|
||||
From b05fd4edd27fae3d00cc31e9d24910ef4925f8c1 Mon Sep 17 00:00:00 2001
|
||||
From: Petr Lautrbach <plautrba@redhat.com>
|
||||
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 <jmarrero@redhat.com>
|
||||
Signed-off-by: Petr Lautrbach <plautrba@redhat.com>
|
||||
Acked-by: Ondrej Mosnacek <omosnace@redhat.com>
|
||||
---
|
||||
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
|
||||
|
@ -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 <plautrba@redhat.com> - 3.4-1
|
||||
- SELinux userspace 3.4 release
|
||||
|
||||
* Wed Apr 27 2022 Petr Lautrbach <plautrba@redhat.com> - 3.3-3
|
||||
- allow spaces in user/group names (#2049665)
|
||||
- Fall back to semanage_copy_dir when rename() fails (#2068085)
|
||||
|
2
sources
2
sources
@ -1 +1 @@
|
||||
SHA512 (libsemanage-3.3.tar.gz) = 6026d9773c0886436ad801bc0c8beac888b6fb62034edeb863192dea4b6ef34a88e080758820fe635a20e048ac666beee505a0f946258f18571709cca5228aad
|
||||
SHA512 (libsemanage-3.4.tar.gz) = 831dc789545bb9a0b009bdb4f7fe52f6197ad8325946640f886a960d08e40b8a69eccd5a70cce51466bb5cb7f742feb78d19a9ec63383fbd03aa451508677e73
|
||||
|
Loading…
Reference in New Issue
Block a user