greybus: firmware: fix information leak
authorJohan Hovold <johan@hovoldconsulting.com>
Thu, 19 Nov 2015 17:27:59 +0000 (18:27 +0100)
committerGreg Kroah-Hartman <gregkh@google.com>
Fri, 20 Nov 2015 00:07:48 +0000 (16:07 -0800)
Add missing sanity checks on get_firmware-request offset and size
parameters to fix potential information leaks.

This prevents remotely controlled information leaks as the requestor
currently controls both the 32-bit firmware-image offset and the amount
of data that is returned (up to host-device MTU).

Signed-off-by: Johan Hovold <johan@hovoldconsulting.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
drivers/staging/greybus/firmware.c

index b16f13318be4141187dc6866dbece58ca448cfb9..4e1530fe9ae576dc84c0b1d20b41c1a44a08ab5c 100644 (file)
@@ -87,6 +87,7 @@ static int gb_firmware_get_firmware(struct gb_operation *op)
 {
        struct gb_connection *connection = op->connection;
        struct gb_firmware *firmware = connection->private;
+       const struct firmware *fw = firmware->fw;
        struct gb_firmware_get_firmware_request *firmware_request = op->request->payload;
        struct gb_firmware_get_firmware_response *firmware_response;
        struct device *dev = &connection->bundle->dev;
@@ -99,7 +100,7 @@ static int gb_firmware_get_firmware(struct gb_operation *op)
                return -EINVAL;
        }
 
-       if (!firmware->fw) {
+       if (!fw) {
                dev_err(dev, "%s: firmware not available\n", __func__);
                return -EINVAL;
        }
@@ -107,6 +108,12 @@ static int gb_firmware_get_firmware(struct gb_operation *op)
        offset = le32_to_cpu(firmware_request->offset);
        size = le32_to_cpu(firmware_request->size);
 
+       if (offset >= fw->size || size > fw->size - offset) {
+               dev_warn(dev, "bad firmware request (offs = %u, size = %u)\n",
+                               offset, size);
+               return -EINVAL;
+       }
+
        if (!gb_operation_response_alloc(op, sizeof(*firmware_response) + size,
                                         GFP_KERNEL)) {
                dev_err(dev, "%s: error allocating response\n", __func__);
@@ -114,7 +121,7 @@ static int gb_firmware_get_firmware(struct gb_operation *op)
        }
 
        firmware_response = op->response->payload;
-       memcpy(firmware_response->data, firmware->fw->data + offset, size);
+       memcpy(firmware_response->data, fw->data + offset, size);
 
        return 0;
 }