Commit d0cfd109 authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

greybus: ap: validate the rest of the svc message buffer sizes

parent 00c52e4d
...@@ -112,49 +112,86 @@ static void svc_management(struct svc_function_unipro_management *management, ...@@ -112,49 +112,86 @@ static void svc_management(struct svc_function_unipro_management *management,
} }
static void svc_hotplug(struct svc_function_hotplug *hotplug, static void svc_hotplug(struct svc_function_hotplug *hotplug,
struct greybus_host_device *hd) int payload_length, struct greybus_host_device *hd)
{ {
u8 module_id = hotplug->module_id; u8 module_id = hotplug->module_id;
switch (hotplug->hotplug_event) { switch (hotplug->hotplug_event) {
case SVC_HOTPLUG_EVENT: case SVC_HOTPLUG_EVENT:
/* Add a new module to the system */ /* Add a new module to the system */
if (payload_length < 0x03) {
/* Hotplug message is at lest 3 bytes big */
dev_err(hd->parent,
"Illegal size of svc hotplug message %d\n",
payload_length);
return;
}
dev_dbg(hd->parent, "module id %d added\n", module_id); dev_dbg(hd->parent, "module id %d added\n", module_id);
gb_add_module(hd, module_id, hotplug->data); gb_add_module(hd, module_id, hotplug->data,
payload_length - 0x02);
break; break;
case SVC_HOTUNPLUG_EVENT: case SVC_HOTUNPLUG_EVENT:
/* Remove a module from the system */ /* Remove a module from the system */
if (payload_length != 0x02) {
/* Hotunplug message is only 2 bytes big */
dev_err(hd->parent,
"Illegal size of svc hotunplug message %d\n",
payload_length);
return;
}
dev_dbg(hd->parent, "module id %d removed\n", module_id); dev_dbg(hd->parent, "module id %d removed\n", module_id);
gb_remove_module(hd, module_id); gb_remove_module(hd, module_id);
break; break;
default: default:
dev_err(hd->parent, dev_err(hd->parent,
"received invalid hotplug message type %d\n", "Received invalid hotplug message type %d\n",
hotplug->hotplug_event); hotplug->hotplug_event);
break; break;
} }
} }
static void svc_ddb(struct svc_function_ddb *ddb, static void svc_ddb(struct svc_function_ddb *ddb,
struct greybus_host_device *hd) int payload_length, struct greybus_host_device *hd)
{ {
/*
* Need to properly validate payload_length once we start
* to handle ddb messages, but for now, we don't, so no need to check
* anything.
*/
/* What? An AP should not get this message */ /* What? An AP should not get this message */
dev_err(hd->parent, "Got an svc DDB message???\n"); dev_err(hd->parent, "Got an svc DDB message???\n");
} }
static void svc_power(struct svc_function_power *power, static void svc_power(struct svc_function_power *power,
struct greybus_host_device *hd) int payload_length, struct greybus_host_device *hd)
{ {
u8 module_id = power->module_id; u8 module_id = power->module_id;
/*
* The AP is only allowed to get a Battery Status message, not a Battery
* Status Request
*/
if (power->power_type != SVC_POWER_BATTERY_STATUS) { if (power->power_type != SVC_POWER_BATTERY_STATUS) {
dev_err(hd->parent, "received invalid power type %d\n", dev_err(hd->parent, "Received invalid power type %d\n",
power->power_type); power->power_type);
return; return;
} }
/*
* As struct struct svc_function_power_battery_status_request is 0 bytes
* big, we can just check the union of the whole structure to validate
* the size of this message.
*/
if (payload_length != sizeof(struct svc_function_power)) {
dev_err(hd->parent,
"Illegal size of svc power message %d\n",
payload_length);
return;
}
dev_dbg(hd->parent, "power status for module id %d is %d\n", dev_dbg(hd->parent, "power status for module id %d is %d\n",
module_id, power->status.status); module_id, power->status.status);
...@@ -163,14 +200,14 @@ static void svc_power(struct svc_function_power *power, ...@@ -163,14 +200,14 @@ static void svc_power(struct svc_function_power *power,
} }
static void svc_epm(struct svc_function_epm *epm, static void svc_epm(struct svc_function_epm *epm,
struct greybus_host_device *hd) int payload_length, struct greybus_host_device *hd)
{ {
/* What? An AP should not get this message */ /* What? An AP should not get this message */
dev_err(hd->parent, "Got an EPM message???\n"); dev_err(hd->parent, "Got an EPM message???\n");
} }
static void svc_suspend(struct svc_function_suspend *suspend, static void svc_suspend(struct svc_function_suspend *suspend,
struct greybus_host_device *hd) int payload_length, struct greybus_host_device *hd)
{ {
/* What? An AP should not get this message */ /* What? An AP should not get this message */
dev_err(hd->parent, "Got an suspend message???\n"); dev_err(hd->parent, "Got an suspend message???\n");
...@@ -227,19 +264,19 @@ static void ap_process_event(struct work_struct *work) ...@@ -227,19 +264,19 @@ static void ap_process_event(struct work_struct *work)
svc_management(&svc_msg->management, payload_length, hd); svc_management(&svc_msg->management, payload_length, hd);
break; break;
case SVC_FUNCTION_HOTPLUG: case SVC_FUNCTION_HOTPLUG:
svc_hotplug(&svc_msg->hotplug, hd); svc_hotplug(&svc_msg->hotplug, payload_length, hd);
break; break;
case SVC_FUNCTION_DDB: case SVC_FUNCTION_DDB:
svc_ddb(&svc_msg->ddb, hd); svc_ddb(&svc_msg->ddb, payload_length, hd);
break; break;
case SVC_FUNCTION_POWER: case SVC_FUNCTION_POWER:
svc_power(&svc_msg->power, hd); svc_power(&svc_msg->power, payload_length, hd);
break; break;
case SVC_FUNCTION_EPM: case SVC_FUNCTION_EPM:
svc_epm(&svc_msg->epm, hd); svc_epm(&svc_msg->epm, payload_length, hd);
break; break;
case SVC_FUNCTION_SUSPEND: case SVC_FUNCTION_SUSPEND:
svc_suspend(&svc_msg->suspend, hd); svc_suspend(&svc_msg->suspend, payload_length, hd);
break; break;
default: default:
dev_err(hd->parent, "received invalid SVC function ID %d\n", dev_err(hd->parent, "received invalid SVC function ID %d\n",
......
...@@ -346,7 +346,8 @@ static int create_cport(struct greybus_device *gdev, ...@@ -346,7 +346,8 @@ static int create_cport(struct greybus_device *gdev,
* Pass in a buffer that _should_ contain a Greybus module manifest * Pass in a buffer that _should_ contain a Greybus module manifest
* and spit out a greybus device structure. * and spit out a greybus device structure.
*/ */
void gb_add_module(struct greybus_host_device *hd, u8 module_id, u8 *data) void gb_add_module(struct greybus_host_device *hd, u8 module_id,
u8 *data, int size)
{ {
// FIXME - should be the new module call... // FIXME - should be the new module call...
} }
......
...@@ -288,7 +288,8 @@ const u8 *greybus_string(struct greybus_device *gdev, int id); ...@@ -288,7 +288,8 @@ const u8 *greybus_string(struct greybus_device *gdev, int id);
/* Internal functions to gb module, move to internal .h file eventually. */ /* Internal functions to gb module, move to internal .h file eventually. */
void gb_add_module(struct greybus_host_device *hd, u8 module_id, u8 *data); void gb_add_module(struct greybus_host_device *hd, u8 module_id,
u8 *data, int size);
void gb_remove_module(struct greybus_host_device *hd, u8 module_id); void gb_remove_module(struct greybus_host_device *hd, u8 module_id);
int gb_new_ap_msg(u8 *data, int length, struct greybus_host_device *hd); int gb_new_ap_msg(u8 *data, int length, struct greybus_host_device *hd);
......
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