mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-07-23 01:37:32 -04:00
drm/amdkfd: Use memdup_array_user to copy data from/to user space at kfd ioctls
Several kfd ioctls need transfer array data from/to user space. Kfd driver uses kmalloc_array with user provided size. That can oversize alloc or 32-bit wrap with hostile value. Replace it by memdup_array_user that does overflow checking and allocates through dedicated slab caches, also physical continuous as kmalloc. Signed-off-by: Xiaogang Chen <xiaogang.chen@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> (cherry picked from commit 4eca4742eb215951f9739ffe0122d179d545a7a4)
This commit is contained in:
committed by
Alex Deucher
parent
516bf737a5
commit
2321831d7e
@@ -1299,18 +1299,11 @@ static int kfd_ioctl_map_memory_to_gpu(struct file *filep,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
devices_arr = kmalloc_array(args->n_devices, sizeof(*devices_arr),
|
||||
GFP_KERNEL);
|
||||
if (!devices_arr)
|
||||
return -ENOMEM;
|
||||
devices_arr = memdup_array_user((void *)args->device_ids_array_ptr,
|
||||
args->n_devices, sizeof(*devices_arr));
|
||||
|
||||
err = copy_from_user(devices_arr,
|
||||
(void __user *)args->device_ids_array_ptr,
|
||||
args->n_devices * sizeof(*devices_arr));
|
||||
if (err != 0) {
|
||||
err = -EFAULT;
|
||||
goto copy_from_user_failed;
|
||||
}
|
||||
if (IS_ERR(devices_arr))
|
||||
return PTR_ERR(devices_arr);
|
||||
|
||||
mutex_lock(&p->mutex);
|
||||
pdd = kfd_process_device_data_by_id(p, GET_GPU_ID(args->handle));
|
||||
@@ -1391,7 +1384,6 @@ static int kfd_ioctl_map_memory_to_gpu(struct file *filep,
|
||||
map_memory_to_gpu_failed:
|
||||
sync_memory_failed:
|
||||
mutex_unlock(&p->mutex);
|
||||
copy_from_user_failed:
|
||||
kfree(devices_arr);
|
||||
|
||||
return err;
|
||||
@@ -1416,18 +1408,11 @@ static int kfd_ioctl_unmap_memory_from_gpu(struct file *filep,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
devices_arr = kmalloc_array(args->n_devices, sizeof(*devices_arr),
|
||||
GFP_KERNEL);
|
||||
if (!devices_arr)
|
||||
return -ENOMEM;
|
||||
devices_arr = memdup_array_user((void *)args->device_ids_array_ptr,
|
||||
args->n_devices, sizeof(*devices_arr));
|
||||
|
||||
err = copy_from_user(devices_arr,
|
||||
(void __user *)args->device_ids_array_ptr,
|
||||
args->n_devices * sizeof(*devices_arr));
|
||||
if (err != 0) {
|
||||
err = -EFAULT;
|
||||
goto copy_from_user_failed;
|
||||
}
|
||||
if (IS_ERR(devices_arr))
|
||||
return PTR_ERR(devices_arr);
|
||||
|
||||
mutex_lock(&p->mutex);
|
||||
pdd = kfd_process_device_data_by_id(p, GET_GPU_ID(args->handle));
|
||||
@@ -1493,7 +1478,6 @@ static int kfd_ioctl_unmap_memory_from_gpu(struct file *filep,
|
||||
unmap_memory_from_gpu_failed:
|
||||
sync_memory_failed:
|
||||
mutex_unlock(&p->mutex);
|
||||
copy_from_user_failed:
|
||||
kfree(devices_arr);
|
||||
return err;
|
||||
}
|
||||
@@ -2353,17 +2337,11 @@ static int criu_restore_devices(struct kfd_process *p,
|
||||
if (*priv_offset + (args->num_devices * sizeof(*device_privs)) > max_priv_data_size)
|
||||
return -EINVAL;
|
||||
|
||||
device_buckets = kmalloc_objs(*device_buckets, args->num_devices);
|
||||
if (!device_buckets)
|
||||
return -ENOMEM;
|
||||
device_buckets = memdup_array_user((void *)args->devices,
|
||||
args->num_devices, sizeof(*device_buckets));
|
||||
|
||||
ret = copy_from_user(device_buckets, (void __user *)args->devices,
|
||||
args->num_devices * sizeof(*device_buckets));
|
||||
if (ret) {
|
||||
pr_err("Failed to copy devices buckets from user\n");
|
||||
ret = -EFAULT;
|
||||
goto exit;
|
||||
}
|
||||
if (IS_ERR(device_buckets))
|
||||
return PTR_ERR(device_buckets);
|
||||
|
||||
for (i = 0; i < args->num_devices; i++) {
|
||||
struct kfd_node *dev;
|
||||
|
||||
Reference in New Issue
Block a user