]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
udev: Fix initializing varlink server from listen fd
authorDaan De Meyer <daan.j.demeyer@gmail.com>
Mon, 30 Jun 2025 11:06:46 +0000 (13:06 +0200)
committerDaanDeMeyer <daan.j.demeyer@gmail.com>
Thu, 3 Jul 2025 09:22:34 +0000 (11:22 +0200)
manager_listen_fds() instructs sd_listen_fds_with_names() to unset
the environment which means that when sd_varlink_server_listen_auto()
is called from manager_start_varlink_server(), when it eventually calls
sd_listen_fds_with_names() it will return zero because the environment
has already been unset in manager_listen_fds().

Fix the issue by not using sd_varlink_server_listen_auto() but instead
keeping track of the varlink socket in manager_listen_fds() and returning
it and passing it to manager_start_varlink_server().

src/udev/udev-manager.c
src/udev/udev-varlink.c
src/udev/udev-varlink.h

index 280626da9e7df298ce29af08fe89a5da24a79418..34032184c6c373cde82115af251fa8073ca57e1b 100644 (file)
@@ -1405,11 +1405,13 @@ static int manager_setup_event(Manager *manager) {
         return 0;
 }
 
-static int manager_listen_fds(Manager *manager) {
+static int manager_listen_fds(Manager *manager, int *ret_varlink_fd) {
         _cleanup_strv_free_ char **names = NULL;
+        int varlink_fd = -EBADF;
         int r;
 
         assert(manager);
+        assert(ret_varlink_fd);
 
         int n = sd_listen_fds_with_names(/* unset_environment = */ true, &names);
         if (n < 0)
@@ -1418,9 +1420,10 @@ static int manager_listen_fds(Manager *manager) {
         for (int i = 0; i < n; i++) {
                 int fd = SD_LISTEN_FDS_START + i;
 
-                if (streq(names[i], "varlink"))
-                        r = 0; /* The fd will be handled by sd_varlink_server_listen_auto(). */
-                else if (streq(names[i], "systemd-udevd-control.socket"))
+                if (streq(names[i], "varlink")) {
+                        varlink_fd = fd;
+                        r = 0;
+                } else if (streq(names[i], "systemd-udevd-control.socket"))
                         r = manager_init_ctrl(manager, fd);
                 else if (streq(names[i], "systemd-udevd-kernel.socket"))
                         r = manager_init_device_monitor(manager, fd);
@@ -1437,10 +1440,13 @@ static int manager_listen_fds(Manager *manager) {
                         close_and_notify_warn(fd, names[i]);
         }
 
+        *ret_varlink_fd = varlink_fd;
+
         return 0;
 }
 
 int manager_main(Manager *manager) {
+        _cleanup_close_ int varlink_fd = -EBADF;
         int r;
 
         assert(manager);
@@ -1458,7 +1464,7 @@ int manager_main(Manager *manager) {
         if (r < 0)
                 return r;
 
-        r = manager_listen_fds(manager);
+        r = manager_listen_fds(manager, &varlink_fd);
         if (r < 0)
                 return r;
 
@@ -1466,7 +1472,7 @@ int manager_main(Manager *manager) {
         if (r < 0)
                 return r;
 
-        r = manager_start_varlink_server(manager);
+        r = manager_start_varlink_server(manager, TAKE_FD(varlink_fd));
         if (r < 0)
                 return r;
 
index 5228d3512c9435dd0da72da680b9728ad8f488f4..9a887d9c7f25478fc7d507b9eccc2fd87d2e0a06 100644 (file)
@@ -1,5 +1,6 @@
 /* SPDX-License-Identifier: LGPL-2.1-or-later */
 
+#include "fd-util.h"
 #include "json-util.h"
 #include "log.h"
 #include "string-util.h"
@@ -165,8 +166,9 @@ static int vl_method_exit(sd_varlink *link, sd_json_variant *parameters, sd_varl
         return sd_varlink_reply(link, NULL);
 }
 
-int manager_start_varlink_server(Manager *manager) {
+int manager_start_varlink_server(Manager *manager, int fd) {
         _cleanup_(sd_varlink_server_unrefp) sd_varlink_server *v = NULL;
+        _cleanup_close_ int fd_close = fd;
         int r;
 
         assert(manager);
@@ -183,14 +185,14 @@ int manager_start_varlink_server(Manager *manager) {
         if (r < 0)
                 return log_error_errno(r, "Failed to attach Varlink connection to event loop: %m");
 
-        r = sd_varlink_server_listen_auto(v);
-        if (r < 0)
-                return log_error_errno(r, "Failed to bind to passed Varlink socket: %m");
-        if (r == 0) {
+        if (fd < 0)
                 r = sd_varlink_server_listen_address(v, UDEV_VARLINK_ADDRESS, 0600);
-                if (r < 0)
-                        return log_error_errno(r, "Failed to bind to Varlink socket: %m");
-        }
+        else
+                r = sd_varlink_server_listen_fd(v, fd);
+        if (r < 0)
+                return log_error_errno(r, "Failed to bind to Varlink socket: %m");
+
+        TAKE_FD(fd_close);
 
         r = sd_varlink_server_add_interface_many(
                         v,
index 080f7c95a7520a45ecfe43d926cfa2c192e2375e..fb14ac711dd03ab79fb9e735fb5a678d96e409f0 100644 (file)
@@ -3,5 +3,5 @@
 
 #include "udev-forward.h"
 
-int manager_start_varlink_server(Manager *manager);
+int manager_start_varlink_server(Manager *manager, int fd);
 int udev_varlink_connect(sd_varlink **ret, usec_t timeout);