From 0a9f7b5487a60a9856cd92c0c069047ef6610276 Mon Sep 17 00:00:00 2001 From: Paul Meyer Date: Mon, 29 Jun 2026 12:21:02 +0200 Subject: [PATCH] vmspawn: allow TDX guest to connect to host QGS To query a TD quote, the TDX guest must connect to the Quote Generation Service (QGS), a SGX enclave running on the host. We check if the service is exposed via a well-known unix socket, then pass that socket or a fallback well-known vsock address to QEMU. Signed-off-by: Paul Meyer --- man/systemd-vmspawn.xml | 6 +++++- src/vmspawn/vmspawn.c | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/man/systemd-vmspawn.xml b/man/systemd-vmspawn.xml index 66c49352a9..64cfab8294 100644 --- a/man/systemd-vmspawn.xml +++ b/man/systemd-vmspawn.xml @@ -379,7 +379,11 @@ measured individually by systemd-stub into RTMR 2. For direct linux boot, firmware measures the kernel PE into RTMR 1, and the Linux EFI stub measures initrd and command line into RTMR 2. A vTPM, if attached via , must be treated - as untrusted by the guest. + as untrusted by the guest. To obtain TD Quotes for remote attestation, the guest is wired + to the host's local TDX Quote Generation Service automatically: the unix socket + up /run/tdx-qgs/qgs.socket is used if it exists, otherwise vsock port 4050 + on the host (cid 2). If the QGS is listening on neither channel, the guest's quote requests will + fail. diff --git a/src/vmspawn/vmspawn.c b/src/vmspawn/vmspawn.c index 41cf611aa9..2c35fef032 100644 --- a/src/vmspawn/vmspawn.c +++ b/src/vmspawn/vmspawn.c @@ -105,6 +105,13 @@ #define DISK_SERIAL_MAX_LEN_NVME 20 #define DISK_SERIAL_MAX_LEN_VIRTIO_BLK 20 +/* Well-known endpoints for the host's TDX Quote Generation Service (qgsd), auto-discovered so the + * guest can obtain TD Quotes. The Intel reference qgsd listens on a unix socket; the common + * deployment listens on vsock port 4050 (cid 2 = host). */ +#define TDX_QGS_UNIX_SOCKET_PATH "/run/tdx-qgs/qgs.socket" +#define TDX_QGS_VSOCK_CID "2" +#define TDX_QGS_VSOCK_PORT "4050" + /* First and one-past-last pcie.0 device-numbers used for multifunction-packed * pcie-root-ports. Sits above the auto-assigned virtio devices (0x01-0x03) and * below 0x1f, which q35 reserves for ICH9 LPC at 0x1f.0 (single-function). */ @@ -2936,6 +2943,36 @@ static int run_virtual_machine(int kvm_device_fd, int vhost_device_fd) { "qom-type", "tdx-guest"); if (r < 0) return r; + + /* The guest needs a connection to the TDX Quote Generation Service (QGS) running on + * the host to obtain TD Quotes (e.g. via the systemd-report-sign-tsm). There are two + * well-known interfaces for QGS: a well-known unix socket, or vsock port 4050. QEMU + * only connects on a GetQuote request, and pointing at an absent QGS is harmless, + * the request just fails and the guest gets no quote. */ + r = is_socket(TDX_QGS_UNIX_SOCKET_PATH); + if (r < 0) + log_debug_errno(r, "Failed to check for QGS socket '%s', falling back to vsock: %m", TDX_QGS_UNIX_SOCKET_PATH); + if (r > 0) { + r = qemu_config_key(config_file, "quote-generation-socket.type", "unix"); + if (r < 0) + return r; + r = qemu_config_key(config_file, "quote-generation-socket.path", TDX_QGS_UNIX_SOCKET_PATH); + if (r < 0) + return r; + log_debug("Using TDX Quote Generation Service at unix socket %s.", TDX_QGS_UNIX_SOCKET_PATH); + } else { + r = qemu_config_key(config_file, "quote-generation-socket.type", "vsock"); + if (r < 0) + return r; + r = qemu_config_key(config_file, "quote-generation-socket.cid", TDX_QGS_VSOCK_CID); + if (r < 0) + return r; + r = qemu_config_key(config_file, "quote-generation-socket.port", TDX_QGS_VSOCK_PORT); + if (r < 0) + return r; + log_debug("No QGS unix socket found, pointing TDX quote generation at vsock %s:%s.", + TDX_QGS_VSOCK_CID, TDX_QGS_VSOCK_PORT); + } } unsigned child_cid = arg_vsock_cid;