[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH] linux-2.6.18: fix hypercall fallback code for very old hypervisors
On Tue, 2012-10-16 at 13:29 +0100, Jan Beulich wrote: > While copying the argument structures in HYPERVISOR_event_channel_op() > and HYPERVISOR_physdev_op() into the local variable is sufficiently > safe even if the actual structure is smaller than the container one, > copying back eventual output values the same way isn't: This may > collide with on-stack variables (particularly "rc") which may change > between the first and second memcpy() (i.e. the second memcpy() could > discard that change). > > Move the fallback code into out-of-line functions, and handle all of > the operations known by this old a hypervisor individually: Some don't > require copying back anything at all, and for the rest use the > individual argument structures' sizes rather than the containter's. CC-ing Konrad (and therefore not trimming quotes) Typo: "containers" > Reported-by: Dan Carpenter <dan.carpenter@xxxxxxxxxx> > Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx> > > --- a/drivers/xen/core/Makefile > +++ b/drivers/xen/core/Makefile > @@ -2,7 +2,7 @@ > # Makefile for the linux kernel. > # > > -obj-y := evtchn.o gnttab.o features.o reboot.o machine_reboot.o > +obj-y := evtchn.o gnttab.o features.o reboot.o machine_reboot.o fallback.o > > obj-$(CONFIG_PCI) += pci.o > obj-$(CONFIG_XEN_PRIVILEGED_GUEST) += firmware.o > --- /dev/null > +++ b/drivers/xen/core/fallback.c > @@ -0,0 +1,88 @@ > +#include <linux/kernel.h> > +#include <linux/string.h> > +#include <asm/bug.h> > +#include <asm/hypervisor.h> > + > +#if CONFIG_XEN_COMPAT <= 0x030002 > + > +#include <xen/interface/event_channel.h> > +#include <xen/interface/physdev.h> > + > +int HYPERVISOR_event_channel_op_compat(int cmd, void *arg) > +{ > + struct evtchn_op op; > + int rc; > + > + op.cmd = cmd; > + memcpy(&op.u, arg, sizeof(op.u)); > + rc = _hypercall1(int, event_channel_op_compat, &op); > + > + switch (cmd) { > + case EVTCHNOP_close: > + case EVTCHNOP_send: > + case EVTCHNOP_bind_vcpu: > + case EVTCHNOP_unmask: > + /* no output */ > + break; > + > +#define COPY_BACK(eop) \ > + case EVTCHNOP_##eop: \ > + memcpy(arg, &op.u.eop, sizeof(op.u.eop)); \ > + break > + > + COPY_BACK(bind_interdomain); > + COPY_BACK(bind_virq); > + COPY_BACK(bind_pirq); > + COPY_BACK(status); > + COPY_BACK(alloc_unbound); > + COPY_BACK(bind_ipi); > +#undef COPY_BACK > + > + default: > + WARN_ON(rc != -ENOSYS); > + break; > + } > + > + return rc; > +} > + > +int HYPERVISOR_physdev_op_compat(int cmd, void *arg) > +{ > + struct physdev_op op; > + int rc; > + > + op.cmd = cmd; > + memcpy(&op.u, arg, sizeof(op.u)); > + rc = _hypercall1(int, physdev_op_compat, &op); > + > + switch (cmd) { > + case PHYSDEVOP_IRQ_UNMASK_NOTIFY: > + case PHYSDEVOP_set_iopl: > + case PHYSDEVOP_set_iobitmap: > + case PHYSDEVOP_apic_write: > + /* no output */ > + break; > + > +#define COPY_BACK(pop) \ > + case PHYSDEVOP_##pop: \ > + memcpy(arg, &op.u.pop, sizeof(op.u.pop)); \ > + break > + > + COPY_BACK(irq_status_query); > +#define apic_read apic_op > + COPY_BACK(apic_read); > +#undef apic_read > +#define ASSIGN_VECTOR irq_op > + COPY_BACK(ASSIGN_VECTOR); > +#undef ASSIGN_VECTOR > +#undef COPY_BACK I think rather than this def/undef dance either a two argument macro or open coding the two cases would be cleaner. > + > + default: > + WARN_ON(rc != -ENOSYS); > + break; > + } > + > + return rc; > +} > + > +#endif /* CONFIG_XEN_COMPAT <= 0x030002 */ > --- a/include/asm-i386/mach-xen/asm/hypercall.h > +++ b/include/asm-i386/mach-xen/asm/hypercall.h > @@ -33,7 +33,6 @@ > #ifndef __HYPERCALL_H__ > #define __HYPERCALL_H__ > > -#include <linux/string.h> /* memcpy() */ > #include <linux/stringify.h> > > #ifndef __HYPERVISOR_H__ > @@ -128,6 +127,11 @@ > __res; \ > }) > > +#if CONFIG_XEN_COMPAT <= 0x030002 > +int __must_check HYPERVISOR_event_channel_op_compat(int, void *); > +int __must_check HYPERVISOR_physdev_op_compat(int, void *); > +#endif > + > static inline int __must_check > HYPERVISOR_set_trap_table( > const trap_info_t *table) > @@ -267,13 +271,8 @@ HYPERVISOR_event_channel_op( > int rc = _hypercall2(int, event_channel_op, cmd, arg); > > #if CONFIG_XEN_COMPAT <= 0x030002 > - if (unlikely(rc == -ENOSYS)) { > - struct evtchn_op op; > - op.cmd = cmd; > - memcpy(&op.u, arg, sizeof(op.u)); > - rc = _hypercall1(int, event_channel_op_compat, &op); > - memcpy(arg, &op.u, sizeof(op.u)); > - } > + if (unlikely(rc == -ENOSYS)) > + rc = HYPERVISOR_event_channel_op_compat(cmd, arg); > #endif > > return rc; > @@ -300,13 +299,8 @@ HYPERVISOR_physdev_op( > int rc = _hypercall2(int, physdev_op, cmd, arg); > > #if CONFIG_XEN_COMPAT <= 0x030002 > - if (unlikely(rc == -ENOSYS)) { > - struct physdev_op op; > - op.cmd = cmd; > - memcpy(&op.u, arg, sizeof(op.u)); > - rc = _hypercall1(int, physdev_op_compat, &op); > - memcpy(arg, &op.u, sizeof(op.u)); > - } > + if (unlikely(rc == -ENOSYS)) > + rc = HYPERVISOR_physdev_op_compat(cmd, arg); > #endif > > return rc; > --- a/include/asm-i386/mach-xen/asm/hypervisor.h > +++ b/include/asm-i386/mach-xen/asm/hypervisor.h > @@ -39,8 +39,6 @@ > #include <linux/errno.h> > #include <xen/interface/xen.h> > #include <xen/interface/platform.h> > -#include <xen/interface/event_channel.h> > -#include <xen/interface/physdev.h> > #include <xen/interface/sched.h> > #include <xen/interface/nmi.h> > #include <xen/interface/tmem.h> > > _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |