Skip to content

Commit

Permalink
Merge remote-tracking branch 'remotes/kraxel/tags/pull-usb-20160223-1…
Browse files Browse the repository at this point in the history
…' into staging

usb: misc bugfixes.

# gpg: Signature made Tue 23 Feb 2016 10:53:01 GMT using RSA key ID D3E87138
# gpg: Good signature from "Gerd Hoffmann (work) <kraxel@redhat.com>"
# gpg:                 aka "Gerd Hoffmann <gerd@kraxel.org>"
# gpg:                 aka "Gerd Hoffmann (private) <kraxel@gmail.com>"

* remotes/kraxel/tags/pull-usb-20160223-1:
  ohci: allocate timer only once.
  usb: add pid check at the first of uhci_handle_td()
  usb: check RNDIS buffer offsets & length
  usb: check RNDIS message length
  tusb6010: move from hw/timer to hw/usb
  usb: check USB configuration descriptor object

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
  • Loading branch information
pm215 committed Feb 23, 2016
2 parents 8eb779e + fa1298c commit ea6e498
Show file tree
Hide file tree
Showing 7 changed files with 43 additions and 46 deletions.
1 change: 0 additions & 1 deletion hw/timer/Makefile.objs
Expand Up @@ -25,7 +25,6 @@ obj-$(CONFIG_OMAP) += omap_gptimer.o
obj-$(CONFIG_OMAP) += omap_synctimer.o
obj-$(CONFIG_PXA2XX) += pxa2xx_timer.o
obj-$(CONFIG_SH4) += sh_timer.o
obj-$(CONFIG_TUSB6010) += tusb6010.o
obj-$(CONFIG_DIGIC) += digic-timer.o

obj-$(CONFIG_MC146818RTC) += mc146818rtc.o
Expand Down
2 changes: 2 additions & 0 deletions hw/usb/Makefile.objs
Expand Up @@ -10,6 +10,8 @@ common-obj-$(CONFIG_USB_EHCI_SYSBUS) += hcd-ehci-sysbus.o
common-obj-$(CONFIG_USB_XHCI) += hcd-xhci.o
common-obj-$(CONFIG_USB_MUSB) += hcd-musb.o

obj-$(CONFIG_TUSB6010) += tusb6010.o

# emulated usb devices
common-obj-$(CONFIG_USB) += dev-hub.o
common-obj-$(CONFIG_USB) += dev-hid.o
Expand Down
18 changes: 9 additions & 9 deletions hw/usb/core.c
Expand Up @@ -129,9 +129,16 @@ static void do_token_setup(USBDevice *s, USBPacket *p)
}

usb_packet_copy(p, s->setup_buf, p->iov.size);
s->setup_index = 0;
p->actual_length = 0;
s->setup_len = (s->setup_buf[7] << 8) | s->setup_buf[6];
s->setup_index = 0;
if (s->setup_len > sizeof(s->data_buf)) {
fprintf(stderr,
"usb_generic_handle_packet: ctrl buffer too small (%d > %zu)\n",
s->setup_len, sizeof(s->data_buf));
p->status = USB_RET_STALL;
return;
}

