diff options
author | Christoph Hellwig <hch@lst.de> | 2020-05-18 08:28:05 +0200 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2020-05-18 17:35:02 -0700 |
commit | 7c1552da900c159a13473a2106c7547746ebe4a1 (patch) | |
tree | 07c7793ab12204af32811dac6f080b8ed12e22ff | |
parent | a307593a644443db12888f45eed0dafb5869e2cc (diff) | |
download | linux-stable-7c1552da900c159a13473a2106c7547746ebe4a1.tar.gz linux-stable-7c1552da900c159a13473a2106c7547746ebe4a1.tar.bz2 linux-stable-7c1552da900c159a13473a2106c7547746ebe4a1.zip |
ipv6: lift copy_from_user out of ipv6_route_ioctl
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>
-rw-r--r-- | include/net/ip6_route.h | 3 | ||||
-rw-r--r-- | net/ipv6/af_inet6.c | 16 | ||||
-rw-r--r-- | net/ipv6/route.c | 44 |
3 files changed, 28 insertions, 35 deletions
diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h index e525f003e619..2a5277758379 100644 --- a/include/net/ip6_route.h +++ b/include/net/ip6_route.h @@ -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); diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index 771a462a8322..a618beb9b6d5 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c @@ -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; diff --git a/net/ipv6/route.c b/net/ipv6/route.c index a8b4add0b545..a52ec1b86432 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -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; } /* |