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

Wei-Lin Chang <[email protected]>
Newsgroups dev.linux.lists.sashiko-reviews,dev.linux.lists.kvmarm
Message-ID <kepali2qvsom3x55qfdsvsf6vs6vcg3ubkz6zisjfoncrwsvaq@5nftl3thh7i2>
On Mon, Aug 10, 2026 at 05:43:08PM +0000, [email protected] wrote:
> 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*?

base is correctly sign-extended now [1].

[1]: https://git.kernel.org/kvmarm/kvmarm/c/239347008564

> 
> > +
> > +	/* 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?

There is no 52-bit support for NV guests.

> 
> [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.

This looks correct to me, but irrelevant to this patch.

> 
> > +	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?

base is sign-extended now, see above.

Thanks,
Wei-Lin Chang

> 
> > +
> >  	return base;
> >  }
> >
> 
> -- 
> Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=1
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.