Re: [PATCH v1 09/11] KVM: arm64: Minimise EL2's exposure of host VGIC state during world switch

Fuad Tabba <[email protected]> Thu, 6 Aug 2026 11:05:16 +0100
Newsgroups dev.linux.lists.kvmarm,dev.linux.lists.sashiko-reviews
Message-ID <CA+EHjTxiHyuw5EjWLha1OySm3xjRH6rbk41On+5V2+ig1FdCmg@mail.gmail.com>
Hi folks,

On Fri, 12 Jun 2026 at 09:05, Fuad Tabba <[email protected]> wrote:
...
> > Pre-existing issues:
> > - [Critical] The GICv5 equivalents of the VGIC save/restore hypercalls (`handle___vgic_v5_save_apr` and `handle___vgic_v5_restore_vmcr_apr`) directly dereference host-provided pointers without validation, allowing a complete bypass of pKVM isolation.
...
> > > +     } else {
> > > +             __vgic_v3_save_aprs(&host_vcpu->arch.vgic_cpu.vgic_v3);
> > > +     }
> > >  }
> >
> > [Severity: Critical]
> > This is a pre-existing issue, but while this patch addresses the VGIC v3 host
> > pointer dereference bypass by using get_host_hyp_vcpus_from_vgic_v3_cpu_if(),
> > does the same pKVM isolation bypass exist in the GICv5 equivalents?
>
> GICv5 is not supported in protected mode. vgic-v5.c:62-64 skips
> GICv5 registration entirely when is_protected_kvm_enabled(), so no
> GICv5-based guest can be created under pKVM. The host never reaches
> these hypercalls through any legitimate code path.

I was wrong here.

skip_v5 only stops the host's own KVM from registering a GICv5 vgic,
so the host can still call __vgic_v5_save_apr and
__vgic_v5_restore_vmcr_apr.

vgic_model has the same gap. EL2 copies it out of the host's `struct
kvm` without validating it, so a host can steer the world switch into
the GICv5 registers, which are UNDEFINED without FEAT_GCIE. That takes
an UNDEF at EL2 and panics the hypervisor. I reproduced it under QEMU
on a GICv3 machine.

I have sent a series for both [1]. The wider point is that "pKVM does
not support GICv5" does not imply "EL2 cannot get there", which is
what I had assumed, so it might be worth another look at the newer
hypercalls in Sascha's IRS series on that basis [2].

Cheers,
/fuad

[1] https://lore.kernel.org/all/[email protected]/
[2] https://lore.kernel.org/all/[email protected]/


>
> >
> > Looking at handle___vgic_v5_save_apr() and handle___vgic_v5_restore_vmcr_apr()
> > in arch/arm64/kvm/hyp/nvhe/hyp-main.c:
> >
> > handle___vgic_v5_save_apr(struct kvm_cpu_context *host_ctxt) {
> >     DECLARE_REG(struct vgic_v5_cpu_if *, cpu_if, host_ctxt, 1);
> >     __vgic_v5_save_apr(kern_hyp_va(cpu_if));
> > }
> >
> > These handlers appear to take a cpu_if pointer directly from the untrusted
> > host context and apply kern_hyp_va() without validation. Could a malicious
> > host provide an address that translates to an arbitrary EL2-private memory
> > location, granting an arbitrary write or read primitive when
> > __vgic_v5_save_apr() or __vgic_v5_restore_vmcr_apr() is invoked?
> >
> > [Severity: Critical]
> > This is also a pre-existing issue, but does a similar arbitrary memory
> > corruption primitive exist in handle___kvm_adjust_pc()?
>
> Yes, pre-existing. It is addressed later in this series by
> "Prevent host PC adjustments for protected vCPUs" (patch 10/11).
>
> Cheers,
> /fuad
>
> >
> > Looking at handle___kvm_adjust_pc() in arch/arm64/kvm/hyp/nvhe/hyp-main.c:
> >
> > static void handle___kvm_adjust_pc(struct kvm_cpu_context *host_ctxt) {
> >     DECLARE_REG(struct kvm_vcpu *, vcpu, host_ctxt, 1);
> >     __kvm_adjust_pc(kern_hyp_va(vcpu));
> > }
> >
> > And __kvm_adjust_pc() in arch/arm64/kvm/hyp/exception.c:
> >
> > void __kvm_adjust_pc(struct kvm_vcpu *vcpu) {
> >     if (vcpu_get_flag(vcpu, PENDING_EXCEPTION)) {
> >         kvm_inject_exception(vcpu);
> >         vcpu_clear_flag(vcpu, PENDING_EXCEPTION);
> >         vcpu_clear_flag(vcpu, EXCEPT_MASK);
> >     }
> >     ...
> > }
> >
> > It seems the host-provided vcpu pointer is converted via kern_hyp_va()
> > without the __get_host_hyp_vcpus() validation barrier. Could a malicious
> > host inject a pointer that translates into EL2-private memory (like
> > hypervisor page tables) and set the PENDING_EXCEPTION bit, forcing
> > __kvm_adjust_pc() to write exception vector addresses and clear flags at
> > specific offsets within the target structure?
> >
> > --
> > Sashiko AI review ยท https://sashiko.dev/#/patchset/[email protected]?part=9