Commit 8c2348e3 authored by Al Viro's avatar Al Viro

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: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent 38c53ca3
...@@ -162,7 +162,11 @@ static int do_vcc_ioctl(struct socket *sock, unsigned int cmd, ...@@ -162,7 +162,11 @@ static int do_vcc_ioctl(struct socket *sock, unsigned int cmd,
if (error != -ENOIOCTLCMD) if (error != -ENOIOCTLCMD)
goto done; 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: done:
return error; return error;
......
...@@ -193,61 +193,63 @@ static int fetch_stats(struct atm_dev *dev, struct atm_dev_stats __user *arg, ...@@ -193,61 +193,63 @@ static int fetch_stats(struct atm_dev *dev, struct atm_dev_stats __user *arg,
return error ? -EFAULT : 0; 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; void __user *buf;
int error, len, number, size = 0; int error, len, size = 0;
struct atm_dev *dev; struct atm_dev *dev;
struct list_head *p; struct list_head *p;
int *tmp_buf, *tmp_p; int *tmp_buf, *tmp_p;
int __user *sioc_len;
int __user *iobuf_len; int __user *iobuf_len;
switch (cmd) { if (IS_ENABLED(CONFIG_COMPAT) && compat) {
case ATM_GETNAMES:
if (IS_ENABLED(CONFIG_COMPAT) && compat) {
#ifdef CONFIG_COMPAT #ifdef CONFIG_COMPAT
struct compat_atm_iobuf __user *ciobuf = arg; struct compat_atm_iobuf __user *ciobuf = arg;
compat_uptr_t cbuf; compat_uptr_t cbuf;
iobuf_len = &ciobuf->length; iobuf_len = &ciobuf->length;
if (get_user(cbuf, &ciobuf->buffer)) if (get_user(cbuf, &ciobuf->buffer))
return -EFAULT; return -EFAULT;
buf = compat_ptr(cbuf); buf = compat_ptr(cbuf);
#endif #endif
} else { } else {
struct atm_iobuf __user *iobuf = arg; struct atm_iobuf __user *iobuf = arg;
iobuf_len = &iobuf->length; iobuf_len = &iobuf->length;
if (get_user(buf, &iobuf->buffer)) if (get_user(buf, &iobuf->buffer))
return -EFAULT;
}
if (get_user(len, iobuf_len))
return -EFAULT; return -EFAULT;
mutex_lock(&atm_dev_mutex); }
list_for_each(p, &atm_devs) if (get_user(len, iobuf_len))
size += sizeof(int); return -EFAULT;
if (size > len) { mutex_lock(&atm_dev_mutex);
mutex_unlock(&atm_dev_mutex); list_for_each(p, &atm_devs)
return -E2BIG; size += sizeof(int);
} if (size > len) {
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); mutex_unlock(&atm_dev_mutex);
error = ((copy_to_user(buf, tmp_buf, size)) || return -E2BIG;
put_user(size, iobuf_len))
? -EFAULT : 0;
kfree(tmp_buf);
return error;
default:
break;
} }
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) { if (IS_ENABLED(CONFIG_COMPAT) && compat) {
#ifdef CONFIG_COMPAT #ifdef CONFIG_COMPAT
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
extern struct list_head atm_devs; extern struct list_head atm_devs;
extern struct mutex atm_dev_mutex; 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); int atm_dev_ioctl(unsigned int cmd, void __user *arg, int compat);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment