GetConnectionCredentials - add smack support
authorPatrick Ohly <patrick.ohly@intel.com>
Fri, 20 Jun 2014 14:55:00 +0000 (16:55 +0200)
committerAdrian Szyndela <adrian.s@samsung.com>
Fri, 19 Feb 2016 10:09:56 +0000 (11:09 +0100)
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
bus/driver.c
bus/smack.c
dbus/Makefile.am
dbus/dbus-connection.c
dbus/dbus-connection.h
doc/dbus-specification.xml

index 4e46b0b..73ada3c 100644 (file)
@@ -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                                  \
index a6e87a0..8fe4f3f 100644 (file)
@@ -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;
 
index d4546a3..300d9da 100644 (file)
 #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;
 
index a7b3491..d54c261 100644 (file)
@@ -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
index 81b3a83..0d9b4c9 100644 (file)
 #include "dbus-bus.h"
 #include "dbus-marshal-basic.h"
 
+#ifdef DBUS_ENABLE_SMACK
+#include <sys/smack.h>
+#include <stdlib.h>
+#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.
index fe4d04e..aac5704 100644 (file)
@@ -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,
index 1e0fe20..c2d5c20 100644 (file)
                   </para>
                 </entry>
               </row>
-
+              <row>
+                <entry>SmackLabel</entry>
+                <entry>STRING</entry>
+                <entry>The Smack label of the process at the time when it connected
+                  to D-Bus, on platforms that have this concept.</entry>
+              </row>
             </tbody>
           </tgroup>
         </informaltable>