@@ -1027,7 +1027,7 @@ static void syncobj_wait_syncobj_func(struct drm_syncobj *syncobj,
}
static signed long drm_syncobj_array_wait_timeout(struct drm_syncobj **syncobjs,
- void __user *user_points,
+ u64 __user *user_points,
uint32_t count,
uint32_t flags,
signed long timeout,
@@ -1035,9 +1035,8 @@ static signed long drm_syncobj_array_wait_timeout(struct drm_syncobj **syncobjs,
ktime_t *deadline)
{
struct syncobj_wait_entry *entries;
- struct dma_fence *fence;
- uint64_t *points;
uint32_t signaled_count, i;
+ struct dma_fence *fence;
if (flags & (DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT |
DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE)) {
@@ -1045,24 +1044,14 @@ static signed long drm_syncobj_array_wait_timeout(struct drm_syncobj **syncobjs,
lockdep_assert_none_held_once();
}
- points = kmalloc_array(count, sizeof(*points), GFP_KERNEL);
- if (points == NULL)
- return -ENOMEM;
-
- if (!user_points) {
- memset(points, 0, count * sizeof(uint64_t));
-
- } else if (copy_from_user(points, user_points,
- sizeof(uint64_t) * count)) {
- timeout = -EFAULT;
- goto err_free_points;
- }
+ if (user_points &&
+ !access_ok(user_points, count * sizeof(*user_points)))
+ return -EFAULT;
entries = kcalloc(count, sizeof(*entries), GFP_KERNEL);
- if (!entries) {
- timeout = -ENOMEM;
- goto err_free_points;
- }
+ if (!entries)
+ return -ENOMEM;
+
/* Walk the list of sync objects and initialize entries. We do
* this up-front so that we can properly return -EINVAL if there is
* a syncobj with a missing fence and then never have the chance of
@@ -1073,9 +1062,13 @@ static signed long drm_syncobj_array_wait_timeout(struct drm_syncobj **syncobjs,
struct dma_fence *fence;
entries[i].task = current;
- entries[i].point = points[i];
+ if (user_points && get_user(entries[i].point, user_points++)) {
+ timeout = -EFAULT;
+ goto cleanup_entries;
+ }
fence = drm_syncobj_fence_get(syncobjs[i]);
- if (!fence || dma_fence_chain_find_seqno(&fence, points[i])) {
+ if (!fence ||
+ dma_fence_chain_find_seqno(&fence, entries[i].point)) {
dma_fence_put(fence);
if (flags & (DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT |
DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE)) {
@@ -1181,9 +1174,6 @@ static signed long drm_syncobj_array_wait_timeout(struct drm_syncobj **syncobjs,
}
kfree(entries);
-err_free_points:
- kfree(points);
-
return timeout;
}