diff options
| author | Stephen Warren <swarren@wwwdotorg.org> | 2014-09-09 16:15:24 +0100 | 
|---|---|---|
| committer | Nick Dyer <nick.dyer@itdev.co.uk> | 2014-09-09 16:30:30 +0100 | 
| commit | 4f1ce8cfd495b6b4ec983c727d1910c0ce26b8ed (patch) | |
| tree | 72cb60a25de076e2c2ec1cc0a4db75dba36a7b3e | |
| parent | b96fee16f8fcdbc54cdecbac4769bc6d43f3c322 (diff) | |
| download | olio-linux-3.10-4f1ce8cfd495b6b4ec983c727d1910c0ce26b8ed.tar.xz olio-linux-3.10-4f1ce8cfd495b6b4ec983c727d1910c0ce26b8ed.zip  | |
Input: atmel_mxt_ts - fix double free of input device
[reworked after comments by Dmitry Torokhov. Move free of input device into
separate function. Only call in paths that require it. Move mxt_initialize
after sysfs init, because otherwise an error in the sysfs init may interfere
with the async return from the firmware loader. Add guards for sysfs
functions. ]
Signed-off-by: Nick Dyer <nick.dyer@itdev.co.uk>
| -rw-r--r-- | drivers/input/touchscreen/atmel_mxt_ts.c | 21 | 
1 files changed, 12 insertions, 9 deletions
diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index 4cb916cf6ed..b948f99a230 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c @@ -1798,7 +1798,6 @@ static void mxt_free_input_device(struct mxt_data *data)  static void mxt_free_object_table(struct mxt_data *data)  {  	mxt_debug_msg_remove(data); -	mxt_free_input_device(data);  	data->object_table = NULL;  	data->info = NULL; @@ -2788,11 +2787,13 @@ static int mxt_load_fw(struct device *dev)  		ret = mxt_lookup_bootloader_address(data, 0);  		if (ret)  			goto release_firmware; + +		mxt_free_input_device(data); +		mxt_free_object_table(data);  	} else {  		enable_irq(data->irq);  	} -	mxt_free_object_table(data);  	INIT_COMPLETION(data->bl_completion);  	ret = mxt_check_bootloader(data, MXT_WAITING_BOOTLOAD_CMD, false); @@ -3311,15 +3312,11 @@ static int mxt_probe(struct i2c_client *client, const struct i2c_device_id *id)  	disable_irq(data->irq); -	error = mxt_initialize(data); -	if (error) -		goto err_free_irq; -  	error = sysfs_create_group(&client->dev.kobj, &mxt_attr_group);  	if (error) {  		dev_err(&client->dev, "Failure %d creating sysfs group\n",  			error); -		goto err_free_object; +		goto err_free_irq;  	}  	sysfs_bin_attr_init(&data->mem_access_attr); @@ -3336,12 +3333,17 @@ static int mxt_probe(struct i2c_client *client, const struct i2c_device_id *id)  		goto err_remove_sysfs_group;  	} +	error = mxt_initialize(data); +	if (error) +		goto err_remove_mem_access; +  	return 0; +err_remove_mem_access: +	sysfs_remove_bin_file(&client->dev.kobj, &data->mem_access_attr); +	data->mem_access_attr.attr.name = NULL;  err_remove_sysfs_group:  	sysfs_remove_group(&client->dev.kobj, &mxt_attr_group); -err_free_object: -	mxt_free_object_table(data);  err_free_irq:  	free_irq(client->irq, data);  err_free_mem: @@ -3361,6 +3363,7 @@ static int mxt_remove(struct i2c_client *client)  	free_irq(data->irq, data);  	regulator_put(data->reg_avdd);  	regulator_put(data->reg_vdd); +	mxt_free_input_device(data);  	mxt_free_object_table(data);  	kfree(data);  |