From: Tyler Hicks Date: Thu, 13 Feb 2014 15:59:53 +0000 (-0600) Subject: Store AppArmor label of connecting processes X-Git-Tag: dbus-1.9.12~10 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=cd23a5df10b0465c99f91b5f9c4e160480078c1a;p=thirdparty%2Fdbus.git 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 --- diff --git a/bus/apparmor.c b/bus/apparmor.c index 3b2be3528..d22ac672e 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 66a77c0e1..861094e7e 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 57ad5c780..3fab59ff5 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 64da1292c..93f996747 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,