[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [PATCH v3] x86: Fix XEN_DOMCTL_gdbsx_guestmemio crash
On 25/04/2022 2:36 pm, Jan Beulich wrote: > On 25.04.2022 14:37, Andrew Cooper wrote: >> When CONFIG_GDBSX is compiled out, iommu_do_domctl() falls over a NULL >> pointer. One of several bugs here is known-but-compiled-out subops >> falling >> into the default chain and hitting unrelated logic. >> >> Remove the CONFIG_GDBSX ifdefary in arch_do_domctl() by implementing >> gdbsx_domctl() and moving the logic across. >> >> As minor cleanup, >> * gdbsx_guest_mem_io() can become static >> * Remove opencoding of domain_vcpu() and %pd >> >> Signed-off-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx> > > Technically > Reviewed-by: Jan Beulich <jbeulich@xxxxxxxx> Thanks. I'll tweak the commit message now that the IOMMU fix has gone in. > Yet as mentioned before, ... > >> --- a/xen/arch/x86/domctl.c >> +++ b/xen/arch/x86/domctl.c >> @@ -816,71 +816,12 @@ long arch_do_domctl( >> } >> #endif >> >> -#ifdef CONFIG_GDBSX >> case XEN_DOMCTL_gdbsx_guestmemio: >> - ret = gdbsx_guest_mem_io(d, &domctl->u.gdbsx_guest_memio); >> - if ( !ret ) >> - copyback = true; >> - break; >> - >> case XEN_DOMCTL_gdbsx_pausevcpu: >> - { >> - struct vcpu *v; >> - >> - ret = -EBUSY; >> - if ( !d->controller_pause_count ) >> - break; >> - ret = -EINVAL; >> - if ( domctl->u.gdbsx_pauseunp_vcpu.vcpu >= d->max_vcpus || >> - (v = d->vcpu[domctl->u.gdbsx_pauseunp_vcpu.vcpu]) == >> NULL ) >> - break; >> - ret = vcpu_pause_by_systemcontroller(v); >> - break; >> - } >> - >> case XEN_DOMCTL_gdbsx_unpausevcpu: >> - { >> - struct vcpu *v; >> - >> - ret = -EBUSY; >> - if ( !d->controller_pause_count ) >> - break; >> - ret = -EINVAL; >> - if ( domctl->u.gdbsx_pauseunp_vcpu.vcpu >= d->max_vcpus || >> - (v = d->vcpu[domctl->u.gdbsx_pauseunp_vcpu.vcpu]) == >> NULL ) >> - break; >> - ret = vcpu_unpause_by_systemcontroller(v); >> - if ( ret == -EINVAL ) >> - printk(XENLOG_G_WARNING >> - "WARN: d%d attempting to unpause %pv which is not >> paused\n", >> - currd->domain_id, v); >> - break; >> - } >> - >> case XEN_DOMCTL_gdbsx_domstatus: >> - { >> - struct vcpu *v; >> - >> - domctl->u.gdbsx_domstatus.vcpu_id = -1; >> - domctl->u.gdbsx_domstatus.paused = d->controller_pause_count >> > 0; >> - if ( domctl->u.gdbsx_domstatus.paused ) >> - { >> - for_each_vcpu ( d, v ) >> - { >> - if ( v->arch.gdbsx_vcpu_event ) >> - { >> - domctl->u.gdbsx_domstatus.vcpu_id = v->vcpu_id; >> - domctl->u.gdbsx_domstatus.vcpu_ev = >> - v->arch.gdbsx_vcpu_event; >> - v->arch.gdbsx_vcpu_event = 0; >> - break; >> - } >> - } >> - } >> - copyback = true; >> + ret = gdbsx_domctl(d, domctl, ©back); >> break; >> - } >> -#endif > > ... I'm not overly happy with the retaining of the case labels here > (and the knock on effect it'll have for other subsystem domctl-s), The crash in do_iommu_op() happened because things which weren't iommu subops ended up in a function only expecting iommu subops, *because* unrelated case labels got compiled out. We've also had multiple XSAs elsewhere created by related "just chain everything through default:" patterns. The legacy MSR paths are still especially guilty of doing this. The case labels need to never ever get compiled out, even if their subsystem has been. So you have a choice between this patch, or a pattern of the form: case XEN_DOMCTL_gdbsx_domstatus: if ( !IS_ENABLED(CONFIG_GDBSX) ) { ret = -Exxx; break; } ... but the top level case labels need to stay one way or another. For this patch, it moves a chunk of logic out of a fairly generic file into its proper subsystem file, and a few extra case labels is a very cheap price to pay. ~Andrew
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |