[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Xen-devel] memory corruption in HYPERVISOR_physdev_op()



On Mon, 2012-10-15 at 11:48 +0100, Jan Beulich wrote:
> >>> On 15.10.12 at 12:27, Ian Campbell <Ian.Campbell@xxxxxxxxxx> wrote:
> > On Fri, 2012-09-14 at 14:24 +0300, Dan Carpenter wrote:
> >> My static analyzer complains about potential memory corruption in
> >> HYPERVISOR_physdev_op()
> >> 
> >> arch/x86/include/asm/xen/hypercall.h
> >>    389  static inline int
> >>    390  HYPERVISOR_physdev_op(int cmd, void *arg)
> >>    391  {
> >>    392          int rc = _hypercall2(int, physdev_op, cmd, arg);
> >>    393          if (unlikely(rc == -ENOSYS)) {
> >>    394                  struct physdev_op op;
> >>    395                  op.cmd = cmd;
> >>    396                  memcpy(&op.u, arg, sizeof(op.u));
> >>    397                  rc = _hypercall1(int, physdev_op_compat, &op);
> >>    398                  memcpy(arg, &op.u, sizeof(op.u));
> >>                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> >> Some of the arg buffers are not as large as sizeof(op.u) which is either
> >> 12 or 16 depending on the size of longs in struct physdev_apic.
> > 
> > Nasty!
> 
> Wasn't it that pv-ops expects Xen 4.0.1 or newer anyway? If so,
> what does this code exist for in the first place (it's framed by
> #if CONFIG_XEN_COMPAT <= 0x030002 in the Xenified kernel)?

I think the 4.0.1 or newer requirement is for dom0 only. I guess physdev
op is only used in dom0 though? Or does passthrough need it?

> 
> >>    399          }
> >>    400          return rc;
> >>    401  }
> >> 
> >> One example of this is in xen_initdom_restore_msi_irqs().
> >> 
> >> arch/x86/pci/xen.c
> >>    337                  struct physdev_pci_device restore_ext;
> >>    338  
> >>    339                  restore_ext.seg = pci_domain_nr(dev->bus);
> >>    340                  restore_ext.bus = dev->bus->number;
> >>    341                  restore_ext.devfn = dev->devfn;
> >>    342                  ret = 
> > HYPERVISOR_physdev_op(PHYSDEVOP_restore_msi_ext,
> >>    343                                          &restore_ext);
> >>                                                 ^^^^^^^^^^^^
> >> There are only 4 bytes here.
> >> 
> >>    344                  if (ret == -ENOSYS)
> >>                             ^^^^^^^^^^^^^^
> >> If we hit this condition, we have corrupted some memory.
> > 
> > I can see the memory corruption but how does it relate to ret ==
> > -ENOSYS?
> 
> The (supposedly) corrupting code site inside an
> 
>       if (unlikely(rc == -ENOSYS)) {

Ah, for some reason I assumed this was in the eventual caller, even
though it was staring me right in the face in the full quote.

> Supposedly because as long as the argument passed to the
> function is in memory accessed by the local CPU only and
> doesn't overlap with storage used for "rc" (e.g. living in a
> register), there's no corruption possible afaict - the second
> memcpy() would just copy back what the first one obtained
> from there.
> 
> Fixing this other than by removing the broken code would be
> pretty hard I'm afraid (and I tend to leave the code untouched
> altogether in the Xenified tree).

Given that it is compat code the list of subops which needs to supported
in this case is small and finite so a simple lookup table or even switch
stmt for the size might be an option.

Ian.


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.