Replace k(v)malloc_array() + copy_from_user() with (v)memdup_array_user().

This shrinks the source code and improves separation between the kernel
and userspace slabs.

Signed-off-by: Tvrtko Ursulin <tvrtko.ursu...@igalia.com>
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 33 ++++++++------------------
 1 file changed, 10 insertions(+), 23 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
index 7e2ab0e5be96..4240a6de1f32 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
@@ -178,25 +178,17 @@ static int amdgpu_cs_pass1(struct amdgpu_cs_parser *p,
        struct amdgpu_fpriv *fpriv = p->filp->driver_priv;
        unsigned int num_ibs[AMDGPU_CS_GANG_SIZE] = { };
        struct amdgpu_vm *vm = &fpriv->vm;
-       uint64_t *chunk_array_user;
        uint64_t *chunk_array;
        uint32_t uf_offset = 0;
        size_t size;
        int ret;
        int i;
 
-       chunk_array = kvmalloc_array(cs->in.num_chunks, sizeof(uint64_t),
-                                    GFP_KERNEL);
-       if (!chunk_array)
-               return -ENOMEM;
-
-       /* get chunks */
-       chunk_array_user = u64_to_user_ptr(cs->in.chunks);
-       if (copy_from_user(chunk_array, chunk_array_user,
-                          sizeof(uint64_t)*cs->in.num_chunks)) {
-               ret = -EFAULT;
-               goto free_chunk;
-       }
+       chunk_array = memdup_array_user(u64_to_user_ptr(cs->in.chunks),
+                                       cs->in.num_chunks,
+                                       sizeof(uint64_t));
+       if (IS_ERR(chunk_array))
+               return PTR_ERR(chunk_array);
 
        p->nchunks = cs->in.num_chunks;
        p->chunks = kvmalloc_array(p->nchunks, sizeof(struct amdgpu_cs_chunk),
@@ -209,7 +201,6 @@ static int amdgpu_cs_pass1(struct amdgpu_cs_parser *p,
        for (i = 0; i < p->nchunks; i++) {
                struct drm_amdgpu_cs_chunk __user *chunk_ptr = NULL;
                struct drm_amdgpu_cs_chunk user_chunk;
-               uint32_t __user *cdata;
 
                chunk_ptr = u64_to_user_ptr(chunk_array[i]);
                if (copy_from_user(&user_chunk, chunk_ptr,
@@ -222,20 +213,16 @@ static int amdgpu_cs_pass1(struct amdgpu_cs_parser *p,
                p->chunks[i].length_dw = user_chunk.length_dw;
 
                size = p->chunks[i].length_dw;
-               cdata = u64_to_user_ptr(user_chunk.chunk_data);
 
-               p->chunks[i].kdata = kvmalloc_array(size, sizeof(uint32_t),
-                                                   GFP_KERNEL);
-               if (p->chunks[i].kdata == NULL) {
-                       ret = -ENOMEM;
+               p->chunks[i].kdata = 
vmemdup_array_user(u64_to_user_ptr(user_chunk.chunk_data),
+                                                       size,
+                                                       sizeof(uint32_t));
+               if (IS_ERR(p->chunks[i].kdata)) {
+                       ret = PTR_ERR(p->chunks[i].kdata);
                        i--;
                        goto free_partial_kdata;
                }
                size *= sizeof(uint32_t);
-               if (copy_from_user(p->chunks[i].kdata, cdata, size)) {
-                       ret = -EFAULT;
-                       goto free_partial_kdata;
-               }
 
                /* Assume the worst on the following checks */
                ret = -EINVAL;
-- 
2.48.0

Reply via email to