mirror of
https://github.com/systemd/systemd.git
synced 2026-08-11 09:36:28 +00:00
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 for83359c4da0(cherry picked from commit85afe8e82d)
This commit is contained in:
10
hwdb.d/70-vsock.hwdb
Normal file
10
hwdb.d/70-vsock.hwdb
Normal file
@@ -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
|
||||
@@ -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')
|
||||
|
||||
|
||||
@@ -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 = [
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 "-.:")
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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',
|
||||
|
||||
92
src/shared/vsock-util.c
Normal file
92
src/shared/vsock-util.c
Normal file
@@ -0,0 +1,92 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
6
src/shared/vsock-util.h
Normal file
6
src/shared/vsock-util.h
Normal file
@@ -0,0 +1,6 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
#pragma once
|
||||
|
||||
#include <linux/vm_sockets.h> /* IWYU pragma: export */
|
||||
|
||||
int vsock_get_local_cid(unsigned *ret);
|
||||
@@ -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));
|
||||
|
||||
Reference in New Issue
Block a user