From: Daan De Meyer Date: Tue, 13 Jun 2023 08:26:00 +0000 (+0200) Subject: sd-daemon: Add vsock fallback to SOCK_STREAM X-Git-Tag: v254-rc1~223^2 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=refs%2Fpull%2F28010%2Fhead;p=thirdparty%2Fsystemd.git sd-daemon: Add vsock fallback to SOCK_STREAM SOCK_SEQPACKET is only supported on recent kernels. Let's add a fallback to SOCK_STREAM if it is not supported. To accomodate SOCK_STREAM, we also modify pid_notify_with_fds_internal() to do sendmsg() in a loop as with SOCK_STREAM, sendmsg() is not guaranteed to write all data in a single syscall or fail otherwise. --- diff --git a/src/libsystemd/sd-daemon/sd-daemon.c b/src/libsystemd/sd-daemon/sd-daemon.c index 7d31ae89ceb..5711e5e18a4 100644 --- a/src/libsystemd/sd-daemon/sd-daemon.c +++ b/src/libsystemd/sd-daemon/sd-daemon.c @@ -466,6 +466,7 @@ static int pid_notify_with_fds_internal( struct cmsghdr *cmsg = NULL; const char *e; bool send_ucred; + ssize_t n; int type, r; if (!state) @@ -502,6 +503,10 @@ static int pid_notify_with_fds_internal( type = SOCK_SEQPACKET; fd = socket(address.sockaddr.sa.sa_family, type|SOCK_CLOEXEC, 0); + if (fd < 0 && ERRNO_IS_NOT_SUPPORTED(errno)) { + type = SOCK_STREAM; + fd = socket(address.sockaddr.sa.sa_family, type|SOCK_CLOEXEC, 0); + } if (fd < 0) return log_debug_errno(errno, "Failed to open %s socket to '%s': %m", socket_address_type_to_string(type), e); } @@ -563,21 +568,32 @@ static int pid_notify_with_fds_internal( } } - /* First try with fake ucred data, as requested */ - if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) >= 0) - return 1; - - /* If that failed, try with our own ucred instead */ - if (send_ucred) { - msghdr.msg_controllen -= CMSG_SPACE(sizeof(struct ucred)); - if (msghdr.msg_controllen == 0) + do { + /* First try with fake ucred data, as requested */ + n = sendmsg(fd, &msghdr, MSG_NOSIGNAL); + if (n < 0) { + if (!send_ucred) + return log_debug_errno(errno, "Failed to send notify message to '%s': %m", e); + + /* If that failed, try with our own ucred instead */ + msghdr.msg_controllen -= CMSG_SPACE(sizeof(struct ucred)); + if (msghdr.msg_controllen == 0) + msghdr.msg_control = NULL; + + n = 0; + send_ucred = false; + } else { + /* Unless we're using SOCK_STREAM, we expect to write all the contents immediately. */ + if (type != SOCK_STREAM && (size_t) n < IOVEC_TOTAL_SIZE(msghdr.msg_iov, msghdr.msg_iovlen)) + return -EIO; + + /* Make sure we only send fds and ucred once, even if we're using SOCK_STREAM. */ msghdr.msg_control = NULL; + msghdr.msg_controllen = 0; + } + } while (!IOVEC_INCREMENT(msghdr.msg_iov, msghdr.msg_iovlen, n)); - if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) >= 0) - return 1; - } - - return log_debug_errno(errno, "Failed to send notify message to '%s': %m", e); + return 1; } _public_ int sd_pid_notify_with_fds(