From 6de02a13232a84261bd2d5e07013d6e6572cd60f Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Mon, 3 Dec 2018 11:10:44 +0100 Subject: usb-mtp: fix utf16_to_str MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make utf16_to_str return an allocated string. Remove the assumtion that the number of string bytes equals the number of utf16 chars (which is only true for ascii chars). Instead call wcstombs twice, once to figure the storage size and once for the actual conversion (as suggested by the wcstombs manpage). FIXME: surrogate pairs are not working correctly. Pre-existing bug, fixing that is left for another day. Reported-by: Michael Hanselmann Signed-off-by: Gerd Hoffmann Reviewed-by: Peter Maydell Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Markus Armbruster Message-id: 20181203101045.27976-2-kraxel@redhat.com --- hw/usb/dev-mtp.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) (limited to 'hw') diff --git a/hw/usb/dev-mtp.c b/hw/usb/dev-mtp.c index 00a3691..0f6a970 100644 --- a/hw/usb/dev-mtp.c +++ b/hw/usb/dev-mtp.c @@ -1593,17 +1593,23 @@ static void usb_mtp_cancel_packet(USBDevice *dev, USBPacket *p) fprintf(stderr, "%s\n", __func__); } -static void utf16_to_str(uint8_t len, uint16_t *arr, char *name) +static char *utf16_to_str(uint8_t len, uint16_t *arr) { - int count; - wchar_t *wstr = g_new0(wchar_t, len); + wchar_t *wstr = g_new0(wchar_t, len + 1); + int count, dlen; + char *dest; for (count = 0; count < len; count++) { + /* FIXME: not working for surrogate pairs */ wstr[count] = (wchar_t)arr[count]; } + wstr[count] = 0; - wcstombs(name, wstr, len); + dlen = wcstombs(NULL, wstr, 0) + 1; + dest = g_malloc(dlen); + wcstombs(dest, wstr, dlen); g_free(wstr); + return dest; } /* Wrapper around write, returns 0 on failure */ @@ -1703,7 +1709,7 @@ static void usb_mtp_write_metadata(MTPState *s) { MTPData *d = s->data_out; ObjectInfo *dataset = (ObjectInfo *)d->data; - char *filename = g_new0(char, dataset->length); + char *filename; MTPObject *o; MTPObject *p = usb_mtp_object_lookup(s, s->dataset.parent_handle); uint32_t next_handle = s->next_handle; @@ -1711,7 +1717,7 @@ static void usb_mtp_write_metadata(MTPState *s) assert(!s->write_pending); assert(p != NULL); - utf16_to_str(dataset->length, dataset->filename, filename); + filename = utf16_to_str(dataset->length, dataset->filename); o = usb_mtp_object_lookup_name(p, filename, dataset->length); if (o != NULL) { -- cgit v1.1 From c52d46e041b42bb1ee6f692e00a0abe37a9659f6 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Mon, 3 Dec 2018 11:10:45 +0100 Subject: usb-mtp: outlaw slashes in filenames MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Slash is unix directory separator, so they are not allowed in filenames. Note this also stops the classic escape via "../". Fixes: CVE-2018-16867 Reported-by: Michael Hanselmann Signed-off-by: Gerd Hoffmann Reviewed-by: Philippe Mathieu-Daudé Message-id: 20181203101045.27976-3-kraxel@redhat.com --- hw/usb/dev-mtp.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'hw') diff --git a/hw/usb/dev-mtp.c b/hw/usb/dev-mtp.c index 0f6a970..100b717 100644 --- a/hw/usb/dev-mtp.c +++ b/hw/usb/dev-mtp.c @@ -1719,6 +1719,12 @@ static void usb_mtp_write_metadata(MTPState *s) filename = utf16_to_str(dataset->length, dataset->filename); + if (strchr(filename, '/')) { + usb_mtp_queue_result(s, RES_PARAMETER_NOT_SUPPORTED, d->trans, + 0, 0, 0, 0); + return; + } + o = usb_mtp_object_lookup_name(p, filename, dataset->length); if (o != NULL) { next_handle = o->handle; -- cgit v1.1