stm class: Fix unbalanced module/device refcounting
STM code takes references to the stm device and its module for the duration of the character device's existence or the stm_source link. Dropping these references is not well balanced everywhere, which may lead to leaks. This patch balances the acquisition and releasing of these two references and annotates each site so that it's easier to verify correctness by reading the code. Signed-off-by: Alexander Shishkin <alexander.shishkin@linux.intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
cde4ad8368
commit
f7c81c7176
|
@ -113,6 +113,7 @@ struct stm_device *stm_find_device(const char *buf)
|
||||||
|
|
||||||
stm = to_stm_device(dev);
|
stm = to_stm_device(dev);
|
||||||
if (!try_module_get(stm->owner)) {
|
if (!try_module_get(stm->owner)) {
|
||||||
|
/* matches class_find_device() above */
|
||||||
put_device(dev);
|
put_device(dev);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -125,7 +126,7 @@ struct stm_device *stm_find_device(const char *buf)
|
||||||
* @stm: stm device, previously acquired by stm_find_device()
|
* @stm: stm device, previously acquired by stm_find_device()
|
||||||
*
|
*
|
||||||
* This drops the module reference and device reference taken by
|
* This drops the module reference and device reference taken by
|
||||||
* stm_find_device().
|
* stm_find_device() or stm_char_open().
|
||||||
*/
|
*/
|
||||||
void stm_put_device(struct stm_device *stm)
|
void stm_put_device(struct stm_device *stm)
|
||||||
{
|
{
|
||||||
|
@ -365,6 +366,8 @@ static int stm_char_open(struct inode *inode, struct file *file)
|
||||||
return nonseekable_open(inode, file);
|
return nonseekable_open(inode, file);
|
||||||
|
|
||||||
err_free:
|
err_free:
|
||||||
|
/* matches class_find_device() above */
|
||||||
|
put_device(dev);
|
||||||
kfree(stmf);
|
kfree(stmf);
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
|
@ -375,6 +378,11 @@ static int stm_char_release(struct inode *inode, struct file *file)
|
||||||
struct stm_file *stmf = file->private_data;
|
struct stm_file *stmf = file->private_data;
|
||||||
|
|
||||||
stm_output_free(stmf->stm, &stmf->output);
|
stm_output_free(stmf->stm, &stmf->output);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* matches the stm_char_open()'s
|
||||||
|
* class_find_device() + try_module_get()
|
||||||
|
*/
|
||||||
stm_put_device(stmf->stm);
|
stm_put_device(stmf->stm);
|
||||||
kfree(stmf);
|
kfree(stmf);
|
||||||
|
|
||||||
|
@ -539,10 +547,8 @@ static int stm_char_policy_set_ioctl(struct stm_file *stmf, void __user *arg)
|
||||||
ret = stm->data->link(stm->data, stmf->output.master,
|
ret = stm->data->link(stm->data, stmf->output.master,
|
||||||
stmf->output.channel);
|
stmf->output.channel);
|
||||||
|
|
||||||
if (ret) {
|
if (ret)
|
||||||
stm_output_free(stmf->stm, &stmf->output);
|
stm_output_free(stmf->stm, &stmf->output);
|
||||||
stm_put_device(stmf->stm);
|
|
||||||
}
|
|
||||||
|
|
||||||
err_free:
|
err_free:
|
||||||
kfree(id);
|
kfree(id);
|
||||||
|
@ -679,6 +685,7 @@ int stm_register_device(struct device *parent, struct stm_data *stm_data,
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
err_device:
|
err_device:
|
||||||
|
/* matches device_initialize() above */
|
||||||
put_device(&stm->dev);
|
put_device(&stm->dev);
|
||||||
err_free:
|
err_free:
|
||||||
kfree(stm);
|
kfree(stm);
|
||||||
|
@ -791,7 +798,6 @@ static int stm_source_link_add(struct stm_source_device *src,
|
||||||
|
|
||||||
fail_free_output:
|
fail_free_output:
|
||||||
stm_output_free(stm, &src->output);
|
stm_output_free(stm, &src->output);
|
||||||
stm_put_device(stm);
|
|
||||||
|
|
||||||
fail_detach:
|
fail_detach:
|
||||||
mutex_lock(&stm->link_mutex);
|
mutex_lock(&stm->link_mutex);
|
||||||
|
@ -905,8 +911,10 @@ static ssize_t stm_source_link_store(struct device *dev,
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
err = stm_source_link_add(src, link);
|
err = stm_source_link_add(src, link);
|
||||||
if (err)
|
if (err) {
|
||||||
|
/* matches the stm_find_device() above */
|
||||||
stm_put_device(link);
|
stm_put_device(link);
|
||||||
|
}
|
||||||
|
|
||||||
return err ? : count;
|
return err ? : count;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue