summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOmar Ramirez Luna <omar.ramirez@ti.com>2012-01-30 19:20:17 -0600
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-02-14 15:38:51 -0800
commit2573897816e604952ee9f7dbe798094d80c1e31d (patch)
tree93c3eb36a923cb1d46505004e8d9b239299a46b7
parent00da8eddf9eb8d432533c3a83da3a6470a45dfc4 (diff)
staging: tidspbridge: fix bridge_open memory leaks
There are two members of pr_ctxt allocated during bridge_open that are never freed resulting in memory leaks, these are stream_id and node_id, they are now freed on release of the handle (bridge_release) right before freeing pr_ctxt. Error path for bridge_open was also fixed since the same variables could result in memory leaking due to missing handling of failure scenarios. While at it, the indentation changes were introduced to avoid interleaved goto statements inside big if blocks. Signed-off-by: Omar Ramirez Luna <omar.ramirez@ti.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/staging/tidspbridge/rmgr/drv_interface.c55
1 files changed, 32 insertions, 23 deletions
diff --git a/drivers/staging/tidspbridge/rmgr/drv_interface.c b/drivers/staging/tidspbridge/rmgr/drv_interface.c
index c14fa8ec3fa8..3cac01492063 100644
--- a/drivers/staging/tidspbridge/rmgr/drv_interface.c
+++ b/drivers/staging/tidspbridge/rmgr/drv_interface.c
@@ -139,35 +139,42 @@ static int bridge_open(struct inode *ip, struct file *filp)
}
#endif
pr_ctxt = kzalloc(sizeof(struct process_context), GFP_KERNEL);
- if (pr_ctxt) {
- pr_ctxt->res_state = PROC_RES_ALLOCATED;
- spin_lock_init(&pr_ctxt->dmm_map_lock);
- INIT_LIST_HEAD(&pr_ctxt->dmm_map_list);
- spin_lock_init(&pr_ctxt->dmm_rsv_lock);
- INIT_LIST_HEAD(&pr_ctxt->dmm_rsv_list);
-
- pr_ctxt->node_id = kzalloc(sizeof(struct idr), GFP_KERNEL);
- if (pr_ctxt->node_id) {
- idr_init(pr_ctxt->node_id);
- } else {
- status = -ENOMEM;
- goto err;
- }
+ if (!pr_ctxt)
+ return -ENOMEM;
+
+ pr_ctxt->res_state = PROC_RES_ALLOCATED;
+ spin_lock_init(&pr_ctxt->dmm_map_lock);
+ INIT_LIST_HEAD(&pr_ctxt->dmm_map_list);
+ spin_lock_init(&pr_ctxt->dmm_rsv_lock);
+ INIT_LIST_HEAD(&pr_ctxt->dmm_rsv_list);
- pr_ctxt->stream_id = kzalloc(sizeof(struct idr), GFP_KERNEL);
- if (pr_ctxt->stream_id)
- idr_init(pr_ctxt->stream_id);
- else
- status = -ENOMEM;
- } else {
+ pr_ctxt->node_id = kzalloc(sizeof(struct idr), GFP_KERNEL);
+ if (!pr_ctxt->node_id) {
status = -ENOMEM;
+ goto err1;
}
-err:
+
+ idr_init(pr_ctxt->node_id);
+
+ pr_ctxt->stream_id = kzalloc(sizeof(struct idr), GFP_KERNEL);
+ if (!pr_ctxt->stream_id) {
+ status = -ENOMEM;
+ goto err2;
+ }
+
+ idr_init(pr_ctxt->stream_id);
+
filp->private_data = pr_ctxt;
+
#ifdef CONFIG_TIDSPBRIDGE_RECOVERY
- if (!status)
- atomic_inc(&bridge_cref);
+ atomic_inc(&bridge_cref);
#endif
+ return 0;
+
+err2:
+ kfree(pr_ctxt->node_id);
+err1:
+ kfree(pr_ctxt);
return status;
}
@@ -189,6 +196,8 @@ static int bridge_release(struct inode *ip, struct file *filp)
flush_signals(current);
drv_remove_all_resources(pr_ctxt);
proc_detach(pr_ctxt);
+ kfree(pr_ctxt->node_id);
+ kfree(pr_ctxt->stream_id);
kfree(pr_ctxt);
filp->private_data = NULL;