Commit 66979aae authored by Tyler Hicks's avatar Tyler Hicks Committed by Simon McVittie

Mediation of processes eavesdropping

When an AppArmor confined process wants to eavesdrop on a bus, a check
is performed to see if the action should be allowed.

The check is based on the connection's label and the bus type.

This patch adds a new hook, which was not previously included in the
SELinux mediation, to mediate eavesdropping from
bus_driver_handle_add_match().

A new function is added to bus/signals.c to see if a match rule is an
eavesdropping rule since the rule flags field is private to signals.c.

An example AppArmor rule that would allow a process to eavesdrop on the
session bus would be:

  dbus eavesdrop bus=session,

Bug: https://bugs.freedesktop.org/show_bug.cgi?id=75113Signed-off-by: default avatarTyler Hicks <tyhicks@canonical.com>
Reviewed-by: default avatarSimon McVittie <simon.mcvittie@collabora.co.uk>
parent d9a2fdb9
......@@ -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 */
}
......@@ -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 */
......@@ -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))
......
......@@ -410,6 +410,15 @@ bus_match_rule_set_client_is_eavesdropping (BusMatchRule *rule,
rule->flags &= ~(BUS_MATCH_CLIENT_IS_EAVESDROPPING);
}
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,
......
......@@ -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);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment