| From: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| Date: Sun, 29 Apr 2018 17:41:55 +0200 |
| Subject: USB: serial: visor: handle potential invalid device configuration |
| |
| commit 4842ed5bfcb9daf6660537d70503c18d38dbdbb8 upstream. |
| |
| If we get an invalid device configuration from a palm 3 type device, we |
| might incorrectly parse things, and we have the potential to crash in |
| "interesting" ways. |
| |
| Fix this up by verifying the size of the configuration passed to us by |
| the device, and only if it is correct, will we handle it. |
| |
| Note that this also fixes an information leak of slab data. |
| |
| Reported-by: Andrey Konovalov <andreyknvl@google.com> |
| Reviewed-by: Andrey Konovalov <andreyknvl@google.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| [ johan: add comment about the info leak ] |
| Signed-off-by: Johan Hovold <johan@kernel.org> |
| Signed-off-by: Ben Hutchings <ben@decadent.org.uk> |
| --- |
| drivers/usb/serial/visor.c | 69 +++++++++++++++++++------------------- |
| 1 file changed, 35 insertions(+), 34 deletions(-) |
| |
| --- a/drivers/usb/serial/visor.c |
| +++ b/drivers/usb/serial/visor.c |
| @@ -338,47 +338,48 @@ static int palm_os_3_probe(struct usb_se |
| goto exit; |
| } |
| |
| - if (retval == sizeof(*connection_info)) { |
| - connection_info = (struct visor_connection_info *) |
| - transfer_buffer; |
| - |
| - num_ports = le16_to_cpu(connection_info->num_ports); |
| - for (i = 0; i < num_ports; ++i) { |
| - switch ( |
| - connection_info->connections[i].port_function_id) { |
| - case VISOR_FUNCTION_GENERIC: |
| - string = "Generic"; |
| - break; |
| - case VISOR_FUNCTION_DEBUGGER: |
| - string = "Debugger"; |
| - break; |
| - case VISOR_FUNCTION_HOTSYNC: |
| - string = "HotSync"; |
| - break; |
| - case VISOR_FUNCTION_CONSOLE: |
| - string = "Console"; |
| - break; |
| - case VISOR_FUNCTION_REMOTE_FILE_SYS: |
| - string = "Remote File System"; |
| - break; |
| - default: |
| - string = "unknown"; |
| - break; |
| - } |
| - dev_info(dev, "%s: port %d, is for %s use\n", |
| - serial->type->description, |
| - connection_info->connections[i].port, string); |
| - } |
| + if (retval != sizeof(*connection_info)) { |
| + dev_err(dev, "Invalid connection information received from device\n"); |
| + retval = -ENODEV; |
| + goto exit; |
| } |
| - /* |
| - * Handle devices that report invalid stuff here. |
| - */ |
| + |
| + connection_info = (struct visor_connection_info *)transfer_buffer; |
| + |
| + num_ports = le16_to_cpu(connection_info->num_ports); |
| + |
| + /* Handle devices that report invalid stuff here. */ |
| if (num_ports == 0 || num_ports > 2) { |
| dev_warn(dev, "%s: No valid connect info available\n", |
| serial->type->description); |
| num_ports = 2; |
| } |
| |
| + for (i = 0; i < num_ports; ++i) { |
| + switch (connection_info->connections[i].port_function_id) { |
| + case VISOR_FUNCTION_GENERIC: |
| + string = "Generic"; |
| + break; |
| + case VISOR_FUNCTION_DEBUGGER: |
| + string = "Debugger"; |
| + break; |
| + case VISOR_FUNCTION_HOTSYNC: |
| + string = "HotSync"; |
| + break; |
| + case VISOR_FUNCTION_CONSOLE: |
| + string = "Console"; |
| + break; |
| + case VISOR_FUNCTION_REMOTE_FILE_SYS: |
| + string = "Remote File System"; |
| + break; |
| + default: |
| + string = "unknown"; |
| + break; |
| + } |
| + dev_info(dev, "%s: port %d, is for %s use\n", |
| + serial->type->description, |
| + connection_info->connections[i].port, string); |
| + } |
| dev_info(dev, "%s: Number of ports: %d\n", serial->type->description, |
| num_ports); |
| |