On 7/29/2026 8:35 AM, Ackerley Tng via B4 Relay wrote:
From: Ackerley Tng <[email protected]>
Move the folio initialization logic from kvm_gmem_get_pfn() into
__kvm_gmem_get_pfn() to also zero pages if the page is to be used in
kvm_gmem_populate().
With in-place conversion, the existing data in a guest_memfd page can be
populated into guest memory through platform-specific ioctls.
Without first zeroing the page obtained using __kvm_gmem_get_pfn(), it
might contain uninitialized host memory, which would leak to the guest if
the populate completes.
guest_memfd pages are zeroed at most once in the page's entire lifetime
with guest_memfd, and that is tracked using the uptodate flag.
Zeroing the page in __kvm_gmem_get_pfn() is chosen over zeroing in
kvm_gmem_get_folio() since other flows, such as a future write() syscall,
can get a page, write to the page and then set page uptodate without
zeroing.
This aligns with the concept of zeroing before first use - the other place
where zeroing happens is in kvm_gmem_fault_user_mapping().
Don't mark the page uptodate again after populating, since the page would
already be marked uptodate before the post_populate() call.
Reviewed-by: Fuad Tabba <[email protected]>
Tested-by: Shivank Garg <[email protected]>
Signed-off-by: Ackerley Tng <[email protected]>
Reviewed-by: Xiaoyao Li <[email protected]>
---
virt/kvm/guest_memfd.c | 12 +++++-------
1 file changed, 5 insertions(+), 7 deletions(-)
diff --git a/virt/kvm/guest_memfd.c b/virt/kvm/guest_memfd.c
index 505bb6747620b..ea2752989f8bd 100644
--- a/virt/kvm/guest_memfd.c
+++ b/virt/kvm/guest_memfd.c
@@ -1078,6 +1078,11 @@ static struct folio *__kvm_gmem_get_pfn(struct file
*file,
return ERR_PTR(-EHWPOISON);
}
+ if (!folio_test_uptodate(folio)) {
+ clear_highpage(folio_page(folio, 0));
+ folio_mark_uptodate(folio);
+ }
+
*pfn = folio_file_pfn(folio, index);
if (max_order)
*max_order = 0;
@@ -1107,11 +1112,6 @@ int kvm_gmem_get_pfn(struct kvm *kvm, struct
kvm_memory_slot *slot,
goto out;
}
- if (!folio_test_uptodate(folio)) {
- clear_highpage(folio_page(folio, 0));
- folio_mark_uptodate(folio);
- }
-
#ifdef CONFIG_HAVE_KVM_ARCH_GMEM_CONVERT
if (kvm_gmem_is_private_mem(file_inode(file), index))
r = kvm_arch_gmem_make_private(kvm, gfn, *pfn,
@@ -1171,8 +1171,6 @@ static long __kvm_gmem_populate(struct kvm *kvm, struct
kvm_memory_slot *slot,
}
ret = post_populate(kvm, gfn, pfn, src_page, opaque);
- if (!ret)
- folio_mark_uptodate(folio);
out_put_folio:
folio_put(folio);