atm: separate ATM_GETNAMES handling from the rest of atm_dev_ioctl()
authorAl Viro <viro@zeniv.linux.org.uk>
Sun, 10 May 2020 21:20:49 +0000 (17:20 -0400)
committerAl Viro <viro@zeniv.linux.org.uk>
Thu, 21 May 2020 00:31:33 +0000 (20:31 -0400)
atm_dev_ioctl() does copyin in two different ways - one for
ATM_GETNAMES, another for everything else.  Start with separating
the former into a new helper (atm_getnames()).  The next step
will be to lift the copyin into the callers.

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
net/atm/ioctl.c
net/atm/resources.c
net/atm/resources.h

index d955b68..0b4b077 100644 (file)
@@ -162,7 +162,11 @@ static int do_vcc_ioctl(struct socket *sock, unsigned int cmd,
        if (error != -ENOIOCTLCMD)
                goto done;
 
-       error = atm_dev_ioctl(cmd, argp, compat);
+       if (cmd == ATM_GETNAMES) {
+               error = atm_getnames(argp, compat);
+       } else {
+               error = atm_dev_ioctl(cmd, argp, compat);
+       }
 
 done:
        return error;
index 889349c..a2ab759 100644 (file)
@@ -193,61 +193,63 @@ static int fetch_stats(struct atm_dev *dev, struct atm_dev_stats __user *arg,
        return error ? -EFAULT : 0;
 }
 
-int atm_dev_ioctl(unsigned int cmd, void __user *arg, int compat)
+int atm_getnames(void __user *arg, int compat)
 {
        void __user *buf;
-       int error, len, number, size = 0;
+       int error, len, size = 0;
        struct atm_dev *dev;
        struct list_head *p;
        int *tmp_buf, *tmp_p;
-       int __user *sioc_len;
        int __user *iobuf_len;
 
-       switch (cmd) {
-       case ATM_GETNAMES:
-               if (IS_ENABLED(CONFIG_COMPAT) && compat) {
+       if (IS_ENABLED(CONFIG_COMPAT) && compat) {
 #ifdef CONFIG_COMPAT
-                       struct compat_atm_iobuf __user *ciobuf = arg;
-                       compat_uptr_t cbuf;
-                       iobuf_len = &ciobuf->length;
-                       if (get_user(cbuf, &ciobuf->buffer))
-                               return -EFAULT;
-                       buf = compat_ptr(cbuf);
+               struct compat_atm_iobuf __user *ciobuf = arg;
+               compat_uptr_t cbuf;
+               iobuf_len = &ciobuf->length;
+               if (get_user(cbuf, &ciobuf->buffer))
+                       return -EFAULT;
+               buf = compat_ptr(cbuf);
 #endif
-               } else {
-                       struct atm_iobuf __user *iobuf = arg;
-                       iobuf_len = &iobuf->length;
-                       if (get_user(buf, &iobuf->buffer))
-                               return -EFAULT;
-               }
-               if (get_user(len, iobuf_len))
+       } else {
+               struct atm_iobuf __user *iobuf = arg;
+               iobuf_len = &iobuf->length;
+               if (get_user(buf, &iobuf->buffer))
                        return -EFAULT;
-               mutex_lock(&atm_dev_mutex);
-               list_for_each(p, &atm_devs)
-                       size += sizeof(int);
-               if (size > len) {
-                       mutex_unlock(&atm_dev_mutex);
-                       return -E2BIG;
-               }
-               tmp_buf = kmalloc(size, GFP_ATOMIC);
-               if (!tmp_buf) {
-                       mutex_unlock(&atm_dev_mutex);
-                       return -ENOMEM;
-               }
-               tmp_p = tmp_buf;
-               list_for_each(p, &atm_devs) {
-                       dev = list_entry(p, struct atm_dev, dev_list);
-                       *tmp_p++ = dev->number;
-               }
+       }
+       if (get_user(len, iobuf_len))
+               return -EFAULT;
+       mutex_lock(&atm_dev_mutex);
+       list_for_each(p, &atm_devs)
+               size += sizeof(int);
+       if (size > len) {
                mutex_unlock(&atm_dev_mutex);
-               error = ((copy_to_user(buf, tmp_buf, size)) ||
-                        put_user(size, iobuf_len))
-                       ? -EFAULT : 0;
-               kfree(tmp_buf);
-               return error;
-       default:
-               break;
+               return -E2BIG;
        }
+       tmp_buf = kmalloc(size, GFP_ATOMIC);
+       if (!tmp_buf) {
+               mutex_unlock(&atm_dev_mutex);
+               return -ENOMEM;
+       }
+       tmp_p = tmp_buf;
+       list_for_each(p, &atm_devs) {
+               dev = list_entry(p, struct atm_dev, dev_list);
+               *tmp_p++ = dev->number;
+       }
+       mutex_unlock(&atm_dev_mutex);
+       error = ((copy_to_user(buf, tmp_buf, size)) ||
+                put_user(size, iobuf_len))
+               ? -EFAULT : 0;
+       kfree(tmp_buf);
+       return error;
+}
+
+int atm_dev_ioctl(unsigned int cmd, void __user *arg, int compat)
+{
+       void __user *buf;
+       int error, len, number, size = 0;
+       struct atm_dev *dev;
+       int __user *sioc_len;
 
        if (IS_ENABLED(CONFIG_COMPAT) && compat) {
 #ifdef CONFIG_COMPAT
index 048232e..18f8e59 100644 (file)
@@ -14,6 +14,7 @@
 extern struct list_head atm_devs;
 extern struct mutex atm_dev_mutex;
 
+int atm_getnames(void __user *arg, int compat);
 int atm_dev_ioctl(unsigned int cmd, void __user *arg, int compat);