Re: [PATCH v1 09/11] KVM: arm64: Minimise EL2's exposure of host VGIC state during world switch
Sascha Bischoff <[email protected]> Fri, 7 Aug 2026 10:08:51 +0000
| Newsgroups | dev.linux.lists.kvmarm,dev.linux.lists.sashiko-reviews |
|---|---|
| Message-ID | <[email protected]> |
Hi Fuad, On Thu, 2026-08-06 at 11:05 +0100, Fuad Tabba wrote: > 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]. Yeah, that's very much my bad. I'd been working under the wrong assumption here, so thank you for addressing these issues. I've gone and replicated what you did for the other hypercalls in [1] for my upcoming v5 posting of the GICv5 IRS series. The calls become NOPs with pKVM enabled. Thanks again, Sascha > > 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