Commit 90c1a742 authored by Michael Hanselmann's avatar Michael Hanselmann Committed by Gerd Hoffmann
Browse files

usb-mtp: Limit filename to object information size



The filename length in MTP metadata is specified by the guest. By
trusting it directly it'd theoretically be possible to get the host to
write memory parts outside the filename buffer into a filename. In
practice though there are usually NUL bytes stopping the string
operations.

Also use the opportunity to not assign the filename member twice.

Signed-off-by: default avatarMichael Hanselmann <public@hansmi.ch>
Message-id: ab70659d8d5c580bdf150a5f7d5cc60c8e374ffc.1544740018.git.public@hansmi.ch

[ kraxel: codestyle fix: break a long line ]

Signed-off-by: default avatarGerd Hoffmann <kraxel@redhat.com>
parent bab9df35
Loading
Loading
Loading
Loading
+5 −4
Original line number Diff line number Diff line
@@ -1710,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;
@@ -1722,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,
@@ -1738,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) {
@@ -1807,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;