Commit 59e67606 authored by Alexander Viro's avatar Alexander Viro Committed by Linus Torvalds

[PATCH] sparse (compat_ioctl): SIOCGIFCONF

	Switched to compat_alloc_user_space(), killed kmalloc and set_fs(),
annotated, somewhat cleaned up.
parent 031e2236
...@@ -490,55 +490,54 @@ static int dev_ifconf(unsigned int fd, unsigned int cmd, unsigned long arg) ...@@ -490,55 +490,54 @@ static int dev_ifconf(unsigned int fd, unsigned int cmd, unsigned long arg)
{ {
struct ifconf32 ifc32; struct ifconf32 ifc32;
struct ifconf ifc; struct ifconf ifc;
struct ifreq32 *ifr32; struct ifconf __user *uifc;
struct ifreq *ifr; struct ifreq32 __user *ifr32;
mm_segment_t old_fs; struct ifreq __user *ifr;
unsigned int i, j; unsigned int i, j;
int err; int err;
if (copy_from_user(&ifc32, compat_ptr(arg), sizeof(struct ifconf32))) if (copy_from_user(&ifc32, compat_ptr(arg), sizeof(struct ifconf32)))
return -EFAULT; return -EFAULT;
if(ifc32.ifcbuf == 0) { if (ifc32.ifcbuf == 0) {
ifc32.ifc_len = 0; ifc32.ifc_len = 0;
ifc.ifc_len = 0; ifc.ifc_len = 0;
ifc.ifc_buf = NULL; ifc.ifc_req = NULL;
uifc = compat_alloc_user_space(sizeof(struct ifconf));
} else { } else {
ifc.ifc_len = ((ifc32.ifc_len / sizeof (struct ifreq32)) + 1) * size_t len =((ifc32.ifc_len / sizeof (struct ifreq32)) + 1) *
sizeof (struct ifreq); sizeof (struct ifreq);
/* should the size be limited? -arnd */ uifc = compat_alloc_user_space(sizeof(struct ifconf) + len);
ifc.ifc_buf = kmalloc (ifc.ifc_len, GFP_KERNEL); ifc.ifc_len = len;
if (!ifc.ifc_buf) ifr = ifc.ifc_req = (void __user *)(uifc + 1);
return -ENOMEM;
}
ifr = ifc.ifc_req;
ifr32 = compat_ptr(ifc32.ifcbuf); ifr32 = compat_ptr(ifc32.ifcbuf);
for (i = 0; i < ifc32.ifc_len; i += sizeof (struct ifreq32)) { for (i = 0; i < ifc32.ifc_len; i += sizeof (struct ifreq32)) {
if (copy_from_user(ifr, ifr32, sizeof (struct ifreq32))) { if (copy_in_user(ifr, ifr32, sizeof(struct ifreq32)))
kfree (ifc.ifc_buf);
return -EFAULT; return -EFAULT;
}
ifr++; ifr++;
ifr32++; ifr32++;
} }
old_fs = get_fs(); set_fs (KERNEL_DS); }
err = sys_ioctl (fd, SIOCGIFCONF, (unsigned long)&ifc); if (copy_to_user(uifc, &ifc, sizeof(struct ifconf)))
set_fs (old_fs); return -EFAULT;
if (!err) {
err = sys_ioctl (fd, SIOCGIFCONF, (unsigned long)uifc);
if (err)
return err;
if (copy_from_user(&ifc, uifc, sizeof(struct ifconf)))
return -EFAULT;
ifr = ifc.ifc_req; ifr = ifc.ifc_req;
ifr32 = compat_ptr(ifc32.ifcbuf); ifr32 = compat_ptr(ifc32.ifcbuf);
for (i = 0, j = 0; i < ifc32.ifc_len && j < ifc.ifc_len; for (i = 0, j = 0; i < ifc32.ifc_len && j < ifc.ifc_len;
i += sizeof (struct ifreq32), j += sizeof (struct ifreq)) { i += sizeof (struct ifreq32), j += sizeof (struct ifreq)) {
int k = copy_to_user(ifr32, ifr, sizeof (struct ifreq32)); if (copy_in_user(ifr32, ifr, sizeof (struct ifreq32)))
return -EFAULT;
ifr32++; ifr32++;
ifr++; ifr++;
if (k) {
err = -EFAULT;
break;
} }
}
if (!err) {
if (ifc32.ifcbuf == 0) { if (ifc32.ifcbuf == 0) {
/* Translate from 64-bit structure multiple to /* Translate from 64-bit structure multiple to
* a 32-bit one. * a 32-bit one.
...@@ -553,12 +552,9 @@ static int dev_ifconf(unsigned int fd, unsigned int cmd, unsigned long arg) ...@@ -553,12 +552,9 @@ static int dev_ifconf(unsigned int fd, unsigned int cmd, unsigned long arg)
ifc32.ifc_len = i - sizeof (struct ifreq32); ifc32.ifc_len = i - sizeof (struct ifreq32);
} }
if (copy_to_user(compat_ptr(arg), &ifc32, sizeof(struct ifconf32))) if (copy_to_user(compat_ptr(arg), &ifc32, sizeof(struct ifconf32)))
err = -EFAULT; return -EFAULT;
}
} return 0;
if(ifc.ifc_buf != NULL)
kfree (ifc.ifc_buf);
return err;
} }
static int ethtool_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) static int ethtool_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
......
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