linux-s390.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v3 0/2] KVM: s390: Fix two bugs
@ 2025-08-25 15:18 Claudio Imbrenda
  2025-08-25 15:18 ` [PATCH v3 1/2] KVM: s390: Fix incorrect usage of mmu_notifier_register() Claudio Imbrenda
  2025-08-25 15:18 ` [PATCH v3 2/2] KVM: s390: Fix FOLL_*/FAULT_FLAG_* confusion Claudio Imbrenda
  0 siblings, 2 replies; 4+ messages in thread
From: Claudio Imbrenda @ 2025-08-25 15:18 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-s390, kvm, david, frankja, seiden, nsg, nrb, schlameuss,
	hca, mhartmay, borntraeger

This small series fixes two bugs in s390 KVM. One is small and trivial,
the other is pretty bad.

* The wrong type of flag was being passed to vcpu_dat_fault_handler();
  it expects a FOLL_* flag, but a FAULT_FLAG_* was passed instead.
* Due to incorrect usage of mmu_notifier_register(), in some rare cases
  when running a secure guest, the struct mm for the userspace process
  would get freed too early and cause a use-after-free.

v2->v3
* Make sure .ops is not NULL before calling mmu_notifier_register() to
  avoid NULL pointer errors (thanks Marc)
v1->v2
* Rename the parameters of __kvm_s390_handle_dat_fault() and
  vcpu_dat_fault_handler() from flags to foll (thanks Christian)

Claudio Imbrenda (2):
  KVM: s390: Fix incorrect usage of mmu_notifier_register()
  KVM: s390: Fix FOLL_*/FAULT_FLAG_* confusion

 arch/s390/kvm/kvm-s390.c | 24 ++++++++++++------------
 arch/s390/kvm/pv.c       | 16 +++++++++++-----
 2 files changed, 23 insertions(+), 17 deletions(-)

-- 
2.51.0


^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH v3 1/2] KVM: s390: Fix incorrect usage of mmu_notifier_register()
  2025-08-25 15:18 [PATCH v3 0/2] KVM: s390: Fix two bugs Claudio Imbrenda
@ 2025-08-25 15:18 ` Claudio Imbrenda
  2025-08-25 15:18 ` [PATCH v3 2/2] KVM: s390: Fix FOLL_*/FAULT_FLAG_* confusion Claudio Imbrenda
  1 sibling, 0 replies; 4+ messages in thread
From: Claudio Imbrenda @ 2025-08-25 15:18 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-s390, kvm, david, frankja, seiden, nsg, nrb, schlameuss,
	hca, mhartmay, borntraeger

If mmu_notifier_register() fails, for example because a signal was
pending, the mmu_notifier will not be registered. But when the VM gets
destroyed, it will get unregistered anyway and that will cause one
extra mmdrop(), which will eventually cause the mm of the process to
be freed too early, and cause a use-after free.

This bug happens rarely, and only when secure guests are involved.

The solution is to check the return value of mmu_notifier_register()
and return it to the caller (ultimately it will be propagated all the
way to userspace). In case of -EINTR, userspace will try again.

Fixes: ca2fd0609b5d ("KVM: s390: pv: add mmu_notifier")
Signed-off-by: Claudio Imbrenda <imbrenda@linux.ibm.com>
Reviewed-by: Christian Borntraeger <borntraeger@linux.ibm.com>
Reviewed-by: David Hildenbrand <david@redhat.com>
Reviewed-by: Steffen Eiden <seiden@linux.ibm.com>
Reviewed-by: Christoph Schlameuss <schlameuss@linux.ibm.com>
---
 arch/s390/kvm/pv.c | 16 +++++++++++-----
 1 file changed, 11 insertions(+), 5 deletions(-)

diff --git a/arch/s390/kvm/pv.c b/arch/s390/kvm/pv.c
index 14c330ec8ceb..ede790798fa3 100644
--- a/arch/s390/kvm/pv.c
+++ b/arch/s390/kvm/pv.c
@@ -622,6 +622,17 @@ int kvm_s390_pv_init_vm(struct kvm *kvm, u16 *rc, u16 *rrc)
 	int cc, ret;
 	u16 dummy;
 
+	/* Add the notifier only once. No races because we hold kvm->lock */
+	if (kvm->arch.pv.mmu_notifier.ops != &kvm_s390_pv_mmu_notifier_ops) {
+		/* The notifier will be unregistered when the VM is destroyed */
+		kvm->arch.pv.mmu_notifier.ops = &kvm_s390_pv_mmu_notifier_ops;
+		ret = mmu_notifier_register(&kvm->arch.pv.mmu_notifier, kvm->mm);
+		if (ret) {
+			kvm->arch.pv.mmu_notifier.ops = NULL;
+			return ret;
+		}
+	}
+
 	ret = kvm_s390_pv_alloc_vm(kvm);
 	if (ret)
 		return ret;
