aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/host1x/job.c
diff options
context:
space:
mode:
authorArto Merilainen <amerilainen@nvidia.com>2013-05-29 06:26:03 -0400
committerThierry Reding <thierry.reding@gmail.com>2013-06-22 06:43:52 -0400
commit5060d8ec7cfc29dd399b4fe952ba96e7a88aa778 (patch)
tree8a8234fd8eb8798c72b5f3493237a9a2ec435b15 /drivers/gpu/host1x/job.c
parent64c173d3a2bb367c901f1f0a66c1d4e338d8cb2c (diff)
gpu: host1x: Check reloc table before usage
The firewall assumed that the user space always delivers a relocation table when it is accessing address registers. If userspace did not deliver a relocation table and tried to access the address registers, the code performed bad memory accesses. This patch modifies the firewall to check correctly that the firewall table is available before accessing it. In addition, check_reloc() is converted to use boolean return value (true when the reloc is valid, false when invalid). Signed-off-by: Arto Merilainen <amerilainen@nvidia.com> Acked-By: Terje Bergstrom <tbergstrom@nvidia.com> Signed-off-by: Thierry Reding <thierry.reding@gmail.com>
Diffstat (limited to 'drivers/gpu/host1x/job.c')
-rw-r--r--drivers/gpu/host1x/job.c26
1 files changed, 13 insertions, 13 deletions
diff --git a/drivers/gpu/host1x/job.c b/drivers/gpu/host1x/job.c
index 2974ac8d70a7..83804fdf9c99 100644
--- a/drivers/gpu/host1x/job.c
+++ b/drivers/gpu/host1x/job.c
@@ -268,15 +268,15 @@ static unsigned int do_relocs(struct host1x_job *job, struct host1x_bo *cmdbuf)
268 return 0; 268 return 0;
269} 269}
270 270
271static int check_reloc(struct host1x_reloc *reloc, struct host1x_bo *cmdbuf, 271static bool check_reloc(struct host1x_reloc *reloc, struct host1x_bo *cmdbuf,
272 unsigned int offset) 272 unsigned int offset)
273{ 273{
274 offset *= sizeof(u32); 274 offset *= sizeof(u32);
275 275
276 if (reloc->cmdbuf != cmdbuf || reloc->cmdbuf_offset != offset) 276 if (reloc->cmdbuf != cmdbuf || reloc->cmdbuf_offset != offset)
277 return -EINVAL; 277 return false;
278 278
279 return 0; 279 return true;
280} 280}
281 281
282struct host1x_firewall { 282struct host1x_firewall {
@@ -307,10 +307,10 @@ static int check_mask(struct host1x_firewall *fw)
307 307
308 if (mask & 1) { 308 if (mask & 1) {
309 if (fw->job->is_addr_reg(fw->dev, fw->class, reg)) { 309 if (fw->job->is_addr_reg(fw->dev, fw->class, reg)) {
310 bool bad_reloc = check_reloc(fw->reloc, 310 if (!fw->num_relocs)
311 fw->cmdbuf_id, 311 return -EINVAL;
312 fw->offset); 312 if (!check_reloc(fw->reloc, fw->cmdbuf_id,
313 if (!fw->num_relocs || bad_reloc) 313 fw->offset))
314 return -EINVAL; 314 return -EINVAL;
315 fw->reloc++; 315 fw->reloc++;
316 fw->num_relocs--; 316 fw->num_relocs--;
@@ -335,9 +335,9 @@ static int check_incr(struct host1x_firewall *fw)
335 return -EINVAL; 335 return -EINVAL;
336 336
337 if (fw->job->is_addr_reg(fw->dev, fw->class, reg)) { 337 if (fw->job->is_addr_reg(fw->dev, fw->class, reg)) {
338 bool bad_reloc = check_reloc(fw->reloc, fw->cmdbuf_id, 338 if (!fw->num_relocs)
339 fw->offset); 339 return -EINVAL;
340 if (!fw->num_relocs || bad_reloc) 340 if (!check_reloc(fw->reloc, fw->cmdbuf_id, fw->offset))
341 return -EINVAL; 341 return -EINVAL;
342 fw->reloc++; 342 fw->reloc++;
343 fw->num_relocs--; 343 fw->num_relocs--;
@@ -361,9 +361,9 @@ static int check_nonincr(struct host1x_firewall *fw)
361 return -EINVAL; 361 return -EINVAL;
362 362
363 if (is_addr_reg) { 363 if (is_addr_reg) {
364 bool bad_reloc = check_reloc(fw->reloc, fw->cmdbuf_id, 364 if (!fw->num_relocs)
365 fw->offset); 365 return -EINVAL;
366 if (!fw->num_relocs || bad_reloc) 366 if (!check_reloc(fw->reloc, fw->cmdbuf_id, fw->offset))
367 return -EINVAL; 367 return -EINVAL;
368 fw->reloc++; 368 fw->reloc++;
369 fw->num_relocs--; 369 fw->num_relocs--;