diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2020-05-10 17:20:49 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2020-05-20 20:31:33 -0400 |
commit | 8c2348e36af0da79477b0726781da297263269a4 (patch) | |
tree | 7531d2169816af383653297b7560a6be3d3eb7c5 | |
parent | 38c53ca3c114fa2a7030f0d1f54feaf044957609 (diff) | |
download | linux-8c2348e36af0da79477b0726781da297263269a4.tar.bz2 |
atm: separate ATM_GETNAMES handling from the rest of atm_dev_ioctl()
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>
-rw-r--r-- | net/atm/ioctl.c | 6 | ||||
-rw-r--r-- | net/atm/resources.c | 88 | ||||
-rw-r--r-- | net/atm/resources.h | 1 |
3 files changed, 51 insertions, 44 deletions
diff --git a/net/atm/ioctl.c b/net/atm/ioctl.c index d955b683aa7c..0b4b07740fe4 100644 --- a/net/atm/ioctl.c +++ b/net/atm/ioctl.c @@ -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; diff --git a/net/atm/resources.c b/net/atm/resources.c index 889349c6d90d..a2ab75929eec 100644 --- a/net/atm/resources.c +++ b/net/atm/resources.c @@ -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 diff --git a/net/atm/resources.h b/net/atm/resources.h index 048232e4d4c6..18f8e5948ce4 100644 --- a/net/atm/resources.h +++ b/net/atm/resources.h @@ -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); |