@@ -657,11 +668,6 @@ int kvm_s390_pv_init_vm(struct kvm *kvm, u16 *rc, u16 *rrc)
 		return -EIO;
 	}
 	kvm->arch.gmap->guest_handle = uvcb.guest_handle;
-	/* Add the notifier only once. No races because we hold kvm->lock */
-	if (kvm->arch.pv.mmu_notifier.ops != &kvm_s390_pv_mmu_notifier_ops) {
-		kvm->arch.pv.mmu_notifier.ops = &kvm_s390_pv_mmu_notifier_ops;
-		mmu_notifier_register(&kvm->arch.pv.mmu_notifier, kvm->mm);
-	}
 	return 0;
 }
 
-- 
2.51.0


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH v3 2/2] KVM: s390: Fix FOLL_*/FAULT_FLAG_* confusion
  2025-08-25 15:18 [PATCH v3 0/2] KVM: s390: Fix two bugs Claudio Imbrenda
  2025-08-25 15:18 ` [PATCH v3 1/2] KVM: s390: Fix incorrect usage of mmu_notifier_register() Claudio Imbrenda
@ 2025-08-25 15:18 ` Claudio Imbrenda
  2025-09-02  9:22   ` Christoph Schlameuss
  1 sibling, 1 reply; 4+ messages in thread
From: Claudio Imbrenda @ 2025-08-25 15:18 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-s390, kvm, david, frankja, seiden, nsg, nrb, schlameuss,
	hca, mhartmay, borntraeger

Pass the right type of flag to vcpu_dat_fault_handler(); it expects a
FOLL_* flag (in particular FOLL_WRITE), but FAULT_FLAG_WRITE is passed
instead.

This still works because they happen to have the same integer value,
but it's a mistake, thus the fix.

Signed-off-by: Claudio Imbrenda <imbrenda@linux.ibm.com>
Fixes: 05066cafa925 ("s390/mm/fault: Handle guest-related program interrupts in KVM")
Acked-by: Christian Borntraeger <borntraeger@linux.ibm.com>
Reviewed-by: David Hildenbrand <david@redhat.com>
Reviewed-by: Steffen Eiden <seiden@linux.ibm.com>
---
 arch/s390/kvm/kvm-s390.c | 24 ++++++++++++------------
 1 file changed, 12 insertions(+), 12 deletions(-)

diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
index d5ad10791c25..4280b25b6b04 100644
--- a/arch/s390/kvm/kvm-s390.c
+++ b/arch/s390/kvm/kvm-s390.c
@@ -4863,12 +4863,12 @@ static void kvm_s390_assert_primary_as(struct kvm_vcpu *vcpu)
  * @vcpu: the vCPU whose gmap is to be fixed up
  * @gfn: the guest frame number used for memslots (including fake memslots)
  * @gaddr: the gmap address, does not have to match @gfn for ucontrol gmaps
- * @flags: FOLL_* flags
+ * @foll: FOLL_* flags
  *
  * Return: 0 on success, < 0 in case of error.
  * Context: The mm lock must not be held before calling. May sleep.
  */
-int __kvm_s390_handle_dat_fault(struct kvm_vcpu *vcpu, gfn_t gfn, gpa_t gaddr, unsigned int flags)
+int __kvm_s390_handle_dat_fault(struct kvm_vcpu *vcpu, gfn_t gfn, gpa_t gaddr, unsigned int foll)
 {
 	struct kvm_memory_slot *slot;
 	unsigned int fault_flags;
@@ -4882,13 +4882,13 @@ int __kvm_s390_handle_dat_fault(struct kvm_vcpu *vcpu, gfn_t gfn, gpa_t gaddr, u
 	if (!slot || slot->flags & KVM_MEMSLOT_INVALID)
 		return vcpu_post_run_addressing_exception(vcpu);
 
-	fault_flags = flags & FOLL_WRITE ? FAULT_FLAG_WRITE : 0;
+	fault_flags = foll & FOLL_WRITE ? FAULT_FLAG_WRITE : 0;
 	if (vcpu->arch.gmap->pfault_enabled)
-		flags |= FOLL_NOWAIT;
+		foll |= FOLL_NOWAIT;
 	vmaddr = __gfn_to_hva_memslot(slot, gfn);
 
 try_again:
-	pfn = __kvm_faultin_pfn(slot, gfn, flags, &writable, &page);
+	pfn = __kvm_faultin_pfn(slot, gfn, foll, &writable, &page);
 
 	/* Access outside memory, inject addressing exception */
 	if (is_noslot_pfn(pfn))
@@ -4904,7 +4904,7 @@ int __kvm_s390_handle_dat_fault(struct kvm_vcpu *vcpu, gfn_t gfn, gpa_t gaddr, u
 			return 0;
 		vcpu->stat.pfault_sync++;
 		/* Could not setup async pfault, try again synchronously */
-		flags &= ~FOLL_NOWAIT;
+		foll &= ~FOLL_NOWAIT;
 		goto try_again;
 	}
 	/* Any other error */
@@ -4924,7 +4924,7 @@ int __kvm_s390_handle_dat_fault(struct kvm_vcpu *vcpu, gfn_t gfn, gpa_t gaddr, u
 	return rc;
 }
 
-static int vcpu_dat_fault_handler(struct kvm_vcpu *vcpu, unsigned long gaddr, unsigned int flags)
+static int vcpu_dat_fault_handler(struct kvm_vcpu *vcpu, unsigned long gaddr, unsigned int foll)
 {
 	unsigned long gaddr_tmp;
 	gfn_t gfn;
@@ -4949,18 +4949,18 @@ static int vcpu_dat_fault_handler(struct kvm_vcpu *vcpu, unsigned long gaddr, un
 		}
 		gfn = gpa_to_gfn(gaddr_tmp);
 	}
-	return __kvm_s390_handle_dat_fault(vcpu, gfn, gaddr, flags);
+	return __kvm_s390_handle_dat_fault(vcpu, gfn, gaddr, foll);
 }
 
 static int vcpu_post_run_handle_fault(struct kvm_vcpu *vcpu)
 {
-	unsigned int flags = 0;
+	unsigned int foll = 0;
 	unsigned long gaddr;
 	int rc;
 
 	gaddr = current->thread.gmap_teid.addr * PAGE_SIZE;
 	if (kvm_s390_cur_gmap_fault_is_write())
-		flags = FAULT_FLAG_WRITE;
+		foll = FOLL_WRITE;
 
 	switch (current->thread.gmap_int_code & PGM_INT_CODE_MASK) {
 	case 0:
@@ -5002,7 +5002,7 @@ static int vcpu_post_run_handle_fault(struct kvm_vcpu *vcpu)
 			send_sig(SIGSEGV, current, 0);
 		if (rc != -ENXIO)
 			break;
-		flags = FAULT_FLAG_WRITE;
+		foll = FOLL_WRITE;
 		fallthrough;
 	case PGM_PROTECTION:
 	case PGM_SEGMENT_TRANSLATION:
@@ -5012,7 +5012,7 @@ static int vcpu_post_run_handle_fault(struct kvm_vcpu *vcpu)
 	case PGM_REGION_SECOND_TRANS:
 	case PGM_REGION_THIRD_TRANS:
 		kvm_s390_assert_primary_as(vcpu);
-		return vcpu_dat_fault_handler(vcpu, gaddr, flags);
+		return vcpu_dat_fault_handler(vcpu, gaddr, foll);
 	default:
 		KVM_BUG(1, vcpu->kvm, "Unexpected program interrupt 0x%x, TEID 0x%016lx",
 			current->thread.gmap_int_code, current->thread.gmap_teid.val);
-- 
2.51.0


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH v3 2/2] KVM: s390: Fix FOLL_*/FAULT_FLAG_* confusion
  2025-08-25 15:18 ` [PATCH v3 2/2] KVM: s390: Fix FOLL_*/FAULT_FLAG_* confusion Claudio Imbrenda
