summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTuomas Tynkkynen <ttynkkynen@nvidia.com>2012-08-24 15:14:45 +0300
committerSimone Willett <swillett@nvidia.com>2012-08-27 19:45:25 -0700
commit104cdeb7986e543cd3697769828ad8f33240a5fb (patch)
tree42a36877f9c7a651619e585c7d80b0cceac1a7f5
parenta4c597152f0b69ba1172b3d52d4e9d39ea3bbd53 (diff)
video: tegra: host: fix integer overflows
job_size() calculates the size of a job structure based on a struct passed as a ioctl parameter. This calculation was not checked for overflow. Bug 1038551 Change-Id: I13d087dbd5aad5fef1c5d13ceb23e50f565acf95 Signed-off-by: Tuomas Tynkkynen <ttynkkynen@nvidia.com> Reviewed-on: http://git-master/r/127185 Reviewed-by: Automatic_Commit_Validation_User GVS: Gerrit_Virtual_Submit Reviewed-by: Terje Bergstrom <tbergstrom@nvidia.com>
-rw-r--r--drivers/video/tegra/host/nvhost_job.c31
1 files changed, 23 insertions, 8 deletions
diff --git a/drivers/video/tegra/host/nvhost_job.c b/drivers/video/tegra/host/nvhost_job.c
index f93d7df1a552..f0f7e64d4504 100644
--- a/drivers/video/tegra/host/nvhost_job.c
+++ b/drivers/video/tegra/host/nvhost_job.c
@@ -34,19 +34,27 @@
/* Magic to use to fill freed handle slots */
#define BAD_MAGIC 0xdeadbeef
-static int job_size(struct nvhost_submit_hdr_ext *hdr)
+static size_t job_size(struct nvhost_submit_hdr_ext *hdr)
{
- int num_relocs = hdr ? hdr->num_relocs : 0;
- int num_waitchks = hdr ? hdr->num_waitchks : 0;
- int num_cmdbufs = hdr ? hdr->num_cmdbufs : 0;
- int num_unpins = num_cmdbufs + num_relocs;
+ s64 num_relocs = hdr ? (int)hdr->num_relocs : 0;
+ s64 num_waitchks = hdr ? (int)hdr->num_waitchks : 0;
+ s64 num_cmdbufs = hdr ? (int)hdr->num_cmdbufs : 0;
+ s64 num_unpins = num_cmdbufs + num_relocs;
+ s64 total;
- return sizeof(struct nvhost_job)
+ if(num_relocs < 0 || num_waitchks < 0 || num_cmdbufs < 0)
+ return 0;
+
+ total = sizeof(struct nvhost_job)
+ num_relocs * sizeof(struct nvhost_reloc)
+ num_relocs * sizeof(struct nvhost_reloc_shift)
+ num_unpins * sizeof(struct mem_handle *)
+ num_waitchks * sizeof(struct nvhost_waitchk)
+ num_cmdbufs * sizeof(struct nvhost_job_gather);
+
+ if(total > ULONG_MAX)
+ return 0;
+ return (size_t)total;
}
static void init_fields(struct nvhost_job *job,
@@ -63,7 +71,11 @@ static void init_fields(struct nvhost_job *job,
job->priority = priority;
job->clientid = clientid;
- /* Redistribute memory to the structs */
+ /*
+ * Redistribute memory to the structs.
+ * Overflows and negative conditions have
+ * already been checked in job_alloc().
+ */
mem += sizeof(struct nvhost_job);
job->relocarray = num_relocs ? mem : NULL;
mem += num_relocs * sizeof(struct nvhost_reloc);
@@ -91,8 +103,11 @@ struct nvhost_job *nvhost_job_alloc(struct nvhost_channel *ch,
int clientid)
{
struct nvhost_job *job = NULL;
+ size_t size = job_size(hdr);
- job = vzalloc(job_size(hdr));
+ if(!size)
+ goto error;
+ job = vzalloc(size);
if (!job)
goto error;