All of lore.kernel.org
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "David Ballesteros" <davimaba.v@proton.me>
Cc: kvm@vger.kernel.org
Subject: Re: [PATCH 1/2] KVM: Bound per-VM GFN materialization in KVM_SET_MEMORY_ATTRIBUTES
Date: Fri, 11 Sep 2026 19:05:28 +0000	[thread overview]
Message-ID: <20260911190529.2E9AA1F000FF@smtp.kernel.org> (raw)
In-Reply-To: <20260911184819.101123-2-davimaba.v@proton.me>

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

New issues:
- [High] Recounting materialized entries on every mutation is an O(N) operation that causes severe CPU exhaustion.
- [High] The arbitrary 128 GiB limit (KVM_MEM_ATTR_MAX_GFNS) introduces a severe functional regression for large confidential VMs.
- [Medium] Iterating the XArray using xas_for_each() without holding rcu_read_lock() triggers lockdep warnings.

Pre-existing issues:
- [High] The KVM_MEM_ATTR_MAX_GFNS limit check is bypassed when clearing attributes, failing to fix the memory exhaustion DoS.
--

commit 200db6833ee43dd9cdcad914e3c4e7942e9f7e5a
Author: David Ballesteros <davimaba.v@proton.me>
KVM: Bound per-VM GFN materialization in KVM_SET_MEMORY_ATTRIBUTES

This commit attempts to fix a memory exhaustion denial of service by
capping the maximum number of materialized memory attribute GFNs per VM.
It introduces a counter for materialized entries and restricts updates
exceeding a hardcoded limit.

> diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
> --- a/include/linux/kvm_host.h
> +++ b/include/linux/kvm_host.h
> @@ -573,6 +573,13 @@ static inline int kvm_vcpu_exiting_guest_mode(struct kvm_vcpu *vcpu)
>  #define KVM_MEM_MAX_NR_PAGES ((1UL << 31) - 1)
> +/*
> + * Hardening bound: maximum number of GFNs with a materialized entry in
> + * mem_attr_array per VM (~300 MiB of xa_nodes at 2^25).  Without it,
> + * KVM_SET_MEMORY_ATTRIBUTES grows the array without limit (~9.3 bytes of
> + * kernel memory per GFN) on GFNs with no backing memory.
> + */
> +#define KVM_MEM_ATTR_MAX_GFNS	(1UL << 25)

[Severity: High]
Does this limit cause legitimate large enterprise confidential VMs to fail?

A limit of 1UL << 25 pages equates to exactly 128 GiB of memory on systems
using a 4 KiB page size. Since AMD SEV-SNP and Intel TDX VMs routinely require
hundreds of gigabytes or even terabytes of private memory, capping the
allowed private memory to 128 GiB per VM seems like a functional regression
that will break existing large setups with -ENOSPC.

> diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
> --- a/virt/kvm/kvm_main.c
> +++ b/virt/kvm/kvm_main.c
> @@ -2544,6 +2545,33 @@ static bool kvm_pre_set_memory_attributes(struct kvm *kvm,
> [ ... ]
> +static unsigned long kvm_count_mem_attr_entries(struct kvm *kvm)
> +{
> +	XA_STATE(xas, &kvm->mem_attr_array, 0);
> +	unsigned long count = 0;
> +	void *entry;
> +
> +	xas_for_each(&xas, entry, ULONG_MAX) {

[Severity: Medium]
Will this xas_for_each() loop trigger lockdep warnings when PROVE_RCU is
enabled? 

The caller holds the slots_lock, but iterating the XArray using this
macro implicitly dereferences node pointers. XArray requires either
rcu_read_lock() or the internal xa_lock to satisfy its lockdep invariants
during traversal, neither of which appear to be held here.

> @@ -2579,6 +2608,23 @@ static int kvm_vm_set_mem_attributes(struct kvm *kvm, gfn_t start, gfn_t end,
> [ ... ]
> +	if (attributes &&
> +	    kvm->mem_attr_gfn_count + (end - start) > KVM_MEM_ATTR_MAX_GFNS) {
> +		r = -ENOSPC;
> +		goto out_unlock;
> +	}

[Severity: High]
This is a pre-existing issue, but does bypassing the limit check when clearing
attributes re-expose the vulnerability?

Because this check requires attributes to be non-zero, a caller can set a
single attribute at index 0, and then call KVM_SET_MEMORY_ATTRIBUTES with
attributes set to 0 for an enormous range. The kvm_range_has_memory_attributes()
function will evaluate to false due to the index 0 entry, and this limit check
will be bypassed.

> [ ... ]
>  	for (i = start; i < end; i++) {
>  		r = xa_reserve(&kvm->mem_attr_array, i, GFP_KERNEL_ACCOUNT);
>  		if (r)
>  			goto out_unlock;

...which causes this subsequent loop to unconditionally reserve XArray nodes for
billions of GFNs until the host hits ENOMEM, exiting without freeing the leaked
reservations.

> [ ... ]
>  out_unlock:
> +	/*
> +	 * Resynchronize with the actual state only when the array may have
> +	 * changed: on ENOMEM partway through the reserve loop, partially
> +	 * reserved GFNs are retained and must be counted, and a successful
> +	 * set or clear changes the population.  Non-mutating exits skip the
> +	 * walk so idempotent requests stay O(1).
> +	 */
> +	if (mutated)
> +		kvm->mem_attr_gfn_count = kvm_count_mem_attr_entries(kvm);
>  	mutex_unlock(&kvm->slots_lock);

[Severity: High]
Does this trigger a severe CPU denial of service during standard memory updates?

When a guest issues a series of 1-page memory attribute updates, this mutated
flag will be true for each successful update. Calling kvm_count_mem_attr_entries()
then iterates over up to 33.5 million populated entries in the XArray while holding
the slots_lock.

Performing an O(N) iteration that takes tens of milliseconds on every successful
mutation yields an O(N^2) complexity that ties up the CPU and monopolizes the
slots_lock for long periods, blocking memslot and dirty logging operations.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260911184819.101123-1-davimaba.v@proton.me?part=1

  reply	other threads:[~2026-09-11 19:05 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-11 18:48 [PATCH 0/2] KVM: unbounded per-VM kernel memory growth via KVM_SET_MEMORY_ATTRIBUTES David Ballesteros
2026-09-11 18:48 ` [PATCH 1/2] KVM: Bound per-VM GFN materialization in KVM_SET_MEMORY_ATTRIBUTES David Ballesteros
2026-09-11 19:05   ` sashiko-bot [this message]
2026-09-11 18:48 ` [PATCH 2/2] KVM: Account mem_attr_array nodes to the caller's memcg David Ballesteros
2026-09-11 19:02   ` sashiko-bot
2026-09-11 20:32 ` [PATCH v2 0/2] KVM: unbounded per-VM kernel memory growth via KVM_SET_MEMORY_ATTRIBUTES David Ballesteros
2026-09-11 21:19   ` David Ballesteros
2026-09-11 22:13   ` [PATCH v3 " David Ballesteros
2026-09-11 22:13     ` [PATCH v3 1/2] KVM: Bound per-VM GFN materialization in KVM_SET_MEMORY_ATTRIBUTES David Ballesteros
2026-09-11 22:32       ` sashiko-bot
2026-09-11 22:13     ` [PATCH v2 2/2] KVM: Account mem_attr_array nodes to the caller's memcg David Ballesteros
2026-09-11 20:32 ` [PATCH v2 1/2] KVM: Bound per-VM GFN materialization in KVM_SET_MEMORY_ATTRIBUTES David Ballesteros
2026-09-11 20:45   ` sashiko-bot
2026-09-11 20:32 ` [PATCH v2 2/2] KVM: Account mem_attr_array nodes to the caller's memcg David Ballesteros
2026-09-11 20:44   ` sashiko-bot
2026-09-12  8:48 ` [syzbot ci] Re: KVM: unbounded per-VM kernel memory growth via KVM_SET_MEMORY_ATTRIBUTES syzbot ci

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=20260911190529.2E9AA1F000FF@smtp.kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=davimaba.v@proton.me \
    --cc=kvm@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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.