@@ -1211,48 +1211,46 @@ signed long drm_timeout_abs_to_jiffies(int64_t timeout_nsec)
EXPORT_SYMBOL(drm_timeout_abs_to_jiffies);
static int drm_syncobj_array_find(struct drm_file *file_private,
- void __user *user_handles,
- uint32_t count_handles,
+ u32 __user *handles,
+ uint32_t count,
struct drm_syncobj ***syncobjs_out)
{
- uint32_t i, *handles;
struct drm_syncobj **syncobjs;
+ uint32_t i;
int ret;
- handles = kmalloc_array(count_handles, sizeof(*handles), GFP_KERNEL);
- if (handles == NULL)
+ if (!access_ok(handles, count * sizeof(*handles)))
+ return -EFAULT;
+
+ syncobjs = kmalloc_array(count, sizeof(*syncobjs), GFP_KERNEL);
+ if (!syncobjs)
return -ENOMEM;
- if (copy_from_user(handles, user_handles,
- sizeof(uint32_t) * count_handles)) {
- ret = -EFAULT;
- goto err_free_handles;
- }
+ for (i = 0; i < count; i++) {
+ u64 handle;
- syncobjs = kmalloc_array(count_handles, sizeof(*syncobjs), GFP_KERNEL);
- if (syncobjs == NULL) {
- ret = -ENOMEM;
- goto err_free_handles;
- }
-
- for (i = 0; i < count_handles; i++) {
- syncobjs[i] = drm_syncobj_find(file_private, handles[i]);
+ if (get_user(handle, handles++)) {
+ ret = -EFAULT;
+ syncobjs[i] = NULL;
+ goto err_put_syncobjs;
+ }
+ syncobjs[i] = drm_syncobj_find(file_private, handle);
if (!syncobjs[i]) {
ret = -ENOENT;
goto err_put_syncobjs;
}
}
- kfree(handles);
*syncobjs_out = syncobjs;
return 0;
err_put_syncobjs:
- while (i-- > 0)
- drm_syncobj_put(syncobjs[i]);
+ while (i > 0) {
+ if (syncobjs[i])
+ drm_syncobj_put(syncobjs[i]);
+ i--;
+ }
kfree(syncobjs);
-err_free_handles:
- kfree(handles);
return ret;
}