summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArto Merilainen <amerilainen@nvidia.com>2016-05-10 09:16:03 +0300
committerWinnie Hsu <whsu@nvidia.com>2016-05-24 16:04:24 -0700
commit58e3084c00ca7b7ae59f906bb4e1948b0f1e291f (patch)
treea3a4914591a3486e2b489f579784b8177e95d680
parentbb7faf0544ccc7c310c27dd43857dc2a62fc7e5c (diff)
video: tegra: host: Fix ch open error handling
In case kernel fails to open a channel (e.g. due to inability to allocate hardware context or turn on the device), the channel open function releases the resources that were already allocated successfully. However, currently the error path additionally calls the channel release function for putting the channel pointer after the private data structures have been freed - thereby causing use-after-free memory usage. This patch reworks error handling in channel open to release channel without risking usage of already freed memory. Bug 1763577 Change-Id: Ic7562e69f2babad653afc7a11e413701494a30b4 Signed-off-by: Arto Merilainen <amerilainen@nvidia.com> Reviewed-on: http://git-master/r/1148081 Reviewed-by: Winnie Hsu <whsu@nvidia.com> Tested-by: Winnie Hsu <whsu@nvidia.com>
-rw-r--r--drivers/video/tegra/host/bus_client.c9
1 files changed, 5 insertions, 4 deletions
diff --git a/drivers/video/tegra/host/bus_client.c b/drivers/video/tegra/host/bus_client.c
index 3eaa07bd7413..2bf11ed426c0 100644
--- a/drivers/video/tegra/host/bus_client.c
+++ b/drivers/video/tegra/host/bus_client.c
@@ -248,10 +248,9 @@ static int __nvhost_channelopen(struct inode *inode,
trace_nvhost_channel_open(dev_name(&ch->dev->dev));
priv = kzalloc(sizeof(*priv), GFP_KERNEL);
- if (!priv) {
- nvhost_putchannel(ch, 1);
+ if (!priv)
goto fail;
- }
+
filp->private_data = priv;
priv->ch = ch;
if (nvhost_module_add_client(ch->dev, priv))
@@ -281,13 +280,15 @@ static int __nvhost_channelopen(struct inode *inode,
priv->timeout = 0;
mutex_unlock(&channel_lock);
return 0;
+
fail_priv:
nvhost_module_remove_client(ch->dev, priv);
fail_add_client:
kfree(priv);
fail:
+ nvhost_putchannel(ch, 1);
mutex_unlock(&channel_lock);
- nvhost_channelrelease(inode, filp);
+
return -ENOMEM;
}