diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2018-12-16 12:05:08 +0000 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2018-12-16 12:05:08 +0000 |
commit | 3866e6bebd0cd498e684f1d3ab10b64c853d186f (patch) | |
tree | 869a8176bc781baafc316ec0c6e16362b324f88e /hw/usb | |
parent | 81781be3c99235a59c8efee6aecb3d81b500e838 (diff) | |
parent | 90c1a74271ce4667d16eeca575dfa78a6c7d465c (diff) |
Merge remote-tracking branch 'remotes/kraxel/tags/usb-20181214-pull-request' into staging
usb: fixes for mtp, ehci, usb-host and pvusb (xen).
# gpg: Signature made Fri 14 Dec 2018 10:38:33 GMT
# gpg: using RSA key 4CB6D8EED3E87138
# 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>"
# Primary key fingerprint: A032 8CFF B93A 17A7 9901 FE7D 4CB6 D8EE D3E8 7138
* remotes/kraxel/tags/usb-20181214-pull-request:
usb-mtp: Limit filename to object information size
usb-mtp: use O_NOFOLLOW and O_CLOEXEC.
ehci: fix fetch qtd race
usb-host: reset and close libusb_device_handle before qemu exit
pvusb: set max grants only in initialise
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw/usb')
-rw-r--r-- | hw/usb/dev-mtp.c | 22 | ||||
-rw-r--r-- | hw/usb/hcd-ehci.c | 12 | ||||
-rw-r--r-- | hw/usb/host-libusb.c | 2 | ||||
-rw-r--r-- | hw/usb/xen-usb.c | 12 |
4 files changed, 32 insertions, 16 deletions
diff --git a/hw/usb/dev-mtp.c b/hw/usb/dev-mtp.c index 100b7171f4..6098005cd4 100644 --- a/hw/usb/dev-mtp.c +++ b/hw/usb/dev-mtp.c @@ -653,13 +653,18 @@ static void usb_mtp_object_readdir(MTPState *s, MTPObject *o) { struct dirent *entry; DIR *dir; + int fd; if (o->have_children) { return; } o->have_children = true; - dir = opendir(o->path); + fd = open(o->path, O_DIRECTORY | O_CLOEXEC | O_NOFOLLOW); + if (fd < 0) { + return; + } + dir = fdopendir(fd); if (!dir) { return; } @@ -1007,7 +1012,7 @@ static MTPData *usb_mtp_get_object(MTPState *s, MTPControl *c, trace_usb_mtp_op_get_object(s->dev.addr, o->handle, o->path); - d->fd = open(o->path, O_RDONLY); + d->fd = open(o->path, O_RDONLY | O_CLOEXEC | O_NOFOLLOW); if (d->fd == -1) { usb_mtp_data_free(d); return NULL; @@ -1031,7 +1036,7 @@ static MTPData *usb_mtp_get_partial_object(MTPState *s, MTPControl *c, c->argv[1], c->argv[2]); d = usb_mtp_data_alloc(c); - d->fd = open(o->path, O_RDONLY); + d->fd = open(o->path, O_RDONLY | O_CLOEXEC | O_NOFOLLOW); if (d->fd == -1) { usb_mtp_data_free(d); return NULL; @@ -1658,7 +1663,7 @@ static void usb_mtp_write_data(MTPState *s) 0, 0, 0, 0); goto done; } - d->fd = open(path, O_CREAT | O_WRONLY, mask); + d->fd = open(path, O_CREAT | O_WRONLY | O_CLOEXEC | O_NOFOLLOW, mask); if (d->fd == -1) { usb_mtp_queue_result(s, RES_STORE_FULL, d->trans, 0, 0, 0, 0); @@ -1705,7 +1710,7 @@ free: s->write_pending = false; } -static void usb_mtp_write_metadata(MTPState *s) +static void usb_mtp_write_metadata(MTPState *s, uint64_t dlen) { MTPData *d = s->data_out; ObjectInfo *dataset = (ObjectInfo *)d->data; @@ -1717,7 +1722,9 @@ static void usb_mtp_write_metadata(MTPState *s) assert(!s->write_pending); assert(p != NULL); - filename = utf16_to_str(dataset->length, dataset->filename); + filename = utf16_to_str(MIN(dataset->length, + dlen - offsetof(ObjectInfo, filename)), + dataset->filename); if (strchr(filename, '/')) { usb_mtp_queue_result(s, RES_PARAMETER_NOT_SUPPORTED, d->trans, @@ -1733,7 +1740,6 @@ static void usb_mtp_write_metadata(MTPState *s) s->dataset.filename = filename; s->dataset.format = dataset->format; s->dataset.size = dataset->size; - s->dataset.filename = filename; s->write_pending = true; if (s->dataset.format == FMT_ASSOCIATION) { @@ -1802,7 +1808,7 @@ static void usb_mtp_get_data(MTPState *s, mtp_container *container, if (d->offset == d->length) { /* The operation might have already failed */ if (!s->result) { - usb_mtp_write_metadata(s); + usb_mtp_write_metadata(s, dlen); } usb_mtp_data_free(s->data_out); s->data_out = NULL; diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c index e5acfc5ba5..8d44d483df 100644 --- a/hw/usb/hcd-ehci.c +++ b/hw/usb/hcd-ehci.c @@ -1783,9 +1783,17 @@ static int ehci_state_fetchqtd(EHCIQueue *q) EHCIqtd qtd; EHCIPacket *p; int again = 1; + uint32_t addr; - if (get_dwords(q->ehci, NLPTR_GET(q->qtdaddr), (uint32_t *) &qtd, - sizeof(EHCIqtd) >> 2) < 0) { + addr = NLPTR_GET(q->qtdaddr); + if (get_dwords(q->ehci, addr + 8, &qtd.token, 1) < 0) { + return 0; + } + barrier(); + if (get_dwords(q->ehci, addr + 0, &qtd.next, 1) < 0 || + get_dwords(q->ehci, addr + 4, &qtd.altnext, 1) < 0 || + get_dwords(q->ehci, addr + 12, qtd.bufptr, + ARRAY_SIZE(qtd.bufptr)) < 0) { return 0; } ehci_trace_qtd(q, NLPTR_GET(q->qtdaddr), &qtd); diff --git a/hw/usb/host-libusb.c b/hw/usb/host-libusb.c index b6602ded4e..833250a886 100644 --- a/hw/usb/host-libusb.c +++ b/hw/usb/host-libusb.c @@ -988,7 +988,9 @@ static void usb_host_exit_notifier(struct Notifier *n, void *data) if (s->dh) { usb_host_release_interfaces(s); + libusb_reset_device(s->dh); usb_host_attach_kernel(s); + libusb_close(s->dh); } } diff --git a/hw/usb/xen-usb.c b/hw/usb/xen-usb.c index 5b2e21ed18..f5d5c91094 100644 --- a/hw/usb/xen-usb.c +++ b/hw/usb/xen-usb.c @@ -860,10 +860,14 @@ static int usbback_connect(struct XenDevice *xendev) struct usbif_conn_sring *conn_sring; int urb_ring_ref; int conn_ring_ref; - unsigned int i; + unsigned int i, max_grants; TR_BUS(xendev, "start\n"); + /* max_grants: for each request and for the rings (request and connect). */ + max_grants = USBIF_MAX_SEGMENTS_PER_REQUEST * USB_URB_RING_SIZE + 2; + xen_be_set_max_grant_refs(xendev, max_grants); + usbif = container_of(xendev, struct usbback_info, xendev); if (xenstore_read_fe_int(xendev, "urb-ring-ref", &urb_ring_ref)) { @@ -1005,7 +1009,7 @@ static void usbback_alloc(struct XenDevice *xendev) { struct usbback_info *usbif; USBPort *p; - unsigned int i, max_grants; + unsigned int i; usbif = container_of(xendev, struct usbback_info, xendev); @@ -1021,10 +1025,6 @@ static void usbback_alloc(struct XenDevice *xendev) QTAILQ_INIT(&usbif->req_free_q); QSIMPLEQ_INIT(&usbif->hotplug_q); usbif->bh = qemu_bh_new(usbback_bh, usbif); - - /* max_grants: for each request and for the rings (request and connect). */ - max_grants = USBIF_MAX_SEGMENTS_PER_REQUEST * USB_URB_RING_SIZE + 2; - xen_be_set_max_grant_refs(xendev, max_grants); } static int usbback_free(struct XenDevice *xendev) |