@ 2025-09-02  9:22   ` Christoph Schlameuss
  0 siblings, 0 replies; 4+ messages in thread
From: Christoph Schlameuss @ 2025-09-02  9:22 UTC (permalink / raw)
  To: Claudio Imbrenda, linux-kernel
  Cc: linux-s390, kvm, david, frankja, seiden, nsg, nrb, hca, mhartmay,
	borntraeger

On Mon Aug 25, 2025 at 5:18 PM CEST, Claudio Imbrenda wrote:
> Pass the right type of flag to vcpu_dat_fault_handler(); it expects a
> FOLL_* flag (in particular FOLL_WRITE), but FAULT_FLAG_WRITE is passed
> instead.
>
> This still works because they happen to have the same integer value,
> but it's a mistake, thus the fix.
>
> Signed-off-by: Claudio Imbrenda <imbrenda@linux.ibm.com>
> Fixes: 05066cafa925 ("s390/mm/fault: Handle guest-related program interrupts in KVM")
> Acked-by: Christian Borntraeger <borntraeger@linux.ibm.com>
> Reviewed-by: David Hildenbrand <david@redhat.com>
> Reviewed-by: Steffen Eiden <seiden@linux.ibm.com>

Reviewed-by: Christoph Schlameuß <schlameuss@de.ibm.com>

> ---
>  arch/s390/kvm/kvm-s390.c | 24 ++++++++++++------------
>  1 file changed, 12 insertions(+), 12 deletions(-)

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2025-09-03  7:41 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-08-25 15:18 [PATCH v3 0/2] KVM: s390: Fix two bugs Claudio Imbrenda
2025-08-25 15:18 ` [PATCH v3 1/2] KVM: s390: Fix incorrect usage of mmu_notifier_register() Claudio Imbrenda
2025-08-25 15:18 ` [PATCH v3 2/2] KVM: s390: Fix FOLL_*/FAULT_FLAG_* confusion Claudio Imbrenda
2025-09-02  9:22   ` Christoph Schlameuss

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).