policycoreutils/SOURCES/0046-semodule-add-command-l...

145 lines
5.0 KiB
Diff

From e3fc737e43561ecadcb977ce4c9a1db44be636ae Mon Sep 17 00:00:00 2001
From: Ondrej Mosnacek <omosnace@redhat.com>
Date: Thu, 3 Feb 2022 17:53:27 +0100
Subject: [PATCH] semodule: add command-line option to detect module changes
Add a new command-line option "--rebuild-if-modules-changed" to control
the newly introduced check_ext_changes libsemanage flag.
For example, running `semodule --rebuild-if-modules-changed` will ensure
that any externally added/removed modules (e.g. by an RPM transaction)
are reflected in the compiled policy, while skipping the most expensive
part of the rebuild if no module change was deteceted since the last
libsemanage transaction.
Signed-off-by: Ondrej Mosnacek <omosnace@redhat.com>
---
policycoreutils/semodule/semodule.8 | 7 +++++++
policycoreutils/semodule/semodule.c | 32 ++++++++++++++++++++++-------
2 files changed, 32 insertions(+), 7 deletions(-)
diff --git a/policycoreutils/semodule/semodule.8 b/policycoreutils/semodule/semodule.8
index 3a2fb21c..d1735d21 100644
--- a/policycoreutils/semodule/semodule.8
+++ b/policycoreutils/semodule/semodule.8
@@ -23,6 +23,13 @@ force a reload of policy
.B \-B, \-\-build
force a rebuild of policy (also reloads unless \-n is used)
.TP
+.B \-\-rebuild-if-modules-changed
+Force a rebuild of the policy if any changes to module content are detected
+(by comparing with checksum from the last transaction). One can use this
+instead of \-B to ensure that any changes to the module store done by an
+external tool (e.g. a package manager) are applied, while automatically
+skipping the rebuild if there are no new changes.
+.TP
.B \-D, \-\-disable_dontaudit
Temporarily remove dontaudits from policy. Reverts whenever policy is rebuilt
.TP
diff --git a/policycoreutils/semodule/semodule.c b/policycoreutils/semodule/semodule.c
index 243b1add..22a42a75 100644
--- a/policycoreutils/semodule/semodule.c
+++ b/policycoreutils/semodule/semodule.c
@@ -46,6 +46,7 @@ static int verbose;
static int reload;
static int no_reload;
static int build;
+static int check_ext_changes;
static int disable_dontaudit;
static int preserve_tunables;
static int ignore_module_cache;
@@ -148,6 +149,9 @@ static void usage(char *progname)
printf(" -c, --cil extract module as cil. This only affects module extraction.\n");
printf(" -H, --hll extract module as hll. This only affects module extraction.\n");
printf(" -m, --checksum print module checksum (SHA256).\n");
+ printf(" --rebuild-if-modules-changed\n"
+ " force policy rebuild if module content changed since\n"
+ " last rebuild (based on checksum)\n");
}
/* Sets the global mode variable to new_mode, but only if no other
@@ -179,6 +183,7 @@ static void set_mode(enum client_modes new_mode, char *arg)
static void parse_command_line(int argc, char **argv)
{
static struct option opts[] = {
+ {"rebuild-if-modules-changed", 0, NULL, '\0'},
{"store", required_argument, NULL, 's'},
{"base", required_argument, NULL, 'b'},
{"help", 0, NULL, 'h'},
@@ -206,15 +211,26 @@ static void parse_command_line(int argc, char **argv)
};
int extract_selected = 0;
int cil_hll_set = 0;
- int i;
+ int i, longind;
verbose = 0;
reload = 0;
no_reload = 0;
+ check_ext_changes = 0;
priority = 400;
while ((i =
- getopt_long(argc, argv, "s:b:hi:l::vr:u:RnNBDCPX:e:d:p:S:E:cHm", opts,
- NULL)) != -1) {
+ getopt_long(argc, argv, "s:b:hi:l::vr:u:RnNBDCPX:e:d:p:S:E:cHm",
+ opts, &longind)) != -1) {
switch (i) {
+ case '\0':
+ switch(longind) {
+ case 0: /* --rebuild-if-modules-changed */
+ check_ext_changes = 1;
+ break;
+ default:
+ usage(argv[0]);
+ exit(1);
+ }
+ break;
case 'b':
fprintf(stderr, "The --base option is deprecated. Use --install instead.\n");
set_mode(INSTALL_M, optarg);
@@ -299,13 +315,13 @@ static void parse_command_line(int argc, char **argv)
}
}
}
- if ((build || reload) && num_commands) {
+ if ((build || reload || check_ext_changes) && num_commands) {
fprintf(stderr,
"build or reload should not be used with other commands\n");
usage(argv[0]);
exit(1);
}
- if (num_commands == 0 && reload == 0 && build == 0) {
+ if (num_commands == 0 && reload == 0 && build == 0 && check_ext_changes == 0) {
fprintf(stderr, "At least one mode must be specified.\n");
usage(argv[0]);
exit(1);
@@ -392,7 +408,7 @@ int main(int argc, char *argv[])
}
parse_command_line(argc, argv);
- if (build)
+ if (build || check_ext_changes)
commit = 1;
sh = semanage_handle_create();
@@ -431,7 +447,7 @@ int main(int argc, char *argv[])
}
}
- if (build) {
+ if (build || check_ext_changes) {
if ((result = semanage_begin_transaction(sh)) < 0) {
fprintf(stderr, "%s: Could not begin transaction: %s\n",
argv[0], errno ? strerror(errno) : "");
@@ -805,6 +821,8 @@ cleanup_disable:
semanage_set_reload(sh, 0);
if (build)
semanage_set_rebuild(sh, 1);
+ if (check_ext_changes)
+ semanage_set_check_ext_changes(sh, 1);
if (disable_dontaudit)
semanage_set_disable_dontaudit(sh, 1);
else if (build)
--
2.30.2