aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6
diff options
context:
space:
mode:
authorEric Dumazet <eric.dumazet@gmail.com>2012-02-09 16:13:19 -0500
committerLuis Henriques <luis.henriques@canonical.com>2012-03-08 07:23:31 -0500
commit1fd4aa39b59cf19231abd742d8b00561b4d5d7a1 (patch)
tree4fa63f5184f09ed2d8142401d7e6da353f3f9aa3 /net/ipv6
parent47024c94e55428e8cac942cde4d11c613aecaa70 (diff)
net: fix NULL dereferences in check_peer_redir()
BugLink: http://bugs.launchpad.net/bugs/931719 [ Upstream commit d3aaeb38c40e5a6c08dd31a1b64da65c4352be36, along with dependent backports of commits: 69cce1d1404968f78b177a0314f5822d5afdbbfb 9de79c127cccecb11ae6a21ab1499e87aa222880 218fa90f072e4aeff9003d57e390857f4f35513e 580da35a31f91a594f3090b7a2c39b85cb051a12 f7e57044eeb1841847c24aa06766c8290c202583 e049f28883126c689cf95859480d9ee4ab23b7fa ] Gergely Kalman reported crashes in check_peer_redir(). It appears commit f39925dbde778 (ipv4: Cache learned redirect information in inetpeer.) added a race, leading to possible NULL ptr dereference. Since we can now change dst neighbour, we should make sure a reader can safely use a neighbour. Add RCU protection to dst neighbour, and make sure check_peer_redir() can be called safely by different cpus in parallel. As neighbours are already freed after one RCU grace period, this patch should not add typical RCU penalty (cache cold effects) Many thanks to Gergely for providing a pretty report pointing to the bug. Reported-by: Gergely Kalman <synapse@hippy.csoma.elte.hu> Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Signed-off-by: Tim Gardner <tim.gardner@canonical.com>
Diffstat (limited to 'net/ipv6')
-rw-r--r--net/ipv6/addrconf.c2
-rw-r--r--net/ipv6/ip6_fib.c2
-rw-r--r--net/ipv6/ip6_output.c40
-rw-r--r--net/ipv6/ndisc.c4
-rw-r--r--net/ipv6/route.c59
-rw-r--r--net/ipv6/sit.c4
6 files changed, 74 insertions, 37 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 498b927f68b..0f335c67eb8 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -656,7 +656,7 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, int pfxlen,
656 * layer address of our nexhop router 656 * layer address of our nexhop router
657 */ 657 */
658 658
659 if (rt->rt6i_nexthop == NULL) 659 if (dst_get_neighbour_raw(&rt->dst) == NULL)
660 ifa->flags &= ~IFA_F_OPTIMISTIC; 660 ifa->flags &= ~IFA_F_OPTIMISTIC;
661 661
662 ifa->idev = idev; 662 ifa->idev = idev;
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c
index 4076a0b14b2..0f9b37a1c1d 100644
--- a/net/ipv6/ip6_fib.c
+++ b/net/ipv6/ip6_fib.c
@@ -1455,7 +1455,7 @@ static int fib6_age(struct rt6_info *rt, void *arg)
1455 RT6_TRACE("aging clone %p\n", rt); 1455 RT6_TRACE("aging clone %p\n", rt);
1456 return -1; 1456 return -1;
1457 } else if ((rt->rt6i_flags & RTF_GATEWAY) && 1457 } else if ((rt->rt6i_flags & RTF_GATEWAY) &&
1458 (!(rt->rt6i_nexthop->flags & NTF_ROUTER))) { 1458 (!(dst_get_neighbour_raw(&rt->dst)->flags & NTF_ROUTER))) {
1459 RT6_TRACE("purging route %p via non-router but gateway\n", 1459 RT6_TRACE("purging route %p via non-router but gateway\n",
1460 rt); 1460 rt);
1461 return -1; 1461 return -1;
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index e17596b8407..9cbf17686a1 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -100,6 +100,8 @@ static int ip6_finish_output2(struct sk_buff *skb)
100{ 100{
101 struct dst_entry *dst = skb_dst(skb); 101 struct dst_entry *dst = skb_dst(skb);
102 struct net_device *dev = dst->dev; 102 struct net_device *dev = dst->dev;
103 struct neighbour *neigh;
104 int res;
103 105
104 skb->protocol = htons(ETH_P_IPV6); 106 skb->protocol = htons(ETH_P_IPV6);
105 skb->dev = dev; 107 skb->dev = dev;
@@ -134,10 +136,22 @@ static int ip6_finish_output2(struct sk_buff *skb)
134 skb->len); 136 skb->len);
135 } 137 }
136 138
137 if (dst->hh) 139 rcu_read_lock();
138 return neigh_hh_output(dst->hh, skb); 140 if (dst->hh) {
139 else if (dst->neighbour) 141 res = neigh_hh_output(dst->hh, skb);
140 return dst->neighbour->output(skb); 142
143 rcu_read_unlock();
144 return res;
145 } else {
146 neigh = dst_get_neighbour(dst);
147 if (neigh) {
148 res = neigh->output(skb);
149
150 rcu_read_unlock();
151 return res;
152 }
153 rcu_read_unlock();
154 }
141 155
142 IP6_INC_STATS_BH(dev_net(dst->dev), 156 IP6_INC_STATS_BH(dev_net(dst->dev),
143 ip6_dst_idev(dst), IPSTATS_MIB_OUTNOROUTES); 157 ip6_dst_idev(dst), IPSTATS_MIB_OUTNOROUTES);
@@ -385,6 +399,7 @@ int ip6_forward(struct sk_buff *skb)
385 struct ipv6hdr *hdr = ipv6_hdr(skb); 399 struct ipv6hdr *hdr = ipv6_hdr(skb);
386 struct inet6_skb_parm *opt = IP6CB(skb); 400 struct inet6_skb_parm *opt = IP6CB(skb);
387 struct net *net = dev_net(dst->dev); 401 struct net *net = dev_net(dst->dev);
402 struct neighbour *n;
388 u32 mtu; 403 u32 mtu;
389 404
390 if (net->ipv6.devconf_all->forwarding == 0) 405 if (net->ipv6.devconf_all->forwarding == 0)
@@ -459,11 +474,10 @@ int ip6_forward(struct sk_buff *skb)
459 send redirects to source routed frames. 474 send redirects to source routed frames.
460 We don't send redirects to frames decapsulated from IPsec. 475 We don't send redirects to frames decapsulated from IPsec.
461 */ 476 */
462 if (skb->dev == dst->dev && dst->neighbour && opt->srcrt == 0 && 477 n = dst_get_neighbour(dst);
463 !skb_sec_path(skb)) { 478 if (skb->dev == dst->dev && n && opt->srcrt == 0 && !skb_sec_path(skb)) {
464 struct in6_addr *target = NULL; 479 struct in6_addr *target = NULL;
465 struct rt6_info *rt; 480 struct rt6_info *rt;
466 struct neighbour *n = dst->neighbour;
467 481
468 /* 482 /*
469 * incoming and outgoing devices are the same 483 * incoming and outgoing devices are the same
@@ -949,8 +963,11 @@ out:
949static int ip6_dst_lookup_tail(struct sock *sk, 963static int ip6_dst_lookup_tail(struct sock *sk,
950 struct dst_entry **dst, struct flowi6 *fl6) 964 struct dst_entry **dst, struct flowi6 *fl6)
951{ 965{
952 int err;
953 struct net *net = sock_net(sk); 966 struct net *net = sock_net(sk);
967#ifdef CONFIG_IPV6_OPTIMISTIC_DAD
968 struct neighbour *n;
969#endif
970 int err;
954 971
955 if (*dst == NULL) 972 if (*dst == NULL)
956 *dst = ip6_route_output(net, sk, fl6); 973 *dst = ip6_route_output(net, sk, fl6);
@@ -976,11 +993,14 @@ static int ip6_dst_lookup_tail(struct sock *sk,
976 * dst entry and replace it instead with the 993 * dst entry and replace it instead with the
977 * dst entry of the nexthop router 994 * dst entry of the nexthop router
978 */ 995 */
979 if ((*dst)->neighbour && !((*dst)->neighbour->nud_state & NUD_VALID)) { 996 rcu_read_lock();
997 n = dst_get_neighbour(*dst);
998 if (n && !(n->nud_state & NUD_VALID)) {
980 struct inet6_ifaddr *ifp; 999 struct inet6_ifaddr *ifp;
981 struct flowi6 fl_gw6; 1000 struct flowi6 fl_gw6;
982 int redirect; 1001 int redirect;
983 1002
1003 rcu_read_unlock();
984 ifp = ipv6_get_ifaddr(net, &fl6->saddr, 1004 ifp = ipv6_get_ifaddr(net, &fl6->saddr,
985 (*dst)->dev, 1); 1005 (*dst)->dev, 1);
986 1006
@@ -1000,6 +1020,8 @@ static int ip6_dst_lookup_tail(struct sock *sk,
1000 if ((err = (*dst)->error)) 1020 if ((err = (*dst)->error))
1001 goto out_err_release; 1021 goto out_err_release;
1002 } 1022 }
1023 } else {
1024 rcu_read_unlock();
1003 } 1025 }
1004#endif 1026#endif
1005 1027
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
index 7596f071d30..10a8d411707 100644
--- a/net/ipv6/ndisc.c
+++ b/net/ipv6/ndisc.c
@@ -1244,7 +1244,7 @@ static void ndisc_router_discovery(struct sk_buff *skb)
1244 rt = rt6_get_dflt_router(&ipv6_hdr(skb)->saddr, skb->dev); 1244 rt = rt6_get_dflt_router(&ipv6_hdr(skb)->saddr, skb->dev);
1245 1245
1246 if (rt) 1246 if (rt)
1247 neigh = rt->rt6i_nexthop; 1247 neigh = dst_get_neighbour(&rt->dst);
1248 1248
1249 if (rt && lifetime == 0) { 1249 if (rt && lifetime == 0) {
1250 neigh_clone(neigh); 1250 neigh_clone(neigh);
@@ -1265,7 +1265,7 @@ static void ndisc_router_discovery(struct sk_buff *skb)
1265 return; 1265 return;
1266 } 1266 }
1267 1267
1268 neigh = rt->rt6i_nexthop; 1268 neigh = dst_get_neighbour(&rt->dst);
1269 if (neigh == NULL) { 1269 if (neigh == NULL) {
1270 ND_PRINTK0(KERN_ERR 1270 ND_PRINTK0(KERN_ERR
1271 "ICMPv6 RA: %s() got default router without neighbour.\n", 1271 "ICMPv6 RA: %s() got default router without neighbour.\n",
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 0ef1f086feb..e70e902a5d0 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -356,7 +356,7 @@ out:
356#ifdef CONFIG_IPV6_ROUTER_PREF 356#ifdef CONFIG_IPV6_ROUTER_PREF
357static void rt6_probe(struct rt6_info *rt) 357static void rt6_probe(struct rt6_info *rt)
358{ 358{
359 struct neighbour *neigh = rt ? rt->rt6i_nexthop : NULL; 359 struct neighbour *neigh;
360 /* 360 /*
361 * Okay, this does not seem to be appropriate 361 * Okay, this does not seem to be appropriate
362 * for now, however, we need to check if it 362 * for now, however, we need to check if it
@@ -365,8 +365,10 @@ static void rt6_probe(struct rt6_info *rt)
365 * Router Reachability Probe MUST be rate-limited 365 * Router Reachability Probe MUST be rate-limited
366 * to no more than one per minute. 366 * to no more than one per minute.
367 */ 367 */
368 rcu_read_lock();
369 neigh = rt ? dst_get_neighbour(&rt->dst) : NULL;
368 if (!neigh || (neigh->nud_state & NUD_VALID)) 370 if (!neigh || (neigh->nud_state & NUD_VALID))
369 return; 371 goto out;
370 read_lock_bh(&neigh->lock); 372 read_lock_bh(&neigh->lock);
371 if (!(neigh->nud_state & NUD_VALID) && 373 if (!(neigh->nud_state & NUD_VALID) &&
372 time_after(jiffies, neigh->updated + rt->rt6i_idev->cnf.rtr_probe_interval)) { 374 time_after(jiffies, neigh->updated + rt->rt6i_idev->cnf.rtr_probe_interval)) {
@@ -379,8 +381,11 @@ static void rt6_probe(struct rt6_info *rt)
379 target = (struct in6_addr *)&neigh->primary_key; 381 target = (struct in6_addr *)&neigh->primary_key;
380 addrconf_addr_solict_mult(target, &mcaddr); 382 addrconf_addr_solict_mult(target, &mcaddr);
381 ndisc_send_ns(rt->rt6i_dev, NULL, target, &mcaddr, NULL); 383 ndisc_send_ns(rt->rt6i_dev, NULL, target, &mcaddr, NULL);
382 } else 384 } else {
383 read_unlock_bh(&neigh->lock); 385 read_unlock_bh(&neigh->lock);
386 }
387out:
388 rcu_read_unlock();
384} 389}
385#else 390#else
386static inline void rt6_probe(struct rt6_info *rt) 391static inline void rt6_probe(struct rt6_info *rt)
@@ -404,8 +409,11 @@ static inline int rt6_check_dev(struct rt6_info *rt, int oif)
404 409
405static inline int rt6_check_neigh(struct rt6_info *rt) 410static inline int rt6_check_neigh(struct rt6_info *rt)
406{ 411{
407 struct neighbour *neigh = rt->rt6i_nexthop; 412 struct neighbour *neigh;
408 int m; 413 int m;
414
415 rcu_read_lock();
416 neigh = dst_get_neighbour(&rt->dst);
409 if (rt->rt6i_flags & RTF_NONEXTHOP || 417 if (rt->rt6i_flags & RTF_NONEXTHOP ||
410 !(rt->rt6i_flags & RTF_GATEWAY)) 418 !(rt->rt6i_flags & RTF_GATEWAY))
411 m = 1; 419 m = 1;
@@ -422,6 +430,7 @@ static inline int rt6_check_neigh(struct rt6_info *rt)
422 read_unlock_bh(&neigh->lock); 430 read_unlock_bh(&neigh->lock);
423 } else 431 } else
424 m = 0; 432 m = 0;
433 rcu_read_unlock();
425 return m; 434 return m;
426} 435}
427 436
@@ -745,8 +754,7 @@ static struct rt6_info *rt6_alloc_cow(struct rt6_info *ort, const struct in6_add
745 dst_free(&rt->dst); 754 dst_free(&rt->dst);
746 return NULL; 755 return NULL;
747 } 756 }
748 rt->rt6i_nexthop = neigh; 757 dst_set_neighbour(&rt->dst, neigh);
749
750 } 758 }
751 759
752 return rt; 760 return rt;
@@ -760,7 +768,7 @@ static struct rt6_info *rt6_alloc_clone(struct rt6_info *ort, const struct in6_a
760 rt->rt6i_dst.plen = 128; 768 rt->rt6i_dst.plen = 128;
761 rt->rt6i_flags |= RTF_CACHE; 769 rt->rt6i_flags |= RTF_CACHE;
762 rt->dst.flags |= DST_HOST; 770 rt->dst.flags |= DST_HOST;
763 rt->rt6i_nexthop = neigh_clone(ort->rt6i_nexthop); 771 dst_set_neighbour(&rt->dst, neigh_clone(dst_get_neighbour_raw(&ort->dst)));
764 } 772 }
765 return rt; 773 return rt;
766} 774}
@@ -794,7 +802,7 @@ restart:
794 dst_hold(&rt->dst); 802 dst_hold(&rt->dst);
795 read_unlock_bh(&table->tb6_lock); 803 read_unlock_bh(&table->tb6_lock);
796 804
797 if (!rt->rt6i_nexthop && !(rt->rt6i_flags & RTF_NONEXTHOP)) 805 if (!dst_get_neighbour_raw(&rt->dst) && !(rt->rt6i_flags & RTF_NONEXTHOP))
798 nrt = rt6_alloc_cow(rt, &fl6->daddr, &fl6->saddr); 806 nrt = rt6_alloc_cow(rt, &fl6->daddr, &fl6->saddr);
799 else if (!(rt->dst.flags & DST_HOST)) 807 else if (!(rt->dst.flags & DST_HOST))
800 nrt = rt6_alloc_clone(rt, &fl6->daddr); 808 nrt = rt6_alloc_clone(rt, &fl6->daddr);
@@ -1058,7 +1066,7 @@ struct dst_entry *icmp6_dst_alloc(struct net_device *dev,
1058 } 1066 }
1059 1067
1060 rt->rt6i_idev = idev; 1068 rt->rt6i_idev = idev;
1061 rt->rt6i_nexthop = neigh; 1069 dst_set_neighbour(&rt->dst, neigh);
1062 atomic_set(&rt->dst.__refcnt, 1); 1070 atomic_set(&rt->dst.__refcnt, 1);
1063 dst_metric_set(&rt->dst, RTAX_HOPLIMIT, 255); 1071 dst_metric_set(&rt->dst, RTAX_HOPLIMIT, 255);
1064 rt->dst.output = ip6_output; 1072 rt->dst.output = ip6_output;
@@ -1338,12 +1346,12 @@ int ip6_route_add(struct fib6_config *cfg)
1338 rt->rt6i_prefsrc.plen = 0; 1346 rt->rt6i_prefsrc.plen = 0;
1339 1347
1340 if (cfg->fc_flags & (RTF_GATEWAY | RTF_NONEXTHOP)) { 1348 if (cfg->fc_flags & (RTF_GATEWAY | RTF_NONEXTHOP)) {
1341 rt->rt6i_nexthop = __neigh_lookup_errno(&nd_tbl, &rt->rt6i_gateway, dev); 1349 struct neighbour *neigh = __neigh_lookup_errno(&nd_tbl, &rt->rt6i_gateway, dev);
1342 if (IS_ERR(rt->rt6i_nexthop)) { 1350 if (IS_ERR(neigh)) {
1343 err = PTR_ERR(rt->rt6i_nexthop); 1351 err = PTR_ERR(neigh);
1344 rt->rt6i_nexthop = NULL;
1345 goto out; 1352 goto out;
1346 } 1353 }
1354 dst_set_neighbour(&rt->dst, neigh);
1347 } 1355 }
1348 1356
1349 rt->rt6i_flags = cfg->fc_flags; 1357 rt->rt6i_flags = cfg->fc_flags;
@@ -1574,7 +1582,7 @@ void rt6_redirect(const struct in6_addr *dest, const struct in6_addr *src,
1574 dst_confirm(&rt->dst); 1582 dst_confirm(&rt->dst);
1575 1583
1576 /* Duplicate redirect: silently ignore. */ 1584 /* Duplicate redirect: silently ignore. */
1577 if (neigh == rt->dst.neighbour) 1585 if (neigh == dst_get_neighbour_raw(&rt->dst))
1578 goto out; 1586 goto out;
1579 1587
1580 nrt = ip6_rt_copy(rt); 1588 nrt = ip6_rt_copy(rt);
@@ -1590,7 +1598,7 @@ void rt6_redirect(const struct in6_addr *dest, const struct in6_addr *src,
1590 nrt->dst.flags |= DST_HOST; 1598 nrt->dst.flags |= DST_HOST;
1591 1599
1592 ipv6_addr_copy(&nrt->rt6i_gateway, (struct in6_addr*)neigh->primary_key); 1600 ipv6_addr_copy(&nrt->rt6i_gateway, (struct in6_addr*)neigh->primary_key);
1593 nrt->rt6i_nexthop = neigh_clone(neigh); 1601 dst_set_neighbour(&nrt->dst, neigh_clone(neigh));
1594 1602
1595 if (ip6_ins_rt(nrt)) 1603 if (ip6_ins_rt(nrt))
1596 goto out; 1604 goto out;
@@ -1670,7 +1678,7 @@ again:
1670 1. It is connected route. Action: COW 1678 1. It is connected route. Action: COW
1671 2. It is gatewayed route or NONEXTHOP route. Action: clone it. 1679 2. It is gatewayed route or NONEXTHOP route. Action: clone it.
1672 */ 1680 */
1673 if (!rt->rt6i_nexthop && !(rt->rt6i_flags & RTF_NONEXTHOP)) 1681 if (!dst_get_neighbour_raw(&rt->dst) && !(rt->rt6i_flags & RTF_NONEXTHOP))
1674 nrt = rt6_alloc_cow(rt, daddr, saddr); 1682 nrt = rt6_alloc_cow(rt, daddr, saddr);
1675 else 1683 else
1676 nrt = rt6_alloc_clone(rt, daddr); 1684 nrt = rt6_alloc_clone(rt, daddr);
@@ -2035,7 +2043,7 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev,
2035 2043
2036 return ERR_CAST(neigh); 2044 return ERR_CAST(neigh);
2037 } 2045 }
2038 rt->rt6i_nexthop = neigh; 2046 dst_set_neighbour(&rt->dst, neigh);
2039 2047
2040 ipv6_addr_copy(&rt->rt6i_dst.addr, addr); 2048 ipv6_addr_copy(&rt->rt6i_dst.addr, addr);
2041 rt->rt6i_dst.plen = 128; 2049 rt->rt6i_dst.plen = 128;
@@ -2312,6 +2320,7 @@ static int rt6_fill_node(struct net *net,
2312 struct nlmsghdr *nlh; 2320 struct nlmsghdr *nlh;
2313 long expires; 2321 long expires;
2314 u32 table; 2322 u32 table;
2323 struct neighbour *n;
2315 2324
2316 if (prefix) { /* user wants prefix routes only */ 2325 if (prefix) { /* user wants prefix routes only */
2317 if (!(rt->rt6i_flags & RTF_PREFIX_RT)) { 2326 if (!(rt->rt6i_flags & RTF_PREFIX_RT)) {
@@ -2400,8 +2409,11 @@ static int rt6_fill_node(struct net *net,
2400 if (rtnetlink_put_metrics(skb, dst_metrics_ptr(&rt->dst)) < 0) 2409 if (rtnetlink_put_metrics(skb, dst_metrics_ptr(&rt->dst)) < 0)
2401 goto nla_put_failure; 2410 goto nla_put_failure;
2402 2411
2403 if (rt->dst.neighbour) 2412 rcu_read_lock();
2404 NLA_PUT(skb, RTA_GATEWAY, 16, &rt->dst.neighbour->primary_key); 2413 n = dst_get_neighbour(&rt->dst);
2414 if (n)
2415 NLA_PUT(skb, RTA_GATEWAY, 16, &n->primary_key);
2416 rcu_read_unlock();
2405 2417
2406 if (rt->dst.dev) 2418 if (rt->dst.dev)
2407 NLA_PUT_U32(skb, RTA_OIF, rt->rt6i_dev->ifindex); 2419 NLA_PUT_U32(skb, RTA_OIF, rt->rt6i_dev->ifindex);
@@ -2585,6 +2597,7 @@ struct rt6_proc_arg
2585static int rt6_info_route(struct rt6_info *rt, void *p_arg) 2597static int rt6_info_route(struct rt6_info *rt, void *p_arg)
2586{ 2598{
2587 struct seq_file *m = p_arg; 2599 struct seq_file *m = p_arg;
2600 struct neighbour *n;
2588 2601
2589 seq_printf(m, "%pi6 %02x ", &rt->rt6i_dst.addr, rt->rt6i_dst.plen); 2602 seq_printf(m, "%pi6 %02x ", &rt->rt6i_dst.addr, rt->rt6i_dst.plen);
2590 2603
@@ -2593,12 +2606,14 @@ static int rt6_info_route(struct rt6_info *rt, void *p_arg)
2593#else 2606#else
2594 seq_puts(m, "00000000000000000000000000000000 00 "); 2607 seq_puts(m, "00000000000000000000000000000000 00 ");
2595#endif 2608#endif
2596 2609 rcu_read_lock();
2597 if (rt->rt6i_nexthop) { 2610 n = dst_get_neighbour(&rt->dst);
2598 seq_printf(m, "%pi6", rt->rt6i_nexthop->primary_key); 2611 if (n) {
2612 seq_printf(m, "%pi6", n->primary_key);
2599 } else { 2613 } else {
2600 seq_puts(m, "00000000000000000000000000000000"); 2614 seq_puts(m, "00000000000000000000000000000000");
2601 } 2615 }
2616 rcu_read_unlock();
2602 seq_printf(m, " %08x %08x %08x %08x %8s\n", 2617 seq_printf(m, " %08x %08x %08x %08x %8s\n",
2603 rt->rt6i_metric, atomic_read(&rt->dst.__refcnt), 2618 rt->rt6i_metric, atomic_read(&rt->dst.__refcnt),
2604 rt->dst.__use, rt->rt6i_flags, 2619 rt->dst.__use, rt->rt6i_flags,
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c
index 38490d5c7e1..f56acd09659 100644
--- a/net/ipv6/sit.c
+++ b/net/ipv6/sit.c
@@ -679,7 +679,7 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb,
679 struct neighbour *neigh = NULL; 679 struct neighbour *neigh = NULL;
680 680
681 if (skb_dst(skb)) 681 if (skb_dst(skb))
682 neigh = skb_dst(skb)->neighbour; 682 neigh = dst_get_neighbour(skb_dst(skb));
683 683
684 if (neigh == NULL) { 684 if (neigh == NULL) {
685 if (net_ratelimit()) 685 if (net_ratelimit())
@@ -704,7 +704,7 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb,
704 struct neighbour *neigh = NULL; 704 struct neighbour *neigh = NULL;
705 705
706 if (skb_dst(skb)) 706 if (skb_dst(skb))
707 neigh = skb_dst(skb)->neighbour; 707 neigh = dst_get_neighbour(skb_dst(skb));
708 708
709 if (neigh == NULL) { 709 if (neigh == NULL) {
710 if (net_ratelimit()) 710 if (net_ratelimit())