usb: misc bugfixes.
-----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.22 (GNU/Linux) iQIcBAABAgAGBQJWzDoNAAoJEEy22O7T6HE4uPoP/0219mBQ3GpHOD+NMNjL0ukb biBUeN1Sglo6XJ/D8UadGH0IBiwePyLCEIcwiF9NRTWfgWQHWR+onaZocHgROMgw 9SjERlgx1H/ghYvuavRviKzwJcou4lORyE1ypSRHGKNTcBJd/WnINNbH704QNEnH RI4N2apAPL9Ch1vWEgSSEeIenNIMsojTl6pkuka4TsgyYuI+cZKMhmgjqHBpvCkW psDh3IBmXdCDEfAI6Go+5a8a0yzwk78Lqoao6PLdfv7txZRnjqcuypTrco7zdH2T Df8NEfixi+57uPBntjoXZfK+iAQAD/CuLgsOpaTtehnckYbMMjYMyfop+ZLyrBKN Fn1m7BM6T7Ia+X28VOmQIK3tq+n03ioOricxBGTd3trm3MCYl2D4tE3jl9czx+Nf 0UcbzhWdKTFzYrr8pCmAIQvr3VH096bo7MK0t9/ld4OD4vAgknVMLbPiEgV8e23I iBXW6ZofL3dSEmIizeZ0kDegqO7SFDRoQkyqWUCQdsnhappMUIERmuYku8ATJUt+ Pa9NDDOc6VGKd3+LtmVCi3WtoYspaKIENx9hf47+kswVth8afhIEhND4ztBKqLd9 1jlr4sjotEFE1qphVyMfElWt4wf+mk0TzTo8KvuUn3jRdqxWy8WLVF7jrA565X7T BsjCVTxk9zebeN2pXYsg =f11y -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/kraxel/tags/pull-usb-20160223-1' 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>
This commit is contained in:
commit
ea6e4981bf
@ -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
|
||||
|
@ -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
|
||||
|
@ -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];
|
||||
@ -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
|
||||
@ -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)) {
|
||||
|
@ -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,
|
||||
@ -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,
|
||||
@ -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);
|
||||
@ -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);
|
||||
|
@ -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
|
||||
@ -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
|
||||
@ -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"
|
||||
@ -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)
|
||||
@ -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),
|
||||
|
@ -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);
|
||||
@ -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) {
|
||||
|
Loading…
Reference in New Issue
Block a user