From ee3bd83e0eb457b2cf83956004d1cfd4ef829ed4 Mon Sep 17 00:00:00 2001 From: Tyler Hicks Date: Wed, 4 Feb 2015 17:53:31 +0000 Subject: [PATCH 30/31] Add DBus method to return the AA context of a connection This is not intended for upstream inclusion. It implements a bus method (GetConnectionAppArmorSecurityContext) to get a connection's AppArmor security context but upstream D-Bus has recently added a generic way of getting a connection's security credentials (GetConnectionCredentials). Ubuntu should carry this patch until packages in the archive are moved over to the new, generic method of getting a connection's credentials. [Altered by Simon McVittie: survive non-UTF-8 contexts which would otherwise be a local denial of service, except that Ubuntu inherits a non-fatal warnings patch from Debian; new commit message taken from the Ubuntu changelog; do not emit unreachable code if AppArmor is disabled.] --- bus/apparmor.c | 15 +++++++++ bus/apparmor.h | 1 + bus/driver.c | 89 ++++++++++++++++++++++++++++++++++++++++++++++++++++ dbus/dbus-protocol.h | 2 ++ 4 files changed, 107 insertions(+) diff --git a/bus/apparmor.c b/bus/apparmor.c index 6a8691a..4c6dfd2 100644 --- a/bus/apparmor.c +++ b/bus/apparmor.c @@ -105,6 +105,21 @@ bus_apparmor_confinement_new (char *label, return confinement; } +const char* +bus_apparmor_confinement_get_label (BusAppArmorConfinement *confinement) +{ +#ifdef HAVE_APPARMOR + if (!apparmor_enabled) + return NULL; + + _dbus_assert (confinement != NULL); + + return confinement->label; +#else + return NULL; +#endif +} + void bus_apparmor_confinement_unref (BusAppArmorConfinement *confinement) { diff --git a/bus/apparmor.h b/bus/apparmor.h index 4a47aec..e9fcc1b 100644 --- a/bus/apparmor.h +++ b/bus/apparmor.h @@ -39,6 +39,7 @@ dbus_bool_t bus_apparmor_enabled (void); void bus_apparmor_confinement_unref (BusAppArmorConfinement *confinement); void bus_apparmor_confinement_ref (BusAppArmorConfinement *confinement); +const char* bus_apparmor_confinement_get_label (BusAppArmorConfinement *confinement); BusAppArmorConfinement* bus_apparmor_init_connection_confinement (DBusConnection *connection, DBusError *error); diff --git a/bus/driver.c b/bus/driver.c index aab922a..4dcf76c 100644 --- a/bus/driver.c +++ b/bus/driver.c @@ -1760,6 +1760,91 @@ bus_driver_handle_get_connection_credentials (DBusConnection *connection, } static dbus_bool_t +bus_driver_handle_get_connection_apparmor_security_context (DBusConnection *connection, + BusTransaction *transaction, + DBusMessage *message, + DBusError *error) +{ + const char *service; + DBusString str; + BusRegistry *registry; + BusService *serv; + DBusConnection *primary_connection; + DBusMessage *reply; + BusAppArmorConfinement *confinement; + const char *label; + + _DBUS_ASSERT_ERROR_IS_CLEAR (error); + + registry = bus_connection_get_registry (connection); + + service = NULL; + reply = NULL; + confinement = NULL; + + if (! dbus_message_get_args (message, error, DBUS_TYPE_STRING, &service, + DBUS_TYPE_INVALID)) + goto failed; + + _dbus_verbose ("asked for security context of connection %s\n", service); + + _dbus_string_init_const (&str, service); + serv = bus_registry_lookup (registry, &str); + if (serv == NULL) + { + dbus_set_error (error, + DBUS_ERROR_NAME_HAS_NO_OWNER, + "Could not get security context of name '%s': no such name", service); + goto failed; + } + + primary_connection = bus_service_get_primary_owners_connection (serv); + + reply = dbus_message_new_method_return (message); + if (reply == NULL) + goto oom; + + confinement = bus_connection_dup_apparmor_confinement (primary_connection); + label = bus_apparmor_confinement_get_label (confinement); + + if (label == NULL) + { + dbus_set_error (error, + DBUS_ERROR_APPARMOR_SECURITY_CONTEXT_UNKNOWN, + "Could not determine security context for '%s'", service); + goto failed; + } + + if (!dbus_validate_utf8 (label, error)) + goto failed; + + if (! dbus_message_append_args (reply, + DBUS_TYPE_STRING, + &label, + DBUS_TYPE_INVALID)) + goto failed; + + if (! bus_transaction_send_from_driver (transaction, connection, reply)) + goto oom; + + bus_apparmor_confinement_unref (confinement); + dbus_message_unref (reply); + + return TRUE; + + oom: + BUS_SET_OOM (error); + + failed: + _DBUS_ASSERT_ERROR_IS_SET (error); + if (confinement) + bus_apparmor_confinement_unref (confinement); + if (reply) + dbus_message_unref (reply); + return FALSE; +} + +static dbus_bool_t bus_driver_handle_reload_config (DBusConnection *connection, BusTransaction *transaction, DBusMessage *message, @@ -2115,6 +2200,10 @@ static const MessageHandler dbus_message_handlers[] = { DBUS_TYPE_STRING_AS_STRING, DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_BYTE_AS_STRING, bus_driver_handle_get_connection_selinux_security_context }, + { "GetConnectionAppArmorSecurityContext", + DBUS_TYPE_STRING_AS_STRING, + DBUS_TYPE_STRING_AS_STRING, + bus_driver_handle_get_connection_apparmor_security_context }, { "ReloadConfig", "", "", diff --git a/dbus/dbus-protocol.h b/dbus/dbus-protocol.h index 933c365..2b7fd23 100644 --- a/dbus/dbus-protocol.h +++ b/dbus/dbus-protocol.h @@ -444,6 +444,8 @@ extern "C" { #define DBUS_ERROR_INVALID_FILE_CONTENT "org.freedesktop.DBus.Error.InvalidFileContent" /** Asked for SELinux security context and it wasn't available. */ #define DBUS_ERROR_SELINUX_SECURITY_CONTEXT_UNKNOWN "org.freedesktop.DBus.Error.SELinuxSecurityContextUnknown" +/** Asked for AppArmor security context and it wasn't available. */ +#define DBUS_ERROR_APPARMOR_SECURITY_CONTEXT_UNKNOWN "org.freedesktop.DBus.Error.AppArmorSecurityContextUnknown" /** Asked for ADT audit data and it wasn't available. */ #define DBUS_ERROR_ADT_AUDIT_DATA_UNKNOWN "org.freedesktop.DBus.Error.AdtAuditDataUnknown" /** There's already an object with the requested object path. */ -- 2.1.4