diff options
author | Rui Miguel Silva <rui.silva@linaro.org> | 2016-02-04 14:00:36 +0000 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@google.com> | 2016-02-05 16:37:34 -0800 |
commit | 9d15134d067ecb52bf02136234fbd1d09e1706d8 (patch) | |
tree | 80ce6d8b07a288e4b741ee545b9d94be5d6da107 /drivers/staging/greybus/power_supply.c | |
parent | db81b76970a2e9f3ffa1ca66e7761f9f4b84efc6 (diff) | |
download | op-kernel-dev-9d15134d067ecb52bf02136234fbd1d09e1706d8.zip op-kernel-dev-9d15134d067ecb52bf02136234fbd1d09e1706d8.tar.gz |
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>
Diffstat (limited to 'drivers/staging/greybus/power_supply.c')
-rw-r--r-- | drivers/staging/greybus/power_supply.c | 57 |
1 files changed, 37 insertions, 20 deletions
diff --git a/drivers/staging/greybus/power_supply.c b/drivers/staging/greybus/power_supply.c index 2dc193a..37bea9c 100644 --- a/drivers/staging/greybus/power_supply.c +++ b/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, |