Kernel KVM virtualization development
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Claudio Imbrenda" <imbrenda@linux.ibm.com>
Cc: linux-s390@vger.kernel.org, kvm@vger.kernel.org,
	"Vasily Gorbik" <gor@linux.ibm.com>,
	"Alexander Gordeev" <agordeev@linux.ibm.com>,
	"Heiko Carstens" <hca@linux.ibm.com>
Subject: Re: [PATCH v6 02/14] KVM: s390: Fix kvm_s390_vcpu_unsetup_cmma()
Date: Thu, 30 Jul 2026 16:55:29 +0000	[thread overview]
Message-ID: <20260730165530.276F11F000E9@smtp.kernel.org> (raw)
In-Reply-To: <20260730162714.133327-3-imbrenda@linux.ibm.com>

Thank you for your contribution! Sashiko AI review found 4 potential issue(s) to consider:

Pre-existing issues:
- [Critical] Unprivileged local memory corruption via `sca_dispose(NULL)` leading to freeing physical pages 1, 2, and 3.
- [High] Memory leak of `vcpu->arch.mc` in the error path of `kvm_arch_vcpu_create()`.
- [High] Missing lock acquisition when removing a child gmap in the vCPU creation error path.
- [High] When `uv_call` fails during `kvm_s390_pv_create_cpu()`, newly allocated `stor_base` and `sida_addr` pages are permanently leaked.
--

--- Patch [2]: [PATCH v6 02/14] KVM: s390: Fix kvm_s390_vcpu_unsetup_cmma() ---
commit b2abac5b0352ced2b250d10ad5dfc60b18cae87c
Author: Claudio Imbrenda <imbrenda@linux.ibm.com>

KVM: s390: Fix kvm_s390_vcpu_unsetup_cmma()

In some cases kvm_s390_vcpu_unsetup_cmma() can be called with a 0
cbrlo; in such cases, if running with V != R, free_page() will attempt
to free physical page 0.

Fix by freeing cbrlo only if it's non-zero.

Fixes: b31605c12f4e ("KVM: s390: make cmma usage conditionally")
Fixes: 29b40f105ec8 ("KVM: s390: protvirt: Add initial vm and cpu lifecycle handling")

> diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
> index f86b4b0b356f4..9ec5833a09732 100644
> --- a/arch/s390/kvm/kvm-s390.c
> +++ b/arch/s390/kvm/kvm-s390.c
> @@ -3677,7 +3677,8 @@ static void kvm_s390_vcpu_crypto_setup(struct kvm_vcpu *vcpu)
>  
>  void kvm_s390_vcpu_unsetup_cmma(struct kvm_vcpu *vcpu)
>  {
> -	free_page((unsigned long)phys_to_virt(vcpu->arch.sie_block->cbrlo));
> +	if (vcpu->arch.sie_block->cbrlo)
> +		free_page((unsigned long)phys_to_virt(vcpu->arch.sie_block->cbrlo));
>  	vcpu->arch.sie_block->cbrlo = 0;
>  }

While reviewing this code, a few other things were noticed nearby.

arch/s390/kvm/kvm-s390.c:kvm_arch_vcpu_create() {
[ ... ]
out_ucontrol_uninit:
	if (kvm_is_ucontrol(vcpu->kvm)) {
		gmap_remove_child(vcpu->arch.gmap);

[Severity: High]
This is a pre-existing issue, but is it possible we are missing a lock here?

In kvm_arch_vcpu_create(), if a ucontrol VM's vCPU setup fails, it calls
gmap_remove_child(vcpu->arch.gmap).

The gmap_remove_child() function expects the parent gmap's children_lock to
be held and concurrently modifies the parent gmap's children list. However,
this error path appears to omit acquiring the children_lock.

Could this lead to a data race and list corruption?


		vcpu->arch.gmap = gmap_put(vcpu->arch.gmap);
	}
out_free_sie_block:
	free_page((unsigned long)(vcpu->arch.sie_block));
	return rc;
}

[Severity: High]
This is a pre-existing issue, but what happens to the vcpu->arch.mc memory
when we take this error path?

When an error occurs in kvm_arch_vcpu_create() after vcpu->arch.mc
allocation, the code jumps to out_ucontrol_uninit and out_free_sie_block.

While it frees the sie_block and removes the gmap child, it seems to never
free the memory allocated by kvm_s390_new_mmu_cache(vcpu->arch.mc).

Can userspace repeatedly trigger vCPU creation failures to leak memory and
cause a local denial of service?


arch/s390/kvm/kvm-s390.c:kvm_arch_init_vm() {
[ ... ]
out_err:
	free_page((unsigned long)kvm->arch.sie_page2);
	debug_unregister(kvm->arch.dbf);
	sca_dispose(kvm);
[ ... ]
}

arch/s390/kvm/kvm-s390.c:sca_dispose() {
	free_pages_exact(kvm->arch.sca, sizeof(*kvm->arch.sca));
	kvm->arch.sca = NULL;
}

[Severity: Critical]
This is a pre-existing issue, but is there a risk of memory corruption here?

In kvm_arch_init_vm(), if VM creation fails early, the code jumps to out_err
before kvm->arch.sca is allocated.

Since the kvm structure is zero-allocated, kvm->arch.sca is NULL.

The sca_dispose() function calls
free_pages_exact(kvm->arch.sca, sizeof(*kvm->arch.sca)). The size of
struct esca_block is roughly 16KB.

