From: Chitoku Date: Wed, 10 Jun 2026 15:06:33 +0000 (+0900) Subject: vsock-util: allow VMADDR_CID_ANY as local CID if enabled in hwdb X-Git-Tag: v261-rc4~36 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=85afe8e82d8be44d2dafb2b7cfd243954d346c5a;p=thirdparty%2Fsystemd.git vsock-util: allow VMADDR_CID_ANY as local CID if enabled in hwdb On Hyper-V guests, `VMADDR_CID_ANY` is valid as per implementation in kernel driver: net/vmw_vsock/hyperv_transport.c. Fixes https://github.com/systemd/systemd/issues/42496 Follow-up for 83359c4da02a82d2972cf957d9855ea957359287 --- diff --git a/hwdb.d/70-vsock.hwdb b/hwdb.d/70-vsock.hwdb new file mode 100644 index 00000000000..ca2b8e559bc --- /dev/null +++ b/hwdb.d/70-vsock.hwdb @@ -0,0 +1,10 @@ +# This file is part of systemd. +# +# Database for AF_VSOCK driver implementations. +# +# Permitted keys: +# Specify if the driver uses VMADDR_CID_ANY as the local CID. +# VSOCK_ACCEPT_VMADDR_CID_ANY=1|0 + +dmi:bvnMicrosoftCorporation:*:pvrHyper-V* + VSOCK_ACCEPT_VMADDR_CID_ANY=1 diff --git a/hwdb.d/meson.build b/hwdb.d/meson.build index 3299eaf8a75..2c0fc6839da 100644 --- a/hwdb.d/meson.build +++ b/hwdb.d/meson.build @@ -41,6 +41,7 @@ hwdb_files_test = files( '70-software-radio.hwdb', '70-sound-card.hwdb', '70-touchpad.hwdb', + '70-vsock.hwdb', '80-ieee1394-unit-function.hwdb', '82-net-auto-link-local.hwdb') diff --git a/hwdb.d/parse_hwdb.py b/hwdb.d/parse_hwdb.py index 5b9d528119f..fc4b93e510b 100755 --- a/hwdb.d/parse_hwdb.py +++ b/hwdb.d/parse_hwdb.py @@ -260,6 +260,7 @@ def property_grammar(): ('IMDS_KEY_USERDATA', name_literal), ('IMDS_KEY_USERDATA_BASE', name_literal), ('IMDS_KEY_USERDATA_BASE64', name_literal), + ('VSOCK_ACCEPT_VMADDR_CID_ANY', zero_one), ) fixed_props = [Literal(name)('NAME') - Suppress('=') - val('VALUE') for name, val in props] kbd_props = [ diff --git a/src/basic/socket-util.c b/src/basic/socket-util.c index c48ffbc3d0e..614f762b57d 100644 --- a/src/basic/socket-util.c +++ b/src/basic/socket-util.c @@ -1798,30 +1798,6 @@ int socket_address_parse_vsock(SocketAddress *ret_address, const char *s) { return 0; } -int vsock_get_local_cid(unsigned *ret) { - _cleanup_close_ int vsock_fd = -EBADF; - - vsock_fd = open("/dev/vsock", O_RDONLY|O_CLOEXEC); - if (vsock_fd < 0) - return log_debug_errno(errno, "Failed to open %s: %m", "/dev/vsock"); - - unsigned tmp; - if (ioctl(vsock_fd, IOCTL_VM_SOCKETS_GET_LOCAL_CID, &tmp) < 0) - return log_debug_errno(errno, "Failed to query local AF_VSOCK CID: %m"); - log_debug("Local AF_VSOCK CID: %u", tmp); - - /* If ret == NULL, we're just want to check if AF_VSOCK is available, so accept - * any address. Otherwise, filter out special addresses that are cannot be used - * to identify _this_ machine from the outside. */ - if (ret && IN_SET(tmp, VMADDR_CID_LOCAL, VMADDR_CID_HOST, VMADDR_CID_ANY)) - return log_debug_errno(SYNTHETIC_ERRNO(EADDRNOTAVAIL), - "IOCTL_VM_SOCKETS_GET_LOCAL_CID returned special value (%u), ignoring.", tmp); - - if (ret) - *ret = tmp; - return 0; -} - int netlink_socket_get_multicast_groups(int fd, size_t *ret_len, uint32_t **ret_groups) { _cleanup_free_ uint32_t *groups = NULL; socklen_t len = 0, old_len; diff --git a/src/basic/socket-util.h b/src/basic/socket-util.h index 1703a518e48..b3a2733b74a 100644 --- a/src/basic/socket-util.h +++ b/src/basic/socket-util.h @@ -261,8 +261,6 @@ int socket_address_equal_unix(const char *a, const char *b); * authoritative. */ #define SOMAXCONN_DELUXE INT_MAX -int vsock_get_local_cid(unsigned *ret); - int netlink_socket_get_multicast_groups(int fd, size_t *ret_len, uint32_t **ret_groups); int socket_get_cookie(int fd, uint64_t *ret); diff --git a/src/hostname/hostnamed.c b/src/hostname/hostnamed.c index a39bf5a57ea..73c0f2e8efe 100644 --- a/src/hostname/hostnamed.c +++ b/src/hostname/hostnamed.c @@ -38,7 +38,6 @@ #include "parse-util.h" #include "path-util.h" #include "service-util.h" -#include "socket-util.h" #include "stat-util.h" #include "string-util.h" #include "strv.h" @@ -47,6 +46,7 @@ #include "varlink-io.systemd.service.h" #include "varlink-util.h" #include "virt.h" +#include "vsock-util.h" #define VALID_DEPLOYMENT_CHARS (ALPHANUMERICAL "-.:") diff --git a/src/machine/machined.c b/src/machine/machined.c index c419571deed..954e2606921 100644 --- a/src/machine/machined.c +++ b/src/machine/machined.c @@ -32,9 +32,9 @@ #include "service-util.h" #include "set.h" #include "signal-util.h" -#include "socket-util.h" #include "special.h" #include "string-util.h" +#include "vsock-util.h" static Manager* manager_unref(Manager *m); DEFINE_TRIVIAL_CLEANUP_FUNC(Manager*, manager_unref); diff --git a/src/shared/meson.build b/src/shared/meson.build index 82072b06b64..9359b4fee0e 100644 --- a/src/shared/meson.build +++ b/src/shared/meson.build @@ -261,6 +261,7 @@ shared_sources = files( 'vlan-util.c', 'volatile-util.c', 'vpick.c', + 'vsock-util.c', 'wall.c', 'watchdog.c', 'web-util.c', diff --git a/src/shared/vsock-util.c b/src/shared/vsock-util.c new file mode 100644 index 00000000000..1fd05903fa6 --- /dev/null +++ b/src/shared/vsock-util.c @@ -0,0 +1,92 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ + +#include +#include + +#include "sd-hwdb.h" + +#include "fd-util.h" +#include "fileio.h" +#include "log.h" +#include "parse-util.h" +#include "string-util.h" +#include "vsock-util.h" + +static int smbios_get_modalias(char **ret) { + int r; + + assert(ret); + + _cleanup_free_ char *modalias = NULL; + r = read_virtual_file("/sys/devices/virtual/dmi/id/modalias", SIZE_MAX, &modalias, /* ret_size= */ NULL); + if (r < 0) + return r; + + truncate_nl(modalias); + + *ret = TAKE_PTR(modalias); + return 0; +} + +static int smbios_get_accepts_any(void) { + static int accepts_any = -1; + int r; + + if (accepts_any >= 0) + return accepts_any; + + _cleanup_free_ char *modalias = NULL; + r = smbios_get_modalias(&modalias); + if (r == -ENOENT) + return (accepts_any = false); + if (r < 0) + return log_debug_errno(r, "Failed to read DMI modalias: %m"); + + _cleanup_(sd_hwdb_unrefp) sd_hwdb *hwdb = NULL; + r = sd_hwdb_new(&hwdb); + if (r < 0) + return log_debug_errno(r, "Failed to open hwdb: %m"); + + const char *value; + r = sd_hwdb_get(hwdb, modalias, "VSOCK_ACCEPT_VMADDR_CID_ANY", &value); + if (r < 0) { + if (r != -ENOENT) + log_debug_errno(r, "Failed to get VSOCK_ACCEPT_VMADDR_CID_ANY, ignoring: %m"); + return (accepts_any = false); + } + log_debug("VSOCK_ACCEPT_VMADDR_CID_ANY: %s", value); + + r = parse_boolean(value); + if (r < 0) { + log_debug_errno(r, "Failed to parse VSOCK_ACCEPT_VMADDR_CID_ANY, ignoring: %m"); + return (accepts_any = false); + } + + return (accepts_any = r); +} + +int vsock_get_local_cid(unsigned *ret) { + _cleanup_close_ int vsock_fd = -EBADF; + + vsock_fd = open("/dev/vsock", O_RDONLY|O_CLOEXEC); + if (vsock_fd < 0) + return log_debug_errno(errno, "Failed to open %s: %m", "/dev/vsock"); + + unsigned tmp; + if (ioctl(vsock_fd, IOCTL_VM_SOCKETS_GET_LOCAL_CID, &tmp) < 0) + return log_debug_errno(errno, "Failed to query local AF_VSOCK CID: %m"); + log_debug("Local AF_VSOCK CID: %u", tmp); + + /* If ret == NULL, we just want to check if AF_VSOCK is available, so accept any + * address. Otherwise, filter out special addresses that cannot be used to identify + * _this_ machine from the outside. */ + if (ret && + (IN_SET(tmp, VMADDR_CID_LOCAL, VMADDR_CID_HOST) || + (tmp == VMADDR_CID_ANY && smbios_get_accepts_any() <= 0))) + return log_debug_errno(SYNTHETIC_ERRNO(EADDRNOTAVAIL), + "IOCTL_VM_SOCKETS_GET_LOCAL_CID returned special value (%u), ignoring.", tmp); + + if (ret) + *ret = tmp; + return 0; +} diff --git a/src/shared/vsock-util.h b/src/shared/vsock-util.h new file mode 100644 index 00000000000..77332964a0d --- /dev/null +++ b/src/shared/vsock-util.h @@ -0,0 +1,6 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +#pragma once + +#include /* IWYU pragma: export */ + +int vsock_get_local_cid(unsigned *ret); diff --git a/src/ssh-generator/ssh-util.c b/src/ssh-generator/ssh-util.c index b7af0454870..a3863b2805e 100644 --- a/src/ssh-generator/ssh-util.c +++ b/src/ssh-generator/ssh-util.c @@ -5,8 +5,8 @@ #include "errno-util.h" #include "log.h" -#include "socket-util.h" #include "ssh-util.h" +#include "vsock-util.h" int vsock_open_or_warn(int *ret) { int fd = RET_NERRNO(socket(AF_VSOCK, SOCK_STREAM|SOCK_CLOEXEC, 0));