Bläddra i källkod

greybus: power_supply: rework get descriptors

Rework the get property descriptors function to fix a memory handling
error for the response structure. This could corrupt the stack and
throw nonalignment PC or SP error:

Internal error: SP or PC abort: 8a000000 1 PREEMPT SMP
Modules linked in: gb_power_supply(O) gb_arche(O) gb_camera(O) gb_es2(O) gb_vibrator(O) gb_raw(O) g]
CPU: 3 PID: 51 Comm: kworker/u16:2 Tainted: G W O 3.10.73-g8a6af60-00118-g599a5c1 #1
Workqueue: greybus1:svc gb_svc_connection_destroy [greybus]
task: ffffffc0ba249580 ti: ffffffc0ba294000 task.ti: ffffffc0ba294000
PC is at gb_power_supply_connection_init+0x81/0x1dc [gb_power_supply]
LR is at gb_power_supply_connection_init+0x81/0x1dc [gb_power_supply]
pc : [<ffffffbffc03b901>] lr : [<ffffffbffc03b901>] pstate: 80000145
sp : ffffffc0ba297a00
x29: 32002e002a001100 x28: ffffffc042cb2c80

To fix this, allocate firstly the operation and handle request and
response using operation payload.

Signed-off-by: Rui Miguel Silva <rui.silva@linaro.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
Rui Miguel Silva 9 år sedan
förälder
incheckning
9d15134d06
1 ändrade filer med 37 tillägg och 20 borttagningar
  1. 37 20
      drivers/staging/greybus/power_supply.c

+ 37 - 20
drivers/staging/greybus/power_supply.c

@@ -249,39 +249,53 @@ static int gb_power_supply_description_get(struct gb_power_supply *gbpsy)
 static int gb_power_supply_prop_descriptors_get(struct gb_power_supply *gbpsy)
 {
 	struct gb_connection *connection = get_conn_from_psy(gbpsy);
-	struct gb_power_supply_get_property_descriptors_request req;
-	struct gb_power_supply_get_property_descriptors_response resp;
+	struct gb_power_supply_get_property_descriptors_request *req;
+	struct gb_power_supply_get_property_descriptors_response *resp;
+	struct gb_operation *op;
+	u8 props_count = gbpsy->properties_count;
 	int ret;
 	int i;
 
-	if (gbpsy->properties_count == 0)
+	if (props_count == 0)
 		return 0;
 
-	req.psy_id = gbpsy->id;
+	op = gb_operation_create(connection,
+				 GB_POWER_SUPPLY_TYPE_GET_PROP_DESCRIPTORS,
+				 sizeof(req), sizeof(*resp) + props_count *
+				 sizeof(struct gb_power_supply_props_desc),
+				 GFP_KERNEL);
+	if (!op)
+		return -ENOMEM;
 
-	ret = gb_operation_sync(connection,
-				GB_POWER_SUPPLY_TYPE_GET_PROP_DESCRIPTORS,
-				&req, sizeof(req), &resp,
-				sizeof(resp) + gbpsy->properties_count *
-				sizeof(struct gb_power_supply_props_desc));
+	req = op->request->payload;
+	req->psy_id = gbpsy->id;
+
+	ret = gb_operation_request_send_sync(op);
 	if (ret < 0)
-		return ret;
+		goto out_put_operation;
+
+	resp = op->response->payload;
 
 	gbpsy->props = kcalloc(gbpsy->properties_count, sizeof(*gbpsy->props),
 			      GFP_KERNEL);
-	if (!gbpsy->props)
-		return -ENOMEM;
+	if (!gbpsy->props) {
+		ret = -ENOMEM;
+		goto out_put_operation;
+	}
+
+	gbpsy->props_raw = kcalloc(gbpsy->properties_count,
+				   sizeof(*gbpsy->props_raw), GFP_KERNEL);
+	if (!gbpsy->props_raw) {
+		ret = -ENOMEM;
+		goto out_put_operation;
+	}
 
-	gbpsy->props_raw = kzalloc(gbpsy->properties_count *
-				  sizeof(*gbpsy->props_raw), GFP_KERNEL);
-	if (!gbpsy->props_raw)
-		return -ENOMEM;
 
 	/* Store available properties */
 	for (i = 0; i < gbpsy->properties_count; i++) {
-		gbpsy->props[i].prop = resp.props[i].property;
-		gbpsy->props_raw[i] = resp.props[i].property;
-		if (resp.props[i].is_writeable)
+		gbpsy->props[i].prop = resp->props[i].property;
+		gbpsy->props_raw[i] = resp->props[i].property;
+		if (resp->props[i].is_writeable)
 			gbpsy->props[i].is_writeable = true;
 	}
 
@@ -291,7 +305,10 @@ static int gb_power_supply_prop_descriptors_get(struct gb_power_supply *gbpsy)
 	 */
 	_gb_power_supply_append_props(gbpsy);
 
-	return 0;
+out_put_operation:
+	gb_operation_put(op);
+
+	return ret;
 }
 
 static int __gb_power_supply_property_update(struct gb_power_supply *gbpsy,