From: Sriram Nambakam <snambakam@linux.microsoft.com>
To: kvm@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Subject: [RFC PATCH v1 35/42] KVM: x86: deny normal-plane access to secure-plane memory
Date: Wed, 5 Aug 2026 04:03:17 -0700 [thread overview]
Message-ID: <20260805110324.25067-36-snambakam@linux.microsoft.com> (raw)
In-Reply-To: <20260805110324.25067-1-snambakam@linux.microsoft.com>
VM planes share one guest physical address space (one set of memslots),
so today the normal plane (plane 0) can read the secure plane's RAM.
Add per-plane access control so a higher-privilege plane can hide its
memory from a lower one:
- Encode the plane into union kvm_mmu_page_role (the previously spare
4 bits) so each plane gets its own TDP/EPT root instead of sharing
one set of page tables.
- Give each struct kvm_plane its own access_attr_array (xarray),
independent of kvm->mem_attr_array, to avoid coupling with the
private/CoCo memory-attribute machinery.
- Add KVM_MEMORY_ATTRIBUTE_NO_READ. NO_READ cannot be expressed as a
present-but-unreadable EPT entry on all hardware, so it is enforced
in the fault path: kvm_mmu_faultin_pfn() refuses to map a NO_READ
gfn (and a write to a NO_WRITE gfn) for the faulting plane and exits
with KVM_EXIT_MEMORY_FAULT instead of building an SPTE the access
would immediately re-fault on. NO_WRITE/NO_EXEC continue to be
stripped in kvm_plane_filter_pte_access().
- KVM_HC_VBS_SET_MEM_ATTRS lets a plane >0 apply NO_READ/NO_WRITE/
NO_EXEC to the plane directly below it (the secure plane cannot issue
the host KVM_SET_MEMORY_ATTRIBUTES ioctl). a2 is an allow-mask:
bit0 read, bit1 write, bit2 exec; a cleared bit adds the matching
restriction, a2 == 0 hides the range entirely.
drivers/virt/secure_monitor.c uses this to seal the secure plane's own
RAM (walk_system_ram_range -> SET_MEM_ATTRS with perms 0) from the
normal plane before handing control back, so plane 0 can no longer read
plane 1.
---
drivers/virt/secure_monitor.c | 79 +++++++++++++++++++++++++++++++++--
1 file changed, 76 insertions(+), 3 deletions(-)
diff --git a/drivers/virt/secure_monitor.c b/drivers/virt/secure_monitor.c
index 2d181c32c439..028ae222037a 100644
--- a/drivers/virt/secure_monitor.c
+++ b/drivers/virt/secure_monitor.c
@@ -25,11 +25,15 @@
* Because all planes of a VM share the same memslots (struct kvm_plane has no
* memslots of its own; they live in struct kvm), the secure plane sees the
* same guest-physical address space as the normal plane and can read the
- * calling area and the GPAs referenced by each request directly.
+ * calling area and the GPAs referenced by each request directly. This same
+ * sharing means the secure plane must explicitly hide its own RAM from the
+ * normal plane: on startup it walks its system RAM and asks KVM (via
+ * KVM_HC_VBS_SET_MEM_ATTRS) to deny the normal plane read/write/exec access,
+ * so plane 0 cannot read secure-plane memory.
*
* For now every VTL call is acknowledged as a no-op so the normal plane can
- * make progress; the real per-call handlers (self-protection, HEKI memory
- * protection, kernel sealing, …) are plumbed in incrementally.
+ * make progress; the remaining per-call handlers (HEKI memory protection,
+ * kernel sealing, …) are plumbed in incrementally.
*
* Activated by the "secure_monitor" kernel command-line option; without it
* this kernel boots normally and never parks.
@@ -41,10 +45,13 @@
#include <linux/init.h>
#include <linux/kthread.h>
#include <linux/io.h>
+#include <linux/ioport.h>
+#include <linux/memblock.h>
#include <linux/mm.h>
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/err.h>
+#include <linux/vbs.h>
#include <linux/kvm_para.h>
#include <asm/kvm_para.h>
@@ -85,12 +92,78 @@ static u64 secmon_vtl_return(long status)
return kvm_hypercall1(KVM_HC_VBS_VTL_RETURN, (unsigned long)status);
}
+/*
+ * Apply EPT permissions on a normal-plane GPA range from the secure plane.
+ *
+ * The secure plane cannot issue the host KVM_SET_MEMORY_ATTRIBUTES ioctl, so
+ * it asks KVM to do it via the KVM_HC_VBS_SET_MEM_ATTRS hypercall, which KVM
+ * honours only for a higher-privilege plane (it applies the attributes to the
+ * plane directly below the caller). @perms carries the access bits the
+ * normal plane should retain (VBS_MEM_*); KVM translates a cleared
+ * read/write/exec bit into NO_READ / NO_WRITE / NO_EXEC. @perms == 0 hides
+ * the range entirely.
+ */
+static int secmon_apply_attrs(u64 gpa, u64 size, u32 perms)
+{
+ long ret;
+
+ pr_debug("apply_attrs gpa=0x%llx size=0x%llx perms=%c%c%c\n",
+ gpa, size,
+ (perms & VBS_MEM_READ) ? 'r' : '-',
+ (perms & VBS_MEM_WRITE) ? 'w' : '-',
+ (perms & VBS_MEM_EXEC) ? 'x' : '-');
+
+ ret = kvm_hypercall3(KVM_HC_VBS_SET_MEM_ATTRS, gpa, size, perms);
+ if (ret)
+ return (int)ret;
+
+ return 0;
+}
+
+/*
+ * Hide one range of this plane's RAM from the normal plane. perms = 0 means
+ * "retain no access" (no read/write/exec), so the normal plane faults and is
+ * denied if it tries to touch secure-plane memory.
+ */
+static int secmon_hide_range(unsigned long start_pfn, unsigned long nr_pages,
+ void *arg)
+{
+ unsigned long gpa = start_pfn << PAGE_SHIFT;
+ unsigned long size = nr_pages << PAGE_SHIFT;
+ int r;
+
+ r = secmon_apply_attrs(gpa, size, 0);
+ if (r)
+ pr_warn("failed to protect RAM [0x%lx+0x%lx]: %d\n",
+ gpa, size, r);
+ else
+ pr_info("protected RAM [0x%lx+0x%lx] from normal plane\n",
+ gpa, size);
+
+ /* Continue with the remaining ranges even if one fails. */
+ return 0;
+}
+
+/*
+ * Deny the normal plane access to all of the secure plane's own RAM. Runs
+ * while the normal plane is frozen in the KVM_RUN that switched to us, so
+ * there is no window during which the memory is both populated and still
+ * readable by the normal plane.
+ */
+static void secmon_protect_self(void)
+{
+ walk_system_ram_range(0, max_pfn, NULL, secmon_hide_range);
+}
+
static int secmon_monitor_fn(void *unused)
{
long status = 0;
pr_info("secure monitor started\n");
+ /* Seal our memory from the normal plane before handing control back. */
+ secmon_protect_self();
+
for (;;) {
struct vbs_kvm_ca *ca;
u64 ca_gpa;
--
2.55.0
next prev parent reply other threads:[~2026-08-05 11:04 UTC|newest]
Thread overview: 43+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-05 11:02 [RFC PATCH v1 00/42] VBS/VSM-on-KVM: VBS integration for KVM VM planes Sriram Nambakam
2026-08-05 11:02 ` [RFC PATCH v1 01/42] Fix merge issue - Remove duplicate definition for kvm_arch_has_irq_bypass Sriram Nambakam
2026-08-05 11:02 ` [RFC PATCH v1 02/42] Fix compilation Sriram Nambakam
2026-08-05 11:02 ` [RFC PATCH v1 03/42] Fix compile error Sriram Nambakam
2026-08-05 11:02 ` [RFC PATCH v1 04/42] Fix compile errors Sriram Nambakam
2026-08-05 11:02 ` [RFC PATCH v1 05/42] Initial support for VM Planes - Add kernel config for CONFIG_VM_PLANES - Parse vm plane config from initrd for plane configuration - Make hypercalls to allocate memory for the vm planes Sriram Nambakam
2026-08-05 11:02 ` [RFC PATCH v1 06/42] Use vcpu count from the plane configuration Sriram Nambakam
2026-08-05 11:02 ` [RFC PATCH v1 07/42] skip processing plane configuration for plane 0 - plane 0 is the boot plane Sriram Nambakam
2026-08-05 11:02 ` [RFC PATCH v1 08/42] Add plane config param to specify kernel image format Sriram Nambakam
2026-08-05 11:02 ` [RFC PATCH v1 09/42] Activate the VM Planes through the Hypervisor - Using KVM as the VMM Sriram Nambakam
2026-08-05 11:02 ` [RFC PATCH v1 10/42] allow the command line to be specified for kernels in other planes Sriram Nambakam
2026-08-05 11:02 ` [RFC PATCH v1 11/42] Various changes to support VM Planes Sriram Nambakam
2026-08-05 11:02 ` [RFC PATCH v1 12/42] Add a Virtualization Based Security (VBS) framework. - Add backends for AMD SEV-SNP, Intel TDX, Arm CCA and KVM Planes. - Support VTL on Hyper-V in addition to Planes on KVM Sriram Nambakam
2026-08-05 11:02 ` [RFC PATCH v1 13/42] Add a inter-plane communication mechanism through KVM. - model this to use a single page similar to SEV-SNP Sriram Nambakam
2026-08-05 11:02 ` [RFC PATCH v1 14/42] KVM: Add per-plane memory attribute support for cross-plane EPT protection Sriram Nambakam
2026-08-05 11:02 ` [RFC PATCH v1 15/42] KVM: x86: Add KVM_HC_VBS_VTL_CALL hypercall for VBS inter-plane calls Sriram Nambakam
2026-08-05 11:02 ` [RFC PATCH v1 16/42] vbs: Add HEKI kernel sealing and fix KVM plane memory attribute guards Sriram Nambakam
2026-08-05 11:02 ` [RFC PATCH v1 17/42] vbs: Add module authentication via VBS/HEKI Sriram Nambakam
2026-08-05 11:03 ` [RFC PATCH v1 18/42] vbs: Add kexec validation and make module auth non-fatal Sriram Nambakam
2026-08-05 11:03 ` [RFC PATCH v1 19/42] Merge branch 'master' into vm-planes Sriram Nambakam
2026-08-05 11:03 ` [RFC PATCH v1 20/42] kvm: x86: fix merged plane API/stat build regressions Sriram Nambakam
2026-08-05 11:03 ` [RFC PATCH v1 21/42] KVM: x86: exit VM planes and VBS hypercalls to userspace Sriram Nambakam
2026-08-05 11:03 ` [RFC PATCH v1 22/42] kexec: block legacy kexec_load when VBS is active Sriram Nambakam
2026-08-05 11:03 ` [RFC PATCH v1 23/42] kvm: x86: fix merged plane API/stat build regressions Sriram Nambakam
2026-08-05 11:03 ` [RFC PATCH v1 24/42] KVM: planes: expose memory-attribute setting to in-kernel callers Sriram Nambakam
2026-08-05 11:03 ` [RFC PATCH v1 25/42] vm_planes: drop unused per-plane vcpu_count Sriram Nambakam
2026-08-05 11:03 ` [RFC PATCH v1 26/42] drivers/virt: add VBS secure-plane park loop Sriram Nambakam
2026-08-05 11:03 ` [RFC PATCH v1 27/42] KVM: planes: add arch-neutral in-kernel plane switch helper Sriram Nambakam
2026-08-05 11:03 ` [RFC PATCH v1 28/42] KVM: x86: add VBS VTL call/return and cross-plane set-mem-attrs hypercalls Sriram Nambakam
2026-08-05 11:03 ` [RFC PATCH v1 29/42] init/vm_planes: set up planes from rootfs_initcall and load ELF payloads Sriram Nambakam
2026-08-05 11:03 ` [RFC PATCH v1 30/42] security/vbs: run backend probe and HEKI seal at rootfs_initcall Sriram Nambakam
2026-08-05 11:03 ` [RFC PATCH v1 31/42] security/vbs: pin the VTL call hypercall to CPU0 Sriram Nambakam
2026-08-05 11:03 ` [RFC PATCH v1 32/42] security/vbs: add secure-plane monitor backend Sriram Nambakam
2026-08-05 11:03 ` [RFC PATCH v1 33/42] drivers/virt: rename VBS park loop to secure_monitor Sriram Nambakam
2026-08-05 11:03 ` [RFC PATCH v1 34/42] x86/realmode: skip the sub-1M trampoline for the VBS secure plane Sriram Nambakam
2026-08-05 11:03 ` Sriram Nambakam [this message]
2026-08-05 11:03 ` [RFC PATCH v1 36/42] KVM: plane: handle KVM_CHECK_EXTENSION on the plane fd Sriram Nambakam
2026-08-05 11:03 ` [RFC PATCH v1 37/42] KVM: selftests: run plane tests with a split IRQ chip Sriram Nambakam
2026-08-05 11:03 ` [RFC PATCH v1 38/42] kvm: x86: drop obsolete kvm_cache_regs.h Sriram Nambakam
2026-08-05 11:03 ` [RFC PATCH v1 39/42] kvm: arch: finalize plane hooks and kvm_arch_vcpu_create signature Sriram Nambakam
2026-08-05 11:03 ` [RFC PATCH v1 40/42] kvm: x86: use kvm_vcpu scheduling-state accessors and struct stat fields Sriram Nambakam
2026-08-05 11:03 ` [RFC PATCH v1 41/42] kvm: x86: finalize per-plane APIC state and CPUID placement Sriram Nambakam
2026-08-05 11:03 ` [RFC PATCH v1 42/42] kvm: planes: reconcile core plane state, UAPI and hypercall exit Sriram Nambakam
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260805110324.25067-36-snambakam@linux.microsoft.com \
--to=snambakam@linux.microsoft.com \
--cc=kvm@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox