Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2bc43b5c authored by Florian Mickler's avatar Florian Mickler Committed by Eric Anholt
Browse files

drm/i915: Fix use of uninitialized var in 40a5f0de



i915_gem_put_relocs_to_user returned an uninitialized value which
got returned to userspace. This caused libdrm in my setup to never
get out of a do{}while() loop retrying i915_gem_execbuffer.

result was hanging X, overheating of cpu and 2-3gb of logfile-spam.

This patch adresses the issue by
 1. initializing vars in this file where necessary
 2. correcting wrongly interpreted return values of copy_[from/to]_user

Signed-off-by: default avatarFlorian Mickler <florian@mickler.org>
[anholt: cleanups of unnecessary changes, consistency in APIs]
Signed-off-by: default avatarEric Anholt <eric@anholt.net>
parent 5b40f871
Loading
Loading
Loading
Loading
+22 −12
Original line number Diff line number Diff line
@@ -141,15 +141,18 @@ fast_shmem_read(struct page **pages,
		int length)
{
	char __iomem *vaddr;
	int ret;
	int unwritten;

	vaddr = kmap_atomic(pages[page_base >> PAGE_SHIFT], KM_USER0);
	if (vaddr == NULL)
		return -ENOMEM;
	ret = __copy_to_user_inatomic(data, vaddr + page_offset, length);
	unwritten = __copy_to_user_inatomic(data, vaddr + page_offset, length);
	kunmap_atomic(vaddr, KM_USER0);

	return ret;
	if (unwritten)
		return -EFAULT;

	return 0;
}

static inline int
@@ -3000,13 +3003,13 @@ i915_gem_get_relocs_from_user(struct drm_i915_gem_exec_object *exec_list,
			drm_free(*relocs, reloc_count * sizeof(**relocs),
				 DRM_MEM_DRIVER);
			*relocs = NULL;
			return ret;
			return -EFAULT;
		}

		reloc_index += exec_list[i].relocation_count;
	}

	return ret;
	return 0;
}

static int
@@ -3015,23 +3018,28 @@ i915_gem_put_relocs_to_user(struct drm_i915_gem_exec_object *exec_list,
			    struct drm_i915_gem_relocation_entry *relocs)
{
	uint32_t reloc_count = 0, i;
	int ret;
	int ret = 0;

	for (i = 0; i < buffer_count; i++) {
		struct drm_i915_gem_relocation_entry __user *user_relocs;
		int unwritten;

		user_relocs = (void __user *)(uintptr_t)exec_list[i].relocs_ptr;

		if (ret == 0) {
			ret = copy_to_user(user_relocs,
		unwritten = copy_to_user(user_relocs,
					 &relocs[reloc_count],
					 exec_list[i].relocation_count *
					 sizeof(*relocs));

		if (unwritten) {
			ret = -EFAULT;
			goto err;
		}

		reloc_count += exec_list[i].relocation_count;
	}

err:
	drm_free(relocs, reloc_count * sizeof(*relocs), DRM_MEM_DRIVER);

	return ret;
@@ -3306,11 +3314,13 @@ i915_gem_execbuffer(struct drm_device *dev, void *data,
				   (uintptr_t) args->buffers_ptr,
				   exec_list,
				   sizeof(*exec_list) * args->buffer_count);
		if (ret)
		if (ret) {
			ret = -EFAULT;
			DRM_ERROR("failed to copy %d exec entries "
				  "back to user (%d)\n",
				  args->buffer_count, ret);
		}
	}

	/* Copy the updated relocations out regardless of current error
	 * state.  Failure to update the relocs would mean that the next