]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blame - releases/4.9.28/ipv6-reorder-ip6_route_dev_notifier-after-ipv6_dev_notf.patch
5.1-stable patches
[thirdparty/kernel/stable-queue.git] / releases / 4.9.28 / ipv6-reorder-ip6_route_dev_notifier-after-ipv6_dev_notf.patch
CommitLineData
8dced6ec
GKH
1From foo@baz Thu May 11 11:08:24 CEST 2017
2From: WANG Cong <xiyou.wangcong@gmail.com>
3Date: Mon, 8 May 2017 10:12:13 -0700
4Subject: ipv6: reorder ip6_route_dev_notifier after ipv6_dev_notf
5
6From: WANG Cong <xiyou.wangcong@gmail.com>
7
8
9[ Upstream commit 242d3a49a2a1a71d8eb9f953db1bcaa9d698ce00 ]
10
11For each netns (except init_net), we initialize its null entry
12in 3 places:
13
141) The template itself, as we use kmemdup()
152) Code around dst_init_metrics() in ip6_route_net_init()
163) ip6_route_dev_notify(), which is supposed to initialize it after
17 loopback registers
18
19Unfortunately the last one still happens in a wrong order because
20we expect to initialize net->ipv6.ip6_null_entry->rt6i_idev to
21net->loopback_dev's idev, thus we have to do that after we add
22idev to loopback. However, this notifier has priority == 0 same as
23ipv6_dev_notf, and ipv6_dev_notf is registered after
24ip6_route_dev_notifier so it is called actually after
25ip6_route_dev_notifier. This is similar to commit 2f460933f58e
26("ipv6: initialize route null entry in addrconf_init()") which
27fixes init_net.
28
29Fix it by picking a smaller priority for ip6_route_dev_notifier.
30Also, we have to release the refcnt accordingly when unregistering
31loopback_dev because device exit functions are called before subsys
32exit functions.
33
34Acked-by: David Ahern <dsahern@gmail.com>
35Tested-by: David Ahern <dsahern@gmail.com>
36Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>
37Signed-off-by: David S. Miller <davem@davemloft.net>
38Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
39---
40 include/net/addrconf.h | 2 ++
41 net/ipv6/addrconf.c | 1 +
42 net/ipv6/route.c | 13 +++++++++++--
43 3 files changed, 14 insertions(+), 2 deletions(-)
44
45--- a/include/net/addrconf.h
46+++ b/include/net/addrconf.h
47@@ -20,6 +20,8 @@
48 #define ADDRCONF_TIMER_FUZZ (HZ / 4)
49 #define ADDRCONF_TIMER_FUZZ_MAX (HZ)
50
51+#define ADDRCONF_NOTIFY_PRIORITY 0
52+
53 #include <linux/in.h>
54 #include <linux/in6.h>
55
56--- a/net/ipv6/addrconf.c
57+++ b/net/ipv6/addrconf.c
58@@ -3492,6 +3492,7 @@ static int addrconf_notify(struct notifi
59 */
60 static struct notifier_block ipv6_dev_notf = {
61 .notifier_call = addrconf_notify,
62+ .priority = ADDRCONF_NOTIFY_PRIORITY,
63 };
64
65 static void addrconf_type_change(struct net_device *dev, unsigned long event)
66--- a/net/ipv6/route.c
67+++ b/net/ipv6/route.c
68@@ -3480,7 +3480,10 @@ static int ip6_route_dev_notify(struct n
69 struct net_device *dev = netdev_notifier_info_to_dev(ptr);
70 struct net *net = dev_net(dev);
71
72- if (event == NETDEV_REGISTER && (dev->flags & IFF_LOOPBACK)) {
73+ if (!(dev->flags & IFF_LOOPBACK))
74+ return NOTIFY_OK;
75+
76+ if (event == NETDEV_REGISTER) {
77 net->ipv6.ip6_null_entry->dst.dev = dev;
78 net->ipv6.ip6_null_entry->rt6i_idev = in6_dev_get(dev);
79 #ifdef CONFIG_IPV6_MULTIPLE_TABLES
80@@ -3489,6 +3492,12 @@ static int ip6_route_dev_notify(struct n
81 net->ipv6.ip6_blk_hole_entry->dst.dev = dev;
82 net->ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(dev);
83 #endif
84+ } else if (event == NETDEV_UNREGISTER) {
85+ in6_dev_put(net->ipv6.ip6_null_entry->rt6i_idev);
86+#ifdef CONFIG_IPV6_MULTIPLE_TABLES
87+ in6_dev_put(net->ipv6.ip6_prohibit_entry->rt6i_idev);
88+ in6_dev_put(net->ipv6.ip6_blk_hole_entry->rt6i_idev);
89+#endif
90 }
91
92 return NOTIFY_OK;
93@@ -3795,7 +3804,7 @@ static struct pernet_operations ip6_rout
94
95 static struct notifier_block ip6_route_dev_notifier = {
96 .notifier_call = ip6_route_dev_notify,
97- .priority = 0,
98+ .priority = ADDRCONF_NOTIFY_PRIORITY - 10,
99 };
100
101 void __init ip6_route_init_special_entries(void)