The free_pages_exact(virt, size) function loops from addr = virt to
addr + PAGE_ALIGN(size), incrementing by PAGE_SIZE, and calls
free_page(addr).

For virt == NULL, it iterates through addresses 0, 4096, 8192, and 12288.

While free_page(0) is safely ignored, free_page(4096) translates to
__free_pages(virt_to_page(4096), 0) and incorrectly frees host physical pages
1, 2, and 3 into the buddy allocator.

Can an unprivileged user trigger this trivially by calling
ioctl(KVM_CREATE_VM, 1)?


arch/s390/kvm/pv.c:kvm_s390_pv_create_cpu() {
[ ... ]
	cc = uv_call(0, (u64)&uvcb);
[ ... ]
	if (cc) {
		u16 dummy;

		kvm_s390_pv_destroy_cpu(vcpu, &dummy, &dummy);
		return -EIO;
	}
[ ... ]
}

arch/s390/kvm/pv.c:kvm_s390_pv_destroy_cpu() {
	int cc;

	if (!kvm_s390_pv_cpu_get_handle(vcpu))
		return 0;
[ ... ]
}

[Severity: High]
This is a pre-existing issue, but does this error handling permanently leak
the newly allocated stor_base and sida_addr pages?

The kvm_s390_pv_create_cpu() function allocates vcpu->arch.pv.stor_base
and sida_addr. If uv_call fails, it jumps to error handling which
calls kvm_s390_pv_destroy_cpu(vcpu).

However, kvm_s390_pv_destroy_cpu() begins with an early return:
if (!kvm_s390_pv_cpu_get_handle(vcpu)) return 0;

Because vcpu->arch.pv.handle is only set upon successful uv_call completion,
the handle is 0 here. Thus, the destruction routine does nothing and bypasses
the free_pages() blocks entirely.

Could a compromised or malicious userspace trigger failures in uv_call to
repeatedly leak host memory?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260730162714.133327-1-imbrenda@linux.ibm.com?part=2

  reply	other threads:[~2026-07-30 16:55 UTC|newest]

Thread overview: 29+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-30 16:27 [PATCH v6 00/14] KVM: s390: Misc fixes Claudio Imbrenda
2026-07-30 16:27 ` [PATCH v6 01/14] KVM: s390: Fix unlikely NULL gmap dereference Claudio Imbrenda
2026-07-30 16:50   ` sashiko-bot
2026-07-30 16:27 ` [PATCH v6 02/14] KVM: s390: Fix kvm_s390_vcpu_unsetup_cmma() Claudio Imbrenda
2026-07-30 16:55   ` sashiko-bot [this message]
2026-07-30 16:27 ` [PATCH v6 03/14] KVM: s390: Fix overclearing ESCA in case of error Claudio Imbrenda
2026-07-30 17:04   ` sashiko-bot
2026-07-30 16:27 ` [PATCH v6 04/14] KVM: s390: ucontrol: Fix sca_clear_ext_call() Claudio Imbrenda
2026-07-30 16:51   ` sashiko-bot
2026-07-30 16:27 ` [PATCH v6 05/14] KVM: s390: Fix leaking of PGM_ADDRESSING to userspace Claudio Imbrenda
2026-07-30 16:40   ` sashiko-bot
2026-07-30 16:27 ` [PATCH v6 06/14] KVM: s390: Fix race in __do_essa() Claudio Imbrenda
2026-07-30 16:47   ` sashiko-bot
2026-07-30 16:27 ` [PATCH v6 07/14] KVM: s390: cmma: Fix dirty tracking when removing memslot Claudio Imbrenda
2026-07-30 16:48   ` sashiko-bot
2026-07-30 16:27 ` [PATCH v6 08/14] KVM: s390: ucontrol: Add missing locking around gmap_remove_child() Claudio Imbrenda
2026-07-30 16:48   ` sashiko-bot
2026-07-30 16:27 ` [PATCH v6 09/14] KVM: s390: Free the mmu cache when kvm_arch_vcpu_create() fails Claudio Imbrenda
2026-07-30 16:44   ` sashiko-bot
2026-07-30 16:27 ` [PATCH v6 10/14] KVM: s390: Return -EINTR if a signal is pending while faulting-in Claudio Imbrenda
2026-07-30 16:53   ` sashiko-bot
2026-07-30 16:27 ` [PATCH v6 11/14] KVM: s390: Fix ordering when adding to SCA Claudio Imbrenda
2026-07-30 16:54   ` sashiko-bot
2026-07-30 16:27 ` [PATCH v6 12/14] KVM: s390: Fix cleanup in kvm_s390_pv_create_cpu() Claudio Imbrenda
2026-07-30 16:52   ` sashiko-bot
2026-07-30 16:27 ` [PATCH v6 13/14] KVM: s390: Fix kvm_arch_commit_memory_region() when low on memory Claudio Imbrenda
2026-07-30 17:02   ` sashiko-bot
2026-07-30 16:27 ` [PATCH v6 14/14] KVM: s390: Move DAT table updates to kvm_arch_prepare_memory_region() Claudio Imbrenda
2026-07-30 17:01   ` sashiko-bot

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=20260730165530.276F11F000E9@smtp.kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=agordeev@linux.ibm.com \
    --cc=gor@linux.ibm.com \
    --cc=hca@linux.ibm.com \
    --cc=imbrenda@linux.ibm.com \
    --cc=kvm@vger.kernel.org \
    --cc=linux-s390@vger.kernel.org \
    --cc=sashiko-reviews@lists.linux.dev \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox