All of lore.kernel.org
 help / color / mirror / Atom feed
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


  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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.