mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-30 03:27:44 -04:00
net: separate SIOCGIFCONF handling from dev_ioctl()
Only two of dev_ioctl() callers may pass SIOCGIFCONF to it. Separating that codepath from the rest of dev_ioctl() allows both to simplify dev_ioctl() itself (all other cases work with struct ifreq *) *and* seriously simplify the compat side of that beast: all it takes is passing to inet_gifconf() an extra argument - the size of individual records (sizeof(struct ifreq) or sizeof(struct compat_ifreq)). With dev_ifconf() called directly from sock_do_ioctl()/compat_dev_ifconf() that's easy to arrange. As the result, compat side of SIOCGIFCONF doesn't need any allocations, copy_in_user() back and forth, etc. Reviewed-by: Christoph Hellwig <[email protected]> Signed-off-by: Al Viro <[email protected]>
This commit is contained in:
parent
be1b6e8b54
commit
36fd633ec9
4 changed files with 42 additions and 86 deletions
|
|
@ -1188,22 +1188,25 @@ rarok:
|
|||
goto out;
|
||||
}
|
||||
|
||||
static int inet_gifconf(struct net_device *dev, char __user *buf, int len)
|
||||
static int inet_gifconf(struct net_device *dev, char __user *buf, int len, int size)
|
||||
{
|
||||
struct in_device *in_dev = __in_dev_get_rtnl(dev);
|
||||
struct in_ifaddr *ifa;
|
||||
struct ifreq ifr;
|
||||
int done = 0;
|
||||
|
||||
if (WARN_ON(size > sizeof(struct ifreq)))
|
||||
goto out;
|
||||
|
||||
if (!in_dev)
|
||||
goto out;
|
||||
|
||||
for (ifa = in_dev->ifa_list; ifa; ifa = ifa->ifa_next) {
|
||||
if (!buf) {
|
||||
done += sizeof(ifr);
|
||||
done += size;
|
||||
continue;
|
||||
}
|
||||
if (len < (int) sizeof(ifr))
|
||||
if (len < size)
|
||||
break;
|
||||
memset(&ifr, 0, sizeof(struct ifreq));
|
||||
strcpy(ifr.ifr_name, ifa->ifa_label);
|
||||
|
|
@ -1212,13 +1215,12 @@ static int inet_gifconf(struct net_device *dev, char __user *buf, int len)
|
|||
(*(struct sockaddr_in *)&ifr.ifr_addr).sin_addr.s_addr =
|
||||
ifa->ifa_local;
|
||||
|
||||
if (copy_to_user(buf, &ifr, sizeof(struct ifreq))) {
|
||||
if (copy_to_user(buf + done, &ifr, size)) {
|
||||
done = -EFAULT;
|
||||
break;
|
||||
}
|
||||
buf += sizeof(struct ifreq);
|
||||
len -= sizeof(struct ifreq);
|
||||
done += sizeof(struct ifreq);
|
||||
len -= size;
|
||||
done += size;
|
||||
}
|
||||
out:
|
||||
return done;
|
||||
|
|
|
|||
Loading…
Reference in a new issue