|
|
e3782d |
From 8b74179ee31652bbaaf979777b9e829b426053ef Mon Sep 17 00:00:00 2001
|
|
|
e3782d |
From: David King <dking@redhat.com>
|
|
|
e3782d |
Date: Tue, 4 Nov 2014 10:10:36 +0000
|
|
|
e3782d |
Subject: [PATCH] selinux: Check ListNames permissions with MLS
|
|
|
e3782d |
|
|
|
e3782d |
https://bugzilla.redhat.com/show_bug.cgi?id=1118399
|
|
|
e3782d |
---
|
|
|
e3782d |
bus/driver.c | 52 +++++++++++++++++++++++++
|
|
|
e3782d |
bus/selinux.c | 123 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
e3782d |
bus/selinux.h | 5 +++
|
|
|
e3782d |
3 files changed, 180 insertions(+)
|
|
|
e3782d |
|
|
|
e3782d |
diff --git a/bus/driver.c b/bus/driver.c
|
|
|
e3782d |
index 574e0f3..20cc940 100644
|
|
|
e3782d |
--- a/bus/driver.c
|
|
|
e3782d |
+++ b/bus/driver.c
|
|
|
e3782d |
@@ -379,6 +379,9 @@ bus_driver_handle_list_services (DBusConnection *connection,
|
|
|
e3782d |
char **services;
|
|
|
e3782d |
BusRegistry *registry;
|
|
|
e3782d |
int i;
|
|
|
e3782d |
+#ifdef HAVE_SELINUX
|
|
|
e3782d |
+ dbus_bool_t mls_enabled;
|
|
|
e3782d |
+#endif
|
|
|
e3782d |
DBusMessageIter iter;
|
|
|
e3782d |
DBusMessageIter sub;
|
|
|
e3782d |
|
|
|
e3782d |
@@ -425,9 +428,58 @@ bus_driver_handle_list_services (DBusConnection *connection,
|
|
|
e3782d |
}
|
|
|
e3782d |
}
|
|
|
e3782d |
|
|
|
e3782d |
+#ifdef HAVE_SELINUX
|
|
|
e3782d |
+ mls_enabled = bus_selinux_mls_enabled ();
|
|
|
e3782d |
+#endif
|
|
|
e3782d |
i = 0;
|
|
|
e3782d |
while (i < len)
|
|
|
e3782d |
{
|
|
|
e3782d |
+#ifdef HAVE_SELINUX
|
|
|
e3782d |
+ if (mls_enabled)
|
|
|
e3782d |
+ {
|
|
|
e3782d |
+ const char *requester;
|
|
|
e3782d |
+ BusService *service;
|
|
|
e3782d |
+ DBusString str;
|
|
|
e3782d |
+ DBusConnection *service_conn;
|
|
|
e3782d |
+ DBusConnection *requester_conn;
|
|
|
e3782d |
+
|
|
|
e3782d |
+ requester = dbus_message_get_destination (reply);
|
|
|
e3782d |
+ _dbus_string_init_const (&str, requester);
|
|
|
e3782d |
+ service = bus_registry_lookup (registry, &str);
|
|
|
e3782d |
+
|
|
|
e3782d |
+ if (service == NULL)
|
|
|
e3782d |
+ {
|
|
|
e3782d |
+ _dbus_warn_check_failed ("service lookup failed: %s", requester);
|
|
|
e3782d |
+ ++i;
|
|
|
e3782d |
+ continue;
|
|
|
e3782d |
+ }
|
|
|
e3782d |
+ requester_conn = bus_service_get_primary_owners_connection (service);
|
|
|
e3782d |
+ _dbus_string_init_const (&str, services[i]);
|
|
|
e3782d |
+ service = bus_registry_lookup (registry, &str);
|
|
|
e3782d |
+ if (service == NULL)
|
|
|
e3782d |
+ {
|
|
|
e3782d |
+ _dbus_warn_check_failed ("service lookup failed: %s", services[i]);
|
|
|
e3782d |
+ ++i;
|
|
|
e3782d |
+ continue;
|
|
|
e3782d |
+ }
|
|
|
e3782d |
+ service_conn = bus_service_get_primary_owners_connection (service);
|
|
|
e3782d |
+
|
|
|
e3782d |
+ if (!bus_selinux_allows_name (requester_conn, service_conn, error))
|
|
|
e3782d |
+ {
|
|
|
e3782d |
+ if (dbus_error_is_set (error) &&
|
|
|
e3782d |
+ dbus_error_has_name (error, DBUS_ERROR_NO_MEMORY))
|
|
|
e3782d |
+ {
|
|
|
e3782d |
+ dbus_free_string_array (services);
|
|
|
e3782d |
+ dbus_message_unref (reply);
|
|
|
e3782d |
+ return FALSE;
|
|
|
e3782d |
+ }
|
|
|
e3782d |
+
|
|
|
e3782d |
+ /* Skip any services which are disallowed by SELinux policy. */
|
|
|
e3782d |
+ ++i;
|
|
|
e3782d |
+ continue;
|
|
|
e3782d |
+ }
|
|
|
e3782d |
+ }
|
|
|
e3782d |
+#endif
|
|
|
e3782d |
if (!dbus_message_iter_append_basic (&sub, DBUS_TYPE_STRING,
|
|
|
e3782d |
&services[i]))
|
|
|
e3782d |
{
|
|
|
e3782d |
diff --git a/bus/selinux.c b/bus/selinux.c
|
|
|
e3782d |
index 36287e9..6442b79 100644
|
|
|
e3782d |
--- a/bus/selinux.c
|
|
|
e3782d |
+++ b/bus/selinux.c
|
|
|
e3782d |
@@ -63,6 +63,9 @@
|
|
|
e3782d |
/* Store the value telling us if SELinux is enabled in the kernel. */
|
|
|
e3782d |
static dbus_bool_t selinux_enabled = FALSE;
|
|
|
e3782d |
|
|
|
e3782d |
+/* Store the value telling us if SELinux with MLS is enabled in the kernel. */
|
|
|
e3782d |
+static dbus_bool_t selinux_mls_enabled = FALSE;
|
|
|
e3782d |
+
|
|
|
e3782d |
/* Store an avc_entry_ref to speed AVC decisions. */
|
|
|
e3782d |
static struct avc_entry_ref aeref;
|
|
|
e3782d |
|
|
|
e3782d |
@@ -289,6 +292,20 @@ bus_selinux_enabled (void)
|
|
|
e3782d |
}
|
|
|
e3782d |
|
|
|
e3782d |
/**
|
|
|
e3782d |
+ * Return whether or not SELinux with MLS support is enabled; must be
|
|
|
e3782d |
+ * called after bus_selinux_init.
|
|
|
e3782d |
+ */
|
|
|
e3782d |
+dbus_bool_t
|
|
|
e3782d |
+bus_selinux_mls_enabled (void)
|
|
|
e3782d |
+{
|
|
|
e3782d |
+#ifdef HAVE_SELINUX
|
|
|
e3782d |
+ return selinux_mls_enabled;
|
|
|
e3782d |
+#else
|
|
|
e3782d |
+ return FALSE;
|
|
|
e3782d |
+#endif /* HAVE_SELINUX */
|
|
|
e3782d |
+}
|
|
|
e3782d |
+
|
|
|
e3782d |
+/**
|
|
|
e3782d |
* Do early initialization; determine whether SELinux is enabled.
|
|
|
e3782d |
*/
|
|
|
e3782d |
dbus_bool_t
|
|
|
e3782d |
@@ -308,6 +325,16 @@ bus_selinux_pre_init (void)
|
|
|
e3782d |
}
|
|
|
e3782d |
|
|
|
e3782d |
selinux_enabled = r != 0;
|
|
|
e3782d |
+
|
|
|
e3782d |
+ r = is_selinux_mls_enabled ();
|
|
|
e3782d |
+ if (r < 0)
|
|
|
e3782d |
+ {
|
|
|
e3782d |
+ _dbus_warn ("Could not tell if SELinux MLS is enabled: %s\n",
|
|
|
e3782d |
+ _dbus_strerror (errno));
|
|
|
e3782d |
+ return FALSE;
|
|
|
e3782d |
+ }
|
|
|
e3782d |
+
|
|
|
e3782d |
+ selinux_mls_enabled = r != 0;
|
|
|
e3782d |
return TRUE;
|
|
|
e3782d |
#else
|
|
|
e3782d |
return TRUE;
|
|
|
e3782d |
@@ -724,6 +751,102 @@ bus_connection_read_selinux_context (DBusConnection *connection,
|
|
|
e3782d |
#endif /* HAVE_SELINUX */
|
|
|
e3782d |
|
|
|
e3782d |
/**
|
|
|
e3782d |
+ * Check if SELinux security controls allow one connection to determine the
|
|
|
e3782d |
+ * name of the other, taking into account MLS considerations.
|
|
|
e3782d |
+ *
|
|
|
e3782d |
+ * @param source the requester of the name.
|
|
|
e3782d |
+ * @param destination the name being requested.
|
|
|
e3782d |
+ * @returns whether the name should be visible by the source of the request
|
|
|
e3782d |
+ */
|
|
|
e3782d |
+dbus_bool_t
|
|
|
e3782d |
+bus_selinux_allows_name (DBusConnection *source,
|
|
|
e3782d |
+ DBusConnection *destination,
|
|
|
e3782d |
+ DBusError *error)
|
|
|
e3782d |
+{
|
|
|
e3782d |
+#ifdef HAVE_SELINUX
|
|
|
e3782d |
+ int err;
|
|
|
e3782d |
+ char *policy_type;
|
|
|
e3782d |
+ unsigned long spid, tpid;
|
|
|
e3782d |
+ BusSELinuxID *source_sid;
|
|
|
e3782d |
+ BusSELinuxID *dest_sid;
|
|
|
e3782d |
+ dbus_bool_t ret;
|
|
|
e3782d |
+ dbus_bool_t string_alloced;
|
|
|
e3782d |
+ DBusString auxdata;
|
|
|
e3782d |
+
|
|
|
e3782d |
+ if (!selinux_mls_enabled)
|
|
|
e3782d |
+ return TRUE;
|
|
|
e3782d |
+
|
|
|
e3782d |
+ err = selinux_getpolicytype (&policy_type);
|
|
|
e3782d |
+ if (err < 0)
|
|
|
e3782d |
+ {
|
|
|
e3782d |
+ dbus_set_error_const (error, DBUS_ERROR_IO_ERROR,
|
|
|
e3782d |
+ "Failed to get SELinux policy type");
|
|
|
e3782d |
+ return FALSE;
|
|
|
e3782d |
+ }
|
|
|
e3782d |
+
|
|
|
e3782d |
+ /* Only check against MLS policy if running under that policy. */
|
|
|
e3782d |
+ if (strcmp (policy_type, "mls") != 0)
|
|
|
e3782d |
+ {
|
|
|
e3782d |
+ free (policy_type);
|
|
|
e3782d |
+ return TRUE;
|
|
|
e3782d |
+ }
|
|
|
e3782d |
+
|
|
|
e3782d |
+ free (policy_type);
|
|
|
e3782d |
+
|
|
|
e3782d |
+ _dbus_assert (source != NULL);
|
|
|
e3782d |
+ _dbus_assert (destination != NULL);
|
|
|
e3782d |
+
|
|
|
e3782d |
+ if (!source || !dbus_connection_get_unix_process_id (source, &spid))
|
|
|
e3782d |
+ spid = 0;
|
|
|
e3782d |
+ if (!destination || !dbus_connection_get_unix_process_id (destination, &tpid))
|
|
|
e3782d |
+ tpid = 0;
|
|
|
e3782d |
+
|
|
|
e3782d |
+ string_alloced = FALSE;
|
|
|
e3782d |
+ if (!_dbus_string_init (&auxdata))
|
|
|
e3782d |
+ goto oom;
|
|
|
e3782d |
+ string_alloced = TRUE;
|
|
|
e3782d |
+
|
|
|
e3782d |
+ if (spid)
|
|
|
e3782d |
+ {
|
|
|
e3782d |
+ if (!_dbus_string_append (&auxdata, " spid="))
|
|
|
e3782d |
+ goto oom;
|
|
|
e3782d |
+
|
|
|
e3782d |
+ if (!_dbus_string_append_uint (&auxdata, spid))
|
|
|
e3782d |
+ goto oom;
|
|
|
e3782d |
+ }
|
|
|
e3782d |
+
|
|
|
e3782d |
+ if (tpid)
|
|
|
e3782d |
+ {
|
|
|
e3782d |
+ if (!_dbus_string_append (&auxdata, " tpid="))
|
|
|
e3782d |
+ goto oom;
|
|
|
e3782d |
+
|
|
|
e3782d |
+ if (!_dbus_string_append_uint (&auxdata, tpid))
|
|
|
e3782d |
+ goto oom;
|
|
|
e3782d |
+ }
|
|
|
e3782d |
+
|
|
|
e3782d |
+ source_sid = bus_connection_get_selinux_id (source);
|
|
|
e3782d |
+ dest_sid = bus_connection_get_selinux_id (destination);
|
|
|
e3782d |
+
|
|
|
e3782d |
+ ret = bus_selinux_check (source_sid,
|
|
|
e3782d |
+ dest_sid,
|
|
|
e3782d |
+ SECCLASS_CONTEXT,
|
|
|
e3782d |
+ CONTEXT__CONTAINS,
|
|
|
e3782d |
+ &auxdata);
|
|
|
e3782d |
+
|
|
|
e3782d |
+ _dbus_string_free (&auxdata);
|
|
|
e3782d |
+ return ret;
|
|
|
e3782d |
+
|
|
|
e3782d |
+ oom:
|
|
|
e3782d |
+ if (string_alloced)
|
|
|
e3782d |
+ _dbus_string_free (&auxdata);
|
|
|
e3782d |
+ BUS_SET_OOM (error);
|
|
|
e3782d |
+ return FALSE;
|
|
|
e3782d |
+#else
|
|
|
e3782d |
+ return TRUE;
|
|
|
e3782d |
+#endif /* HAVE_SELINUX */
|
|
|
e3782d |
+}
|
|
|
e3782d |
+
|
|
|
e3782d |
+/**
|
|
|
e3782d |
* Read the SELinux ID from the connection.
|
|
|
e3782d |
*
|
|
|
e3782d |
* @param connection the connection to read from
|
|
|
e3782d |
diff --git a/bus/selinux.h b/bus/selinux.h
|
|
|
e3782d |
index 3bab36d..fcaac5f 100644
|
|
|
e3782d |
--- a/bus/selinux.h
|
|
|
e3782d |
+++ b/bus/selinux.h
|
|
|
e3782d |
@@ -32,6 +32,7 @@ dbus_bool_t bus_selinux_full_init(void);
|
|
|
e3782d |
void bus_selinux_shutdown (void);
|
|
|
e3782d |
|
|
|
e3782d |
dbus_bool_t bus_selinux_enabled (void);
|
|
|
e3782d |
+dbus_bool_t bus_selinux_mls_enabled (void);
|
|
|
e3782d |
|
|
|
e3782d |
void bus_selinux_id_ref (BusSELinuxID *sid);
|
|
|
e3782d |
void bus_selinux_id_unref (BusSELinuxID *sid);
|
|
|
e3782d |
@@ -54,6 +55,10 @@ dbus_bool_t bus_selinux_allows_acquire_service (DBusConnection *connection,
|
|
|
e3782d |
const char *service_name,
|
|
|
e3782d |
DBusError *error);
|
|
|
e3782d |
|
|
|
e3782d |
+dbus_bool_t bus_selinux_allows_name (DBusConnection *source,
|
|
|
e3782d |
+ DBusConnection *destination,
|
|
|
e3782d |
+ DBusError *error);
|
|
|
e3782d |
+
|
|
|
e3782d |
dbus_bool_t bus_selinux_allows_send (DBusConnection *sender,
|
|
|
e3782d |
DBusConnection *proposed_recipient,
|
|
|
e3782d |
const char *msgtype, /* Supplementary audit data */
|
|
|
e3782d |
--
|
|
|
e3782d |
2.1.0
|
|
|
e3782d |
|