提交 9aab8bff 编写于 作者: C Chris Wilson 提交者: Jani Nikula

drm/i915: Only copy back the modified fields to userspace from execbuffer

We only want to modifiy a single field in the userspace view of the
execbuffer command buffer, so explicitly change that rather than copy
everything back again.

This serves two purposes:

1. The single fields are much cheaper to copy (constant size so the
copy uses special case code) and much smaller than the whole array.

2. We modify the array for internal use that need to be masked from
the user.

Note: We need this backported since without it the next bugfix will
blow up when userspace recycles batchbuffers and relocations.
Signed-off-by: NChris Wilson <chris@chris-wilson.co.uk>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: stable@vger.kernel.org
Signed-off-by: NDaniel Vetter <daniel.vetter@ffwll.ch>
上级 00731155
...@@ -773,7 +773,7 @@ i915_gem_execbuffer_relocate_slow(struct drm_device *dev, ...@@ -773,7 +773,7 @@ i915_gem_execbuffer_relocate_slow(struct drm_device *dev,
* relocations were valid. * relocations were valid.
*/ */
for (j = 0; j < exec[i].relocation_count; j++) { for (j = 0; j < exec[i].relocation_count; j++) {
if (copy_to_user(&user_relocs[j].presumed_offset, if (__copy_to_user(&user_relocs[j].presumed_offset,
&invalid_offset, &invalid_offset,
sizeof(invalid_offset))) { sizeof(invalid_offset))) {
ret = -EFAULT; ret = -EFAULT;
...@@ -1355,18 +1355,21 @@ i915_gem_execbuffer(struct drm_device *dev, void *data, ...@@ -1355,18 +1355,21 @@ i915_gem_execbuffer(struct drm_device *dev, void *data,
ret = i915_gem_do_execbuffer(dev, data, file, &exec2, exec2_list); ret = i915_gem_do_execbuffer(dev, data, file, &exec2, exec2_list);
if (!ret) { if (!ret) {
struct drm_i915_gem_exec_object __user *user_exec_list =
to_user_ptr(args->buffers_ptr);
/* Copy the new buffer offsets back to the user's exec list. */ /* Copy the new buffer offsets back to the user's exec list. */
for (i = 0; i < args->buffer_count; i++) for (i = 0; i < args->buffer_count; i++) {
exec_list[i].offset = exec2_list[i].offset; ret = __copy_to_user(&user_exec_list[i].offset,
/* ... and back out to userspace */ &exec2_list[i].offset,
ret = copy_to_user(to_user_ptr(args->buffers_ptr), sizeof(user_exec_list[i].offset));
exec_list,
sizeof(*exec_list) * args->buffer_count);
if (ret) { if (ret) {
ret = -EFAULT; ret = -EFAULT;
DRM_DEBUG("failed to copy %d exec entries " DRM_DEBUG("failed to copy %d exec entries "
"back to user (%d)\n", "back to user (%d)\n",
args->buffer_count, ret); args->buffer_count, ret);
break;
}
} }
} }
...@@ -1412,14 +1415,21 @@ i915_gem_execbuffer2(struct drm_device *dev, void *data, ...@@ -1412,14 +1415,21 @@ i915_gem_execbuffer2(struct drm_device *dev, void *data,
ret = i915_gem_do_execbuffer(dev, data, file, args, exec2_list); ret = i915_gem_do_execbuffer(dev, data, file, args, exec2_list);
if (!ret) { if (!ret) {
/* Copy the new buffer offsets back to the user's exec list. */ /* Copy the new buffer offsets back to the user's exec list. */
ret = copy_to_user(to_user_ptr(args->buffers_ptr), struct drm_i915_gem_exec_object2 *user_exec_list =
exec2_list, to_user_ptr(args->buffers_ptr);
sizeof(*exec2_list) * args->buffer_count); int i;
for (i = 0; i < args->buffer_count; i++) {
ret = __copy_to_user(&user_exec_list[i].offset,
&exec2_list[i].offset,
sizeof(user_exec_list[i].offset));
if (ret) { if (ret) {
ret = -EFAULT; ret = -EFAULT;
DRM_DEBUG("failed to copy %d exec entries " DRM_DEBUG("failed to copy %d exec entries "
"back to user (%d)\n", "back to user\n",
args->buffer_count, ret); args->buffer_count);
break;
}
} }
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册