]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
sd-bus: bind outgoing AF_UNIX sockets to abstract addresses conveying client comm...
authorLennart Poettering <lennart@poettering.net>
Fri, 5 May 2023 19:35:19 +0000 (21:35 +0200)
committerLennart Poettering <lennart@poettering.net>
Tue, 16 May 2023 08:17:49 +0000 (10:17 +0200)
Let's pass some additional meta information along bus connections
without actually altering the communication protocol.

Pass the client comm and client description string of the bus via
including it in the abstract namespace client socket address we connect
to. This is purely informational (and entirely user controlled), but has
the benefit that servers can make use of the information if they want,
but really don't have to. It works entirely transparently.

This takes inspiration from how we convey similar information via
credential socket connections.

src/libsystemd/sd-bus/bus-socket.c

index ceda20f289e891b2508f6fa9e999a16f48562945..11f4aa9669d4765672ac4b6a990bb93b99be8d44 100644 (file)
@@ -22,6 +22,7 @@
 #include "memory-util.h"
 #include "path-util.h"
 #include "process-util.h"
+#include "random-util.h"
 #include "signal-util.h"
 #include "stdio-util.h"
 #include "string-util.h"
@@ -889,6 +890,50 @@ fail:
         return r;
 }
 
+static int bind_description(sd_bus *b, int fd, int family) {
+        _cleanup_free_ char *bind_name = NULL, *comm = NULL;
+        union sockaddr_union bsa;
+        const char *d = NULL;
+        int r;
+
+        assert(b);
+        assert(fd >= 0);
+
+        /* If this is an AF_UNIX socket, let's set our client's socket address to carry the description
+         * string for this bus connection. This is useful for debugging things, as the connection name is
+         * visible in various socket-related tools, and can even be queried by the server side. */
+
+        if (family != AF_UNIX)
+                return 0;
+
+        (void) sd_bus_get_description(b, &d);
+
+        /* Generate a recognizable source address in the abstract namespace. We'll include:
+         * - a random 64bit value (to avoid collisions)
+         * - our "comm" process name (suppressed if contains "/" to avoid parsing issues)
+         * - the description string of the bus connection. */
+        (void) get_process_comm(0, &comm);
+        if (comm && strchr(comm, '/'))
+                comm = mfree(comm);
+
+        if (!d && !comm) /* skip if we don't have either field, rely on kernel autobind instead */
+                return 0;
+
+        if (asprintf(&bind_name, "@%" PRIx64 "/bus/%s/%s", random_u64(), strempty(comm), strempty(d)) < 0)
+                return -ENOMEM;
+
+        strshorten(bind_name, sizeof_field(struct sockaddr_un, sun_path));
+
+        r = sockaddr_un_set_path(&bsa.un, bind_name);
+        if (r < 0)
+                return r;
+
+        if (bind(fd, &bsa.sa, r) < 0)
+                return -errno;
+
+        return 0;
+}
+
 int bus_socket_connect(sd_bus *b) {
         bool inotify_done = false;
         int r;
@@ -911,6 +956,10 @@ int bus_socket_connect(sd_bus *b) {
                 if (b->input_fd < 0)
                         return -errno;
 
+                r = bind_description(b, b->input_fd, b->sockaddr.sa.sa_family);
+                if (r < 0)
+                        return r;
+
                 b->input_fd = fd_move_above_stdio(b->input_fd);
 
                 b->output_fd = b->input_fd;