OSDN Git Service

ipv6: lift copy_from_user out of ipv6_route_ioctl
authorChristoph Hellwig <hch@lst.de>
Mon, 18 May 2020 06:28:05 +0000 (08:28 +0200)
committerDavid S. Miller <davem@davemloft.net>
Tue, 19 May 2020 00:35:02 +0000 (17:35 -0700)
Prepare for better compat ioctl handling by moving the user copy out
of ipv6_route_ioctl.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/net/ip6_route.h
net/ipv6/af_inet6.c
net/ipv6/route.c

index e525f00..2a52777 100644 (file)
@@ -118,7 +118,8 @@ void ip6_route_init_special_entries(void);
 int ip6_route_init(void);
 void ip6_route_cleanup(void);
 
-int ipv6_route_ioctl(struct net *net, unsigned int cmd, void __user *arg);
+int ipv6_route_ioctl(struct net *net, unsigned int cmd,
+               struct in6_rtmsg *rtmsg);
 
 int ip6_route_add(struct fib6_config *cfg, gfp_t gfp_flags,
                  struct netlink_ext_ack *extack);
index 771a462..a618beb 100644 (file)
@@ -542,21 +542,25 @@ EXPORT_SYMBOL(inet6_getname);
 
 int inet6_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
 {
+       void __user *argp = (void __user *)arg;
        struct sock *sk = sock->sk;
        struct net *net = sock_net(sk);
 
        switch (cmd) {
        case SIOCADDRT:
-       case SIOCDELRT:
-
-               return ipv6_route_ioctl(net, cmd, (void __user *)arg);
+       case SIOCDELRT: {
+               struct in6_rtmsg rtmsg;
 
+               if (copy_from_user(&rtmsg, argp, sizeof(rtmsg)))
+                       return -EFAULT;
+               return ipv6_route_ioctl(net, cmd, &rtmsg);
+       }
        case SIOCSIFADDR:
-               return addrconf_add_ifaddr(net, (void __user *) arg);
+               return addrconf_add_ifaddr(net, argp);
        case SIOCDIFADDR:
-               return addrconf_del_ifaddr(net, (void __user *) arg);
+               return addrconf_del_ifaddr(net, argp);
        case SIOCSIFDSTADDR:
-               return addrconf_set_dstaddr(net, (void __user *) arg);
+               return addrconf_set_dstaddr(net, argp);
        default:
                if (!sk->sk_prot->ioctl)
                        return -ENOIOCTLCMD;
index a8b4add..a52ec1b 100644 (file)
@@ -4336,41 +4336,29 @@ static void rtmsg_to_fib6_config(struct net *net,
        };
 }
 
-int ipv6_route_ioctl(struct net *net, unsigned int cmd, void __user *arg)
+int ipv6_route_ioctl(struct net *net, unsigned int cmd, struct in6_rtmsg *rtmsg)
 {
        struct fib6_config cfg;
-       struct in6_rtmsg rtmsg;
        int err;
 
-       switch (cmd) {
-       case SIOCADDRT:         /* Add a route */
-       case SIOCDELRT:         /* Delete a route */
-               if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
-                       return -EPERM;
-               err = copy_from_user(&rtmsg, arg,
-                                    sizeof(struct in6_rtmsg));
-               if (err)
-                       return -EFAULT;
+       if (cmd != SIOCADDRT && cmd != SIOCDELRT)
+               return -EINVAL;
+       if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
+               return -EPERM;
 
-               rtmsg_to_fib6_config(net, &rtmsg, &cfg);
+       rtmsg_to_fib6_config(net, rtmsg, &cfg);
 
-               rtnl_lock();
-               switch (cmd) {
-               case SIOCADDRT:
-                       err = ip6_route_add(&cfg, GFP_KERNEL, NULL);
-                       break;
-               case SIOCDELRT:
-                       err = ip6_route_del(&cfg, NULL);
-                       break;
-               default:
-                       err = -EINVAL;
-               }
-               rtnl_unlock();
-
-               return err;
+       rtnl_lock();
+       switch (cmd) {
+       case SIOCADDRT:
+               err = ip6_route_add(&cfg, GFP_KERNEL, NULL);
+               break;
+       case SIOCDELRT:
+               err = ip6_route_del(&cfg, NULL);
+               break;
        }
-
-       return -EINVAL;
+       rtnl_unlock();
+       return err;
 }
 
 /*