Skip to content

Commit 17f5942

Browse files
authored
Merge pull request #28010 from DaanDeMeyer/vsock-type
Vsock improvements
2 parents 1b6e11f + 7f78d34 commit 17f5942

File tree

2 files changed

+54
-27
lines changed

2 files changed

+54
-27
lines changed

src/basic/socket-util.c

+11-3
Original file line numberDiff line numberDiff line change
@@ -1522,13 +1522,20 @@ int socket_address_parse_vsock(SocketAddress *ret_address, const char *s) {
15221522
_cleanup_free_ char *n = NULL;
15231523
char *e, *cid_start;
15241524
unsigned port, cid;
1525-
int r;
1525+
int type, r;
15261526

15271527
assert(ret_address);
15281528
assert(s);
15291529

1530-
cid_start = startswith(s, "vsock:");
1531-
if (!cid_start)
1530+
if ((cid_start = startswith(s, "vsock:")))
1531+
type = 0;
1532+
else if ((cid_start = startswith(s, "vsock-dgram:")))
1533+
type = SOCK_DGRAM;
1534+
else if ((cid_start = startswith(s, "vsock-seqpacket:")))
1535+
type = SOCK_SEQPACKET;
1536+
else if ((cid_start = startswith(s, "vsock-stream:")))
1537+
type = SOCK_STREAM;
1538+
else
15321539
return -EPROTO;
15331540

15341541
e = strchr(cid_start, ':');
@@ -1557,6 +1564,7 @@ int socket_address_parse_vsock(SocketAddress *ret_address, const char *s) {
15571564
.svm_family = AF_VSOCK,
15581565
.svm_port = port,
15591566
},
1567+
.type = type,
15601568
.size = sizeof(struct sockaddr_vm),
15611569
};
15621570

src/libsystemd/sd-daemon/sd-daemon.c

+43-24
Original file line numberDiff line numberDiff line change
@@ -466,7 +466,8 @@ static int pid_notify_with_fds_internal(
466466
struct cmsghdr *cmsg = NULL;
467467
const char *e;
468468
bool send_ucred;
469-
int r;
469+
ssize_t n;
470+
int type, r;
470471

471472
if (!state)
472473
return -EINVAL;
@@ -491,30 +492,37 @@ static int pid_notify_with_fds_internal(
491492
if (address.sockaddr.vm.svm_family == AF_VSOCK && address.sockaddr.vm.svm_cid == VMADDR_CID_ANY)
492493
return -EINVAL;
493494

495+
type = address.type == 0 ? SOCK_DGRAM : address.type;
496+
494497
/* At the time of writing QEMU does not yet support AF_VSOCK + SOCK_DGRAM and returns
495498
* ENODEV. Fallback to SOCK_SEQPACKET in that case. */
496-
fd = socket(address.sockaddr.sa.sa_family, SOCK_DGRAM|SOCK_CLOEXEC, 0);
499+
fd = socket(address.sockaddr.sa.sa_family, type|SOCK_CLOEXEC, 0);
497500
if (fd < 0) {
498-
if (!(ERRNO_IS_NOT_SUPPORTED(errno) || errno == ENODEV) || address.sockaddr.sa.sa_family != AF_VSOCK)
499-
return log_debug_errno(errno, "Failed to open datagram notify socket to '%s': %m", e);
500-
501-
fd = socket(address.sockaddr.sa.sa_family, SOCK_SEQPACKET|SOCK_CLOEXEC, 0);
501+
if (!(ERRNO_IS_NOT_SUPPORTED(errno) || errno == ENODEV) || address.sockaddr.sa.sa_family != AF_VSOCK || address.type > 0)
502+
return log_debug_errno(errno, "Failed to open %s notify socket to '%s': %m", socket_address_type_to_string(type), e);
503+
504+
type = SOCK_SEQPACKET;
505+
fd = socket(address.sockaddr.sa.sa_family, type|SOCK_CLOEXEC, 0);
506+
if (fd < 0 && ERRNO_IS_NOT_SUPPORTED(errno)) {
507+
type = SOCK_STREAM;
508+
fd = socket(address.sockaddr.sa.sa_family, type|SOCK_CLOEXEC, 0);
509+
}
502510
if (fd < 0)
503-
return log_debug_errno(errno, "Failed to open sequential packet socket to '%s': %m", e);
511+
return log_debug_errno(errno, "Failed to open %s socket to '%s': %m", socket_address_type_to_string(type), e);
512+
}
504513

514+
if (address.sockaddr.sa.sa_family == AF_VSOCK) {
505515
r = vsock_bind_privileged_port(fd);
506516
if (r < 0 && !ERRNO_IS_PRIVILEGE(r))
507517
return log_debug_errno(r, "Failed to bind socket to privileged port: %m");
518+
}
508519

520+
if (IN_SET(type, SOCK_STREAM, SOCK_SEQPACKET)) {
509521
if (connect(fd, &address.sockaddr.sa, address.size) < 0)
510522
return log_debug_errno(errno, "Failed to connect socket to '%s': %m", e);
511523

512524
msghdr.msg_name = NULL;
513525
msghdr.msg_namelen = 0;
514-
} else if (address.sockaddr.sa.sa_family == AF_VSOCK) {
515-
r = vsock_bind_privileged_port(fd);
516-
if (r < 0 && !ERRNO_IS_PRIVILEGE(r))
517-
return log_debug_errno(r, "Failed to bind socket to privileged port: %m");
518526
}
519527

520528
(void) fd_inc_sndbuf(fd, SNDBUF_SIZE);
@@ -560,21 +568,32 @@ static int pid_notify_with_fds_internal(
560568
}
561569
}
562570

563-
/* First try with fake ucred data, as requested */
564-
if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) >= 0)
565-
return 1;
566-
567-
/* If that failed, try with our own ucred instead */
568-
if (send_ucred) {
569-
msghdr.msg_controllen -= CMSG_SPACE(sizeof(struct ucred));
570-
if (msghdr.msg_controllen == 0)
571+
do {
572+
/* First try with fake ucred data, as requested */
573+
n = sendmsg(fd, &msghdr, MSG_NOSIGNAL);
574+
if (n < 0) {
575+
if (!send_ucred)
576+
return log_debug_errno(errno, "Failed to send notify message to '%s': %m", e);
577+
578+
/* If that failed, try with our own ucred instead */
579+
msghdr.msg_controllen -= CMSG_SPACE(sizeof(struct ucred));
580+
if (msghdr.msg_controllen == 0)
581+
msghdr.msg_control = NULL;
582+
583+
n = 0;
584+
send_ucred = false;
585+
} else {
586+
/* Unless we're using SOCK_STREAM, we expect to write all the contents immediately. */
587+
if (type != SOCK_STREAM && (size_t) n < IOVEC_TOTAL_SIZE(msghdr.msg_iov, msghdr.msg_iovlen))
588+
return -EIO;
589+
590+
/* Make sure we only send fds and ucred once, even if we're using SOCK_STREAM. */
571591
msghdr.msg_control = NULL;
592+
msghdr.msg_controllen = 0;
593+
}
594+
} while (!IOVEC_INCREMENT(msghdr.msg_iov, msghdr.msg_iovlen, n));
572595

573-
if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) >= 0)
574-
return 1;
575-
}
576-
577-
return log_debug_errno(errno, "Failed to send notify message to '%s': %m", e);
596+
return 1;
578597
}
579598

580599
_public_ int sd_pid_notify_with_fds(

0 commit comments

Comments
 (0)