qemu-patch-raspberry4/hw/usb
Jonathan Davies f30815390a usb: drop unnecessary usb_device_post_load checks
In usb_device_post_load, certain values of dev->setup_len or
dev->setup_index can cause -EINVAL to be returned. One example is when
setup_len exceeds 4096, the hard-coded value of sizeof(dev->data_buf).
This can happen through legitimate guest activity and will cause all
subsequent attempts to migrate the guest to fail in vmstate_load_state.

The values of these variables can be set by USB packets originating in
the guest. There are two ways in which they can be set: in
do_token_setup and in do_parameter in hw/usb/core.c.

It is easy to craft a USB packet in a guest that causes do_token_setup
to set setup_len to a value larger than 4096. When this has been done
once, all subsequent attempts to migrate the VM will fail in
usb_device_post_load until the VM is next power-cycled or a
smaller-sized USB packet is sent to the device.

Sample code for achieving this in a VM started with "-device usb-tablet"
running Linux with CONFIG_HIDRAW=y and HID_MAX_BUFFER_SIZE > 4096:

  #include <sys/types.h>
  #include <sys/stat.h>
  #include <fcntl.h>
  #include <unistd.h>

  int main() {
           char buf[4097];
           int fd = open("/dev/hidraw0", O_RDWR|O_NONBLOCK);

           buf[0] = 0x1;
           write(fd, buf, 4097);

           return 0;
  }

When this code is run in the VM, qemu will output:

  usb_generic_handle_packet: ctrl buffer too small (4097 > 4096)

A subsequent attempt to migrate the VM will fail and output the
following on the destination host:

  qemu-kvm: error while loading state for instance 0x0 of device '0000:00:06.7/1/usb-ptr'
  qemu-kvm: load of migration failed: Invalid argument

The idea behind checking the values of setup_len and setup_index before
they are used is correct, but doing it in usb_device_post_load feels
arbitrary, and will cause unnecessary migration failures. Indeed, none
of the commit messages for c60174e8, 9f8e9895 and 719ffe1f justify why
post_load is the right place to do these checks. They correctly point
out that the important thing to protect is the usb_packet_copy.

Instead, the right place to do the checks is in do_token_setup and
do_parameter. Indeed, there are already some checks here. We can examine
each of the disjuncts currently tested in usb_device_post_load to see
whether any need adding to do_token_setup or do_parameter to improve
safety there:

  * dev->setup_index < 0
     - This test is not needed because setup_index is explicitly set to
0 in do_token_setup and do_parameter.

  * dev->setup_len < 0
     - In both do_token_setup and do_parameter, the value of setup_len
is computed by (s->setup_buf[7] << 8) | s->setup_buf[6]. Since
s->setup_buf is a byte array and setup_len is an int32_t, it's
impossible for this arithmetic to set setup_len's top bit, so it can
never be negative.

  * dev->setup_index > dev->setup_len
     - Since setup_index is 0, this is equivalent to the previous test,
so is redundant.

  * dev->setup_len > sizeof(dev->data_buf)
     - This condition is already explicitly checked in both
do_token_setup and do_parameter.

Hence there is no need to bolster the existing checks in do_token_setup
or do_parameter, and we can safely remove these checks from
usb_device_post_load without reducing safety but allowing migrations to
proceed regardless of what USB packets have been generated by the guest.

