Forwarded: Re: [syzbot] [kvm-x86?] KASAN: use-after-free Read in kvm_setup_guest_pvclock

syzbot posted 1 patch 2 days, 6 hours ago
drivers/gpu/drm/drm_mode_config.c |  4 ++--
virt/kvm/pfncache.c               | 28 ++++++++++++++++++++++++++++
2 files changed, 30 insertions(+), 2 deletions(-)
Forwarded: Re: [syzbot] [kvm-x86?] KASAN: use-after-free Read in kvm_setup_guest_pvclock
Posted by syzbot 2 days, 6 hours ago
For archival purposes, forwarding an incoming command email to
linux-kernel@vger.kernel.org, syzkaller-bugs@googlegroups.com.

***

Subject: Re: [syzbot] [kvm-x86?] KASAN: use-after-free Read in kvm_setup_guest_pvclock
Author: halves@igalia.com

#syz test

Reported-by: syzbot+fb7c2dd166d3ea63df2a@syzkaller.appspotmail.com
Link: https://syzkaller.appspot.com/bug?extid=fb7c2dd166d3ea63df2a
Signed-off-by: Heitor Alves de Siqueira <halves@igalia.com>
---
 drivers/gpu/drm/drm_mode_config.c |  4 ++--
 virt/kvm/pfncache.c               | 28 ++++++++++++++++++++++++++++
 2 files changed, 30 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/drm_mode_config.c b/drivers/gpu/drm/drm_mode_config.c
index 3bcc7bf0900c..e06f1cd149a7 100644
--- a/drivers/gpu/drm/drm_mode_config.c
+++ b/drivers/gpu/drm/drm_mode_config.c
@@ -869,8 +869,8 @@ static void validate_blend_mode_for_alpha_formats(struct drm_plane *plane)
 	for (i = 0; i < plane->format_count; i++) {
 		fmt = drm_format_info(plane->format_types[i]);
 		if (fmt->has_alpha) {
-			WARN(1, "[PLANE:%d:%s] pixel format with alpha exposed but blend mode not setup",
-			     plane->base.id, plane->name);
+			/* WARN(1, "[PLANE:%d:%s] pixel format with alpha exposed but blend mode not setup", */
+			/*      plane->base.id, plane->name); */
 			break;
 		}
 	}
diff --git a/virt/kvm/pfncache.c b/virt/kvm/pfncache.c
index 728d2c1b488a..8a766c4cd4bd 100644
--- a/virt/kvm/pfncache.c
+++ b/virt/kvm/pfncache.c
@@ -152,6 +152,32 @@ static inline bool mmu_notifier_retry_cache(struct kvm *kvm, unsigned long mmu_s
 	return kvm->mmu_invalidate_seq != mmu_seq;
 }
 
+static void kvm_gpc_invalidate_pfn(struct kvm *kvm, kvm_pfn_t pfn)
+{
+	struct gfn_to_pfn_cache *gpc;
+
+	if (is_error_noslot_pfn(pfn))
+		return;
+
+	spin_lock(&kvm->gpc_lock);
+	list_for_each_entry(gpc, &kvm->gpc_list, list) {
+		read_lock_irq(&gpc->lock);
+
+		if (gpc->valid && gpc->pfn == pfn) {
+			read_unlock_irq(&gpc->lock);
+
+			write_lock_irq(&gpc->lock);
+			if (gpc->valid && gpc->pfn == pfn)
+				gpc->valid = false;
+			write_unlock_irq(&gpc->lock);
+			continue;
+		}
+
+		read_unlock_irq(&gpc->lock);
+	}
+	spin_unlock(&kvm->gpc_lock);
+}
+
 static kvm_pfn_t hva_to_pfn_retry(struct gfn_to_pfn_cache *gpc)
 {
 	/* Note, the new page offset may be different than the old! */
@@ -201,6 +227,7 @@ static kvm_pfn_t hva_to_pfn_retry(struct gfn_to_pfn_cache *gpc)
 			if (new_khva != old_khva)
 				gpc_unmap(new_pfn, new_khva);
 
+			kvm_gpc_invalidate_pfn(gpc->kvm, new_pfn);
 			kvm_release_page_unused(page);
 
 			cond_resched();
@@ -221,6 +248,7 @@ static kvm_pfn_t hva_to_pfn_retry(struct gfn_to_pfn_cache *gpc)
 			new_khva = gpc_map(new_pfn);
 
 		if (!new_khva) {
+			kvm_gpc_invalidate_pfn(gpc->kvm, new_pfn);
 			kvm_release_page_unused(page);
 			goto out_error;
 		}
-- 
2.55.0