[tor-commits] [tor/maint-0.2.9] Scale IPv6 address counts in policy_summary_reject to avoid overflow

nickm at torproject.org nickm at torproject.org
Tue Feb 7 14:26:01 UTC 2017


commit 408c53b7a78767e04124fec4c4d470fe474e4906
Author: teor <teor2345 at gmail.com>
Date:   Wed Feb 1 15:31:33 2017 +1100

    Scale IPv6 address counts in policy_summary_reject to avoid overflow
    
    This disregards anything smaller than an IPv6 /64, and rejects ports that
    are rejected on an IPv6 /16 or larger.
    
    Adjust existing unit tests, and add more to cover exceptional cases.
    
    No IPv4 behaviour changes.
    
    Fixes bug 21357
---
 src/or/policies.c      | 35 +++++++++++++++++++++++++++++------
 src/test/test_policy.c | 42 ++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 69 insertions(+), 8 deletions(-)

diff --git a/src/or/policies.c b/src/or/policies.c
index cac475d..6037ee3 100644
--- a/src/or/policies.c
+++ b/src/or/policies.c
@@ -2300,15 +2300,24 @@ policy_summary_item_split(policy_summary_item_t* old, uint16_t new_starts)
 #define AT(x) ((policy_summary_item_t*)smartlist_get(summary, x))
 
 #define IPV4_BITS                (32)
+/* Every IPv4 address is counted as one rejection */
+#define REJECT_CUTOFF_SCALE_IPV4 (0)
 /* Ports are rejected in an IPv4 summary if they are rejected in more than two
  * IPv4 /8 address blocks */
 #define REJECT_CUTOFF_COUNT_IPV4 (U64_LITERAL(1) << \
-                                  (IPV4_BITS - 7))
+                                  (IPV4_BITS - REJECT_CUTOFF_SCALE_IPV4 - 7))
 
 #define IPV6_BITS                (128)
-/* Ports are rejected in an IPv6 summary if they are rejected in at least one
- * IPv6 /64. */
-#define REJECT_CUTOFF_COUNT_IPV6 (UINT64_MAX)
+/* IPv6 /64s are counted as one rejection, anything smaller is ignored */
+#define REJECT_CUTOFF_SCALE_IPV6 (64)
+/* Ports are rejected in an IPv6 summary if they are rejected in more than one
+ * IPv6 /16 address block.
+ * This is rougly equivalent to the IPv4 cutoff, as only five IPv6 /12s (and
+ * some scattered smaller blocks) have been allocated to the RIRs.
+ * Network providers are typically allocated one or more IPv6 /32s.
+ */
+#define REJECT_CUTOFF_COUNT_IPV6 (U64_LITERAL(1) << \
+                                  (IPV6_BITS - REJECT_CUTOFF_SCALE_IPV6 - 16))
 
 /** Split an exit policy summary so that prt_min and prt_max
  * fall at exactly the start and end of an item respectively.
@@ -2381,14 +2390,28 @@ policy_summary_reject(smartlist_t *summary,
   int addrbits = (family == AF_INET) ? IPV4_BITS : IPV6_BITS;
   tor_assert_nonfatal_once(addrbits >= maskbits);
 
+  /* We divide IPv6 address counts by (1 << scale) to keep them in a uint64_t
+   */
+  int scale = ((family == AF_INET) ?
+               REJECT_CUTOFF_SCALE_IPV4 :
+               REJECT_CUTOFF_SCALE_IPV6);
+
+  tor_assert_nonfatal_once(addrbits >= scale);
+  if (maskbits > (addrbits - scale)) {
+    tor_assert_nonfatal_once(family == AF_INET6);
+    /* The address range is so small, we'd need billions of them to reach the
+     * rejection limit. So we ignore this range in the reject count. */
+    return;
+  }
+
   uint64_t count = 0;
-  if (addrbits - maskbits >= 64) {
+  if (addrbits - scale - maskbits >= 64) {
     tor_assert_nonfatal_once(family == AF_INET6);
     /* The address range is so large, it's an automatic rejection for all ports
      * in the range. */
     count = UINT64_MAX;
   } else {
-    count = (U64_LITERAL(1) << (addrbits - maskbits));
+    count = (U64_LITERAL(1) << (addrbits - scale - maskbits));
   }
   tor_assert_nonfatal_once(count > 0);
   while (i < smartlist_len(summary) &&
diff --git a/src/test/test_policy.c b/src/test/test_policy.c
index fb7195a..f2d42b9 100644
--- a/src/test/test_policy.c
+++ b/src/test/test_policy.c
@@ -594,13 +594,51 @@ test_policies_general(void *arg)
   /* short policy with configured netblocks */
   test_policy_summary_helper("reject 149.56.0.0/16,"
                              "reject6 2607:5300::/32,"
+                             "reject6 2608:5300::/64,"
+                             "reject6 2609:5300::/96,"
+                             "accept *:80,"
+                             "accept *:443,"
+                             "reject *:*",
+                             "accept 80,443");
+  /* short policy with large netblocks that do not count as a rejection */
+  test_policy_summary_helper("reject 148.0.0.0/7,"
+                             "reject6 2600::/16,"
                              "accept *:80,"
                              "accept *:443,"
                              "reject *:*",
                              "accept 80,443");
   /* short policy with large netblocks that count as a rejection */
-  test_policy_summary_helper("reject 149.0.0.0/6,"
-                             "reject6 2600::/6,"
+  test_policy_summary_helper("reject 148.0.0.0/6,"
+                             "reject6 2600::/15,"
+                             "accept *:80,"
+                             "accept *:443,"
+                             "reject *:*",
+                             "reject 1-65535");
+  /* short policy with huge netblocks that count as a rejection */
+  test_policy_summary_helper("reject 128.0.0.0/1,"
+                             "reject6 8000::/1,"
+                             "accept *:80,"
+                             "accept *:443,"
+                             "reject *:*",
+                             "reject 1-65535");
+  /* short policy which blocks everything using netblocks */
+  test_policy_summary_helper("reject 0.0.0.0/0,"
+                             "reject6 ::/0,"
+                             "accept *:80,"
+                             "accept *:443,"
+                             "reject *:*",
+                             "reject 1-65535");
+  /* short policy which has repeated redundant netblocks */
+  test_policy_summary_helper("reject 0.0.0.0/0,"
+                             "reject 0.0.0.0/0,"
+                             "reject 0.0.0.0/0,"
+                             "reject 0.0.0.0/0,"
+                             "reject 0.0.0.0/0,"
+                             "reject6 ::/0,"
+                             "reject6 ::/0,"
+                             "reject6 ::/0,"
+                             "reject6 ::/0,"
+                             "reject6 ::/0,"
                              "accept *:80,"
                              "accept *:443,"
                              "reject *:*",





More information about the tor-commits mailing list