-
Notifications
You must be signed in to change notification settings - Fork 152
Description
Solo5 does not change the CPU features exposed to the guest, so the guest gets almost the equivalent of qemu -cpu host
, which exposes a much larger attack surface than necessary.
This has the following features typically available, which are not actually used by unikernels:
-
SVM/VMX for nested virtualization. In the past the Linux kernel had a bug in the SVM implementation which allowed a guest to host escape, see https://googleprojectzero.blogspot.com/2021/06/an-epyc-escape-case-study-of-kvm.html for details. If further bugs like that are found those would be a bug in Linux, and not Solo5. Nevertheless forbidding SVM/VMX just completely eliminates this class of vulnerabilities.
-
AMD SEV might be available due to SVM being available. If SVM is unavailable then this would not be usable either form unikernels.
-
SKINIT/SGX: I have not confirmed that these would actually be usable, but again this seems like unnecessarily larger attack surface
Nested virtualization means that actions of the guest launched by solo5-hvt
could get interpreted by the host Linux kernel, and if it doesn't appropriately filter out unsafe instructions/MSRs/etc. then the nested guest could execute actions on the host, as was the case in the blogpost linked above.
In general new CPUs may get new CPUID features, so the safest approach would be a whitelist option: only expose additional CPUID bits once these are known to be useful for unikernels (e.g. typical "userspace" CPUID flags for SIMD instructions are probably useful, new privileged instructions are probably not useful, unless Solo5 actually wants to use them).
OTOH new CPUID features also get added by microcode updates for speculative attack mitigations, and it'd be desirable for guests to be able to use them as soon as they are available on the host.
For now IMHO the simplest approach would be to query KVM_GET_SUPPORTED_CPUID, and mask out anything related to nested virtualization to reduce the attack surface, and then use KVM_SET_CPUID2. For backwards compatibility a CLI flag to expose the full CPU features might be useful.
Note: this is x86-64 specific, I don't know what the situation is on other architectures, and what'd be required there to reduce the attack surface.