Commit 3866e6be authored by Peter Maydell's avatar Peter Maydell
Browse files

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: default avatarPeter Maydell <peter.maydell@linaro.org>
parents 81781be3 90c1a742
Loading
Loading
Loading
Loading
+14 −8
Original line number Diff line number Diff line
@@ -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;
+10 −2
Original line number Diff line number Diff line
@@ -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);
+2 −0
Original line number Diff line number Diff line
@@ -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);
    }
}

+6 −6
Original line number Diff line number Diff line
@@ -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)