aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKrister Johansen <kjlx@templeofstupid.com>2017-06-08 16:12:14 -0400
committerDavid S. Miller <davem@davemloft.net>2017-06-09 12:26:07 -0400
commit3ad7d2468f79fc13215eb941f766a692d34b1381 (patch)
tree5a742b551c95c8587e40bb5421c214e76d78c5d8
parent2b3a9afc63ab6af58417b3aaca2746dee2fbdc86 (diff)
Ipvlan should return an error when an address is already in use.
The ipvlan code already knows how to detect when a duplicate address is about to be assigned to an ipvlan device. However, that failure is not propogated outward and leads to a silent failure. Introduce a validation step at ip address creation time and allow device drivers to register to validate the incoming ip addresses. The ipvlan code is the first consumer. If it detects an address in use, we can return an error to the user before beginning to commit the new ifa in the networking code. This can be especially useful if it is necessary to provision many ipvlans in containers. The provisioning software (or operator) can use this to detect situations where an ip address is unexpectedly in use. Signed-off-by: Krister Johansen <kjlx@templeofstupid.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/ipvlan/ipvlan_main.c69
-rw-r--r--include/linux/inetdevice.h7
-rw-r--r--include/net/addrconf.h10
-rw-r--r--net/ipv4/devinet.c33
-rw-r--r--net/ipv6/addrconf.c17
-rw-r--r--net/ipv6/addrconf_core.c19
6 files changed, 153 insertions, 2 deletions
diff --git a/drivers/net/ipvlan/ipvlan_main.c b/drivers/net/ipvlan/ipvlan_main.c
index 618ed88fad0f..e4141d62b5c3 100644
--- a/drivers/net/ipvlan/ipvlan_main.c
+++ b/drivers/net/ipvlan/ipvlan_main.c
@@ -824,6 +824,33 @@ static int ipvlan_addr6_event(struct notifier_block *unused,
824 return NOTIFY_OK; 824 return NOTIFY_OK;
825} 825}
826 826
827static int ipvlan_addr6_validator_event(struct notifier_block *unused,
828 unsigned long event, void *ptr)
829{
830 struct in6_validator_info *i6vi = (struct in6_validator_info *)ptr;
831 struct net_device *dev = (struct net_device *)i6vi->i6vi_dev->dev;
832 struct ipvl_dev *ipvlan = netdev_priv(dev);
833
834 /* FIXME IPv6 autoconf calls us from bh without RTNL */
835 if (in_softirq())
836 return NOTIFY_DONE;
837
838 if (!netif_is_ipvlan(dev))
839 return NOTIFY_DONE;
840
841 if (!ipvlan || !ipvlan->port)
842 return NOTIFY_DONE;
843
844 switch (event) {
845 case NETDEV_UP:
846 if (ipvlan_addr_busy(ipvlan->port, &i6vi->i6vi_addr, true))
847 return notifier_from_errno(-EADDRINUSE);
848 break;
849 }
850
851 return NOTIFY_OK;
852}
853
827static int ipvlan_add_addr4(struct ipvl_dev *ipvlan, struct in_addr *ip4_addr) 854static int ipvlan_add_addr4(struct ipvl_dev *ipvlan, struct in_addr *ip4_addr)
828{ 855{
829 if (ipvlan_addr_busy(ipvlan->port, ip4_addr, false)) { 856 if (ipvlan_addr_busy(ipvlan->port, ip4_addr, false)) {
@@ -871,10 +898,37 @@ static int ipvlan_addr4_event(struct notifier_block *unused,
871 return NOTIFY_OK; 898 return NOTIFY_OK;
872} 899}
873 900
901static int ipvlan_addr4_validator_event(struct notifier_block *unused,
902 unsigned long event, void *ptr)
903{
904 struct in_validator_info *ivi = (struct in_validator_info *)ptr;
905 struct net_device *dev = (struct net_device *)ivi->ivi_dev->dev;
906 struct ipvl_dev *ipvlan = netdev_priv(dev);
907
908 if (!netif_is_ipvlan(dev))
909 return NOTIFY_DONE;
910
911 if (!ipvlan || !ipvlan->port)
912 return NOTIFY_DONE;
913
914 switch (event) {
915 case NETDEV_UP:
916 if (ipvlan_addr_busy(ipvlan->port, &ivi->ivi_addr, false))
917 return notifier_from_errno(-EADDRINUSE);
918 break;
919 }
920
921 return NOTIFY_OK;
922}
923
874static struct notifier_block ipvlan_addr4_notifier_block __read_mostly = { 924static struct notifier_block ipvlan_addr4_notifier_block __read_mostly = {
875 .notifier_call = ipvlan_addr4_event, 925 .notifier_call = ipvlan_addr4_event,
876}; 926};
877 927
928static struct notifier_block ipvlan_addr4_vtor_notifier_block __read_mostly = {
929 .notifier_call = ipvlan_addr4_validator_event,
930};
931
878static struct notifier_block ipvlan_notifier_block __read_mostly = { 932static struct notifier_block ipvlan_notifier_block __read_mostly = {
879 .notifier_call = ipvlan_device_event, 933 .notifier_call = ipvlan_device_event,
880}; 934};
@@ -883,6 +937,10 @@ static struct notifier_block ipvlan_addr6_notifier_block __read_mostly = {
883 .notifier_call = ipvlan_addr6_event, 937 .notifier_call = ipvlan_addr6_event,
884}; 938};
885 939
940static struct notifier_block ipvlan_addr6_vtor_notifier_block __read_mostly = {
941 .notifier_call = ipvlan_addr6_validator_event,
942};
943
886static void ipvlan_ns_exit(struct net *net) 944static void ipvlan_ns_exit(struct net *net)
887{ 945{
888 struct ipvlan_netns *vnet = net_generic(net, ipvlan_netid); 946 struct ipvlan_netns *vnet = net_generic(net, ipvlan_netid);
@@ -907,7 +965,10 @@ static int __init ipvlan_init_module(void)
907 ipvlan_init_secret(); 965 ipvlan_init_secret();
908 register_netdevice_notifier(&ipvlan_notifier_block); 966 register_netdevice_notifier(&ipvlan_notifier_block);
909 register_inet6addr_notifier(&ipvlan_addr6_notifier_block); 967 register_inet6addr_notifier(&ipvlan_addr6_notifier_block);
968 register_inet6addr_validator_notifier(
969 &ipvlan_addr6_vtor_notifier_block);
910 register_inetaddr_notifier(&ipvlan_addr4_notifier_block); 970 register_inetaddr_notifier(&ipvlan_addr4_notifier_block);
971 register_inetaddr_validator_notifier(&ipvlan_addr4_vtor_notifier_block);
911 972
912 err = register_pernet_subsys(&ipvlan_net_ops); 973 err = register_pernet_subsys(&ipvlan_net_ops);
913 if (err < 0) 974 if (err < 0)
@@ -922,7 +983,11 @@ static int __init ipvlan_init_module(void)
922 return 0; 983 return 0;
923error: 984error:
924 unregister_inetaddr_notifier(&ipvlan_addr4_notifier_block); 985 unregister_inetaddr_notifier(&ipvlan_addr4_notifier_block);
986 unregister_inetaddr_validator_notifier(
987 &ipvlan_addr4_vtor_notifier_block);
925 unregister_inet6addr_notifier(&ipvlan_addr6_notifier_block); 988 unregister_inet6addr_notifier(&ipvlan_addr6_notifier_block);
989 unregister_inet6addr_validator_notifier(
990 &ipvlan_addr6_vtor_notifier_block);
926 unregister_netdevice_notifier(&ipvlan_notifier_block); 991 unregister_netdevice_notifier(&ipvlan_notifier_block);
927 return err; 992 return err;
928} 993}
@@ -933,7 +998,11 @@ static void __exit ipvlan_cleanup_module(void)
933 unregister_pernet_subsys(&ipvlan_net_ops); 998 unregister_pernet_subsys(&ipvlan_net_ops);
934 unregister_netdevice_notifier(&ipvlan_notifier_block); 999 unregister_netdevice_notifier(&ipvlan_notifier_block);
935 unregister_inetaddr_notifier(&ipvlan_addr4_notifier_block); 1000 unregister_inetaddr_notifier(&ipvlan_addr4_notifier_block);
1001 unregister_inetaddr_validator_notifier(
1002 &ipvlan_addr4_vtor_notifier_block);
936 unregister_inet6addr_notifier(&ipvlan_addr6_notifier_block); 1003 unregister_inet6addr_notifier(&ipvlan_addr6_notifier_block);
1004 unregister_inet6addr_validator_notifier(
1005 &ipvlan_addr6_vtor_notifier_block);
937} 1006}
938 1007
939module_init(ipvlan_init_module); 1008module_init(ipvlan_init_module);
diff --git a/include/linux/inetdevice.h b/include/linux/inetdevice.h
index a2e9d6ea1349..e7c04c4e4bcd 100644
--- a/include/linux/inetdevice.h
+++ b/include/linux/inetdevice.h
@@ -150,8 +150,15 @@ struct in_ifaddr {
150 unsigned long ifa_tstamp; /* updated timestamp */ 150 unsigned long ifa_tstamp; /* updated timestamp */
151}; 151};
152 152
153struct in_validator_info {
154 __be32 ivi_addr;
155 struct in_device *ivi_dev;
156};
157
153int register_inetaddr_notifier(struct notifier_block *nb); 158int register_inetaddr_notifier(struct notifier_block *nb);
154int unregister_inetaddr_notifier(struct notifier_block *nb); 159int unregister_inetaddr_notifier(struct notifier_block *nb);
160int register_inetaddr_validator_notifier(struct notifier_block *nb);
161int unregister_inetaddr_validator_notifier(struct notifier_block *nb);
155 162
156void inet_netconf_notify_devconf(struct net *net, int event, int type, 163void inet_netconf_notify_devconf(struct net *net, int event, int type,
157 int ifindex, struct ipv4_devconf *devconf); 164 int ifindex, struct ipv4_devconf *devconf);
diff --git a/include/net/addrconf.h b/include/net/addrconf.h
index b43a4eec3cec..d0889cb50172 100644
--- a/include/net/addrconf.h
+++ b/include/net/addrconf.h
@@ -48,11 +48,15 @@ struct prefix_info {
48 struct in6_addr prefix; 48 struct in6_addr prefix;
49}; 49};
50 50
51
52#include <linux/netdevice.h> 51#include <linux/netdevice.h>
53#include <net/if_inet6.h> 52#include <net/if_inet6.h>
54#include <net/ipv6.h> 53#include <net/ipv6.h>
55 54
55struct in6_validator_info {
56 struct in6_addr i6vi_addr;
57 struct inet6_dev *i6vi_dev;
58};
59
56#define IN6_ADDR_HSIZE_SHIFT 4 60#define IN6_ADDR_HSIZE_SHIFT 4
57#define IN6_ADDR_HSIZE (1 << IN6_ADDR_HSIZE_SHIFT) 61#define IN6_ADDR_HSIZE (1 << IN6_ADDR_HSIZE_SHIFT)
58 62
@@ -278,6 +282,10 @@ int register_inet6addr_notifier(struct notifier_block *nb);
278int unregister_inet6addr_notifier(struct notifier_block *nb); 282int unregister_inet6addr_notifier(struct notifier_block *nb);
279int inet6addr_notifier_call_chain(unsigned long val, void *v); 283int inet6addr_notifier_call_chain(unsigned long val, void *v);
280 284
285int register_inet6addr_validator_notifier(struct notifier_block *nb);
286int unregister_inet6addr_validator_notifier(struct notifier_block *nb);
287int inet6addr_validator_notifier_call_chain(unsigned long val, void *v);
288
281void inet6_netconf_notify_devconf(struct net *net, int event, int type, 289void inet6_netconf_notify_devconf(struct net *net, int event, int type,
282 int ifindex, struct ipv6_devconf *devconf); 290 int ifindex, struct ipv6_devconf *devconf);
283 291
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index df14815a3b8c..a7dd088d5fc9 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -176,6 +176,7 @@ EXPORT_SYMBOL(__ip_dev_find);
176static void rtmsg_ifa(int event, struct in_ifaddr *, struct nlmsghdr *, u32); 176static void rtmsg_ifa(int event, struct in_ifaddr *, struct nlmsghdr *, u32);
177 177
178static BLOCKING_NOTIFIER_HEAD(inetaddr_chain); 178static BLOCKING_NOTIFIER_HEAD(inetaddr_chain);
179static BLOCKING_NOTIFIER_HEAD(inetaddr_validator_chain);
179static void inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap, 180static void inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap,
180 int destroy); 181 int destroy);
181#ifdef CONFIG_SYSCTL 182#ifdef CONFIG_SYSCTL
@@ -441,6 +442,8 @@ static int __inet_insert_ifa(struct in_ifaddr *ifa, struct nlmsghdr *nlh,
441{ 442{
442 struct in_device *in_dev = ifa->ifa_dev; 443 struct in_device *in_dev = ifa->ifa_dev;
443 struct in_ifaddr *ifa1, **ifap, **last_primary; 444 struct in_ifaddr *ifa1, **ifap, **last_primary;
445 struct in_validator_info ivi;
446 int ret;
444 447
445 ASSERT_RTNL(); 448 ASSERT_RTNL();
446 449
@@ -471,6 +474,23 @@ static int __inet_insert_ifa(struct in_ifaddr *ifa, struct nlmsghdr *nlh,
471 } 474 }
472 } 475 }
473 476
477 /* Allow any devices that wish to register ifaddr validtors to weigh
478 * in now, before changes are committed. The rntl lock is serializing
479 * access here, so the state should not change between a validator call
480 * and a final notify on commit. This isn't invoked on promotion under
481 * the assumption that validators are checking the address itself, and
482 * not the flags.
483 */
484 ivi.ivi_addr = ifa->ifa_address;
485 ivi.ivi_dev = ifa->ifa_dev;
486 ret = blocking_notifier_call_chain(&inetaddr_validator_chain,
487 NETDEV_UP, &ivi);
488 ret = notifier_to_errno(ret);
489 if (ret) {
490 inet_free_ifa(ifa);
491 return ret;
492 }
493
474 if (!(ifa->ifa_flags & IFA_F_SECONDARY)) { 494 if (!(ifa->ifa_flags & IFA_F_SECONDARY)) {
475 prandom_seed((__force u32) ifa->ifa_local); 495 prandom_seed((__force u32) ifa->ifa_local);
476 ifap = last_primary; 496 ifap = last_primary;
@@ -1356,6 +1376,19 @@ int unregister_inetaddr_notifier(struct notifier_block *nb)
1356} 1376}
1357EXPORT_SYMBOL(unregister_inetaddr_notifier); 1377EXPORT_SYMBOL(unregister_inetaddr_notifier);
1358 1378
1379int register_inetaddr_validator_notifier(struct notifier_block *nb)
1380{
1381 return blocking_notifier_chain_register(&inetaddr_validator_chain, nb);
1382}
1383EXPORT_SYMBOL(register_inetaddr_validator_notifier);
1384
1385int unregister_inetaddr_validator_notifier(struct notifier_block *nb)
1386{
1387 return blocking_notifier_chain_unregister(&inetaddr_validator_chain,
1388 nb);
1389}
1390EXPORT_SYMBOL(unregister_inetaddr_validator_notifier);
1391
1359/* Rename ifa_labels for a device name change. Make some effort to preserve 1392/* Rename ifa_labels for a device name change. Make some effort to preserve
1360 * existing alias numbering and to create unique labels if possible. 1393 * existing alias numbering and to create unique labels if possible.
1361*/ 1394*/
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 25443fd946a8..0aa36b093013 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -963,6 +963,7 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr,
963 struct net *net = dev_net(idev->dev); 963 struct net *net = dev_net(idev->dev);
964 struct inet6_ifaddr *ifa = NULL; 964 struct inet6_ifaddr *ifa = NULL;
965 struct rt6_info *rt; 965 struct rt6_info *rt;
966 struct in6_validator_info i6vi;
966 unsigned int hash; 967 unsigned int hash;
967 int err = 0; 968 int err = 0;
968 int addr_type = ipv6_addr_type(addr); 969 int addr_type = ipv6_addr_type(addr);
@@ -974,6 +975,9 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr,
974 return ERR_PTR(-EADDRNOTAVAIL); 975 return ERR_PTR(-EADDRNOTAVAIL);
975 976
976 rcu_read_lock_bh(); 977 rcu_read_lock_bh();
978
979 in6_dev_hold(idev);
980
977 if (idev->dead) { 981 if (idev->dead) {
978 err = -ENODEV; /*XXX*/ 982 err = -ENODEV; /*XXX*/
979 goto out2; 983 goto out2;
@@ -984,6 +988,17 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr,
984 goto out2; 988 goto out2;
985 } 989 }
986 990
991 i6vi.i6vi_addr = *addr;
992 i6vi.i6vi_dev = idev;
993 rcu_read_unlock_bh();
994
995 err = inet6addr_validator_notifier_call_chain(NETDEV_UP, &i6vi);
996
997 rcu_read_lock_bh();
998 err = notifier_to_errno(err);
999 if (err)
1000 goto out2;
1001
987 spin_lock(&addrconf_hash_lock); 1002 spin_lock(&addrconf_hash_lock);
988 1003
989 /* Ignore adding duplicate addresses on an interface */ 1004 /* Ignore adding duplicate addresses on an interface */
@@ -1034,7 +1049,6 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr,
1034 ifa->rt = rt; 1049 ifa->rt = rt;
1035 1050
1036 ifa->idev = idev; 1051 ifa->idev = idev;
1037 in6_dev_hold(idev);
1038 /* For caller */ 1052 /* For caller */
1039 in6_ifa_hold(ifa); 1053 in6_ifa_hold(ifa);
1040 1054
@@ -1062,6 +1076,7 @@ out2:
1062 inet6addr_notifier_call_chain(NETDEV_UP, ifa); 1076 inet6addr_notifier_call_chain(NETDEV_UP, ifa);
1063 else { 1077 else {
1064 kfree(ifa); 1078 kfree(ifa);
1079 in6_dev_put(idev);
1065 ifa = ERR_PTR(err); 1080 ifa = ERR_PTR(err);
1066 } 1081 }
1067 1082
diff --git a/net/ipv6/addrconf_core.c b/net/ipv6/addrconf_core.c
index bfa941fc1165..9e3488d50b15 100644
--- a/net/ipv6/addrconf_core.c
+++ b/net/ipv6/addrconf_core.c
@@ -88,6 +88,7 @@ int __ipv6_addr_type(const struct in6_addr *addr)
88EXPORT_SYMBOL(__ipv6_addr_type); 88EXPORT_SYMBOL(__ipv6_addr_type);
89 89
90static ATOMIC_NOTIFIER_HEAD(inet6addr_chain); 90static ATOMIC_NOTIFIER_HEAD(inet6addr_chain);
91static ATOMIC_NOTIFIER_HEAD(inet6addr_validator_chain);
91 92
92int register_inet6addr_notifier(struct notifier_block *nb) 93int register_inet6addr_notifier(struct notifier_block *nb)
93{ 94{
@@ -107,6 +108,24 @@ int inet6addr_notifier_call_chain(unsigned long val, void *v)
107} 108}
108EXPORT_SYMBOL(inet6addr_notifier_call_chain); 109EXPORT_SYMBOL(inet6addr_notifier_call_chain);
109 110
111int register_inet6addr_validator_notifier(struct notifier_block *nb)
112{
113 return atomic_notifier_chain_register(&inet6addr_validator_chain, nb);
114}
115EXPORT_SYMBOL(register_inet6addr_validator_notifier);
116
117int unregister_inet6addr_validator_notifier(struct notifier_block *nb)
118{
119 return atomic_notifier_chain_unregister(&inet6addr_validator_chain, nb);
120}
121EXPORT_SYMBOL(unregister_inet6addr_validator_notifier);
122
123int inet6addr_validator_notifier_call_chain(unsigned long val, void *v)
124{
125 return atomic_notifier_call_chain(&inet6addr_validator_chain, val, v);
126}
127EXPORT_SYMBOL(inet6addr_validator_notifier_call_chain);
128
110static int eafnosupport_ipv6_dst_lookup(struct net *net, struct sock *u1, 129static int eafnosupport_ipv6_dst_lookup(struct net *net, struct sock *u1,
111 struct dst_entry **u2, 130 struct dst_entry **u2,
112 struct flowi6 *u3) 131 struct flowi6 *u3)