request = (s->setup_buf[0] << 8) | s->setup_buf[1];
value = (s->setup_buf[3] << 8) | s->setup_buf[2];
Expand All @@ -152,13 +159,6 @@ static void do_token_setup(USBDevice *s, USBPacket *p)
}
s->setup_state = SETUP_STATE_DATA;
} else {
if (s->setup_len > sizeof(s->data_buf)) {
fprintf(stderr,
"usb_generic_handle_packet: ctrl buffer too small (%d > %zu)\n",
s->setup_len, sizeof(s->data_buf));
p->status = USB_RET_STALL;
return;
}
if (s->setup_len == 0)
s->setup_state = SETUP_STATE_ACK;
else
Expand All @@ -177,7 +177,7 @@ static void do_token_in(USBDevice *s, USBPacket *p)
request = (s->setup_buf[0] << 8) | s->setup_buf[1];
value = (s->setup_buf[3] << 8) | s->setup_buf[2];
index = (s->setup_buf[5] << 8) | s->setup_buf[4];

switch(s->setup_state) {
case SETUP_STATE_ACK:
if (!(s->setup_buf[0] & USB_DIR_IN)) {
Expand Down
12 changes: 8 additions & 4 deletions hw/usb/dev-network.c
Expand Up @@ -654,7 +654,8 @@ typedef struct USBNetState {

static int is_rndis(USBNetState *s)
{
return s->dev.config->bConfigurationValue == DEV_RNDIS_CONFIG_VALUE;
return s->dev.config ?
s->dev.config->bConfigurationValue == DEV_RNDIS_CONFIG_VALUE : 0;
}

static int ndis_query(USBNetState *s, uint32_t oid,
Expand Down Expand Up @@ -915,8 +916,9 @@ static int rndis_query_response(USBNetState *s,

bufoffs = le32_to_cpu(buf->InformationBufferOffset) + 8;
buflen = le32_to_cpu(buf->InformationBufferLength);
if (bufoffs + buflen > length)
if (buflen > length || bufoffs >= length || bufoffs + buflen > length) {
return USB_RET_STALL;
}

infobuflen = ndis_query(s, le32_to_cpu(buf->OID),
bufoffs + (uint8_t *) buf, buflen, infobuf,
Expand Down Expand Up @@ -961,8 +963,9 @@ static int rndis_set_response(USBNetState *s,

bufoffs = le32_to_cpu(buf->InformationBufferOffset) + 8;
buflen = le32_to_cpu(buf->InformationBufferLength);
if (bufoffs + buflen > length)
if (buflen > length || bufoffs >= length || bufoffs + buflen > length) {
return USB_RET_STALL;
}

ret = ndis_set(s, le32_to_cpu(buf->OID),
bufoffs + (uint8_t *) buf, buflen);
Expand Down Expand Up @@ -1212,8 +1215,9 @@ static void usb_net_handle_dataout(USBNetState *s, USBPacket *p)
if (le32_to_cpu(msg->MessageType) == RNDIS_PACKET_MSG) {
uint32_t offs = 8 + le32_to_cpu(msg->DataOffset);
uint32_t size = le32_to_cpu(msg->DataLength);
if (offs + size <= len)
if (offs < len && size < len && offs + size <= len) {
qemu_send_packet(qemu_get_queue(s->nic), s->out_buf + offs, size);
}
}
s->out_ptr -= len;
memmove(s->out_buf, &s->out_buf[len], s->out_ptr);
Expand Down
34 changes: 8 additions & 26 deletions hw/usb/hcd-ohci.c
Expand Up @@ -1347,16 +1347,6 @@ static void ohci_frame_boundary(void *opaque)
*/
static int ohci_bus_start(OHCIState *ohci)
{
ohci->eof_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL,
ohci_frame_boundary,
ohci);

if (ohci->eof_timer == NULL) {
trace_usb_ohci_bus_eof_timer_failed(ohci->name);
ohci_die(ohci);
return 0;
}

trace_usb_ohci_start(ohci->name);

/* Delay the first SOF event by one frame time as
Expand All @@ -1373,11 +1363,7 @@ static int ohci_bus_start(OHCIState *ohci)
static void ohci_bus_stop(OHCIState *ohci)
{
trace_usb_ohci_stop(ohci->name);
if (ohci->eof_timer) {
timer_del(ohci->eof_timer);
timer_free(ohci->eof_timer);
}
ohci->eof_timer = NULL;
timer_del(ohci->eof_timer);
}

/* Sets a flag in a port status register but only set it if the port is
Expand Down Expand Up @@ -1907,6 +1893,9 @@ static void usb_ohci_init(OHCIState *ohci, DeviceState *dev,
usb_packet_init(&ohci->usb_packet);

ohci->async_td = 0;

ohci->eof_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL,
ohci_frame_boundary, ohci);
}

#define TYPE_PCI_OHCI "pci-ohci"
Expand Down Expand Up @@ -1976,6 +1965,9 @@ static void usb_ohci_exit(PCIDevice *dev)
if (!ohci->masterbus) {
usb_bus_release(&s->bus);
}

timer_del(s->eof_timer);
timer_free(s->eof_timer);
}

static void usb_ohci_reset_pci(DeviceState *d)
Expand Down Expand Up @@ -2041,23 +2033,13 @@ static bool ohci_eof_timer_needed(void *opaque)
{
OHCIState *ohci = opaque;

return ohci->eof_timer != NULL;
}

static int ohci_eof_timer_pre_load(void *opaque)
{
OHCIState *ohci = opaque;

ohci_bus_start(ohci);

return 0;
return timer_pending(ohci->eof_timer);
}

static const VMStateDescription vmstate_ohci_eof_timer = {
.name = "ohci-core/eof-timer",
.version_id = 1,
.minimum_version_id = 1,
.pre_load = ohci_eof_timer_pre_load,
.needed = ohci_eof_timer_needed,
.fields = (VMStateField[]) {
VMSTATE_TIMER_PTR(eof_timer, OHCIState),
Expand Down
22 changes: 16 additions & 6 deletions hw/usb/hcd-uhci.c
Expand Up @@ -773,8 +773,22 @@ static int uhci_handle_td(UHCIState *s, UHCIQueue *q, uint32_t qh_addr,
bool spd;
bool queuing = (q != NULL);
uint8_t pid = td->token & 0xff;
UHCIAsync *async = uhci_async_find_td(s, td_addr);
UHCIAsync *async;

switch (pid) {
case USB_TOKEN_OUT:
case USB_TOKEN_SETUP:
case USB_TOKEN_IN:
break;
default:
/* invalid pid : frame interrupted */
s->status |= UHCI_STS_HCPERR;
s->cmd &= ~UHCI_CMD_RS;
uhci_update_irq(s);
return TD_RESULT_STOP_FRAME;
}

async = uhci_async_find_td(s, td_addr);
if (async) {
if (uhci_queue_verify(async->queue, qh_addr, td, td_addr, queuing)) {
assert(q == NULL || q == async->queue);
Expand Down Expand Up @@ -880,11 +894,7 @@ static int uhci_handle_td(UHCIState *s, UHCIQueue *q, uint32_t qh_addr,
break;

default:
/* invalid pid : frame interrupted */
uhci_async_free(async);
s->status |= UHCI_STS_HCPERR;
uhci_update_irq(s);
return TD_RESULT_STOP_FRAME;
abort(); /* Never to execute */
}

if (async->packet.status == USB_RET_ASYNC) {
Expand Down
File renamed without changes.

0 comments on commit ea6e498

Please sign in to comment.