Signed-off-by: Jonathan Davies <jonathan.davies@nutanix.com>
Message-Id: <20190107175117.23769-1-jonathan.davies@nutanix.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2019-01-08 12:37:52 +01:00
..
bus.c usb: drop unnecessary usb_device_post_load checks 2019-01-08 12:37:52 +01:00
ccid-card-emulated.c hw/usb: fix mistaken de-initialization of CCID state 2019-01-07 14:12:20 +01:00
ccid-card-passthru.c hw/usb: Use the IEC binary prefix definitions 2018-07-02 15:41:16 +02:00
ccid.h usb-ccid: convert CCIDCardClass::exitfn() -> unrealize() 2018-01-26 07:59:33 +01:00
chipidea.c usb: Add basic code to emulate Chipidea USB IP 2018-02-09 10:40:30 +00:00
combined-packet.c hw/usb: Use the IEC binary prefix definitions 2018-07-02 15:41:16 +02:00
core.c usb: don't wakeup during coldplug 2017-05-29 14:18:09 +02:00
desc-msos.c usb: use local path for local headers 2018-06-01 19:20:38 +03:00
desc.c usb: use local path for local headers 2018-06-01 19:20:38 +03:00
desc.h all: Clean up includes 2016-02-23 12:43:05 +00:00
dev-audio.c usb: use local path for local headers 2018-06-01 19:20:38 +03:00
dev-bluetooth.c usb: use local path for local headers 2018-06-01 19:20:38 +03:00
dev-hid.c usb: use local path for local headers 2018-06-01 19:20:38 +03:00
dev-hub.c usb-hub: clear suspend on detach 2018-10-01 10:49:54 +02:00
dev-mtp.c usb-mtp: Limit filename to object information size 2018-12-14 08:57:17 +01:00
dev-network.c usb: use local path for local headers 2018-06-01 19:20:38 +03:00
dev-serial.c usb: use local path for local headers 2018-06-01 19:20:38 +03:00
dev-smartcard-reader.c hw/usb: Use the IEC binary prefix definitions 2018-07-02 15:41:16 +02:00
dev-storage.c block: Remove deprecated -drive option serial 2018-08-15 12:50:39 +02:00
dev-uas.c Revert "usb: release the created buses" 2018-06-18 09:15:51 +02:00
dev-wacom.c usb: use local path for local headers 2018-06-01 19:20:38 +03:00
hcd-ehci-pci.c pci: Add INTERFACE_CONVENTIONAL_PCI_DEVICE to Conventional PCI devices 2017-10-15 05:54:43 +03:00
hcd-ehci-sysbus.c ehci: Add ppc4xx-ehci for the USB 2.0 controller in embedded PPC SoCs 2017-09-27 13:05:41 +10:00
hcd-ehci.c ehci: fix fetch qtd race 2018-12-10 15:30:18 +01:00
hcd-ehci.h ehci: Add ppc4xx-ehci for the USB 2.0 controller in embedded PPC SoCs 2017-09-27 13:05:41 +10:00
hcd-musb.c Replace all occurances of __FUNCTION__ with __func__ 2018-01-22 09:46:18 +01:00
hcd-ohci.c usb: ohci: make num_ports to an unsinged integer 2018-10-29 10:25:12 +01:00
hcd-uhci.c pci: Add INTERFACE_CONVENTIONAL_PCI_DEVICE to Conventional PCI devices 2017-10-15 05:54:43 +03:00
hcd-xhci-nec.c xhci: split into multiple files 2017-05-29 14:03:35 +02:00
hcd-xhci.c xhci: fix guest-triggerable assert 2018-07-03 09:50:39 +02:00
hcd-xhci.h xhci: split into multiple files 2017-05-29 14:03:35 +02:00
host-libusb.c usb-host: reset and close libusb_device_handle before qemu exit 2018-12-10 14:39:54 +01:00
host-stub.c usb: Remove legacy -usbdevice options (host, serial, disk and net) 2018-01-26 07:15:08 +01:00
host.h usb-host: move legacy cmd line bits 2013-02-19 12:30:05 +01:00
libhw.c usb: Clean up includes 2016-01-29 15:07:23 +00:00
Makefile.objs usb: Add basic code to emulate Chipidea USB IP 2018-02-09 10:40:30 +00:00
quirks-ftdi-ids.h usbredir: Add support for buffered bulk input (v2) 2013-01-08 10:56:58 +01:00
quirks-pl2303-ids.h usbredir: Add support for buffered bulk input (v2) 2013-01-08 10:56:58 +01:00
quirks.c usb: Clean up includes 2016-01-29 15:07:23 +00:00
quirks.h usbredir: Add support for buffered bulk input (v2) 2013-01-08 10:56:58 +01:00
redirect.c vmstate: constify VMStateField 2018-11-27 15:35:15 +01:00
trace-events trace-events: fix code style: print 0x before hex numbers 2017-08-01 12:13:07 +01:00
tusb6010.c usb/tusb6010: Convert sysbus init function to realize function 2018-12-13 13:48:02 +00:00
xen-usb.c pvusb: set max grants only in initialise 2018-12-10 14:13:35 +01:00