Hi All,
I am currently working on an update for dbus-broker to trigger reload of
its configuration whenever an SELinux policy load event is seen.
For some background dbus-broker is comprised of two major elements the
launcher and the broker. To trigger a config reload you can either send
a SIGHUP to the launcher or send a message to the launcher over dbus.
In most cases the launcher will be the brokers parent.
Here is a link to my current PR:
https://github.com/bus1/dbus-broker/pull/379
In this current state things work. The broker will see the POLICY_LOAD
event and properly send a SIGHUP to its parent, but as David pointed out
my initial attempt at the fix is no good since there is no guarantee
that the brokers parent will be the launcher.
My attempts at moving the callback registration into the launcher have
been less successful. From what my debugging has told me is that the
selinux_set_callback is going through successfully and the function
pointer is correctly pointing to the callback function I define. But
when I trigger a load_policy my callback function is never called.
I am not familiar with how the callbacks in libselinux work under the
hood so I am unsure about what could be blocking them in this situation.
Here is my current diff with all of my debug taken out to make it easier
to read:
diff --git a/Makefile b/Makefile
index d806160..3b29620 100644
--- a/Makefile
+++ b/Makefile
@@ -66,6 +66,7 @@ FORCE:
MESON_SETUP = \
meson \
setup \
+ --prefix=/usr \
--buildtype "debugoptimized" \
--reconfigure \
--warnlevel "2" \
diff --git a/meson_options.txt b/meson_options.txt
index 5227a93..3f65964 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -4,6 +4,6 @@ option('docs', type: 'boolean', value: false,
description: 'Build documentation'
option('launcher', type: 'boolean', value: true, description: 'Build
compatibility launcher')
option('linux-4-17', type: 'boolean', value: false, description:
'Require linux-4.17 at runtime and make use of its features')
option('reference-test', type: 'boolean', value: false, description:
'Run test suite against reference implementation')
-option('selinux', type: 'boolean', value: false, description: 'SELinux
support')
+option('selinux', type: 'boolean', value: true, description: 'SELinux
support')
option('system-console-users', type: 'array', value: [], description:
'Additional set of names of system-users to be considered at-console')
option('tests', type: 'boolean', value: false, description: 'Include
tests in the distribution')
diff --git a/src/launch/main.c b/src/launch/main.c
index ed08e85..46cb5f0 100644
--- a/src/launch/main.c
+++ b/src/launch/main.c
@@ -9,6 +9,7 @@
#include <systemd/sd-daemon.h>
#include "launch/launcher.h"
#include "util/error.h"
+#include "util/selinux.h"
enum {
_MAIN_SUCCESS,
@@ -164,6 +165,8 @@ int main(int argc, char **argv) {
if (r)
goto exit;
+ bus_selinux_register_load_cb();
+
sigemptyset(&mask_new);
sigaddset(&mask_new, SIGCHLD);
sigaddset(&mask_new, SIGTERM);
diff --git a/src/util/selinux-fallback.c b/src/util/selinux-fallback.c
index 0654a07..7e00c3c 100644
--- a/src/util/selinux-fallback.c
+++ b/src/util/selinux-fallback.c
@@ -60,3 +60,7 @@ int bus_selinux_init_global(void) {
void bus_selinux_deinit_global(void) {
return;
}
+
+void bus_selinux_register_load_cb(void) {
+ return;
+}
diff --git a/src/util/selinux.c b/src/util/selinux.c
index a72cc0a..c9ed99d 100644
--- a/src/util/selinux.c
+++ b/src/util/selinux.c
@@ -6,6 +6,7 @@
#include <c-stdaux.h>
#include <selinux/selinux.h>
#include <selinux/avc.h>
+#include <signal.h>
#include <stdlib.h>
#include "util/audit.h"
#include "util/error.h"
@@ -413,3 +414,50 @@ void bus_selinux_deinit_global(void) {
bus_selinux_avc_open = false;
}
}
+
+/**
+ * On a policy reload we need to reparse the SELinux configuration
file, since
+ * this could have changed. Send a SIGHUP to reload all configs.
+ */
+static int policy_reload_callback(int seqno) {
+ return raise(SIGHUP);
+}
+
+/**
+ * bus_selinux_register_load_cb() - register SIGHUP callback for policy
load
+ *
+ * Will register a call back to raise a SIGHUP when a SELinux policy load
+ * is seen.
+ */
+void bus_selinux_register_load_cb(void) {
+ int r;
+ if (!is_selinux_enabled())
+ return ;
+
+ if (!bus_selinux_status_open) {
+ r = selinux_status_open(0);
+ if (r == 0) {
+ /*
+ * The status page was successfully opened and
can now
+ * be used for faster selinux status-checks.
+ */
+ bus_selinux_status_open = true;
+ } else if (r > 0) {
+ /*
+ * >0 indicates success but with the
netlink-fallback.
+ * We didn't request the netlink-fallback, so
close the
+ * status-page again and treat it as unavailable.
+ */
+ selinux_status_close();
+ } else {
+ /*
+ * If the status page could not be opened,
treat it as
+ * unavailable and use the slower fallback
functions.
+ */
+ }
+ }
+
+ selinux_set_callback(SELINUX_CB_POLICYLOAD, (union
selinux_callback)policy_reload_callback);
+
+ return;
+}
diff --git a/src/util/selinux.h b/src/util/selinux.h
index 435c8a8..d5452fd 100644
--- a/src/util/selinux.h
+++ b/src/util/selinux.h
@@ -36,3 +36,5 @@ int bus_selinux_check_send(BusSELinuxRegistry *registry,
int bus_selinux_init_global(void);
void bus_selinux_deinit_global(void);
+
+void bus_selinux_register_load_cb(void);
Note that I have tried moving where the callback registration happens in
the launcher with no luck. I know I can go down the dbus message path
but the SIGHUP from the launcher seems so much more straight forward.
Thanks in advance for any insight folks might have.