ip_rt_ioctl(): take copyin to caller
authorAl Viro <viro@zeniv.linux.org.uk>
Sat, 1 Jul 2017 12:03:10 +0000 (08:03 -0400)
committerAl Viro <viro@zeniv.linux.org.uk>
Thu, 25 Jan 2018 00:13:45 +0000 (19:13 -0500)
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
include/net/route.h
net/ipv4/af_inet.c
net/ipv4/fib_frontend.c
net/ipv4/ipconfig.c

index d538e6d..1eb9ce4 100644 (file)
@@ -217,7 +217,7 @@ unsigned int inet_addr_type_dev_table(struct net *net,
                                      const struct net_device *dev,
                                      __be32 addr);
 void ip_rt_multicast_event(struct in_device *);
-int ip_rt_ioctl(struct net *, unsigned int cmd, void __user *arg);
+int ip_rt_ioctl(struct net *, unsigned int cmd, struct rtentry *rt);
 void ip_rt_get_source(u8 *src, struct sk_buff *skb, struct rtable *rt);
 struct rtable *rt_dst_alloc(struct net_device *dev,
                             unsigned int flags, u16 type,
index 1c2bfee..c24008d 100644 (file)
@@ -874,6 +874,7 @@ int inet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
        struct net *net = sock_net(sk);
        void __user *p = (void __user *)arg;
        struct ifreq ifr;
+       struct rtentry rt;
 
        switch (cmd) {
        case SIOCGSTAMP:
@@ -884,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:
index 08259d0..f05afaf 100644 (file)
@@ -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;
 
index 6895fff..5f396af 100644 (file)
@@ -340,17 +340,6 @@ static int __init ic_dev_ioctl(unsigned int cmd, struct ifreq *arg)
        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.
  */
@@ -412,7 +401,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;