Commit 98645a9c authored by Johan Hovold's avatar Johan Hovold Committed by Greg Kroah-Hartman

greybus: firmware: fix information leak

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: default avatarJohan Hovold <johan@hovoldconsulting.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@google.com>
parent 81ad6994
...@@ -87,6 +87,7 @@ static int gb_firmware_get_firmware(struct gb_operation *op) ...@@ -87,6 +87,7 @@ static int gb_firmware_get_firmware(struct gb_operation *op)
{ {
struct gb_connection *connection = op->connection; struct gb_connection *connection = op->connection;
struct gb_firmware *firmware = connection->private; 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_request *firmware_request = op->request->payload;
struct gb_firmware_get_firmware_response *firmware_response; struct gb_firmware_get_firmware_response *firmware_response;
struct device *dev = &connection->bundle->dev; struct device *dev = &connection->bundle->dev;
...@@ -99,7 +100,7 @@ static int gb_firmware_get_firmware(struct gb_operation *op) ...@@ -99,7 +100,7 @@ static int gb_firmware_get_firmware(struct gb_operation *op)
return -EINVAL; return -EINVAL;
} }
if (!firmware->fw) { if (!fw) {
dev_err(dev, "%s: firmware not available\n", __func__); dev_err(dev, "%s: firmware not available\n", __func__);
return -EINVAL; return -EINVAL;
} }
...@@ -107,6 +108,12 @@ static int gb_firmware_get_firmware(struct gb_operation *op) ...@@ -107,6 +108,12 @@ static int gb_firmware_get_firmware(struct gb_operation *op)
offset = le32_to_cpu(firmware_request->offset); offset = le32_to_cpu(firmware_request->offset);
size = le32_to_cpu(firmware_request->size); 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, if (!gb_operation_response_alloc(op, sizeof(*firmware_response) + size,
GFP_KERNEL)) { GFP_KERNEL)) {
dev_err(dev, "%s: error allocating response\n", __func__); dev_err(dev, "%s: error allocating response\n", __func__);
...@@ -114,7 +121,7 @@ static int gb_firmware_get_firmware(struct gb_operation *op) ...@@ -114,7 +121,7 @@ static int gb_firmware_get_firmware(struct gb_operation *op)
} }
firmware_response = op->response->payload; firmware_response = op->response->payload;
memcpy(firmware_response->data, firmware->fw->data + offset, size); memcpy(firmware_response->data, fw->data + offset, size);
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment