Re: [PATCH v18 06/14] KVM: arm64: Validate GCS exception lock when emulating ERET

[email protected] Mon, 03 Aug 2026 23:41:44 +0000
Newsgroups dev.linux.lists.kvmarm
Message-ID <[email protected]>
Thank you for your contribution! Sashiko AI review found 1 potential issue(=
s) to consider:
- [High] kvm_check_illegal_exlock_return() incorrectly reads the host's phy=
sical GCSCR_EL1 register instead of the guest's virtual registers when emul=
ating an ERET.
--

--- Patch [6]: [PATCH v18 06/14] KVM: arm64: Validate GCS exception lock wh=
en emulating ERET ---
commit 1a99244e8c449893f9c88233d42b775527985630
Author: Mark Brown <[email protected]>

KVM: arm64: Validate GCS exception lock when emulating ERET

This commit adds validation for a GCS-specific case where an illegal
exception return can be generated due to an EXLOCK mismatch, emulating this
behavior for nested guests.

> diff --git a/arch/arm64/include/asm/kvm_nested.h b/arch/arm64/include/asm=
/kvm_nested.h
> index 012d711034d17..b2343f67d15b7 100644
> --- a/arch/arm64/include/asm/kvm_nested.h
> +++ b/arch/arm64/include/asm/kvm_nested.h
[ ... ]
> @@ -240,6 +240,45 @@ static inline bool kvm_auth_eretax(struct kvm_vcpu *=
vcpu, u64 *elr)
>  }
>  #endif
> =20
> +#ifdef CONFIG_ARM64_GCS
> +/*
> + * A subset of the pseudocode ELFromSPSR(), validity checks are
> + * assumed to have been done in code that is not GCS specific.
> + */
> +static inline int exlock_el_from_spsr(u64 spsr)
> +{
> +	return FIELD_GET(GENMASK(3, 2), spsr);
> +}
> +
> +/* See IllegalExceptionReturn() pseudocode */
> +static inline bool kvm_check_illegal_exlock_return(struct kvm_vcpu *vcpu,
> +						   u64 spsr)
> +{
> +	u64 cur_el, target_el;
> +
> +	if (!kvm_has_gcs(vcpu->kvm))
> +		return false;
> +
> +	if (vcpu->arch.ctxt.regs.pstate & PSR_EXLOCK_BIT)
> +		return false;
> +
> +	cur_el =3D exlock_el_from_spsr(vcpu->arch.ctxt.regs.pstate);
> +	target_el =3D exlock_el_from_spsr(spsr);
> +
> +	if (cur_el !=3D target_el)
> +		return false;
> +
> +	return read_sysreg_el1(SYS_GCSCR) & GCSCR_ELx_EXLOCKEN;

[Severity: High]
Does this code read the host's physical GCSCR_EL1 hardware register instead
of the nested guest's virtual register?

When emulating an ERET for a nested guest, this validation is called in the
slow path:

kvm_check_illegal_exception_return()
   kvm_check_illegal_exlock_return()

At this point, the world switch has already finished, meaning the physical
registers hold the host's state. Reading the physical SYS_GCSCR here will
cause the nested guest's ERET behavior to be evaluated against the host
userspace configuration, which might incorrectly trigger or miss architectu=
rally
required exception injections.

Should this fetch the guest's virtual register via vcpu_read_sys_reg()
instead, depending on the value of cur_el?

> +}
> +
> +#else
> +static inline bool kvm_check_illegal_exlock_return(struct kvm_vcpu *vcpu,
> +						   u64 spsr)
> +{
> +	return false;
> +}
> +#endif
[ ... ]
> diff --git a/arch/arm64/kvm/emulate-nested.c b/arch/arm64/kvm/emulate-nes=
ted.c
> index b32742d9dd73e..0f0723f22000a 100644
> --- a/arch/arm64/kvm/emulate-nested.c
> +++ b/arch/arm64/kvm/emulate-nested.c
[ ... ]
> @@ -2740,10 +2740,13 @@ static u64 kvm_check_illegal_exception_return(str=
uct kvm_vcpu *vcpu, u64 spsr)
>  	 * - trying to return to an illegal M value
>  	 * - trying to return to a 32bit EL
>  	 * - trying to return to EL1 with HCR_EL2.TGE set
> +	 * - GCSCR_ELx.EXLOCKEN is 1 and PSTATE.EXLOCK is 0 when attempting
> +	 *   to return from ELx the same EL.
>  	 */
>  	if (mode =3D=3D PSR_MODE_EL3t   || mode =3D=3D PSR_MODE_EL3h ||
>  	    mode =3D=3D 0b00001         || (mode & BIT(1))       ||
>  	    (spsr & PSR_MODE32_BIT) ||
> +	    kvm_check_illegal_exlock_return(vcpu, spsr) ||
>  	    (vcpu_el2_tge_is_set(vcpu) && (mode =3D=3D PSR_MODE_EL1t ||
>  					   mode =3D=3D PSR_MODE_EL1h))) {
>  		u64 mask;

--=20
Sashiko AI review =C2=B7 https://sashiko.dev/#/patchset/20260803-arm64-gcs-=
[email protected]?part=3D6