diff -urN dbus-1.10.24.old/bus/driver.c dbus-1.10.24/bus/driver.c --- dbus-1.10.24.old/bus/driver.c 2017-09-25 16:20:08.000000000 +0100 +++ dbus-1.10.24/bus/driver.c 2018-02-13 10:15:09.570439595 +0000 @@ -555,6 +555,9 @@ char **services; BusRegistry *registry; int i; +#ifdef HAVE_SELINUX + dbus_bool_t mls_enabled; +#endif DBusMessageIter iter; DBusMessageIter sub; @@ -601,9 +604,58 @@ } } +#ifdef HAVE_SELINUX + mls_enabled = bus_selinux_mls_enabled (); +#endif i = 0; while (i < len) { +#ifdef HAVE_SELINUX + if (mls_enabled) + { + const char *requester; + BusService *service; + DBusString str; + DBusConnection *service_conn; + DBusConnection *requester_conn; + + requester = dbus_message_get_destination (reply); + _dbus_string_init_const (&str, requester); + service = bus_registry_lookup (registry, &str); + + if (service == NULL) + { + _dbus_warn_check_failed ("service lookup failed: %s", requester); + ++i; + continue; + } + requester_conn = bus_service_get_primary_owners_connection (service); + _dbus_string_init_const (&str, services[i]); + service = bus_registry_lookup (registry, &str); + if (service == NULL) + { + _dbus_warn_check_failed ("service lookup failed: %s", services[i]); + ++i; + continue; + } + service_conn = bus_service_get_primary_owners_connection (service); + + if (!bus_selinux_allows_name (requester_conn, service_conn, error)) + { + if (dbus_error_is_set (error) && + dbus_error_has_name (error, DBUS_ERROR_NO_MEMORY)) + { + dbus_free_string_array (services); + dbus_message_unref (reply); + return FALSE; + } + + /* Skip any services which are disallowed by SELinux policy. */ + ++i; + continue; + } + } +#endif if (!dbus_message_iter_append_basic (&sub, DBUS_TYPE_STRING, &services[i])) { diff -urN dbus-1.10.24.old/bus/selinux.c dbus-1.10.24/bus/selinux.c --- dbus-1.10.24.old/bus/selinux.c 2017-07-28 07:24:16.000000000 +0100 +++ dbus-1.10.24/bus/selinux.c 2018-02-13 10:35:14.311477447 +0000 @@ -61,6 +61,9 @@ /* Store the value telling us if SELinux is enabled in the kernel. */ static dbus_bool_t selinux_enabled = FALSE; +/* Store the value telling us if SELinux with MLS is enabled in the kernel. */ +static dbus_bool_t selinux_mls_enabled = FALSE; + /* Store an avc_entry_ref to speed AVC decisions. */ static struct avc_entry_ref aeref; @@ -273,6 +276,20 @@ } /** + * Return whether or not SELinux with MLS support is enabled; must be + * called after bus_selinux_init. + */ +dbus_bool_t +bus_selinux_mls_enabled (void) +{ +#ifdef HAVE_SELINUX + return selinux_mls_enabled; +#else + return FALSE; +#endif /* HAVE_SELINUX */ +} + +/** * Do early initialization; determine whether SELinux is enabled. */ dbus_bool_t @@ -292,6 +309,16 @@ } selinux_enabled = r != 0; + + r = is_selinux_mls_enabled (); + if (r < 0) + { + _dbus_warn ("Could not tell if SELinux MLS is enabled: %s\n", + _dbus_strerror (errno)); + return FALSE; + } + + selinux_mls_enabled = r != 0; return TRUE; #else return TRUE; @@ -304,14 +331,18 @@ */ /* security dbus class constants */ #define SECCLASS_DBUS 1 +#define SECCLASS_CONTEXT 2 /* dbus's per access vector constants */ #define DBUS__ACQUIRE_SVC 1 #define DBUS__SEND_MSG 2 +#define CONTEXT__CONTAINS 1 + #ifdef HAVE_SELINUX static struct security_class_mapping dbus_map[] = { { "dbus", { "acquire_svc", "send_msg", NULL } }, + { "context", { "contains", NULL } }, { NULL } }; #endif /* HAVE_SELINUX */ @@ -734,6 +765,102 @@ #endif /* HAVE_SELINUX */ /** + * Check if SELinux security controls allow one connection to determine the + * name of the other, taking into account MLS considerations. + * + * @param source the requester of the name. + * @param destination the name being requested. + * @returns whether the name should be visible by the source of the request + */ +dbus_bool_t +bus_selinux_allows_name (DBusConnection *source, + DBusConnection *destination, + DBusError *error) +{ +#ifdef HAVE_SELINUX + int err; + char *policy_type; + unsigned long spid, tpid; + BusSELinuxID *source_sid; + BusSELinuxID *dest_sid; + dbus_bool_t ret; + dbus_bool_t string_alloced; + DBusString auxdata; + + if (!selinux_mls_enabled) + return TRUE; + + err = selinux_getpolicytype (&policy_type); + if (err < 0) + { + dbus_set_error_const (error, DBUS_ERROR_IO_ERROR, + "Failed to get SELinux policy type"); + return FALSE; + } + + /* Only check against MLS policy if running under that policy. */ + if (strcmp (policy_type, "mls") != 0) + { + free (policy_type); + return TRUE; + } + + free (policy_type); + + _dbus_assert (source != NULL); + _dbus_assert (destination != NULL); + + if (!source || !dbus_connection_get_unix_process_id (source, &spid)) + spid = 0; + if (!destination || !dbus_connection_get_unix_process_id (destination, &tpid)) + tpid = 0; + + string_alloced = FALSE; + if (!_dbus_string_init (&auxdata)) + goto oom; + string_alloced = TRUE; + + if (spid) + { + if (!_dbus_string_append (&auxdata, " spid=")) + goto oom; + + if (!_dbus_string_append_uint (&auxdata, spid)) + goto oom; + } + + if (tpid) + { + if (!_dbus_string_append (&auxdata, " tpid=")) + goto oom; + + if (!_dbus_string_append_uint (&auxdata, tpid)) + goto oom; + } + + source_sid = bus_connection_get_selinux_id (source); + dest_sid = bus_connection_get_selinux_id (destination); + + ret = bus_selinux_check (source_sid, + dest_sid, + SECCLASS_CONTEXT, + CONTEXT__CONTAINS, + &auxdata); + + _dbus_string_free (&auxdata); + return ret; + + oom: + if (string_alloced) + _dbus_string_free (&auxdata); + BUS_SET_OOM (error); + return FALSE; +#else + return TRUE; +#endif /* HAVE_SELINUX */ +} + +/** * Read the SELinux ID from the connection. * * @param connection the connection to read from Binary files dbus-1.10.24.old/bus/.selinux.c.swp and dbus-1.10.24/bus/.selinux.c.swp differ diff -urN dbus-1.10.24.old/bus/selinux.h dbus-1.10.24/bus/selinux.h --- dbus-1.10.24.old/bus/selinux.h 2017-07-28 07:24:16.000000000 +0100 +++ dbus-1.10.24/bus/selinux.h 2018-02-13 10:15:09.573439444 +0000 @@ -32,6 +32,7 @@ void bus_selinux_shutdown (void); dbus_bool_t bus_selinux_enabled (void); +dbus_bool_t bus_selinux_mls_enabled (void); void bus_selinux_id_ref (BusSELinuxID *sid); void bus_selinux_id_unref (BusSELinuxID *sid); @@ -54,6 +55,10 @@ const char *service_name, DBusError *error); +dbus_bool_t bus_selinux_allows_name (DBusConnection *source, + DBusConnection *destination, + DBusError *error); + dbus_bool_t bus_selinux_allows_send (DBusConnection *sender, DBusConnection *proposed_recipient, const char *msgtype, /* Supplementary audit data */