From 8c2348e36af0da79477b0726781da297263269a4 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 10 May 2020 17:20:49 -0400 Subject: 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 --- net/atm/ioctl.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'net/atm/ioctl.c') 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; -- cgit v1.2.3-59-g8ed1b From a3929484af75ee524419edbbc4e9ce012c3d67c9 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 10 May 2020 17:34:20 -0400 Subject: atm: move copyin from atm_getnames() into the caller Signed-off-by: Al Viro --- net/atm/ioctl.c | 19 ++++++++++++++++++- net/atm/resources.c | 19 +------------------ net/atm/resources.h | 2 +- 3 files changed, 20 insertions(+), 20 deletions(-) (limited to 'net/atm/ioctl.c') diff --git a/net/atm/ioctl.c b/net/atm/ioctl.c index 0b4b07740fe4..e239cebf48da 100644 --- a/net/atm/ioctl.c +++ b/net/atm/ioctl.c @@ -56,6 +56,8 @@ static int do_vcc_ioctl(struct socket *sock, unsigned int cmd, int error; struct list_head *pos; void __user *argp = (void __user *)arg; + void __user *buf; + int __user *len; vcc = ATM_SD(sock); switch (cmd) { @@ -163,7 +165,22 @@ static int do_vcc_ioctl(struct socket *sock, unsigned int cmd, goto done; if (cmd == ATM_GETNAMES) { - error = atm_getnames(argp, compat); + if (IS_ENABLED(CONFIG_COMPAT) && compat) { +#ifdef CONFIG_COMPAT + struct compat_atm_iobuf __user *ciobuf = argp; + compat_uptr_t cbuf; + len = &ciobuf->length; + if (get_user(cbuf, &ciobuf->buffer)) + return -EFAULT; + buf = compat_ptr(cbuf); +#endif + } else { + struct atm_iobuf __user *iobuf = argp; + len = &iobuf->length; + if (get_user(buf, &iobuf->buffer)) + return -EFAULT; + } + error = atm_getnames(buf, len); } else { error = atm_dev_ioctl(cmd, argp, compat); } diff --git a/net/atm/resources.c b/net/atm/resources.c index a2ab75929eec..5507cc608969 100644 --- a/net/atm/resources.c +++ b/net/atm/resources.c @@ -193,30 +193,13 @@ static int fetch_stats(struct atm_dev *dev, struct atm_dev_stats __user *arg, return error ? -EFAULT : 0; } -int atm_getnames(void __user *arg, int compat) +int atm_getnames(void __user *buf, int __user *iobuf_len) { - void __user *buf; int error, len, size = 0; struct atm_dev *dev; struct list_head *p; int *tmp_buf, *tmp_p; - int __user *iobuf_len; - 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); -#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)) return -EFAULT; mutex_lock(&atm_dev_mutex); diff --git a/net/atm/resources.h b/net/atm/resources.h index 18f8e5948ce4..5e2c68d37d63 100644 --- a/net/atm/resources.h +++ b/net/atm/resources.h @@ -14,7 +14,7 @@ extern struct list_head atm_devs; extern struct mutex atm_dev_mutex; -int atm_getnames(void __user *arg, int compat); +int atm_getnames(void __user *buf, int __user *iobuf_len); int atm_dev_ioctl(unsigned int cmd, void __user *arg, int compat); -- cgit v1.2.3-59-g8ed1b From 36085049bc0acb6f2e784f430c2cc66944a2ef07 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 10 May 2020 17:41:51 -0400 Subject: atm: switch do_atm_iobuf() to direct use of atm_getnames() ... and sod the compat_alloc_user_space() with its complications Signed-off-by: Al Viro --- net/atm/ioctl.c | 25 +++---------------------- 1 file changed, 3 insertions(+), 22 deletions(-) (limited to 'net/atm/ioctl.c') diff --git a/net/atm/ioctl.c b/net/atm/ioctl.c index e239cebf48da..fdd0e3434523 100644 --- a/net/atm/ioctl.c +++ b/net/atm/ioctl.c @@ -251,32 +251,13 @@ static struct { static int do_atm_iobuf(struct socket *sock, unsigned int cmd, unsigned long arg) { - struct atm_iobuf __user *iobuf; - struct compat_atm_iobuf __user *iobuf32; + struct compat_atm_iobuf __user *iobuf32 = compat_ptr(arg); u32 data; - void __user *datap; - int len, err; - - iobuf = compat_alloc_user_space(sizeof(*iobuf)); - iobuf32 = compat_ptr(arg); - if (get_user(len, &iobuf32->length) || - get_user(data, &iobuf32->buffer)) - return -EFAULT; - datap = compat_ptr(data); - if (put_user(len, &iobuf->length) || - put_user(datap, &iobuf->buffer)) + if (get_user(data, &iobuf32->buffer)) return -EFAULT; - err = do_vcc_ioctl(sock, cmd, (unsigned long) iobuf, 0); - - if (!err) { - if (copy_in_user(&iobuf32->length, &iobuf->length, - sizeof(int))) - err = -EFAULT; - } - - return err; + return atm_getnames(&iobuf32->length, compat_ptr(data)); } static int do_atmif_sioc(struct socket *sock, unsigned int cmd, -- cgit v1.2.3-59-g8ed1b From 8cacb4165985444c275a6f813f91f08479bdbfad Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 10 May 2020 17:53:35 -0400 Subject: atm: lift copyin from atm_dev_ioctl() Signed-off-by: Al Viro --- net/atm/ioctl.c | 25 ++++++++++++++++++++++++- net/atm/resources.c | 35 +++++------------------------------ net/atm/resources.h | 4 ++-- 3 files changed, 31 insertions(+), 33 deletions(-) (limited to 'net/atm/ioctl.c') diff --git a/net/atm/ioctl.c b/net/atm/ioctl.c index fdd0e3434523..52f2c77e656f 100644 --- a/net/atm/ioctl.c +++ b/net/atm/ioctl.c @@ -182,7 +182,30 @@ static int do_vcc_ioctl(struct socket *sock, unsigned int cmd, } error = atm_getnames(buf, len); } else { - error = atm_dev_ioctl(cmd, argp, compat); + int number; + + if (IS_ENABLED(CONFIG_COMPAT) && compat) { +#ifdef CONFIG_COMPAT + struct compat_atmif_sioc __user *csioc = argp; + compat_uptr_t carg; + + len = &csioc->length; + if (get_user(carg, &csioc->arg)) + return -EFAULT; + buf = compat_ptr(carg); + if (get_user(number, &csioc->number)) + return -EFAULT; +#endif + } else { + struct atmif_sioc __user *sioc = argp; + + len = &sioc->length; + if (get_user(buf, &sioc->arg)) + return -EFAULT; + if (get_user(number, &sioc->number)) + return -EFAULT; + } + error = atm_dev_ioctl(cmd, buf, len, number, compat); } done: diff --git a/net/atm/resources.c b/net/atm/resources.c index 5507cc608969..94bdc6527ee8 100644 --- a/net/atm/resources.c +++ b/net/atm/resources.c @@ -227,39 +227,14 @@ int atm_getnames(void __user *buf, int __user *iobuf_len) return error; } -int atm_dev_ioctl(unsigned int cmd, void __user *arg, int compat) +int atm_dev_ioctl(unsigned int cmd, void __user *buf, int __user *sioc_len, + int number, int compat) { - void __user *buf; - int error, len, number, size = 0; + int error, len, size = 0; struct atm_dev *dev; - int __user *sioc_len; - if (IS_ENABLED(CONFIG_COMPAT) && compat) { -#ifdef CONFIG_COMPAT - struct compat_atmif_sioc __user *csioc = arg; - compat_uptr_t carg; - - sioc_len = &csioc->length; - if (get_user(carg, &csioc->arg)) - return -EFAULT; - buf = compat_ptr(carg); - - if (get_user(len, &csioc->length)) - return -EFAULT; - if (get_user(number, &csioc->number)) - return -EFAULT; -#endif - } else { - struct atmif_sioc __user *sioc = arg; - - sioc_len = &sioc->length; - if (get_user(buf, &sioc->arg)) - return -EFAULT; - if (get_user(len, &sioc->length)) - return -EFAULT; - if (get_user(number, &sioc->number)) - return -EFAULT; - } + if (get_user(len, sioc_len)) + return -EFAULT; dev = try_then_request_module(atm_dev_lookup(number), "atm-device-%d", number); diff --git a/net/atm/resources.h b/net/atm/resources.h index 5e2c68d37d63..4a0839e92ff3 100644 --- a/net/atm/resources.h +++ b/net/atm/resources.h @@ -15,8 +15,8 @@ extern struct list_head atm_devs; extern struct mutex atm_dev_mutex; int atm_getnames(void __user *buf, int __user *iobuf_len); -int atm_dev_ioctl(unsigned int cmd, void __user *arg, int compat); - +int atm_dev_ioctl(unsigned int cmd, void __user *buf, int __user *sioc_len, + int number, int compat); #ifdef CONFIG_PROC_FS -- cgit v1.2.3-59-g8ed1b From 0edecc020b33f8e31d8baa80735b45e8e8434700 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 10 May 2020 18:13:56 -0400 Subject: atm: switch do_atmif_sioc() to direct use of atm_dev_ioctl() Signed-off-by: Al Viro --- net/atm/ioctl.c | 25 ++++--------------------- 1 file changed, 4 insertions(+), 21 deletions(-) (limited to 'net/atm/ioctl.c') diff --git a/net/atm/ioctl.c b/net/atm/ioctl.c index 52f2c77e656f..838ebf0cabbf 100644 --- a/net/atm/ioctl.c +++ b/net/atm/ioctl.c @@ -286,30 +286,13 @@ static int do_atm_iobuf(struct socket *sock, unsigned int cmd, static int do_atmif_sioc(struct socket *sock, unsigned int cmd, unsigned long arg) { - struct atmif_sioc __user *sioc; - struct compat_atmif_sioc __user *sioc32; + struct compat_atmif_sioc __user *sioc32 = compat_ptr(arg); + int number; u32 data; - void __user *datap; - int err; - sioc = compat_alloc_user_space(sizeof(*sioc)); - sioc32 = compat_ptr(arg); - - if (copy_in_user(&sioc->number, &sioc32->number, 2 * sizeof(int)) || - get_user(data, &sioc32->arg)) - return -EFAULT; - datap = compat_ptr(data); - if (put_user(datap, &sioc->arg)) + if (get_user(data, &sioc32->arg) || get_user(number, &sioc32->number)) return -EFAULT; - - err = do_vcc_ioctl(sock, cmd, (unsigned long) sioc, 0); - - if (!err) { - if (copy_in_user(&sioc32->length, &sioc->length, - sizeof(int))) - err = -EFAULT; - } - return err; + return atm_dev_ioctl(cmd, compat_ptr(data), &sioc32->length, number, 0); } static int do_atm_ioctl(struct socket *sock, unsigned int cmd32, -- cgit v1.2.3-59-g8ed1b