]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/libsystemd/sd-bus/sd-bus.c
Merge pull request #1162 from dvdhrm/bus-recursive-nodes
[thirdparty/systemd.git] / src / libsystemd / sd-bus / sd-bus.c
index 5434d62af5821249fe81f1e5f7de8f345c641be8..4a9181613a6b0f69294102bff69efa9af4443c11 100644 (file)
@@ -1002,6 +1002,8 @@ static int bus_parse_next_address(sd_bus *b) {
 }
 
 static int bus_start_address(sd_bus *b) {
+        bool container_kdbus_available = false;
+        bool kdbus_available = false;
         int r;
 
         assert(b);
@@ -1011,17 +1013,42 @@ static int bus_start_address(sd_bus *b) {
 
                 bus_close_fds(b);
 
+                /*
+                 * Usually, if you provide multiple different bus-addresses, we
+                 * try all of them in order. We use the first one that
+                 * succeeds. However, if you mix kernel and unix addresses, we
+                 * never try unix-addresses if a previous kernel address was
+                 * tried and kdbus was available. This is required to prevent
+                 * clients to fallback to the bus-proxy if kdbus is available
+                 * but failed (eg., too many connections).
+                 */
+
                 if (b->exec_path)
                         r = bus_socket_exec(b);
-                else if ((b->nspid > 0 || b->machine) && b->kernel)
+
+                else if ((b->nspid > 0 || b->machine) && b->kernel) {
                         r = bus_container_connect_kernel(b);
-                else if ((b->nspid > 0 || b->machine) && b->sockaddr.sa.sa_family != AF_UNSPEC)
-                        r = bus_container_connect_socket(b);
-                else if (b->kernel)
+                        if (r < 0 && !IN_SET(r, -ENOENT, -ESOCKTNOSUPPORT))
+                                container_kdbus_available = true;
+
+                } else if ((b->nspid > 0 || b->machine) && b->sockaddr.sa.sa_family != AF_UNSPEC) {
+                        if (!container_kdbus_available)
+                                r = bus_container_connect_socket(b);
+                        else
+                                skipped = true;
+
+                } else if (b->kernel) {
                         r = bus_kernel_connect(b);
-                else if (b->sockaddr.sa.sa_family != AF_UNSPEC)
-                        r = bus_socket_connect(b);
-                else
+                        if (r < 0 && !IN_SET(r, -ENOENT, -ESOCKTNOSUPPORT))
+                                kdbus_available = true;
+
+                } else if (b->sockaddr.sa.sa_family != AF_UNSPEC) {
+                        if (!kdbus_available)
+                                r = bus_socket_connect(b);
+                        else
+                                skipped = true;
+
+                } else
                         skipped = true;
 
                 if (!skipped) {
@@ -1214,6 +1241,8 @@ fail:
 
 int bus_set_address_user(sd_bus *b) {
         const char *e;
+        uid_t uid;
+        int r;
 
         assert(b);
 
@@ -1221,6 +1250,10 @@ int bus_set_address_user(sd_bus *b) {
         if (e)
                 return sd_bus_set_address(b, e);
 
+        r = cg_pid_get_owner_uid(0, &uid);
+        if (r < 0)
+                uid = getuid();
+
         e = secure_getenv("XDG_RUNTIME_DIR");
         if (e) {
                 _cleanup_free_ char *ee = NULL;
@@ -1229,9 +1262,9 @@ int bus_set_address_user(sd_bus *b) {
                 if (!ee)
                         return -ENOMEM;
 
-                (void) asprintf(&b->address, KERNEL_USER_BUS_ADDRESS_FMT ";" UNIX_USER_BUS_ADDRESS_FMT, getuid(), ee);
+                (void) asprintf(&b->address, KERNEL_USER_BUS_ADDRESS_FMT ";" UNIX_USER_BUS_ADDRESS_FMT, uid, ee);
         } else
-                (void) asprintf(&b->address, KERNEL_USER_BUS_ADDRESS_FMT, getuid());
+                (void) asprintf(&b->address, KERNEL_USER_BUS_ADDRESS_FMT, uid);
 
         if (!b->address)
                 return -ENOMEM;