[RFC PATCH v1 24/42] KVM: planes: expose memory-attribute setting to in-kernel callers
Sriram Nambakam <[email protected]> Wed, 5 Aug 2026 04:03:06 -0700
| Newsgroups | org.kernel.vger.kvm,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <[email protected]> |
A higher-privilege plane needs to restrict a lower plane's access to guest memory by setting NO_WRITE / NO_EXEC EPT attributes (e.g. HEKI sealing plane-0 text/rodata). The enforcement already lives in kvm_plane_filter_pte_access(); wire up the set side: - advertise KVM_MEMORY_ATTRIBUTE_NO_WRITE / NO_EXEC from kvm_supported_mem_attributes() when CONFIG_VM_PLANES is enabled, so userspace and in-kernel callers know the attributes are available. - make kvm_vm_set_mem_attributes() non-static and declare it in kvm_host.h so an in-kernel secure-plane caller can apply attributes without going through the ioctl path. No functional change for non-plane builds. Signed-off-by: Sriram Nambakam <[email protected]> --- include/linux/kvm_host.h | 2 ++ virt/kvm/kvm_main.c | 21 +++++++++++++++++---- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h index e989b293a34a..82e557e66152 100644 --- a/include/linux/kvm_host.h +++ b/include/linux/kvm_host.h @@ -2703,6 +2703,8 @@ static inline unsigned long kvm_get_memory_attributes(struct kvm *kvm, gfn_t gfn bool kvm_range_has_memory_attributes(struct kvm *kvm, gfn_t start, gfn_t end, unsigned long mask, unsigned long attrs); +int kvm_vm_set_mem_attributes(struct kvm *kvm, gfn_t start, gfn_t end, + unsigned long attributes); bool kvm_arch_pre_set_memory_attributes(struct kvm *kvm, struct kvm_gfn_range *range); bool kvm_arch_post_set_memory_attributes(struct kvm *kvm, diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index f703545a7e80..9623ab8ebd9e 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c @@ -2603,10 +2603,23 @@ static int kvm_vm_ioctl_clear_dirty_log(struct kvm *kvm, #ifdef CONFIG_KVM_GENERIC_MEMORY_ATTRIBUTES static u64 kvm_supported_mem_attributes(struct kvm *kvm) { + u64 attrs = 0; + if (!kvm || kvm_arch_has_private_mem(kvm)) - return KVM_MEMORY_ATTRIBUTE_PRIVATE; + attrs |= KVM_MEMORY_ATTRIBUTE_PRIVATE; - return 0; +#ifdef CONFIG_VM_PLANES + /* + * Cross-plane EPT protection: a higher-privilege plane may restrict + * a lower plane's access via NO_WRITE / NO_EXEC (e.g. HEKI sealing + * plane-0 kernel text and rodata). The enforcement path lives in + * kvm_plane_filter_pte_access(); advertise the attributes here so + * KVM_SET_MEMORY_ATTRIBUTES accepts them. + */ + attrs |= KVM_MEMORY_ATTRIBUTE_NO_WRITE | KVM_MEMORY_ATTRIBUTE_NO_EXEC; +#endif + + return attrs; } /* @@ -2716,8 +2729,8 @@ static bool kvm_pre_set_memory_attributes(struct kvm *kvm, } /* Set @attributes for the gfn range [@start, @end). */ -static int kvm_vm_set_mem_attributes(struct kvm *kvm, gfn_t start, gfn_t end, - unsigned long attributes) +int kvm_vm_set_mem_attributes(struct kvm *kvm, gfn_t start, gfn_t end, + unsigned long attributes) { struct kvm_mmu_notifier_range pre_set_range = { .start = start, -- 2.55.0