]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - net/ipv6/route.c
ipv6: fix NULL dereference in ip6_route_dev_notify()
[karo-tx-linux.git] / net / ipv6 / route.c
index 4d30c96a819dee548ec34704a34b22774fac5da1..94d6a13d47f0e9ec5ff4cbc50b90d4cd9ca3f38a 100644 (file)
@@ -417,14 +417,11 @@ static void ip6_dst_ifdown(struct dst_entry *dst, struct net_device *dev,
        struct net_device *loopback_dev =
                dev_net(dev)->loopback_dev;
 
-       if (dev != loopback_dev) {
-               if (idev && idev->dev == dev) {
-                       struct inet6_dev *loopback_idev =
-                               in6_dev_get(loopback_dev);
-                       if (loopback_idev) {
-                               rt->rt6i_idev = loopback_idev;
-                               in6_dev_put(idev);
-                       }
+       if (idev && idev->dev != loopback_dev) {
+               struct inet6_dev *loopback_idev = in6_dev_get(loopback_dev);
+               if (loopback_idev) {
+                       rt->rt6i_idev = loopback_idev;
+                       in6_dev_put(idev);
                }
        }
 }
@@ -2351,6 +2348,7 @@ static void rt6_do_redirect(struct dst_entry *dst, struct sock *sk, struct sk_bu
        if (on_link)
                nrt->rt6i_flags &= ~RTF_GATEWAY;
 
+       nrt->rt6i_protocol = RTPROT_REDIRECT;
        nrt->rt6i_gateway = *(struct in6_addr *)neigh->primary_key;
 
        if (ip6_ins_rt(nrt))
@@ -2461,6 +2459,7 @@ static struct rt6_info *rt6_add_route_info(struct net *net,
                .fc_dst_len     = prefixlen,
                .fc_flags       = RTF_GATEWAY | RTF_ADDRCONF | RTF_ROUTEINFO |
                                  RTF_UP | RTF_PREF(pref),
+               .fc_protocol = RTPROT_RA,
                .fc_nlinfo.portid = 0,
                .fc_nlinfo.nlh = NULL,
                .fc_nlinfo.nl_net = net,
@@ -2513,6 +2512,7 @@ struct rt6_info *rt6_add_dflt_router(const struct in6_addr *gwaddr,
                .fc_ifindex     = dev->ifindex,
                .fc_flags       = RTF_GATEWAY | RTF_ADDRCONF | RTF_DEFAULT |
                                  RTF_UP | RTF_EXPIRES | RTF_PREF(pref),
+               .fc_protocol = RTPROT_RA,
                .fc_nlinfo.portid = 0,
                .fc_nlinfo.nlh = NULL,
                .fc_nlinfo.nl_net = dev_net(dev),
@@ -3424,14 +3424,6 @@ static int rt6_fill_node(struct net *net,
        rtm->rtm_flags = 0;
        rtm->rtm_scope = RT_SCOPE_UNIVERSE;
        rtm->rtm_protocol = rt->rt6i_protocol;
-       if (rt->rt6i_flags & RTF_DYNAMIC)
-               rtm->rtm_protocol = RTPROT_REDIRECT;
-       else if (rt->rt6i_flags & RTF_ADDRCONF) {
-               if (rt->rt6i_flags & (RTF_DEFAULT | RTF_ROUTEINFO))
-                       rtm->rtm_protocol = RTPROT_RA;
-               else
-                       rtm->rtm_protocol = RTPROT_KERNEL;
-       }
 
        if (rt->rt6i_flags & RTF_CACHE)
                rtm->rtm_flags |= RTM_F_CLONED;
@@ -3729,10 +3721,10 @@ static int ip6_route_dev_notify(struct notifier_block *this,
                /* NETDEV_UNREGISTER could be fired for multiple times by
                 * netdev_wait_allrefs(). Make sure we only call this once.
                 */
-               in6_dev_put(net->ipv6.ip6_null_entry->rt6i_idev);
+               in6_dev_put_clear(&net->ipv6.ip6_null_entry->rt6i_idev);
 #ifdef CONFIG_IPV6_MULTIPLE_TABLES
-               in6_dev_put(net->ipv6.ip6_prohibit_entry->rt6i_idev);
-               in6_dev_put(net->ipv6.ip6_blk_hole_entry->rt6i_idev);
+               in6_dev_put_clear(&net->ipv6.ip6_prohibit_entry->rt6i_idev);
+               in6_dev_put_clear(&net->ipv6.ip6_blk_hole_entry->rt6i_idev);
 #endif
        }