Gcc 11 detected a bug in many places using the HYPERVISOR_event_channel_op function was used. This function works on many types of operations, so assumes it can read and write the maximal size of the operation's parameters - 24 bytes. And yet, it was called for smaller, specific, operation object.
This patch fixes all the calls to build a maximal-size operation object. I'm not very happy about this patch - it is only needed for some situation marked unlikely - where all this problematic copying happens - but I want to restore the ability to build on Fedora 34 which has gcc 11. Signed-off-by: Nadav Har'El <[email protected]> --- bsd/sys/xen/evtchn.cc | 77 ++++++++++++++++++------------------ bsd/sys/xen/xenbus/xenbus.cc | 16 ++++---- bsd/sys/xen/evtchn.h | 5 ++- 3 files changed, 50 insertions(+), 48 deletions(-) diff --git a/bsd/sys/xen/evtchn.cc b/bsd/sys/xen/evtchn.cc index 733f0993..52f769fb 100644 --- a/bsd/sys/xen/evtchn.cc +++ b/bsd/sys/xen/evtchn.cc @@ -275,38 +275,38 @@ bind_local_port_to_irq(unsigned int local_port, int * port) int bind_listening_port_to_irq(unsigned int remote_domain, int * port) { - struct evtchn_alloc_unbound alloc_unbound; + struct evtchn_op alloc_unbound; int err; - alloc_unbound.dom = DOMID_SELF; - alloc_unbound.remote_dom = remote_domain; + alloc_unbound.u.alloc_unbound.dom = DOMID_SELF; + alloc_unbound.u.alloc_unbound.remote_dom = remote_domain; err = HYPERVISOR_event_channel_op(EVTCHNOP_alloc_unbound, - &alloc_unbound); + &alloc_unbound.u); - return err ? : bind_local_port_to_irq(alloc_unbound.port, port); + return err ? : bind_local_port_to_irq(alloc_unbound.u.alloc_unbound.port, port); } static int bind_interdomain_evtchn_to_irq(unsigned int remote_domain, unsigned int remote_port, int * port) { - struct evtchn_bind_interdomain bind_interdomain; + struct evtchn_op op; int err; - bind_interdomain.remote_dom = remote_domain; - bind_interdomain.remote_port = remote_port; + op.u.bind_interdomain.remote_dom = remote_domain; + op.u.bind_interdomain.remote_port = remote_port; err = HYPERVISOR_event_channel_op(EVTCHNOP_bind_interdomain, - &bind_interdomain); + &op.u); - return err ? : bind_local_port_to_irq(bind_interdomain.local_port, port); + return err ? : bind_local_port_to_irq(op.u.bind_interdomain.local_port, port); } static int bind_virq_to_irq(unsigned int virq, unsigned int cpu, int * port) { - struct evtchn_bind_virq bind_virq; + struct evtchn_op op; int evtchn = 0, irq; mtx_lock_spin(&irq_mapping_update_lock); @@ -315,11 +315,11 @@ bind_virq_to_irq(unsigned int virq, unsigned int cpu, int * port) if ((irq = find_unbound_irq()) < 0) goto out; - bind_virq.virq = virq; - bind_virq.vcpu = cpu; - HYPERVISOR_event_channel_op(EVTCHNOP_bind_virq, &bind_virq); + op.u.bind_virq.virq = virq; + op.u.bind_virq.vcpu = cpu; + HYPERVISOR_event_channel_op(EVTCHNOP_bind_virq, &op.u); - evtchn = bind_virq.port; + evtchn = op.u.bind_virq.port; evtchn_to_irq[evtchn] = irq; irq_info[irq] = mk_irq_info(IRQT_VIRQ, virq, evtchn); @@ -341,7 +341,7 @@ out: static int bind_ipi_to_irq(unsigned int ipi, unsigned int cpu, int * port) { - struct evtchn_bind_ipi bind_ipi; + struct evtchn_op op; int irq; int evtchn = 0; @@ -351,9 +351,9 @@ bind_ipi_to_irq(unsigned int ipi, unsigned int cpu, int * port) if ((irq = find_unbound_irq()) < 0) goto out; - bind_ipi.vcpu = cpu; - HYPERVISOR_event_channel_op(EVTCHNOP_bind_ipi, &bind_ipi); - evtchn = bind_ipi.port; + op.u.bind_ipi.vcpu = cpu; + HYPERVISOR_event_channel_op(EVTCHNOP_bind_ipi, &op.u); + evtchn = op.u.bind_ipi.port; evtchn_to_irq[evtchn] = irq; irq_info[irq] = mk_irq_info(IRQT_IPI, ipi, evtchn); @@ -375,15 +375,15 @@ out: static void unbind_from_irq(int irq) { - struct evtchn_close close; int evtchn = evtchn_from_irq(irq); int cpu; mtx_lock_spin(&irq_mapping_update_lock); if ((--irq_bindcount[irq] == 0) && VALID_EVTCHN(evtchn)) { - close.port = evtchn; - HYPERVISOR_event_channel_op(EVTCHNOP_close, &close); + struct evtchn_op op; + op.u.close.port = evtchn; + HYPERVISOR_event_channel_op(EVTCHNOP_close, &op.u); switch (type_from_irq(irq)) { case IRQT_VIRQ: @@ -799,7 +799,7 @@ pirq_query_unmask(int pirq) static void xenpic_pirq_enable_intr(struct intsrc *isrc) { - struct evtchn_bind_pirq bind_pirq; + struct evtchn_op op; int evtchn; unsigned int irq; @@ -810,11 +810,11 @@ xenpic_pirq_enable_intr(struct intsrc *isrc) if (VALID_EVTCHN(evtchn)) goto out; - bind_pirq.pirq = irq; + op.u.bind_pirq.pirq = irq; /* NB. We are happy to share unless we are probing. */ - bind_pirq.flags = probing_irq(irq) ? 0 : BIND_PIRQ__WILL_SHARE; + op.u.bind_pirq.flags = probing_irq(irq) ? 0 : BIND_PIRQ__WILL_SHARE; - if (HYPERVISOR_event_channel_op(EVTCHNOP_bind_pirq, &bind_pirq) != 0) { + if (HYPERVISOR_event_channel_op(EVTCHNOP_bind_pirq, &op.u) != 0) { #ifndef XEN_PRIVILEGED_GUEST panic("unexpected pirq call"); #endif @@ -823,7 +823,7 @@ xenpic_pirq_enable_intr(struct intsrc *isrc) mtx_unlock_spin(&irq_mapping_update_lock); return; } - evtchn = bind_pirq.port; + evtchn = op.u.bind_pirq.port; pirq_query_unmask(irq_to_pirq(irq)); @@ -916,8 +916,9 @@ unmask_evtchn(int port) /* Slow path (hypercall) if this is a non-local port. */ if (unlikely(irq_is_legacy || (cpu != cpu_from_evtchn(port)))) { - struct evtchn_unmask unmask = { .port = port }; - (void)HYPERVISOR_event_channel_op(EVTCHNOP_unmask, &unmask); + struct evtchn_op op; + op.u.unmask.port = port; + (void)HYPERVISOR_event_channel_op(EVTCHNOP_unmask, &op.u); return; } @@ -942,8 +943,8 @@ void irq_resume(void) evtchn_op_t op; int cpu, pirq, virq, ipi, irq, evtchn; - struct evtchn_bind_virq bind_virq; - struct evtchn_bind_ipi bind_ipi; + struct evtchn_op op_bind_virq; + struct evtchn_op op_bind_ipi; init_evtchn_cpu_bindings(); @@ -984,10 +985,10 @@ void irq_resume(void) ("irq_info inconsistent")); /* Get a new binding from Xen. */ - bind_virq.virq = virq; - bind_virq.vcpu = 0; - HYPERVISOR_event_channel_op(EVTCHNOP_bind_virq, &bind_virq); - evtchn = bind_virq.port; + op_bind_virq.u.bind_virq.virq = virq; + op_bind_virq.u.bind_virq.vcpu = 0; + HYPERVISOR_event_channel_op(EVTCHNOP_bind_virq, &op_bind_virq.u); + evtchn = op_bind_virq.u.bind_virq.port; /* Record the new mapping. */ evtchn_to_irq[evtchn] = irq; @@ -1007,9 +1008,9 @@ void irq_resume(void) /* Get a new binding from Xen. */ memset(&op, 0, sizeof(op)); - bind_ipi.vcpu = 0; - HYPERVISOR_event_channel_op(EVTCHNOP_bind_ipi, &bind_ipi); - evtchn = bind_ipi.port; + op_bind_ipi.u.bind_ipi.vcpu = 0; + HYPERVISOR_event_channel_op(EVTCHNOP_bind_ipi, &op_bind_ipi.u); + evtchn = op_bind_ipi.u.bind_ipi.port; /* Record the new mapping. */ evtchn_to_irq[evtchn] = irq; diff --git a/bsd/sys/xen/xenbus/xenbus.cc b/bsd/sys/xen/xenbus/xenbus.cc index c92df112..9a166f00 100644 --- a/bsd/sys/xen/xenbus/xenbus.cc +++ b/bsd/sys/xen/xenbus/xenbus.cc @@ -225,32 +225,32 @@ xenbus_grant_ring(device_t dev, unsigned long ring_mfn, grant_ref_t *refp) int xenbus_alloc_evtchn(device_t dev, evtchn_port_t *port) { - struct evtchn_alloc_unbound alloc_unbound; + struct evtchn_op op; int err; - alloc_unbound.dom = DOMID_SELF; - alloc_unbound.remote_dom = xenbus_get_otherend_id(dev); + op.u.alloc_unbound.dom = DOMID_SELF; + op.u.alloc_unbound.remote_dom = xenbus_get_otherend_id(dev); err = HYPERVISOR_event_channel_op(EVTCHNOP_alloc_unbound, - &alloc_unbound); + &op.u); if (err) { xenbus_dev_fatal(dev, -err, "allocating event channel"); return (-err); } - *port = alloc_unbound.port; + *port = op.u.alloc_unbound.port; return (0); } int xenbus_free_evtchn(device_t dev, evtchn_port_t port) { - struct evtchn_close close; + struct evtchn_op op; int err; - close.port = port; + op.u.close.port = port; - err = HYPERVISOR_event_channel_op(EVTCHNOP_close, &close); + err = HYPERVISOR_event_channel_op(EVTCHNOP_close, &op.u); if (err) { xenbus_dev_error(dev, -err, "freeing event channel %d", port); return (-err); diff --git a/bsd/sys/xen/evtchn.h b/bsd/sys/xen/evtchn.h index 6d754b3e..e9bddd72 100644 --- a/bsd/sys/xen/evtchn.h +++ b/bsd/sys/xen/evtchn.h @@ -57,8 +57,9 @@ clear_evtchn(int port) inline void notify_remote_via_evtchn(int port) { - struct evtchn_send send = { .port = port }; - (void)HYPERVISOR_event_channel_op(EVTCHNOP_send, &send); + struct evtchn_op send; + send.u.send.port = port; + (void)HYPERVISOR_event_channel_op(EVTCHNOP_send, &send.u); } /* -- 2.31.1 -- You received this message because you are subscribed to the Google Groups "OSv Development" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. To view this discussion on the web visit https://groups.google.com/d/msgid/osv-dev/20210614062057.1998552-6-nyh%40scylladb.com.
