diff options
author | Terje Bergstrom <tbergstrom@nvidia.com> | 2012-05-31 08:15:28 +0300 |
---|---|---|
committer | Simone Willett <swillett@nvidia.com> | 2012-06-03 08:01:37 -0700 |
commit | fdf40891983fc3fe1942877dcb07a4eab25f1796 (patch) | |
tree | f95b2e3f593cece2d8bd89c7cef8489f9fc42d6e /drivers/video/tegra/host | |
parent | 22049ebd104af134fce3cdf39c813fb993d869e9 (diff) |
video: tegra: host: Restrict register access
Register access (read/write) to modules MPE, ISP and VI lack sanity
check for the register number. Add checks to ensure only aperture is
accessed. Also make sure that the check accounts for wrapping of
values of offset and count.
Also fixes the register offset for reads which are done in multiple
blocks.
Bug 992938
Change-Id: I35f30cbd1dda31956286e48c5995b24fd262d1ae
Signed-off-by: Terje Bergstrom <tbergstrom@nvidia.com>
Reviewed-on: http://git-master/r/105585
Reviewed-by: Automatic_Commit_Validation_User
GVS: Gerrit_Virtual_Submit
Diffstat (limited to 'drivers/video/tegra/host')
-rw-r--r-- | drivers/video/tegra/host/bus_client.c | 32 | ||||
-rw-r--r-- | drivers/video/tegra/host/bus_client.h | 4 | ||||
-rw-r--r-- | drivers/video/tegra/host/dev.c | 11 |
3 files changed, 40 insertions, 7 deletions
diff --git a/drivers/video/tegra/host/bus_client.c b/drivers/video/tegra/host/bus_client.c index 962de32f359f..651a8dec738c 100644 --- a/drivers/video/tegra/host/bus_client.c +++ b/drivers/video/tegra/host/bus_client.c @@ -50,10 +50,28 @@ #include "nvhost_job.h" #include "nvhost_hwctx.h" -void nvhost_read_module_regs(struct nvhost_device *ndev, +static int validate_reg(struct nvhost_device *ndev, u32 offset, int count) +{ + struct resource *r = nvhost_get_resource(ndev, IORESOURCE_MEM, 0); + int err = 0; + + if (offset + 4 * count > resource_size(r) + || (offset + 4 * count < offset)) + err = -EPERM; + + return err; +} + +int nvhost_read_module_regs(struct nvhost_device *ndev, u32 offset, int count, u32 *values) { void __iomem *p = ndev->aperture + offset; + int err; + + /* verify offset */ + err = validate_reg(ndev, offset, count); + if (err) + return err; nvhost_module_busy(ndev); while (count--) { @@ -62,12 +80,20 @@ void nvhost_read_module_regs(struct nvhost_device *ndev, } rmb(); nvhost_module_idle(ndev); + + return 0; } -void nvhost_write_module_regs(struct nvhost_device *ndev, +int nvhost_write_module_regs(struct nvhost_device *ndev, u32 offset, int count, const u32 *values) { void __iomem *p = ndev->aperture + offset; + int err; + + /* verify offset */ + err = validate_reg(ndev, offset, count); + if (err) + return err; nvhost_module_busy(ndev); while (count--) { @@ -76,6 +102,8 @@ void nvhost_write_module_regs(struct nvhost_device *ndev, } wmb(); nvhost_module_idle(ndev); + + return 0; } struct nvhost_channel_userctx { diff --git a/drivers/video/tegra/host/bus_client.h b/drivers/video/tegra/host/bus_client.h index adc3a704ea5d..e95ea0bc3401 100644 --- a/drivers/video/tegra/host/bus_client.h +++ b/drivers/video/tegra/host/bus_client.h @@ -24,10 +24,10 @@ #include <linux/types.h> struct nvhost_device; -void nvhost_read_module_regs(struct nvhost_device *ndev, +int nvhost_read_module_regs(struct nvhost_device *ndev, u32 offset, int count, u32 *values); -void nvhost_write_module_regs(struct nvhost_device *ndev, +int nvhost_write_module_regs(struct nvhost_device *ndev, u32 offset, int count, const u32 *values); int nvhost_client_user_init(struct nvhost_device *dev); diff --git a/drivers/video/tegra/host/dev.c b/drivers/video/tegra/host/dev.c index ca73528fbeeb..67520a884d3e 100644 --- a/drivers/video/tegra/host/dev.c +++ b/drivers/video/tegra/host/dev.c @@ -205,6 +205,7 @@ static int nvhost_ioctl_ctrl_module_regrdwr(struct nvhost_ctrl_userctx *ctx, return -EINVAL; while (num_offsets--) { + int err; int remaining = args->block_size >> 2; u32 offs; if (get_user(offs, offsets)) @@ -216,17 +217,21 @@ static int nvhost_ioctl_ctrl_module_regrdwr(struct nvhost_ctrl_userctx *ctx, if (copy_from_user(vals, values, batch*sizeof(u32))) return -EFAULT; - nvhost_write_module_regs(ndev, + err = nvhost_write_module_regs(ndev, offs, batch, vals); + if (err) + return err; } else { - nvhost_read_module_regs(ndev, + err = nvhost_read_module_regs(ndev, offs, batch, vals); + if (err) + return err; if (copy_to_user(values, vals, batch*sizeof(u32))) return -EFAULT; } remaining -= batch; - offs += batch; + offs += batch*sizeof(u32); values += batch; } } |