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 9ba73b21d63..a5553b49d6c 100644 --- a/hwdb.d/meson.build +++ b/hwdb.d/meson.build @@ -40,6 +40,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 eab09786b67..12761722021 100644 --- a/src/basic/socket-util.c +++ b/src/basic/socket-util.c @@ -1779,30 +1779,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 78b948ad461..9b9a2595b5a 100644 --- a/src/basic/socket-util.h +++ b/src/basic/socket-util.h @@ -263,8 +263,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 04c72e8137b..df48644d439 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" @@ -48,6 +47,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 7c1f57baac3..05c43cc5312 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 bbc03079993..45f2bc3288e 100644 --- a/src/shared/meson.build +++ b/src/shared/meson.build @@ -237,6 +237,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));