diff options
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem_execbuffer.c | 42 |
1 files changed, 29 insertions, 13 deletions
diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index 0e051eca3639..1fa01313d89f 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c | |||
@@ -405,30 +405,46 @@ static int | |||
405 | i915_gem_execbuffer_relocate_object(struct drm_i915_gem_object *obj, | 405 | i915_gem_execbuffer_relocate_object(struct drm_i915_gem_object *obj, |
406 | struct eb_objects *eb) | 406 | struct eb_objects *eb) |
407 | { | 407 | { |
408 | #define N_RELOC(x) ((x) / sizeof(struct drm_i915_gem_relocation_entry)) | ||
409 | struct drm_i915_gem_relocation_entry stack_reloc[N_RELOC(512)]; | ||
408 | struct drm_i915_gem_relocation_entry __user *user_relocs; | 410 | struct drm_i915_gem_relocation_entry __user *user_relocs; |
409 | struct drm_i915_gem_exec_object2 *entry = obj->exec_entry; | 411 | struct drm_i915_gem_exec_object2 *entry = obj->exec_entry; |
410 | int i, ret; | 412 | int remain, ret; |
411 | 413 | ||
412 | user_relocs = (void __user *)(uintptr_t)entry->relocs_ptr; | 414 | user_relocs = (void __user *)(uintptr_t)entry->relocs_ptr; |
413 | for (i = 0; i < entry->relocation_count; i++) { | ||
414 | struct drm_i915_gem_relocation_entry reloc; | ||
415 | 415 | ||
416 | if (__copy_from_user_inatomic(&reloc, | 416 | remain = entry->relocation_count; |
417 | user_relocs+i, | 417 | while (remain) { |
418 | sizeof(reloc))) | 418 | struct drm_i915_gem_relocation_entry *r = stack_reloc; |
419 | int count = remain; | ||
420 | if (count > ARRAY_SIZE(stack_reloc)) | ||
421 | count = ARRAY_SIZE(stack_reloc); | ||
422 | remain -= count; | ||
423 | |||
424 | if (__copy_from_user_inatomic(r, user_relocs, count*sizeof(r[0]))) | ||
419 | return -EFAULT; | 425 | return -EFAULT; |
420 | 426 | ||
421 | ret = i915_gem_execbuffer_relocate_entry(obj, eb, &reloc); | 427 | do { |
422 | if (ret) | 428 | u64 offset = r->presumed_offset; |
423 | return ret; | ||
424 | 429 | ||
425 | if (__copy_to_user_inatomic(&user_relocs[i].presumed_offset, | 430 | ret = i915_gem_execbuffer_relocate_entry(obj, eb, r); |
426 | &reloc.presumed_offset, | 431 | if (ret) |
427 | sizeof(reloc.presumed_offset))) | 432 | return ret; |
428 | return -EFAULT; | 433 | |
434 | if (r->presumed_offset != offset && | ||
435 | __copy_to_user_inatomic(&user_relocs->presumed_offset, | ||
436 | &r->presumed_offset, | ||
437 | sizeof(r->presumed_offset))) { | ||
438 | return -EFAULT; | ||
439 | } | ||
440 | |||
441 | user_relocs++; | ||
442 | r++; | ||
443 | } while (--count); | ||
429 | } | 444 | } |
430 | 445 | ||
431 | return 0; | 446 | return 0; |
447 | #undef N_RELOC | ||
432 | } | 448 | } |
433 | 449 | ||
434 | static int | 450 | static int |