summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bus/apparmor.c117
-rw-r--r--bus/apparmor.h4
-rw-r--r--bus/driver.c10
-rw-r--r--bus/signals.c9
-rw-r--r--bus/signals.h2
5 files changed, 141 insertions, 1 deletions
diff --git a/bus/apparmor.c b/bus/apparmor.c
index 615a5251..8d7e9107 100644
--- a/bus/apparmor.c
+++ b/bus/apparmor.c
@@ -357,6 +357,12 @@ build_message_query (DBusString *query,
query_append (query, member);
}
+static dbus_bool_t
+build_eavesdrop_query (DBusString *query, const char *con, const char *bustype)
+{
+ return build_common_query (query, con, bustype);
+}
+
static void
set_error_from_query_errno (DBusError *error, int error_number)
{
@@ -1007,3 +1013,114 @@ bus_apparmor_allows_send (DBusConnection *sender,
return TRUE;
#endif /* HAVE_APPARMOR */
}
+
+/**
+ * Check if Apparmor security controls allow the connection to eavesdrop on
+ * other connections.
+ *
+ * @param connection the connection attempting to eavesdrop.
+ * @param bustype name of the bus
+ * @param error the reason for failure when FALSE is returned
+ * @returns TRUE if eavesdropping is permitted
+ */
+dbus_bool_t
+bus_apparmor_allows_eavesdropping (DBusConnection *connection,
+ const char *bustype,
+ DBusError *error)
+{
+#ifdef HAVE_APPARMOR
+ BusAppArmorConfinement *con = NULL;
+ DBusString qstr, auxdata;
+ dbus_bool_t allow = FALSE, audit = TRUE;
+ dbus_bool_t free_auxdata = FALSE;
+ unsigned long pid;
+ int res, serrno = 0;
+
+ if (!apparmor_enabled)
+ return TRUE;
+
+ con = bus_connection_dup_apparmor_confinement (connection);
+
+ if (is_unconfined (con->context, con->mode))
+ {
+ allow = TRUE;
+ audit = FALSE;
+ goto out;
+ }
+
+ if (!_dbus_string_init (&qstr))
+ goto oom;
+
+ if (!build_eavesdrop_query (&qstr, con->context, bustype))
+ {
+ _dbus_string_free (&qstr);
+ goto oom;
+ }
+
+ res = aa_query_label (AA_DBUS_EAVESDROP,
+ _dbus_string_get_data (&qstr),
+ _dbus_string_get_length (&qstr),
+ &allow, &audit);
+ _dbus_string_free (&qstr);
+ if (res == -1)
+ {
+ serrno = errno;
+ set_error_from_query_errno (error, serrno);
+ goto audit;
+ }
+
+ /* Don't fail operations on profiles in complain mode */
+ if (modestr_is_complain (con->mode))
+ allow = TRUE;
+
+ if (!allow)
+ dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
+ "Connection \"%s\" is not allowed to eavesdrop due to "
+ "AppArmor policy",
+ bus_connection_is_active (connection) ?
+ bus_connection_get_name (connection) : "(inactive)");
+
+ if (!audit)
+ goto out;
+
+ audit:
+ if (!_dbus_string_init (&auxdata))
+ goto oom;
+ free_auxdata = TRUE;
+
+ if (!_dbus_append_pair_str (&auxdata, "bus", bustype ? bustype : "unknown"))
+ goto oom;
+
+ if (serrno && !_dbus_append_pair_str (&auxdata, "info", strerror (serrno)))
+ goto oom;
+
+ if (!_dbus_append_pair_str (&auxdata, "mask", "eavesdrop"))
+ goto oom;
+
+ if (connection && dbus_connection_get_unix_process_id (connection, &pid) &&
+ !_dbus_append_pair_uint (&auxdata, "pid", pid))
+ goto oom;
+
+ if (con->context && !_dbus_append_pair_str (&auxdata, "profile", con->context))
+ goto oom;
+
+ log_message (allow, "eavesdrop", &auxdata);
+
+ out:
+ if (con != NULL)
+ bus_apparmor_confinement_unref (con);
+ if (free_auxdata)
+ _dbus_string_free (&auxdata);
+
+ return allow;
+
+ oom:
+ if (error != NULL && !dbus_error_is_set (error))
+ BUS_SET_OOM (error);
+ allow = FALSE;
+ goto out;
+
+#else
+ return TRUE;
+#endif /* HAVE_APPARMOR */
+}
diff --git a/bus/apparmor.h b/bus/apparmor.h
index 3f3d6469..4a47aecc 100644
--- a/bus/apparmor.h
+++ b/bus/apparmor.h
@@ -59,4 +59,8 @@ dbus_bool_t bus_apparmor_allows_send (DBusConnection *sender,
const char *source,
DBusError *error);
+dbus_bool_t bus_apparmor_allows_eavesdropping (DBusConnection *connection,
+ const char *bustype,
+ DBusError *error);
+
#endif /* BUS_APPARMOR_H */
diff --git a/bus/driver.c b/bus/driver.c
index 442dd01d..53bd5590 100644
--- a/bus/driver.c
+++ b/bus/driver.c
@@ -24,6 +24,7 @@
#include <config.h>
#include "activation.h"
+#include "apparmor.h"
#include "connection.h"
#include "driver.h"
#include "dispatch.h"
@@ -1110,9 +1111,10 @@ bus_driver_handle_add_match (DBusConnection *connection,
DBusError *error)
{
BusMatchRule *rule;
- const char *text;
+ const char *text, *bustype;
DBusString str;
BusMatchmaker *matchmaker;
+ BusContext *context;
_DBUS_ASSERT_ERROR_IS_CLEAR (error);
@@ -1145,6 +1147,12 @@ bus_driver_handle_add_match (DBusConnection *connection,
if (rule == NULL)
goto failed;
+ context = bus_transaction_get_context (transaction);
+ bustype = context ? bus_context_get_type (context) : NULL;
+ if (bus_match_rule_get_client_is_eavesdropping (rule) &&
+ !bus_apparmor_allows_eavesdropping (connection, bustype, error))
+ goto failed;
+
matchmaker = bus_connection_get_matchmaker (connection);
if (!bus_matchmaker_add_rule (matchmaker, rule))
diff --git a/bus/signals.c b/bus/signals.c
index 4390028f..260dd243 100644
--- a/bus/signals.c
+++ b/bus/signals.c
@@ -411,6 +411,15 @@ bus_match_rule_set_client_is_eavesdropping (BusMatchRule *rule,
}
dbus_bool_t
+bus_match_rule_get_client_is_eavesdropping (BusMatchRule *rule)
+{
+ if (rule->flags & BUS_MATCH_CLIENT_IS_EAVESDROPPING)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+dbus_bool_t
bus_match_rule_set_path (BusMatchRule *rule,
const char *path,
dbus_bool_t is_namespace)
diff --git a/bus/signals.h b/bus/signals.h
index d19fc7c5..0edfb07e 100644
--- a/bus/signals.h
+++ b/bus/signals.h
@@ -73,6 +73,8 @@ dbus_bool_t bus_match_rule_set_arg (BusMatchRule *rule,
void bus_match_rule_set_client_is_eavesdropping (BusMatchRule *rule,
dbus_bool_t is_eavesdropping);
+dbus_bool_t bus_match_rule_get_client_is_eavesdropping (BusMatchRule *rule);
+
BusMatchRule* bus_match_rule_parse (DBusConnection *matches_go_to,
const DBusString *rule_text,
DBusError *error);