From cd23a5df10b0465c99f91b5f9c4e160480078c1a Mon Sep 17 00:00:00 2001 From: Tyler Hicks Date: Thu, 13 Feb 2014 09:59:53 -0600 Subject: [PATCH 07/14] Store AppArmor label of connecting processes When processes connect the bus, the AppArmor confinement context should be stored for later use when checks are to be done during message sending/receiving, acquire a name, and eavesdropping. Code outside of apparmor.c will need to initialize and unreference the confinement context, so bus_apparmor_confinement_unref() can no longer be a static function. [Move bus_apparmor_confinement_unref back to its old location for a more reasonable diff -smcv] Bug: https://bugs.freedesktop.org/show_bug.cgi?id=75113 Reviewed-by: Simon McVittie --- bus/apparmor.c | 54 +++++++++++++++++++++++++++++++++++++++++++++++++++--- bus/apparmor.h | 5 +++++ bus/bus.h | 1 + bus/connection.c | 22 ++++++++++++++++++++++ 4 files changed, 79 insertions(+), 3 deletions(-) diff --git a/bus/apparmor.c b/bus/apparmor.c index 3b2be35..d22ac67 100644 --- a/bus/apparmor.c +++ b/bus/apparmor.c @@ -48,6 +48,8 @@ #include #endif /* HAVE_LIBAUDIT */ +#include "utils.h" + /* Store the value telling us if AppArmor D-Bus mediation is enabled. */ static dbus_bool_t apparmor_enabled = FALSE; @@ -72,8 +74,6 @@ struct BusAppArmorConfinement const char *mode; /* AppArmor confinement mode (freed by freeing *context) */ }; -typedef struct BusAppArmorConfinement BusAppArmorConfinement; - static BusAppArmorConfinement *bus_con = NULL; /** @@ -103,9 +103,10 @@ bus_apparmor_confinement_new (char *context, const char *mode) return confinement; } -static void +void bus_apparmor_confinement_unref (BusAppArmorConfinement *confinement) { +#ifdef HAVE_APPARMOR if (!apparmor_enabled) return; @@ -123,6 +124,7 @@ bus_apparmor_confinement_unref (BusAppArmorConfinement *confinement) free (confinement->context); dbus_free (confinement); } +#endif } void @@ -339,3 +341,49 @@ bus_apparmor_enabled (void) return FALSE; #endif } + +BusAppArmorConfinement* +bus_apparmor_init_connection_confinement (DBusConnection *connection, + DBusError *error) +{ +#ifdef HAVE_APPARMOR + BusAppArmorConfinement *confinement; + char *context, *mode; + int fd; + + if (!apparmor_enabled) + return NULL; + + _dbus_assert (connection != NULL); + + if (!dbus_connection_get_socket (connection, &fd)) + { + dbus_set_error (error, DBUS_ERROR_FAILED, + "Failed to get socket file descriptor of connection"); + return NULL; + } + + if (aa_getpeercon (fd, &context, &mode) == -1) + { + if (errno == ENOMEM) + BUS_SET_OOM (error); + else + dbus_set_error (error, _dbus_error_from_errno (errno), + "Failed to get AppArmor confinement information of socket peer: %s", + _dbus_strerror (errno)); + return NULL; + } + + confinement = bus_apparmor_confinement_new (context, mode); + if (confinement == NULL) + { + BUS_SET_OOM (error); + free (context); + return NULL; + } + + return confinement; +#else + return NULL; +#endif /* HAVE_APPARMOR */ +} diff --git a/bus/apparmor.h b/bus/apparmor.h index 66a77c0..861094e 100644 --- a/bus/apparmor.h +++ b/bus/apparmor.h @@ -27,6 +27,7 @@ #define BUS_APPARMOR_H #include +#include "bus.h" void bus_apparmor_audit_init (void); dbus_bool_t bus_apparmor_pre_init (void); @@ -36,4 +37,8 @@ dbus_bool_t bus_apparmor_full_init (DBusError *error); void bus_apparmor_shutdown (void); dbus_bool_t bus_apparmor_enabled (void); +void bus_apparmor_confinement_unref (BusAppArmorConfinement *confinement); +BusAppArmorConfinement* bus_apparmor_init_connection_confinement (DBusConnection *connection, + DBusError *error); + #endif /* BUS_APPARMOR_H */ diff --git a/bus/bus.h b/bus/bus.h index 57ad5c7..3fab59f 100644 --- a/bus/bus.h +++ b/bus/bus.h @@ -38,6 +38,7 @@ typedef struct BusClientPolicy BusClientPolicy; typedef struct BusPolicyRule BusPolicyRule; typedef struct BusRegistry BusRegistry; typedef struct BusSELinuxID BusSELinuxID; +typedef struct BusAppArmorConfinement BusAppArmorConfinement; typedef struct BusService BusService; typedef struct BusOwner BusOwner; typedef struct BusTransaction BusTransaction; diff --git a/bus/connection.c b/bus/connection.c index 64da129..93f9967 100644 --- a/bus/connection.c +++ b/bus/connection.c @@ -30,6 +30,7 @@ #include "signals.h" #include "expirelist.h" #include "selinux.h" +#include "apparmor.h" #include #include #include @@ -99,6 +100,7 @@ typedef struct char *cached_loginfo_string; BusSELinuxID *selinux_id; + BusAppArmorConfinement *apparmor_confinement; long connection_tv_sec; /**< Time when we connected (seconds component) */ long connection_tv_usec; /**< Time when we connected (microsec component) */ @@ -439,6 +441,9 @@ free_connection_data (void *data) if (d->selinux_id) bus_selinux_id_unref (d->selinux_id); + + if (d->apparmor_confinement) + bus_apparmor_confinement_unref (d->apparmor_confinement); dbus_free (d->cached_loginfo_string); @@ -714,6 +719,19 @@ bus_connections_setup_connection (BusConnections *connections, goto out; } + d->apparmor_confinement = bus_apparmor_init_connection_confinement (connection, + &error); + if (dbus_error_is_set (&error)) + { + /* This is a bit bogus because we pretend all errors + * are OOM; this is done because we know that in bus.c + * an OOM error disconnects the connection, which is + * the same thing we want on any other error. + */ + dbus_error_free (&error); + goto out; + } + if (!dbus_connection_set_watch_functions (connection, add_connection_watch, remove_connection_watch, @@ -801,6 +819,10 @@ bus_connections_setup_connection (BusConnections *connections, if (d->selinux_id) bus_selinux_id_unref (d->selinux_id); d->selinux_id = NULL; + + if (d->apparmor_confinement) + bus_apparmor_confinement_unref (d->apparmor_confinement); + d->apparmor_confinement = NULL; if (!dbus_connection_set_watch_functions (connection, NULL, NULL, NULL, -- 2.1.4