From 13d888ca95c75c14a4919b36cc0a15979fb1d42b Mon Sep 17 00:00:00 2001 From: Patrick Ohly Date: Fri, 20 Jun 2014 16:55:00 +0200 Subject: [PATCH] GetConnectionCredentials - add smack support A process should never change its Smack label while connected to D-Bus. If it did, we would end up with race conditions around permission checking. Therefore we can retrieve the Smack label once, when the process connects, and use that label whenever it is needed. A new public libdbus API also gets added: dbus_connection_get_smack_label() This is primarily for dbus-daemon, but may also be useful for other applications creating direct connections. Change-Id: I16ec50a031809aab879a543ec2d7effd56768bf1 --- bus/Makefile.am | 4 ++-- bus/driver.c | 10 ++++++++++ bus/smack.c | 32 +++++------------------------- dbus/Makefile.am | 9 +++++++-- dbus/dbus-connection.c | 49 +++++++++++++++++++++++++++++++++++++++++++++- dbus/dbus-connection.h | 5 +++++ doc/dbus-specification.xml | 7 ++++++- 7 files changed, 83 insertions(+), 33 deletions(-) diff --git a/bus/Makefile.am b/bus/Makefile.am index 4e46b0b..73ada3c 100644 --- a/bus/Makefile.am +++ b/bus/Makefile.am @@ -109,8 +109,8 @@ BUS_SOURCES= \ services.h \ signals.c \ signals.h \ - smack.c \ - smack.h \ + smack.c \ + smack.h \ stats.c \ stats.h \ test.c \ diff --git a/bus/driver.c b/bus/driver.c index a6e87a0..8fe4f3f 100644 --- a/bus/driver.c +++ b/bus/driver.c @@ -1964,6 +1964,16 @@ bus_driver_handle_get_connection_credentials (DBusConnection *connection, dbus_free (s); } +#ifdef DBUS_ENABLE_SMACK + { + const char *smack_label; + if (dbus_connection_get_smack_label (conn, &smack_label)) { + if (!_dbus_asv_add_string (&array_iter, "SmackLabel", smack_label)) + goto oom; + } + } +#endif + if (!_dbus_asv_close (&reply_iter, &array_iter)) goto oom; diff --git a/bus/smack.c b/bus/smack.c index d4546a3..300d9da 100644 --- a/bus/smack.c +++ b/bus/smack.c @@ -40,22 +40,6 @@ #define SMACK_READ_WRITE "RW" -#ifdef DBUS_ENABLE_SMACK -static char * -bus_smack_get_label (DBusConnection *connection) -{ - char *label; - int sock_fd; - - if (!dbus_connection_get_socket(connection, &sock_fd)) - return NULL; - - if (smack_new_label_from_socket(sock_fd, &label) < 0) - return NULL; - return label; -} -#endif - dbus_bool_t bus_smack_handle_get_connection_context (DBusConnection *connection, BusTransaction *transaction, @@ -69,7 +53,7 @@ bus_smack_handle_get_connection_context (DBusConnection *connection, BusService *service; DBusConnection *remote_connection; DBusMessage *reply = NULL; - char *label; + const char *label; _DBUS_ASSERT_ERROR_IS_CLEAR (error); @@ -99,8 +83,7 @@ bus_smack_handle_get_connection_context (DBusConnection *connection, if (reply == NULL) goto oom; - label = bus_smack_get_label (remote_connection); - if (label == NULL) + if (!dbus_connection_get_smack_label(remote_connection, &label)) { dbus_set_error (error, DBUS_ERROR_FAILED, "Failed to get the socket fd of the connection", @@ -116,7 +99,6 @@ bus_smack_handle_get_connection_context (DBusConnection *connection, goto oom; dbus_message_unref (reply); - dbus_free(label); return TRUE; @@ -127,8 +109,6 @@ err: if (reply != NULL) dbus_message_unref (reply); - dbus_free(label); - return FALSE; #else dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED, @@ -161,15 +141,15 @@ bus_smack_generate_allowed_list (DBusConnection *connection, dbus_bool_t *nomem_err) { #ifdef DBUS_ENABLE_SMACK - char *subject_label; + const char *subject_label; DBusHashIter iter; dbus_bool_t is_allowed; DBusList **allowed_list; /* the label of the subject, is the label on the new connection, either the service itself or one of its clients */ - subject_label = bus_smack_get_label (connection); - if (subject_label == NULL) + + if (!dbus_connection_get_smack_label(connection, &subject_label)) return NULL; allowed_list = dbus_new0 (DBusList*, 1); @@ -226,14 +206,12 @@ bus_smack_generate_allowed_list (DBusConnection *connection, } } - dbus_free(subject_label); return allowed_list; nomem: if (allowed_list != NULL) _dbus_list_clear (allowed_list); - dbus_free(subject_label); *nomem_err = TRUE; return NULL; diff --git a/dbus/Makefile.am b/dbus/Makefile.am index a7b3491..d54c261 100644 --- a/dbus/Makefile.am +++ b/dbus/Makefile.am @@ -6,6 +6,7 @@ AM_CPPFLAGS = \ -I$(top_srcdir) \ $(DBUS_STATIC_BUILD_CPPFLAGS) \ $(SYSTEMD_CFLAGS) \ + $(LIBSMACK_CFLAGS) \ $(VALGRIND_CFLAGS) \ -DDBUS_COMPILATION \ -DDBUS_MACHINE_UUID_FILE=\""$(localstatedir)/lib/dbus/machine-id"\" \ @@ -291,7 +292,7 @@ else SYMBOL_EXPORT_LDFLAGS= endif -libdbus_1_la_LIBADD= $(LIBDBUS_LIBS) +libdbus_1_la_LIBADD= $(LIBDBUS_LIBS) $(LIBSMACK_LIBS) libdbus_1_la_LDFLAGS = \ $(AM_LDFLAGS) \ -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) \ @@ -299,7 +300,11 @@ libdbus_1_la_LDFLAGS = \ -no-undefined \ $(NULL) -libdbus_internal_la_LIBADD=$(LIBDBUS_LIBS) libdbus-1.la +libdbus_internal_la_CPPFLAGS = \ + $(AM_CPPFLAGS) \ + -DDBUS_STATIC_BUILD \ + $(NULL) +libdbus_internal_la_LIBADD=$(LIBDBUS_LIBS) libdbus-1.la $(SYSTEMD_LIBS) $(LIBSMACK_LIBS) if DBUS_WIN # This must be a separate convenience library, otherwise libtool notices diff --git a/dbus/dbus-connection.c b/dbus/dbus-connection.c index 81b3a83..0d9b4c9 100644 --- a/dbus/dbus-connection.c +++ b/dbus/dbus-connection.c @@ -45,6 +45,11 @@ #include "dbus-bus.h" #include "dbus-marshal-basic.h" +#ifdef DBUS_ENABLE_SMACK +#include +#include +#endif + #ifdef DBUS_DISABLE_CHECKS #define TOOK_LOCK_CHECK(connection) #define RELEASING_LOCK_CHECK(connection) @@ -304,6 +309,9 @@ struct DBusConnection DBusObjectTree *objects; /**< Object path handlers registered with this connection */ char *server_guid; /**< GUID of server if we are in shared_connections, #NULL if server GUID is unknown or connection is private */ +#ifdef DBUS_ENABLE_SMACK + char *peer_smack_label; /** Smack label of the peer at the time when the connection was established. Allocated with malloc(), NULL if unknown. */ +#endif /* These two MUST be bools and not bitfields, because they are protected by a separate lock * from connection->mutex and all bitfields in a word have to be read/written together. @@ -1285,6 +1293,19 @@ _dbus_connection_new_for_transport (DBusTransport *transport) if (connection == NULL) goto error; +#ifdef DBUS_ENABLE_SMACK + /* If we cannot get the Smack label, proceed without. */ + { + DBusSocket sock_fd; + if (_dbus_transport_get_socket_fd(transport, &sock_fd)) { + char *label; + if (smack_new_label_from_socket(_dbus_socket_get_int (sock_fd), &label) >= 0) { + connection->peer_smack_label = label; + } + } + } +#endif + _dbus_rmutex_new_at_location (&connection->mutex); if (connection->mutex == NULL) goto error; @@ -2790,7 +2811,12 @@ _dbus_connection_last_unref (DBusConnection *connection) _dbus_rmutex_free_at_location (&connection->slot_mutex); _dbus_rmutex_free_at_location (&connection->mutex); - + +#ifdef DBUS_ENABLE_SMACK + if (connection->peer_smack_label) + free (connection->peer_smack_label); +#endif + dbus_free (connection); } @@ -5275,6 +5301,27 @@ dbus_connection_get_unix_process_id (DBusConnection *connection, return result; } +#ifdef DBUS_ENABLE_SMACK +/** + * Gets the Smack label of the peer at the time when the connection + * was established. Returns #TRUE if the label is filled in. + * + * @param connection the connection + * @param label return location for the Smack label; returned value is valid as long as the connection exists + * @returns #TRUE if uid is filled in with a valid process ID + */ +dbus_bool_t +dbus_connection_get_smack_label (DBusConnection *connection, + const char **label) +{ + _dbus_return_val_if_fail (connection != NULL, FALSE); + _dbus_return_val_if_fail (label != NULL, FALSE); + + *label = connection->peer_smack_label; + return *label != NULL; +} +#endif + /** * Gets the ADT audit data of the connection if any. * Returns #TRUE if the structure pointer is returned. diff --git a/dbus/dbus-connection.h b/dbus/dbus-connection.h index fe4d04e..aac5704 100644 --- a/dbus/dbus-connection.h +++ b/dbus/dbus-connection.h @@ -264,6 +264,11 @@ dbus_bool_t dbus_connection_get_unix_user (DBusConnection DBUS_EXPORT dbus_bool_t dbus_connection_get_unix_process_id (DBusConnection *connection, unsigned long *pid); +#ifdef DBUS_ENABLE_SMACK +DBUS_EXPORT +dbus_bool_t dbus_connection_get_smack_label (DBusConnection *connection, + const char **label); +#endif DBUS_EXPORT dbus_bool_t dbus_connection_get_adt_audit_session_data (DBusConnection *connection, void **data, diff --git a/doc/dbus-specification.xml b/doc/dbus-specification.xml index 1e0fe20..c2d5c20 100644 --- a/doc/dbus-specification.xml +++ b/doc/dbus-specification.xml @@ -6075,7 +6075,12 @@ - + + SmackLabel + STRING + The Smack label of the process at the time when it connected + to D-Bus, on platforms that have this concept. + -- 2.7.4