diff options
Diffstat (limited to 'net/ipv4/arp.c')
-rw-r--r-- | net/ipv4/arp.c | 17 |
1 files changed, 9 insertions, 8 deletions
diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c index 10af759f2630..a2fc7b961dbc 100644 --- a/net/ipv4/arp.c +++ b/net/ipv4/arp.c | |||
@@ -1017,13 +1017,14 @@ static int arp_req_set_proxy(struct net *net, struct net_device *dev, int on) | |||
1017 | IPV4_DEVCONF_ALL(net, PROXY_ARP) = on; | 1017 | IPV4_DEVCONF_ALL(net, PROXY_ARP) = on; |
1018 | return 0; | 1018 | return 0; |
1019 | } | 1019 | } |
1020 | if (__in_dev_get_rtnl(dev)) { | 1020 | if (__in_dev_get_rcu(dev)) { |
1021 | IN_DEV_CONF_SET(__in_dev_get_rtnl(dev), PROXY_ARP, on); | 1021 | IN_DEV_CONF_SET(__in_dev_get_rcu(dev), PROXY_ARP, on); |
1022 | return 0; | 1022 | return 0; |
1023 | } | 1023 | } |
1024 | return -ENXIO; | 1024 | return -ENXIO; |
1025 | } | 1025 | } |
1026 | 1026 | ||
1027 | /* must be called with rcu_read_lock() */ | ||
1027 | static int arp_req_set_public(struct net *net, struct arpreq *r, | 1028 | static int arp_req_set_public(struct net *net, struct arpreq *r, |
1028 | struct net_device *dev) | 1029 | struct net_device *dev) |
1029 | { | 1030 | { |
@@ -1033,7 +1034,7 @@ static int arp_req_set_public(struct net *net, struct arpreq *r, | |||
1033 | if (mask && mask != htonl(0xFFFFFFFF)) | 1034 | if (mask && mask != htonl(0xFFFFFFFF)) |
1034 | return -EINVAL; | 1035 | return -EINVAL; |
1035 | if (!dev && (r->arp_flags & ATF_COM)) { | 1036 | if (!dev && (r->arp_flags & ATF_COM)) { |
1036 | dev = dev_getbyhwaddr(net, r->arp_ha.sa_family, | 1037 | dev = dev_getbyhwaddr_rcu(net, r->arp_ha.sa_family, |
1037 | r->arp_ha.sa_data); | 1038 | r->arp_ha.sa_data); |
1038 | if (!dev) | 1039 | if (!dev) |
1039 | return -ENODEV; | 1040 | return -ENODEV; |
@@ -1225,10 +1226,10 @@ int arp_ioctl(struct net *net, unsigned int cmd, void __user *arg) | |||
1225 | if (!(r.arp_flags & ATF_NETMASK)) | 1226 | if (!(r.arp_flags & ATF_NETMASK)) |
1226 | ((struct sockaddr_in *)&r.arp_netmask)->sin_addr.s_addr = | 1227 | ((struct sockaddr_in *)&r.arp_netmask)->sin_addr.s_addr = |
1227 | htonl(0xFFFFFFFFUL); | 1228 | htonl(0xFFFFFFFFUL); |
1228 | rtnl_lock(); | 1229 | rcu_read_lock(); |
1229 | if (r.arp_dev[0]) { | 1230 | if (r.arp_dev[0]) { |
1230 | err = -ENODEV; | 1231 | err = -ENODEV; |
1231 | dev = __dev_get_by_name(net, r.arp_dev); | 1232 | dev = dev_get_by_name_rcu(net, r.arp_dev); |
1232 | if (dev == NULL) | 1233 | if (dev == NULL) |
1233 | goto out; | 1234 | goto out; |
1234 | 1235 | ||
@@ -1252,12 +1253,12 @@ int arp_ioctl(struct net *net, unsigned int cmd, void __user *arg) | |||
1252 | break; | 1253 | break; |
1253 | case SIOCGARP: | 1254 | case SIOCGARP: |
1254 | err = arp_req_get(&r, dev); | 1255 | err = arp_req_get(&r, dev); |
1255 | if (!err && copy_to_user(arg, &r, sizeof(r))) | ||
1256 | err = -EFAULT; | ||
1257 | break; | 1256 | break; |
1258 | } | 1257 | } |
1259 | out: | 1258 | out: |
1260 | rtnl_unlock(); | 1259 | rcu_read_unlock(); |
1260 | if (cmd == SIOCGARP && !err && copy_to_user(arg, &r, sizeof(r))) | ||
1261 | err = -EFAULT; | ||
1261 | return err; | 1262 | return err; |
1262 | } | 1263 | } |
1263 | 1264 | ||