Skip to content

Commit

Permalink
ipv6: lift copy_from_user out of ipv6_route_ioctl
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Christoph Hellwig authored and David S. Miller committed May 19, 2020
1 parent a307593 commit 7c1552d
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 35 deletions.
3 changes: 2 additions & 1 deletion include/net/ip6_route.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
16 changes: 10 additions & 6 deletions net/ipv6/af_inet6.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
44 changes: 16 additions & 28 deletions net/ipv6/route.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

/*
Expand Down

0 comments on commit 7c1552d

Please sign in to comment.