Skip to content

Commit

Permalink
staging: tidspbridge: fix bridge_open memory leaks
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Omar Ramirez Luna authored and Greg Kroah-Hartman committed Feb 8, 2012
1 parent e5d7965 commit 5a63177
Showing 1 changed file with 32 additions and 23 deletions.
55 changes: 32 additions & 23 deletions drivers/staging/tidspbridge/rmgr/drv_interface.c
Original file line number Diff line number Diff line change
Expand Up @@ -500,35 +500,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;
}

Expand All @@ -550,6 +557,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;
Expand Down

0 comments on commit 5a63177

Please sign in to comment.