]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
nilfs2: replace vmalloc + copy_from_user with vmemdup_user
authorThorsten Blum <thorsten.blum@linux.dev>
Thu, 30 Oct 2025 15:46:43 +0000 (00:46 +0900)
committerAndrew Morton <akpm@linux-foundation.org>
Wed, 12 Nov 2025 18:00:17 +0000 (10:00 -0800)
Replace vmalloc() followed by copy_from_user() with vmemdup_user() to
improve nilfs_ioctl_clean_segments() and nilfs_ioctl_set_suinfo().  Use
kvfree() to free the buffers created by vmemdup_user().

Use u64_to_user_ptr() instead of manually casting the pointers and
remove the obsolete 'out_free' label.

No functional changes intended.

Link: https://lkml.kernel.org/r/20251030154700.7444-1-konishi.ryusuke@gmail.com
Signed-off-by: Thorsten Blum <thorsten.blum@linux.dev>
Signed-off-by: Ryusuke Konishi <konishi.ryusuke@gmail.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
fs/nilfs2/ioctl.c

index 3288c3b4be9ec0f9b5258c8b0242bd8fc9b691dd..e17b8da66491334e2d3d182e84ac6ec08275eb85 100644 (file)
@@ -49,7 +49,7 @@ static int nilfs_ioctl_wrap_copy(struct the_nilfs *nilfs,
                                                   void *, size_t, size_t))
 {
        void *buf;
-       void __user *base = (void __user *)(unsigned long)argv->v_base;
+       void __user *base = u64_to_user_ptr(argv->v_base);
        size_t maxmembs, total, n;
        ssize_t nr;
        int ret, i;
@@ -836,7 +836,6 @@ static int nilfs_ioctl_clean_segments(struct inode *inode, struct file *filp,
                sizeof(struct nilfs_bdesc),
                sizeof(__u64),
        };
-       void __user *base;
        void *kbufs[5];
        struct the_nilfs *nilfs;
        size_t len, nsegs;
@@ -863,7 +862,7 @@ static int nilfs_ioctl_clean_segments(struct inode *inode, struct file *filp,
         * use kmalloc() for its buffer because the memory used for the
         * segment numbers is small enough.
         */
-       kbufs[4] = memdup_array_user((void __user *)(unsigned long)argv[4].v_base,
+       kbufs[4] = memdup_array_user(u64_to_user_ptr(argv[4].v_base),
                                     nsegs, sizeof(__u64));
        if (IS_ERR(kbufs[4])) {
                ret = PTR_ERR(kbufs[4]);
@@ -883,20 +882,14 @@ static int nilfs_ioctl_clean_segments(struct inode *inode, struct file *filp,
                        goto out_free;
 
                len = argv[n].v_size * argv[n].v_nmembs;
-               base = (void __user *)(unsigned long)argv[n].v_base;
                if (len == 0) {
                        kbufs[n] = NULL;
                        continue;
                }
 
-               kbufs[n] = vmalloc(len);
-               if (!kbufs[n]) {
-                       ret = -ENOMEM;
-                       goto out_free;
-               }
-               if (copy_from_user(kbufs[n], base, len)) {
-                       ret = -EFAULT;
-                       vfree(kbufs[n]);
+               kbufs[n] = vmemdup_user(u64_to_user_ptr(argv[n].v_base), len);
+               if (IS_ERR(kbufs[n])) {
+                       ret = PTR_ERR(kbufs[n]);
                        goto out_free;
                }
        }
@@ -928,7 +921,7 @@ static int nilfs_ioctl_clean_segments(struct inode *inode, struct file *filp,
 
 out_free:
        while (--n >= 0)
-               vfree(kbufs[n]);
+               kvfree(kbufs[n]);
        kfree(kbufs[4]);
 out:
        mnt_drop_write_file(filp);
@@ -1181,7 +1174,6 @@ static int nilfs_ioctl_set_suinfo(struct inode *inode, struct file *filp,
        struct nilfs_transaction_info ti;
        struct nilfs_argv argv;
        size_t len;
-       void __user *base;
        void *kbuf;
        int ret;
 
@@ -1212,18 +1204,12 @@ static int nilfs_ioctl_set_suinfo(struct inode *inode, struct file *filp,
                goto out;
        }
 
-       base = (void __user *)(unsigned long)argv.v_base;
-       kbuf = vmalloc(len);
-       if (!kbuf) {
-               ret = -ENOMEM;
+       kbuf = vmemdup_user(u64_to_user_ptr(argv.v_base), len);
+       if (IS_ERR(kbuf)) {
+               ret = PTR_ERR(kbuf);
                goto out;
        }
 
-       if (copy_from_user(kbuf, base, len)) {
-               ret = -EFAULT;
-               goto out_free;
-       }
-
        nilfs_transaction_begin(inode->i_sb, &ti, 0);
        ret = nilfs_sufile_set_suinfo(nilfs->ns_sufile, kbuf, argv.v_size,
                        argv.v_nmembs);
@@ -1232,8 +1218,7 @@ static int nilfs_ioctl_set_suinfo(struct inode *inode, struct file *filp,
        else
                nilfs_transaction_commit(inode->i_sb); /* never fails */
 
-out_free:
-       vfree(kbuf);
+       kvfree(kbuf);
 out:
        mnt_drop_write_file(filp);
        return ret;