Re: [PATCH] KVM: arm64: Correctly cap TLBI Range to the architural limit

[email protected] Mon, 10 Aug 2026 17:43:08 +0000
Newsgroups dev.linux.lists.kvmarm
Message-ID <[email protected]>
Thank you for your contribution! Sashiko AI review found 4 potential issue(s) to consider:

New issues:
- [High] Hardcoded BIT(48) cap truncates valid 52-bit IPAs and underflows for higher addresses
- [High] Upper-half range cap `~base + 1` is completely ineffective due to missing sign-extension

Pre-existing issues:
- [High] Range TLB invalidations for upper-half VAs silently fail to invalidate the VNCR cache
- [High] Malicious guests can still trigger a host WARN_ON because the BIT(48) cap ignores smaller VM ia_bits
--

--- Patch [1]: [PATCH] KVM: arm64: Correctly cap TLBI Range to the architural limit ---
commit 09ab12a5dd613f7e322a9123897db5c50369508d
Author: Marc Zyngier <[email protected]>

KVM: arm64: Correctly cap TLBI Range to the architural limit

This commit caps the range of a TLB invalidation based on the base address
to prevent guests from triggering an overflow when the hypervisor adds the
range to the base address.

Link: https://lore.kernel.org/r/yifz3wn5gk5sr6mapi32trgk5m5kp33bquctsjmkifebnsnndt@fix6u4rthx4g

> diff --git a/arch/arm64/include/asm/kvm_nested.h b/arch/arm64/include/asm/kvm_nested.h
> index cdf3e8422ea12..b68806b3bd6e5 100644
> --- a/arch/arm64/include/asm/kvm_nested.h
> +++ b/arch/arm64/include/asm/kvm_nested.h
> @@ -298,6 +298,12 @@ static inline u64 decode_range_tlbi(u64 val, u64 *range, u16 *asid)
>  	num	= FIELD_GET(GENMASK(43, 39), val);
>  	*range	= __TLBI_RANGE_PAGES(num, scale) << shift;

[Severity: High]
This isn't a bug introduced by this patch, but earlier in
decode_range_tlbi(), base is extracted without sign-extension:

	base = (val & GENMASK(36, 0)) << shift;

For upper-half kernel virtual addresses, base will be zero-extended. When
invalidate_vncr_va() in arch/arm64/kvm/nested.c checks if this invalidation
intersects with a cached VNCR TLB (vt->gva), the cached TLB is correctly
sign-extended. The bounds check incorrectly fails due to comparing a
sign-extended gva against a zero-extended scope->va:

	if (va_end <= scope->va ||
	    va_start >= (scope->va + scope->size))
		continue;

Does this leave stale entries in the VNCR cache and break memory isolation
for nested guests when they invalidate an upper-half VA range via
TLBI RVAE1*?

> +
> +	/* Cap the range to the correct half of the address space */
> +	if (!(base & BIT(48)))
> +		*range = min(*range, (BIT(48) - base));

[Severity: High]
Does this hardcoded BIT(48) cap incorrectly truncate valid 52-bit IPAs?

For guests with a 52-bit IPA space (FEAT_LPA), a valid TLB invalidation over
the entire address space (base=0, range=BIT(52)) appears to be truncated to
BIT(48), potentially leaving stale mappings in the upper 48-52 bits.

Additionally, if the base address exceeds BIT(48) but has bit 48 cleared
(for example, base=BIT(49)), won't (BIT(48) - base) underflow to a massive
unsigned value, bypassing the cap and failing to prevent the overflow?

[Severity: High]
This is a pre-existing issue, but since this cap uses BIT(48), can a nested
guest still trigger the host WARN_ON in __unmap_stage2_range() if the VM's
configured PARange (ia_bits) is smaller than 48?

If a guest supplies a base and range that stays below BIT(48) but exceeds
the VM's actual limit (for example, BIT(40)), it seems _kvm_pgtable_walk() in
arch/arm64/kvm/hyp/pgtable.c will still return -ERANGE:

	if (data->addr > limit || data->end > limit)
		return -ERANGE;

This bypasses the new cap and can trigger the warning, which could act as a
Denial of Service if panic_on_warn is set.

> +	else
> +		*range = min(*range, ~base + 1);

[Severity: High]
Is this upper-half range cap mathematically effective without base being
sign-extended?

Since decode_range_tlbi() leaves base as a positive unsigned 64-bit integer,
~base + 1 evaluates to an extremely large positive value near 2^64. Will
min(*range, ~base + 1) always evaluate to *range, leaving the range uncapped
and still vulnerable to the overflow for upper-half virtual addresses?

> +
>  	return base;
>  }
>

-- 
Sashiko AI review ยท https://sashiko.dev/#/patchset/[email protected]?part=1