Commit 7c1552da authored by Christoph Hellwig's avatar Christoph Hellwig Committed by David S. Miller

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: default avatarChristoph Hellwig <hch@lst.de>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent a307593a
...@@ -118,7 +118,8 @@ void ip6_route_init_special_entries(void); ...@@ -118,7 +118,8 @@ void ip6_route_init_special_entries(void);
int ip6_route_init(void); int ip6_route_init(void);
void ip6_route_cleanup(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, int ip6_route_add(struct fib6_config *cfg, gfp_t gfp_flags,
struct netlink_ext_ack *extack); struct netlink_ext_ack *extack);
......
...@@ -542,21 +542,25 @@ EXPORT_SYMBOL(inet6_getname); ...@@ -542,21 +542,25 @@ EXPORT_SYMBOL(inet6_getname);
int inet6_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) int inet6_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
{ {
void __user *argp = (void __user *)arg;
struct sock *sk = sock->sk; struct sock *sk = sock->sk;
struct net *net = sock_net(sk); struct net *net = sock_net(sk);
switch (cmd) { switch (cmd) {
case SIOCADDRT: case SIOCADDRT:
case SIOCDELRT: case SIOCDELRT: {
struct in6_rtmsg rtmsg;
return ipv6_route_ioctl(net, cmd, (void __user *)arg);
if (copy_from_user(&rtmsg, argp, sizeof(rtmsg)))
return -EFAULT;
return ipv6_route_ioctl(net, cmd, &rtmsg);
}
case SIOCSIFADDR: case SIOCSIFADDR:
return addrconf_add_ifaddr(net, (void __user *) arg); return addrconf_add_ifaddr(net, argp);
case SIOCDIFADDR: case SIOCDIFADDR:
return addrconf_del_ifaddr(net, (void __user *) arg); return addrconf_del_ifaddr(net, argp);
case SIOCSIFDSTADDR: case SIOCSIFDSTADDR:
return addrconf_set_dstaddr(net, (void __user *) arg); return addrconf_set_dstaddr(net, argp);
default: default:
if (!sk->sk_prot->ioctl) if (!sk->sk_prot->ioctl)
return -ENOIOCTLCMD; return -ENOIOCTLCMD;
......
...@@ -4336,41 +4336,29 @@ static void rtmsg_to_fib6_config(struct net *net, ...@@ -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 fib6_config cfg;
struct in6_rtmsg rtmsg;
int err; int err;
switch (cmd) { if (cmd != SIOCADDRT && cmd != SIOCDELRT)
case SIOCADDRT: /* Add a route */ return -EINVAL;
case SIOCDELRT: /* Delete a route */ if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
if (!ns_capable(net->user_ns, CAP_NET_ADMIN)) return -EPERM;
return -EPERM;
err = copy_from_user(&rtmsg, arg,
sizeof(struct in6_rtmsg));
if (err)
return -EFAULT;
rtmsg_to_fib6_config(net, &rtmsg, &cfg); rtmsg_to_fib6_config(net, rtmsg, &cfg);
rtnl_lock(); rtnl_lock();
switch (cmd) { switch (cmd) {
case SIOCADDRT: case SIOCADDRT:
err = ip6_route_add(&cfg, GFP_KERNEL, NULL); err = ip6_route_add(&cfg, GFP_KERNEL, NULL);
break; break;
case SIOCDELRT: case SIOCDELRT:
err = ip6_route_del(&cfg, NULL); err = ip6_route_del(&cfg, NULL);
break; break;
default:
err = -EINVAL;
}
rtnl_unlock();
return err;
} }
rtnl_unlock();
return -EINVAL; return err;
} }
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment