diff options
author | Arto Merilainen <amerilainen@nvidia.com> | 2016-05-10 09:16:03 +0300 |
---|---|---|
committer | Winnie Hsu <whsu@nvidia.com> | 2016-05-24 16:04:24 -0700 |
commit | 58e3084c00ca7b7ae59f906bb4e1948b0f1e291f (patch) | |
tree | a3a4914591a3486e2b489f579784b8177e95d680 | |
parent | bb7faf0544ccc7c310c27dd43857dc2a62fc7e5c (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.c | 9 |
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; } |