From 5dfd796ab702d93415d311515b8a5d0128fa623a Mon Sep 17 00:00:00 2001 From: Kevin Wang Date: Tue, 1 Sep 2026 23:54:10 -0700 Subject: [PATCH] fix(os): drop guest kernel drivers no CVM can reach The guest kernels inherit a bare-metal device set from their baselines -- x86_64_defconfig for mkosi, the linux-yocto machine config for yocto -- and neither fragment says anything about it. So both images ship Broadcom, Intel 1G, Marvell, nForce and Realtek NIC drivers, PCMCIA, AGP, Macintosh platform glue and legacy NVRAM, none of which can appear in a CVM. A host that presents the matching PCI IDs can steer the guest into any of them, and the kernel config is the only device allowlist this project actually has: Intel's authorize_allow_devs filter is out-of-tree and TDX-only, while CONFIG_* is enforced at link time and applies to TDX and SEV-SNP alike. Also dropped are two early-boot debug paths and one egress channel that are harder to justify than the drivers. PROVIDE_OHCI1394_DMA_INIT exists to give a FireWire device access to memory before the kernel is up, which is the primitive an untrusted host would want rather than a feature a tenant needs; EARLY_PRINTK_DBGP is its USB debug port equivalent. NETCONSOLE ships the kernel log to a UDP peer, configurable at runtime by root. Both fragments carry the same list so the two guest kernels keep the same device policy, and both note that passing a ConnectX NIC through later means adding CONFIG_MLX5_CORE and the INFINIBAND stack, not relaxing this. Verified by running each backend's own kconfig flow against linux 6.18.39. mkosi: x86_64_defconfig, merge_config.sh, olddefconfig, then check-kernel-config.sh over the fragment -- exit 0, all sixteen symbols end up unset. yocto: bitbake -c configure virtual/kernel, same sixteen unset in the resulting .config. CONFIG_VIRTIO_NET, CONFIG_GVE, CONFIG_ENA_ETHERNET and CONFIG_DRM are unaffected in both. Note for review: os/yocto's dstack.cfg is not gated by check-kernel-config.sh today (export-artifacts.sh only gates dstack-docker.cfg, because dstack.cfg carries six lines the build does not satisfy), so the yocto half of this rests on the configure run above rather than on CI. Gating it is worth a follow-up. --- os/mkosi/components/kernel/kernel.config | 35 +++++++++++++++++++ .../recipes-kernel/linux/files/dstack.cfg | 24 +++++++++++++ 2 files changed, 59 insertions(+) diff --git a/os/mkosi/components/kernel/kernel.config b/os/mkosi/components/kernel/kernel.config index bb2740cef..56999f818 100644 --- a/os/mkosi/components/kernel/kernel.config +++ b/os/mkosi/components/kernel/kernel.config @@ -302,3 +302,38 @@ CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m # No IP6_NF_* counterpart to dstack-docker.cfg's: this image has no legacy # tables at all, so there is no legacy ip6tables to complete. The nftables # frontend synthesises the IPv6 nat table Incus lists, with no module behind it. + +# Devices that cannot exist in a CVM. x86_64_defconfig builds these for bare +# metal, but a dstack guest only ever sees virtio, plus GVE on GCP and ENA on +# AWS, both enabled above. Leaving the rest in means a host that presents the +# matching PCI IDs can steer the guest into driver code no deployment uses. +# Passing a ConnectX NIC through later is an addition here -- CONFIG_MLX5_CORE +# and the INFINIBAND stack -- not a relaxation of these. +CONFIG_TIGON3=n +CONFIG_E100=n +CONFIG_E1000=n +CONFIG_E1000E=n +CONFIG_SKY2=n +CONFIG_FORCEDETH=n +CONFIG_8139TOO=n +CONFIG_R8169=n +CONFIG_NET_TULIP=n + +# Buses and platform glue with no counterpart in a virtual machine. +CONFIG_PCCARD=n +CONFIG_AGP=n +CONFIG_MACINTOSH_DRIVERS=n +CONFIG_NVRAM=n + +# Early-boot debug paths that exist to give an external device access to memory +# before the kernel is up. PROVIDE_OHCI1394_DMA_INIT enables FireWire DMA +# specifically so a machine can be debugged over the bus, which is the same +# primitive an untrusted host would want; EARLY_PRINTK_DBGP is the USB debug +# port equivalent. Neither is reachable from anything a tenant needs. +CONFIG_PROVIDE_OHCI1394_DMA_INIT=n +CONFIG_EARLY_PRINTK_DBGP=n + +# NETCONSOLE ships the kernel log to a UDP peer. Inside a CVM that is an +# egress channel for whatever the log happens to contain, configurable at +# runtime by root, and nothing in the image uses it. +CONFIG_NETCONSOLE=n diff --git a/os/yocto/layers/meta-dstack/recipes-kernel/linux/files/dstack.cfg b/os/yocto/layers/meta-dstack/recipes-kernel/linux/files/dstack.cfg index 7d5547101..81ee54d79 100644 --- a/os/yocto/layers/meta-dstack/recipes-kernel/linux/files/dstack.cfg +++ b/os/yocto/layers/meta-dstack/recipes-kernel/linux/files/dstack.cfg @@ -103,3 +103,27 @@ CONFIG_FUSE_FS=y CONFIG_CUSE=y CONFIG_TCG_TPM=y CONFIG_TCG_VTPM_PROXY=y + +# Devices that cannot exist in a CVM. The linux-yocto baseline builds these for +# bare metal, but a dstack guest only ever sees virtio, plus gVNIC on GCP and +# ENA on AWS. Leaving them in means a host that presents the matching PCI IDs +# can steer the guest into driver code no deployment uses. Kept in step with +# os/mkosi/components/kernel/kernel.config so both guest kernels carry the same +# device policy. Passing a ConnectX NIC through later is an addition here -- +# CONFIG_MLX5_CORE and the INFINIBAND stack -- not a relaxation of these. +CONFIG_TIGON3=n +CONFIG_E100=n +CONFIG_E1000=n +CONFIG_E1000E=n +CONFIG_SKY2=n +CONFIG_FORCEDETH=n +CONFIG_8139TOO=n +CONFIG_R8169=n +CONFIG_NET_TULIP=n +CONFIG_PCCARD=n +CONFIG_AGP=n +CONFIG_MACINTOSH_DRIVERS=n +CONFIG_NVRAM=n +CONFIG_PROVIDE_OHCI1394_DMA_INIT=n +CONFIG_EARLY_PRINTK_DBGP=n +CONFIG_NETCONSOLE=n