aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2017-07-01 07:53:12 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2018-01-24 19:13:45 -0500
commit03aef17bb79b3dc02b1352ee2f55fca799dbad7f (patch)
tree3055b1bbf427f2ee82da08d3a2a95ccabfc75ebb
parent36fd633ec98acd2028585c22128fcaa3da6d5770 (diff)
devinet_ioctl(): take copyin/copyout to caller
Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r--include/linux/inetdevice.h2
-rw-r--r--net/ipv4/af_inet.c21
-rw-r--r--net/ipv4/devinet.c41
-rw-r--r--net/ipv4/ipconfig.c17
4 files changed, 35 insertions, 46 deletions
diff --git a/include/linux/inetdevice.h b/include/linux/inetdevice.h
index 1ac5bf95bfdd..e16fe7d44a71 100644
--- a/include/linux/inetdevice.h
+++ b/include/linux/inetdevice.h
@@ -173,7 +173,7 @@ static inline struct net_device *ip_dev_find(struct net *net, __be32 addr)
173} 173}
174 174
175int inet_addr_onlink(struct in_device *in_dev, __be32 a, __be32 b); 175int inet_addr_onlink(struct in_device *in_dev, __be32 a, __be32 b);
176int devinet_ioctl(struct net *net, unsigned int cmd, void __user *); 176int devinet_ioctl(struct net *net, unsigned int cmd, struct ifreq *);
177void devinet_init(void); 177void devinet_init(void);
178struct in_device *inetdev_by_index(struct net *, int); 178struct in_device *inetdev_by_index(struct net *, int);
179__be32 inet_select_addr(const struct net_device *dev, __be32 dst, int scope); 179__be32 inet_select_addr(const struct net_device *dev, __be32 dst, int scope);
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index 54cccdd8b1e3..1c2bfee2e249 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -872,6 +872,8 @@ int inet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
872 struct sock *sk = sock->sk; 872 struct sock *sk = sock->sk;
873 int err = 0; 873 int err = 0;
874 struct net *net = sock_net(sk); 874 struct net *net = sock_net(sk);
875 void __user *p = (void __user *)arg;
876 struct ifreq ifr;
875 877
876 switch (cmd) { 878 switch (cmd) {
877 case SIOCGSTAMP: 879 case SIOCGSTAMP:
@@ -891,17 +893,26 @@ int inet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
891 err = arp_ioctl(net, cmd, (void __user *)arg); 893 err = arp_ioctl(net, cmd, (void __user *)arg);
892 break; 894 break;
893 case SIOCGIFADDR: 895 case SIOCGIFADDR:
894 case SIOCSIFADDR:
895 case SIOCGIFBRDADDR: 896 case SIOCGIFBRDADDR:
896 case SIOCSIFBRDADDR:
897 case SIOCGIFNETMASK: 897 case SIOCGIFNETMASK:
898 case SIOCSIFNETMASK:
899 case SIOCGIFDSTADDR: 898 case SIOCGIFDSTADDR:
899 case SIOCGIFPFLAGS:
900 if (copy_from_user(&ifr, p, sizeof(struct ifreq)))
901 return -EFAULT;
902 err = devinet_ioctl(net, cmd, &ifr);
903 if (!err && copy_to_user(p, &ifr, sizeof(struct ifreq)))
904 err = -EFAULT;
905 break;
906
907 case SIOCSIFADDR:
908 case SIOCSIFBRDADDR:
909 case SIOCSIFNETMASK:
900 case SIOCSIFDSTADDR: 910 case SIOCSIFDSTADDR:
901 case SIOCSIFPFLAGS: 911 case SIOCSIFPFLAGS:
902 case SIOCGIFPFLAGS:
903 case SIOCSIFFLAGS: 912 case SIOCSIFFLAGS:
904 err = devinet_ioctl(net, cmd, (void __user *)arg); 913 if (copy_from_user(&ifr, p, sizeof(struct ifreq)))
914 return -EFAULT;
915 err = devinet_ioctl(net, cmd, &ifr);
905 break; 916 break;
906 default: 917 default:
907 if (sk->sk_prot->ioctl) 918 if (sk->sk_prot->ioctl)
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index 1771549d2438..e056c0067f2c 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -946,11 +946,10 @@ static int inet_abc_len(__be32 addr)
946} 946}
947 947
948 948
949int devinet_ioctl(struct net *net, unsigned int cmd, void __user *arg) 949int devinet_ioctl(struct net *net, unsigned int cmd, struct ifreq *ifr)
950{ 950{
951 struct ifreq ifr;
952 struct sockaddr_in sin_orig; 951 struct sockaddr_in sin_orig;
953 struct sockaddr_in *sin = (struct sockaddr_in *)&ifr.ifr_addr; 952 struct sockaddr_in *sin = (struct sockaddr_in *)&ifr->ifr_addr;
954 struct in_device *in_dev; 953 struct in_device *in_dev;
955 struct in_ifaddr **ifap = NULL; 954 struct in_ifaddr **ifap = NULL;
956 struct in_ifaddr *ifa = NULL; 955 struct in_ifaddr *ifa = NULL;
@@ -959,22 +958,16 @@ int devinet_ioctl(struct net *net, unsigned int cmd, void __user *arg)
959 int ret = -EFAULT; 958 int ret = -EFAULT;
960 int tryaddrmatch = 0; 959 int tryaddrmatch = 0;
961 960
962 /* 961 ifr->ifr_name[IFNAMSIZ - 1] = 0;
963 * Fetch the caller's info block into kernel space
964 */
965
966 if (copy_from_user(&ifr, arg, sizeof(struct ifreq)))
967 goto out;
968 ifr.ifr_name[IFNAMSIZ - 1] = 0;
969 962
970 /* save original address for comparison */ 963 /* save original address for comparison */
971 memcpy(&sin_orig, sin, sizeof(*sin)); 964 memcpy(&sin_orig, sin, sizeof(*sin));
972 965
973 colon = strchr(ifr.ifr_name, ':'); 966 colon = strchr(ifr->ifr_name, ':');
974 if (colon) 967 if (colon)
975 *colon = 0; 968 *colon = 0;
976 969
977 dev_load(net, ifr.ifr_name); 970 dev_load(net, ifr->ifr_name);
978 971
979 switch (cmd) { 972 switch (cmd) {
980 case SIOCGIFADDR: /* Get interface address */ 973 case SIOCGIFADDR: /* Get interface address */
@@ -1014,7 +1007,7 @@ int devinet_ioctl(struct net *net, unsigned int cmd, void __user *arg)
1014 rtnl_lock(); 1007 rtnl_lock();
1015 1008
1016 ret = -ENODEV; 1009 ret = -ENODEV;
1017 dev = __dev_get_by_name(net, ifr.ifr_name); 1010 dev = __dev_get_by_name(net, ifr->ifr_name);
1018 if (!dev) 1011 if (!dev)
1019 goto done; 1012 goto done;
1020 1013
@@ -1031,7 +1024,7 @@ int devinet_ioctl(struct net *net, unsigned int cmd, void __user *arg)
1031 This is checked above. */ 1024 This is checked above. */
1032 for (ifap = &in_dev->ifa_list; (ifa = *ifap) != NULL; 1025 for (ifap = &in_dev->ifa_list; (ifa = *ifap) != NULL;
1033 ifap = &ifa->ifa_next) { 1026 ifap = &ifa->ifa_next) {
1034 if (!strcmp(ifr.ifr_name, ifa->ifa_label) && 1027 if (!strcmp(ifr->ifr_name, ifa->ifa_label) &&
1035 sin_orig.sin_addr.s_addr == 1028 sin_orig.sin_addr.s_addr ==
1036 ifa->ifa_local) { 1029 ifa->ifa_local) {
1037 break; /* found */ 1030 break; /* found */
@@ -1044,7 +1037,7 @@ int devinet_ioctl(struct net *net, unsigned int cmd, void __user *arg)
1044 if (!ifa) { 1037 if (!ifa) {
1045 for (ifap = &in_dev->ifa_list; (ifa = *ifap) != NULL; 1038 for (ifap = &in_dev->ifa_list; (ifa = *ifap) != NULL;
1046 ifap = &ifa->ifa_next) 1039 ifap = &ifa->ifa_next)
1047 if (!strcmp(ifr.ifr_name, ifa->ifa_label)) 1040 if (!strcmp(ifr->ifr_name, ifa->ifa_label))
1048 break; 1041 break;
1049 } 1042 }
1050 } 1043 }
@@ -1056,19 +1049,19 @@ int devinet_ioctl(struct net *net, unsigned int cmd, void __user *arg)
1056 switch (cmd) { 1049 switch (cmd) {
1057 case SIOCGIFADDR: /* Get interface address */ 1050 case SIOCGIFADDR: /* Get interface address */
1058 sin->sin_addr.s_addr = ifa->ifa_local; 1051 sin->sin_addr.s_addr = ifa->ifa_local;
1059 goto rarok; 1052 break;
1060 1053
1061 case SIOCGIFBRDADDR: /* Get the broadcast address */ 1054 case SIOCGIFBRDADDR: /* Get the broadcast address */
1062 sin->sin_addr.s_addr = ifa->ifa_broadcast; 1055 sin->sin_addr.s_addr = ifa->ifa_broadcast;
1063 goto rarok; 1056 break;
1064 1057
1065 case SIOCGIFDSTADDR: /* Get the destination address */ 1058 case SIOCGIFDSTADDR: /* Get the destination address */
1066 sin->sin_addr.s_addr = ifa->ifa_address; 1059 sin->sin_addr.s_addr = ifa->ifa_address;
1067 goto rarok; 1060 break;
1068 1061
1069 case SIOCGIFNETMASK: /* Get the netmask for the interface */ 1062 case SIOCGIFNETMASK: /* Get the netmask for the interface */
1070 sin->sin_addr.s_addr = ifa->ifa_mask; 1063 sin->sin_addr.s_addr = ifa->ifa_mask;
1071 goto rarok; 1064 break;
1072 1065
1073 case SIOCSIFFLAGS: 1066 case SIOCSIFFLAGS:
1074 if (colon) { 1067 if (colon) {
@@ -1076,11 +1069,11 @@ int devinet_ioctl(struct net *net, unsigned int cmd, void __user *arg)
1076 if (!ifa) 1069 if (!ifa)
1077 break; 1070 break;
1078 ret = 0; 1071 ret = 0;
1079 if (!(ifr.ifr_flags & IFF_UP)) 1072 if (!(ifr->ifr_flags & IFF_UP))
1080 inet_del_ifa(in_dev, ifap, 1); 1073 inet_del_ifa(in_dev, ifap, 1);
1081 break; 1074 break;
1082 } 1075 }
1083 ret = dev_change_flags(dev, ifr.ifr_flags); 1076 ret = dev_change_flags(dev, ifr->ifr_flags);
1084 break; 1077 break;
1085 1078
1086 case SIOCSIFADDR: /* Set interface address (and family) */ 1079 case SIOCSIFADDR: /* Set interface address (and family) */
@@ -1095,7 +1088,7 @@ int devinet_ioctl(struct net *net, unsigned int cmd, void __user *arg)
1095 break; 1088 break;
1096 INIT_HLIST_NODE(&ifa->hash); 1089 INIT_HLIST_NODE(&ifa->hash);
1097 if (colon) 1090 if (colon)
1098 memcpy(ifa->ifa_label, ifr.ifr_name, IFNAMSIZ); 1091 memcpy(ifa->ifa_label, ifr->ifr_name, IFNAMSIZ);
1099 else 1092 else
1100 memcpy(ifa->ifa_label, dev->name, IFNAMSIZ); 1093 memcpy(ifa->ifa_label, dev->name, IFNAMSIZ);
1101 } else { 1094 } else {
@@ -1182,10 +1175,6 @@ done:
1182 rtnl_unlock(); 1175 rtnl_unlock();
1183out: 1176out:
1184 return ret; 1177 return ret;
1185rarok:
1186 rtnl_unlock();
1187 ret = copy_to_user(arg, &ifr, sizeof(struct ifreq)) ? -EFAULT : 0;
1188 goto out;
1189} 1178}
1190 1179
1191static int inet_gifconf(struct net_device *dev, char __user *buf, int len, int size) 1180static int inet_gifconf(struct net_device *dev, char __user *buf, int len, int size)
diff --git a/net/ipv4/ipconfig.c b/net/ipv4/ipconfig.c
index e9e488e72900..6895fff609b1 100644
--- a/net/ipv4/ipconfig.c
+++ b/net/ipv4/ipconfig.c
@@ -329,17 +329,6 @@ set_sockaddr(struct sockaddr_in *sin, __be32 addr, __be16 port)
329 sin->sin_port = port; 329 sin->sin_port = port;
330} 330}
331 331
332static int __init ic_devinet_ioctl(unsigned int cmd, struct ifreq *arg)
333{
334 int res;
335
336 mm_segment_t oldfs = get_fs();
337 set_fs(get_ds());
338 res = devinet_ioctl(&init_net, cmd, (struct ifreq __user *) arg);
339 set_fs(oldfs);
340 return res;
341}
342
343static int __init ic_dev_ioctl(unsigned int cmd, struct ifreq *arg) 332static int __init ic_dev_ioctl(unsigned int cmd, struct ifreq *arg)
344{ 333{
345 int res; 334 int res;
@@ -375,19 +364,19 @@ static int __init ic_setup_if(void)
375 memset(&ir, 0, sizeof(ir)); 364 memset(&ir, 0, sizeof(ir));
376 strcpy(ir.ifr_ifrn.ifrn_name, ic_dev->dev->name); 365 strcpy(ir.ifr_ifrn.ifrn_name, ic_dev->dev->name);
377 set_sockaddr(sin, ic_myaddr, 0); 366 set_sockaddr(sin, ic_myaddr, 0);
378 if ((err = ic_devinet_ioctl(SIOCSIFADDR, &ir)) < 0) { 367 if ((err = devinet_ioctl(&init_net, SIOCSIFADDR, &ir)) < 0) {
379 pr_err("IP-Config: Unable to set interface address (%d)\n", 368 pr_err("IP-Config: Unable to set interface address (%d)\n",
380 err); 369 err);
381 return -1; 370 return -1;
382 } 371 }
383 set_sockaddr(sin, ic_netmask, 0); 372 set_sockaddr(sin, ic_netmask, 0);
384 if ((err = ic_devinet_ioctl(SIOCSIFNETMASK, &ir)) < 0) { 373 if ((err = devinet_ioctl(&init_net, SIOCSIFNETMASK, &ir)) < 0) {
385 pr_err("IP-Config: Unable to set interface netmask (%d)\n", 374 pr_err("IP-Config: Unable to set interface netmask (%d)\n",
386 err); 375 err);
387 return -1; 376 return -1;
388 } 377 }
389 set_sockaddr(sin, ic_myaddr | ~ic_netmask, 0); 378 set_sockaddr(sin, ic_myaddr | ~ic_netmask, 0);
390 if ((err = ic_devinet_ioctl(SIOCSIFBRDADDR, &ir)) < 0) { 379 if ((err = devinet_ioctl(&init_net, SIOCSIFBRDADDR, &ir)) < 0) {
391 pr_err("IP-Config: Unable to set interface broadcast address (%d)\n", 380 pr_err("IP-Config: Unable to set interface broadcast address (%d)\n",
392 err); 381 err);
393 return -1; 382 return -1;