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>
This commit is contained in:
parent
38c53ca3c1
commit
8c2348e36a
@ -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;
|
||||
|
@ -193,61 +193,63 @@ 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)
|
||||
{
|
||||
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);
|
||||
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;
|
||||
}
|
||||
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;
|
||||
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) {
|
||||
#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);
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_COMPAT) && compat) {
|
||||
#ifdef CONFIG_COMPAT
|
||||
|
@ -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);
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user