mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-30 19:51:31 -04:00
Merge branch 'rebased-net-ioctl' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Signed-off-by: David S. Miller <[email protected]>
This commit is contained in:
commit
8ec59b44a0
12 changed files with 173 additions and 399 deletions
|
|
@ -872,6 +872,9 @@ int inet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
|
|||
struct sock *sk = sock->sk;
|
||||
int err = 0;
|
||||
struct net *net = sock_net(sk);
|
||||
void __user *p = (void __user *)arg;
|
||||
struct ifreq ifr;
|
||||
struct rtentry rt;
|
||||
|
||||
switch (cmd) {
|
||||
case SIOCGSTAMP:
|
||||
|
|
@ -882,8 +885,12 @@ int inet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
|
|||
break;
|
||||
case SIOCADDRT:
|
||||
case SIOCDELRT:
|
||||
if (copy_from_user(&rt, p, sizeof(struct rtentry)))
|
||||
return -EFAULT;
|
||||
err = ip_rt_ioctl(net, cmd, &rt);
|
||||
break;
|
||||
case SIOCRTMSG:
|
||||
err = ip_rt_ioctl(net, cmd, (void __user *)arg);
|
||||
err = -EINVAL;
|
||||
break;
|
||||
case SIOCDARP:
|
||||
case SIOCGARP:
|
||||
|
|
@ -891,17 +898,26 @@ int inet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
|
|||
err = arp_ioctl(net, cmd, (void __user *)arg);
|
||||
break;
|
||||
case SIOCGIFADDR:
|
||||
case SIOCSIFADDR:
|
||||
case SIOCGIFBRDADDR:
|
||||
case SIOCSIFBRDADDR:
|
||||
case SIOCGIFNETMASK:
|
||||
case SIOCSIFNETMASK:
|
||||
case SIOCGIFDSTADDR:
|
||||
case SIOCGIFPFLAGS:
|
||||
if (copy_from_user(&ifr, p, sizeof(struct ifreq)))
|
||||
return -EFAULT;
|
||||
err = devinet_ioctl(net, cmd, &ifr);
|
||||
if (!err && copy_to_user(p, &ifr, sizeof(struct ifreq)))
|
||||
err = -EFAULT;
|
||||
break;
|
||||
|
||||
case SIOCSIFADDR:
|
||||
case SIOCSIFBRDADDR:
|
||||
case SIOCSIFNETMASK:
|
||||
case SIOCSIFDSTADDR:
|
||||
case SIOCSIFPFLAGS:
|
||||
case SIOCGIFPFLAGS:
|
||||
case SIOCSIFFLAGS:
|
||||
err = devinet_ioctl(net, cmd, (void __user *)arg);
|
||||
if (copy_from_user(&ifr, p, sizeof(struct ifreq)))
|
||||
return -EFAULT;
|
||||
err = devinet_ioctl(net, cmd, &ifr);
|
||||
break;
|
||||
default:
|
||||
if (sk->sk_prot->ioctl)
|
||||
|
|
|
|||
|
|
@ -946,11 +946,10 @@ static int inet_abc_len(__be32 addr)
|
|||
}
|
||||
|
||||
|
||||
int devinet_ioctl(struct net *net, unsigned int cmd, void __user *arg)
|
||||
int devinet_ioctl(struct net *net, unsigned int cmd, struct ifreq *ifr)
|
||||
{
|
||||
struct ifreq ifr;
|
||||
struct sockaddr_in sin_orig;
|
||||
struct sockaddr_in *sin = (struct sockaddr_in *)&ifr.ifr_addr;
|
||||
struct sockaddr_in *sin = (struct sockaddr_in *)&ifr->ifr_addr;
|
||||
struct in_device *in_dev;
|
||||
struct in_ifaddr **ifap = NULL;
|
||||
struct in_ifaddr *ifa = NULL;
|
||||
|
|
@ -959,22 +958,16 @@ int devinet_ioctl(struct net *net, unsigned int cmd, void __user *arg)
|
|||
int ret = -EFAULT;
|
||||
int tryaddrmatch = 0;
|
||||
|
||||
/*
|
||||
* Fetch the caller's info block into kernel space
|
||||
*/
|
||||
|
||||
if (copy_from_user(&ifr, arg, sizeof(struct ifreq)))
|
||||
goto out;
|
||||
ifr.ifr_name[IFNAMSIZ - 1] = 0;
|
||||
ifr->ifr_name[IFNAMSIZ - 1] = 0;
|
||||
|
||||
/* save original address for comparison */
|
||||
memcpy(&sin_orig, sin, sizeof(*sin));
|
||||
|
||||
colon = strchr(ifr.ifr_name, ':');
|
||||
colon = strchr(ifr->ifr_name, ':');
|
||||
if (colon)
|
||||
*colon = 0;
|
||||
|
||||
dev_load(net, ifr.ifr_name);
|
||||
dev_load(net, ifr->ifr_name);
|
||||
|
||||
switch (cmd) {
|
||||
case SIOCGIFADDR: /* Get interface address */
|
||||
|
|
@ -1014,7 +1007,7 @@ int devinet_ioctl(struct net *net, unsigned int cmd, void __user *arg)
|
|||
rtnl_lock();
|
||||
|
||||
ret = -ENODEV;
|
||||
dev = __dev_get_by_name(net, ifr.ifr_name);
|
||||
dev = __dev_get_by_name(net, ifr->ifr_name);
|
||||
if (!dev)
|
||||
goto done;
|
||||
|
||||
|
|
@ -1031,7 +1024,7 @@ int devinet_ioctl(struct net *net, unsigned int cmd, void __user *arg)
|
|||
This is checked above. */
|
||||
for (ifap = &in_dev->ifa_list; (ifa = *ifap) != NULL;
|
||||
ifap = &ifa->ifa_next) {
|
||||
if (!strcmp(ifr.ifr_name, ifa->ifa_label) &&
|
||||
if (!strcmp(ifr->ifr_name, ifa->ifa_label) &&
|
||||
sin_orig.sin_addr.s_addr ==
|
||||
ifa->ifa_local) {
|
||||
break; /* found */
|
||||
|
|
@ -1044,7 +1037,7 @@ int devinet_ioctl(struct net *net, unsigned int cmd, void __user *arg)
|
|||
if (!ifa) {
|
||||
for (ifap = &in_dev->ifa_list; (ifa = *ifap) != NULL;
|
||||
ifap = &ifa->ifa_next)
|
||||
if (!strcmp(ifr.ifr_name, ifa->ifa_label))
|
||||
if (!strcmp(ifr->ifr_name, ifa->ifa_label))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -1056,19 +1049,19 @@ int devinet_ioctl(struct net *net, unsigned int cmd, void __user *arg)
|
|||
switch (cmd) {
|
||||
case SIOCGIFADDR: /* Get interface address */
|
||||
sin->sin_addr.s_addr = ifa->ifa_local;
|
||||
goto rarok;
|
||||
break;
|
||||
|
||||
case SIOCGIFBRDADDR: /* Get the broadcast address */
|
||||
sin->sin_addr.s_addr = ifa->ifa_broadcast;
|
||||
goto rarok;
|
||||
break;
|
||||
|
||||
case SIOCGIFDSTADDR: /* Get the destination address */
|
||||
sin->sin_addr.s_addr = ifa->ifa_address;
|
||||
goto rarok;
|
||||
break;
|
||||
|
||||
case SIOCGIFNETMASK: /* Get the netmask for the interface */
|
||||
sin->sin_addr.s_addr = ifa->ifa_mask;
|
||||
goto rarok;
|
||||
break;
|
||||
|
||||
case SIOCSIFFLAGS:
|
||||
if (colon) {
|
||||
|
|
@ -1076,11 +1069,11 @@ int devinet_ioctl(struct net *net, unsigned int cmd, void __user *arg)
|
|||
if (!ifa)
|
||||
break;
|
||||
ret = 0;
|
||||
if (!(ifr.ifr_flags & IFF_UP))
|
||||
if (!(ifr->ifr_flags & IFF_UP))
|
||||
inet_del_ifa(in_dev, ifap, 1);
|
||||
break;
|
||||
}
|
||||
ret = dev_change_flags(dev, ifr.ifr_flags);
|
||||
ret = dev_change_flags(dev, ifr->ifr_flags);
|
||||
break;
|
||||
|
||||
case SIOCSIFADDR: /* Set interface address (and family) */
|
||||
|
|
@ -1095,7 +1088,7 @@ int devinet_ioctl(struct net *net, unsigned int cmd, void __user *arg)
|
|||
break;
|
||||
INIT_HLIST_NODE(&ifa->hash);
|
||||
if (colon)
|
||||
memcpy(ifa->ifa_label, ifr.ifr_name, IFNAMSIZ);
|
||||
memcpy(ifa->ifa_label, ifr->ifr_name, IFNAMSIZ);
|
||||
else
|
||||
memcpy(ifa->ifa_label, dev->name, IFNAMSIZ);
|
||||
} else {
|
||||
|
|
@ -1182,28 +1175,27 @@ done:
|
|||
rtnl_unlock();
|
||||
out:
|
||||
return ret;
|
||||
rarok:
|
||||
rtnl_unlock();
|
||||
ret = copy_to_user(arg, &ifr, sizeof(struct ifreq)) ? -EFAULT : 0;
|
||||
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 +1204,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;
|
||||
|
|
|
|||
|
|
@ -587,10 +587,9 @@ static int rtentry_to_fib_config(struct net *net, int cmd, struct rtentry *rt,
|
|||
* Handle IP routing ioctl calls.
|
||||
* These are used to manipulate the routing tables
|
||||
*/
|
||||
int ip_rt_ioctl(struct net *net, unsigned int cmd, void __user *arg)
|
||||
int ip_rt_ioctl(struct net *net, unsigned int cmd, struct rtentry *rt)
|
||||
{
|
||||
struct fib_config cfg;
|
||||
struct rtentry rt;
|
||||
int err;
|
||||
|
||||
switch (cmd) {
|
||||
|
|
@ -599,11 +598,8 @@ int ip_rt_ioctl(struct net *net, unsigned int cmd, void __user *arg)
|
|||
if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
|
||||
return -EPERM;
|
||||
|
||||
if (copy_from_user(&rt, arg, sizeof(rt)))
|
||||
return -EFAULT;
|
||||
|
||||
rtnl_lock();
|
||||
err = rtentry_to_fib_config(net, cmd, &rt, &cfg);
|
||||
err = rtentry_to_fib_config(net, cmd, rt, &cfg);
|
||||
if (err == 0) {
|
||||
struct fib_table *tb;
|
||||
|
||||
|
|
|
|||
|
|
@ -329,39 +329,6 @@ set_sockaddr(struct sockaddr_in *sin, __be32 addr, __be16 port)
|
|||
sin->sin_port = port;
|
||||
}
|
||||
|
||||
static int __init ic_devinet_ioctl(unsigned int cmd, struct ifreq *arg)
|
||||
{
|
||||
int res;
|
||||
|
||||
mm_segment_t oldfs = get_fs();
|
||||
set_fs(get_ds());
|
||||
res = devinet_ioctl(&init_net, cmd, (struct ifreq __user *) arg);
|
||||
set_fs(oldfs);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int __init ic_dev_ioctl(unsigned int cmd, struct ifreq *arg)
|
||||
{
|
||||
int res;
|
||||
|
||||
mm_segment_t oldfs = get_fs();
|
||||
set_fs(get_ds());
|
||||
res = dev_ioctl(&init_net, cmd, (struct ifreq __user *) arg);
|
||||
set_fs(oldfs);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int __init ic_route_ioctl(unsigned int cmd, struct rtentry *arg)
|
||||
{
|
||||
int res;
|
||||
|
||||
mm_segment_t oldfs = get_fs();
|
||||
set_fs(get_ds());
|
||||
res = ip_rt_ioctl(&init_net, cmd, (void __user *) arg);
|
||||
set_fs(oldfs);
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set up interface addresses and routes.
|
||||
*/
|
||||
|
|
@ -375,19 +342,19 @@ static int __init ic_setup_if(void)
|
|||
memset(&ir, 0, sizeof(ir));
|
||||
strcpy(ir.ifr_ifrn.ifrn_name, ic_dev->dev->name);
|
||||
set_sockaddr(sin, ic_myaddr, 0);
|
||||
if ((err = ic_devinet_ioctl(SIOCSIFADDR, &ir)) < 0) {
|
||||
if ((err = devinet_ioctl(&init_net, SIOCSIFADDR, &ir)) < 0) {
|
||||
pr_err("IP-Config: Unable to set interface address (%d)\n",
|
||||
err);
|
||||
return -1;
|
||||
}
|
||||
set_sockaddr(sin, ic_netmask, 0);
|
||||
if ((err = ic_devinet_ioctl(SIOCSIFNETMASK, &ir)) < 0) {
|
||||
if ((err = devinet_ioctl(&init_net, SIOCSIFNETMASK, &ir)) < 0) {
|
||||
pr_err("IP-Config: Unable to set interface netmask (%d)\n",
|
||||
err);
|
||||
return -1;
|
||||
}
|
||||
set_sockaddr(sin, ic_myaddr | ~ic_netmask, 0);
|
||||
if ((err = ic_devinet_ioctl(SIOCSIFBRDADDR, &ir)) < 0) {
|
||||
if ((err = devinet_ioctl(&init_net, SIOCSIFBRDADDR, &ir)) < 0) {
|
||||
pr_err("IP-Config: Unable to set interface broadcast address (%d)\n",
|
||||
err);
|
||||
return -1;
|
||||
|
|
@ -397,11 +364,11 @@ static int __init ic_setup_if(void)
|
|||
* out, we'll try to muddle along.
|
||||
*/
|
||||
if (ic_dev_mtu != 0) {
|
||||
strcpy(ir.ifr_name, ic_dev->dev->name);
|
||||
ir.ifr_mtu = ic_dev_mtu;
|
||||
if ((err = ic_dev_ioctl(SIOCSIFMTU, &ir)) < 0)
|
||||
rtnl_lock();
|
||||
if ((err = dev_set_mtu(ic_dev->dev, ic_dev_mtu)) < 0)
|
||||
pr_err("IP-Config: Unable to set interface mtu to %d (%d)\n",
|
||||
ic_dev_mtu, err);
|
||||
rtnl_unlock();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -423,7 +390,7 @@ static int __init ic_setup_routes(void)
|
|||
set_sockaddr((struct sockaddr_in *) &rm.rt_genmask, 0, 0);
|
||||
set_sockaddr((struct sockaddr_in *) &rm.rt_gateway, ic_gateway, 0);
|
||||
rm.rt_flags = RTF_UP | RTF_GATEWAY;
|
||||
if ((err = ic_route_ioctl(SIOCADDRT, &rm)) < 0) {
|
||||
if ((err = ip_rt_ioctl(&init_net, SIOCADDRT, &rm)) < 0) {
|
||||
pr_err("IP-Config: Cannot add default route (%d)\n",
|
||||
err);
|
||||
return -1;
|
||||
|
|
|
|||
Loading…
Reference in a new issue