]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
socket-util: introduce socket_autobind() helper 36893/head
authorMike Yuan <me@yhndnzj.com>
Sat, 29 Mar 2025 20:33:58 +0000 (21:33 +0100)
committerMike Yuan <me@yhndnzj.com>
Mon, 31 Mar 2025 16:11:37 +0000 (18:11 +0200)
Prompted by https://github.com/systemd/systemd/pull/36858#discussion_r2017719305
and #36833

src/basic/socket-util.c
src/basic/socket-util.h
src/notify/notify.c

index c095168ed19245dedbdef6007f9f0eb00ca07866..3160f9229888014deca47253d06861b46f648135 100644 (file)
@@ -28,6 +28,7 @@
 #include "parse-util.h"
 #include "path-util.h"
 #include "process-util.h"
+#include "random-util.h"
 #include "socket-util.h"
 #include "string-table.h"
 #include "string-util.h"
@@ -1454,6 +1455,36 @@ int socket_bind_to_ifindex(int fd, int ifindex) {
         return setsockopt_int(fd, SOL_SOCKET, SO_BINDTOIFINDEX, ifindex);
 }
 
+int socket_autobind(int fd, char **ret_name) {
+        _cleanup_free_ char *name = NULL;
+        uint64_t random;
+        int r;
+
+        /* Generate a random abstract socket name and bind fd to it. This is modeled after the kernel
+         * "autobind" feature, but uses 64-bit random number internally. */
+
+        assert(fd >= 0);
+        assert(ret_name);
+
+        random = random_u64();
+
+        if (asprintf(&name, "@%" PRIu64, random) < 0)
+                return -ENOMEM;
+
+        union sockaddr_union sa;
+        assert_cc(DECIMAL_STR_MAX(uint64_t) < sizeof(sa.un.sun_path));
+
+        r = sockaddr_un_set_path(&sa.un, name);
+        if (r < 0)
+                return r;
+
+        if (bind(fd, &sa.sa, r) < 0)
+                return -errno;
+
+        *ret_name = TAKE_PTR(name);
+        return 0;
+}
+
 ssize_t recvmsg_safe(int sockfd, struct msghdr *msg, int flags) {
         ssize_t n;
 
index e21a4427f0dc1678e6a9039ae596e8c5b73f6f8f..c5e389ca3a7467666cc194a58282916c5a8e1aaf 100644 (file)
@@ -322,6 +322,8 @@ static inline int getsockopt_int(int fd, int level, int optname, int *ret) {
 int socket_bind_to_ifname(int fd, const char *ifname);
 int socket_bind_to_ifindex(int fd, int ifindex);
 
+int socket_autobind(int fd, char **ret_name);
+
 /* Define a 64-bit version of timeval/timespec in any case, even on 32-bit userspace. */
 struct timeval_large {
         uint64_t tvl_sec, tvl_usec;
index b736bf704fbff6b47407aa44eb4563474285f719..2b7f1c4177dd91951f049a97be7705c27f92a75d 100644 (file)
@@ -506,17 +506,10 @@ static int action_fork(char *const *_command) {
         if (r < 0)
                 log_debug_errno(r, "Failed to enable SO_PASSPIDFD, ignoring: %m");
 
-        /* Pick an address via auto-bind */
-        union sockaddr_union sa = {
-                .sa.sa_family = AF_UNIX,
-        };
-        if (bind(socket_fd, &sa.sa, offsetof(union sockaddr_union, un.sun_path)) < 0)
-                return log_error_errno(errno, "Failed to bind AF_UNIX socket: %m");
-
         _cleanup_free_ char *addr_string = NULL;
-        r = getsockname_pretty(socket_fd, &addr_string);
+        r = socket_autobind(socket_fd, &addr_string);
         if (r < 0)
-                return log_error_errno(r, "Failed to get socket name: %m");
+                return log_error_errno(r, "Failed to bind notify socket: %m");
 
         _cleanup_free_ char *c = strv_join(command, " ");
         if (!c)