aboutsummaryrefslogtreecommitdiff
path: root/hw/usb
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2018-12-16 12:05:08 +0000
committerPeter Maydell <peter.maydell@linaro.org>2018-12-16 12:05:08 +0000
commit3866e6bebd0cd498e684f1d3ab10b64c853d186f (patch)
tree869a8176bc781baafc316ec0c6e16362b324f88e /hw/usb
parent81781be3c99235a59c8efee6aecb3d81b500e838 (diff)
parent90c1a74271ce4667d16eeca575dfa78a6c7d465c (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.c22
-rw-r--r--hw/usb/hcd-ehci.c12
-rw-r--r--hw/usb/host-libusb.c2
-rw-r--r--hw/usb/xen-usb.c12
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)