ipv6: Honor all IPv6 PIO Valid Lifetime values
authorFernando Gont <fgont@si6networks.com>
Sun, 19 Apr 2020 12:24:57 +0000 (09:24 -0300)
committerDavid S. Miller <davem@davemloft.net>
Thu, 23 Apr 2020 19:29:21 +0000 (12:29 -0700)
RFC4862 5.5.3 e) prevents received Router Advertisements from reducing
the Valid Lifetime of configured addresses to less than two hours, thus
preventing hosts from reacting to the information provided by a router
that has positive knowledge that a prefix has become invalid.

This patch makes hosts honor all Valid Lifetime values, as per
draft-gont-6man-slaac-renum-06, Section 4.2. This is meant to help
mitigate the problem discussed in draft-ietf-v6ops-slaac-renum.

Note: Attacks aiming at disabling an advertised prefix via a Valid
Lifetime of 0 are not really more harmful than other attacks
that can be performed via forged RA messages, such as those
aiming at completely disabling a next-hop router via an RA that
advertises a Router Lifetime of 0, or performing a Denial of
Service (DoS) attack by advertising illegitimate prefixes via
forged PIOs.  In scenarios where RA-based attacks are of concern,
proper mitigations such as RA-Guard [RFC6105] [RFC7113] should
be implemented.

Signed-off-by: Fernando Gont <fgont@si6networks.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/net/addrconf.h
net/ipv6/addrconf.c

index e0eabe5..fdb0710 100644 (file)
@@ -6,8 +6,6 @@
 #define RTR_SOLICITATION_INTERVAL      (4*HZ)
 #define RTR_SOLICITATION_MAX_INTERVAL  (3600*HZ)       /* 1 hour */
 
-#define MIN_VALID_LIFETIME             (2*3600)        /* 2 hours */
-
 #define TEMP_VALID_LIFETIME            (7*86400)
 #define TEMP_PREFERRED_LIFETIME                (86400)
 #define REGEN_MAX_RETRY                        (3)
index 24e319d..27b4fb6 100644 (file)
@@ -2564,7 +2564,7 @@ int addrconf_prefix_rcv_add_addr(struct net *net, struct net_device *dev,
                                 __u32 valid_lft, u32 prefered_lft)
 {
        struct inet6_ifaddr *ifp = ipv6_get_ifaddr(net, addr, dev, 1);
-       int create = 0, update_lft = 0;
+       int create = 0;
 
        if (!ifp && valid_lft) {
                int max_addresses = in6_dev->cnf.max_addresses;
@@ -2608,32 +2608,19 @@ int addrconf_prefix_rcv_add_addr(struct net *net, struct net_device *dev,
                unsigned long now;
                u32 stored_lft;
 
-               /* update lifetime (RFC2462 5.5.3 e) */
+               /* Update lifetime (RFC4862 5.5.3 e)
+                * We deviate from RFC4862 by honoring all Valid Lifetimes to
+                * improve the reaction of SLAAC to renumbering events
+                * (draft-gont-6man-slaac-renum-06, Section 4.2)
+                */
                spin_lock_bh(&ifp->lock);
                now = jiffies;
                if (ifp->valid_lft > (now - ifp->tstamp) / HZ)
                        stored_lft = ifp->valid_lft - (now - ifp->tstamp) / HZ;
                else
                        stored_lft = 0;
-               if (!create && stored_lft) {
-                       const u32 minimum_lft = min_t(u32,
-                               stored_lft, MIN_VALID_LIFETIME);
-                       valid_lft = max(valid_lft, minimum_lft);
-
-                       /* RFC4862 Section 5.5.3e:
-                        * "Note that the preferred lifetime of the
-                        *  corresponding address is always reset to
-                        *  the Preferred Lifetime in the received
-                        *  Prefix Information option, regardless of
-                        *  whether the valid lifetime is also reset or
-                        *  ignored."
-                        *
-                        * So we should always update prefered_lft here.
-                        */
-                       update_lft = 1;
-               }
 
-               if (update_lft) {
+               if (!create && stored_lft) {
                        ifp->valid_lft = valid_lft;
                        ifp->prefered_lft = prefered_lft;
                        ifp->tstamp = now;