diff options
author | Tuomas Tynkkynen <ttynkkynen@nvidia.com> | 2012-08-24 15:14:45 +0300 |
---|---|---|
committer | Simone Willett <swillett@nvidia.com> | 2012-08-27 19:45:25 -0700 |
commit | 104cdeb7986e543cd3697769828ad8f33240a5fb (patch) | |
tree | 42a36877f9c7a651619e585c7d80b0cceac1a7f5 | |
parent | a4c597152f0b69ba1172b3d52d4e9d39ea3bbd53 (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.c | 31 |
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; |