]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
socket-util: make connect_unix_path() work with a NULL path
authorLennart Poettering <lennart@poettering.net>
Fri, 10 Feb 2023 15:43:58 +0000 (16:43 +0100)
committerLennart Poettering <lennart@poettering.net>
Fri, 17 Feb 2023 09:51:35 +0000 (10:51 +0100)
src/basic/socket-util.c

index d7946a3641a5b1f7e56fa6f4f69ba58e76aa0ee9..f01873e6080d37b768325f6a1d1d40bfc4b76f48 100644 (file)
@@ -1425,52 +1425,60 @@ int socket_get_mtu(int fd, int af, size_t *ret) {
         return 0;
 }
 
-int connect_unix_path(int fd, int dir_fd, const char *path) {
-        _cleanup_close_ int inode_fd = -EBADF;
+static int connect_unix_path_simple(int fd, const char *path) {
         union sockaddr_union sa = {
                 .un.sun_family = AF_UNIX,
         };
-        size_t path_len;
-        socklen_t salen;
+        size_t l;
 
         assert(fd >= 0);
-        assert(dir_fd == AT_FDCWD || dir_fd >= 0);
         assert(path);
 
+        l = strlen(path);
+        assert(l > 0);
+        assert(l < sizeof(sa.un.sun_path));
+
+        memcpy(sa.un.sun_path, path, l + 1);
+        return RET_NERRNO(connect(fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + l + 1));
+}
+
+static int connect_unix_inode(int fd, int inode_fd) {
+        assert(fd >= 0);
+        assert(inode_fd >= 0);
+
+        return connect_unix_path_simple(fd, FORMAT_PROC_FD_PATH(inode_fd));
+}
+
+int connect_unix_path(int fd, int dir_fd, const char *path) {
+        _cleanup_close_ int inode_fd = -EBADF;
+
+        assert(fd >= 0);
+        assert(dir_fd == AT_FDCWD || dir_fd >= 0);
+
         /* Connects to the specified AF_UNIX socket in the file system. Works around the 108 byte size limit
          * in sockaddr_un, by going via O_PATH if needed. This hence works for any kind of path. */
 
-        path_len = strlen(path);
+        if (!path)
+                return connect_unix_inode(fd, dir_fd); /* If no path is specified, then dir_fd refers to the socket inode to connect to. */
 
         /* Refuse zero length path early, to make sure AF_UNIX stack won't mistake this for an abstract
          * namespace path, since first char is NUL */
-        if (path_len <= 0)
+        if (isempty(path))
                 return -EINVAL;
 
-        if (dir_fd == AT_FDCWD && path_len < sizeof(sa.un.sun_path)) {
-                memcpy(sa.un.sun_path, path, path_len + 1);
-                salen = offsetof(struct sockaddr_un, sun_path) + path_len + 1;
-        } else {
-                const char *proc;
-                size_t proc_len;
-
-                /* If dir_fd is specified, then we need to go the indirect O_PATH route, because connectat()
-                 * does not exist. If the path is too long, we also need to take the indirect route, since we
-                 * can't fit this into a sockaddr_un directly. */
-
-                inode_fd = openat(dir_fd, path, O_PATH|O_CLOEXEC);
-                if (inode_fd < 0)
-                        return -errno;
+        /* Shortcut for the simple case */
+        if (dir_fd == AT_FDCWD && strlen(path) < sizeof_field(struct sockaddr_un, sun_path))
+                return connect_unix_path_simple(fd, path);
 
-                proc = FORMAT_PROC_FD_PATH(inode_fd);
-                proc_len = strlen(proc);
+        /* If dir_fd is specified, then we need to go the indirect O_PATH route, because connectat() does not
+         * exist. If the path is too long, we also need to take the indirect route, since we can't fit this
+         * into a sockaddr_un directly. */
 
-                assert(proc_len < sizeof(sa.un.sun_path));
-                memcpy(sa.un.sun_path, proc, proc_len + 1);
-                salen = offsetof(struct sockaddr_un, sun_path) + proc_len + 1;
-        }
+        inode_fd = openat(dir_fd, path, O_PATH|O_CLOEXEC);
+        if (inode_fd < 0)
+                return -errno;
 
-        return RET_NERRNO(connect(fd, &sa.sa, salen));
+        return connect_unix_inode(fd, inode_fd);
 }
 
 int socket_address_parse_unix(SocketAddress *ret_address, const char *s) {