Selaa lähdekoodia

Merge remote-tracking branch 'tor-github/pr/239'

Nick Mathewson 5 vuotta sitten
vanhempi
commit
b7ed61167f
4 muutettua tiedostoa jossa 54 lisäystä ja 2 poistoa
  1. 5 0
      changes/bug18642
  2. 8 0
      src/core/or/relay.c
  3. 39 2
      src/feature/relay/dns.c
  4. 2 0
      src/feature/relay/dns.h

+ 5 - 0
changes/bug18642

@@ -0,0 +1,5 @@
+  o Minor features (denial-of-service avoidance):
+    - Make our OOM handler aware of the DNS cache so that it doesn't fill up
+      the memory. This check is important for our DoS mitigation subsystem.
+      Closes ticket 18642. Patch by Neel Chauhan
+

+ 8 - 0
src/core/or/relay.c

@@ -64,6 +64,7 @@
 #include "lib/crypt_ops/crypto_rand.h"
 #include "lib/crypt_ops/crypto_util.h"
 #include "feature/dircache/directory.h"
+#include "feature/relay/dns.h"
 #include "feature/stats/geoip.h"
 #include "feature/hs/hs_cache.h"
 #include "core/mainloop/main.h"
@@ -2538,6 +2539,8 @@ cell_queues_check_size(void)
   const size_t geoip_client_cache_total =
     geoip_client_cache_total_allocation();
   alloc += geoip_client_cache_total;
+  const size_t dns_cache_total = dns_cache_total_allocation();
+  alloc += dns_cache_total;
   if (alloc >= get_options()->MaxMemInQueues_low_threshold) {
     last_time_under_memory_pressure = approx_time();
     if (alloc >= get_options()->MaxMemInQueues) {
@@ -2555,6 +2558,11 @@ cell_queues_check_size(void)
           (size_t)(get_options()->MaxMemInQueues / 10);
         alloc -= geoip_client_cache_handle_oom(now, bytes_to_remove);
       }
+      if (dns_cache_total > get_options()->MaxMemInQueues / 5) {
+        const size_t bytes_to_remove =
+          dns_cache_total - (size_t)(get_options()->MaxMemInQueues / 10);
+        alloc -= dns_cache_handle_oom(now, bytes_to_remove);
+      }
       circuits_handle_oom(alloc);
       return 1;
     }

+ 39 - 2
src/feature/relay/dns.c

@@ -2076,14 +2076,21 @@ dns_cache_entry_count(void)
    return HT_SIZE(&cache_root);
 }
 
+/* Return the total size in bytes of the DNS cache. */
+size_t
+dns_cache_total_allocation(void)
+{
+  return sizeof(struct cached_resolve_t) * dns_cache_entry_count() +
+         HT_MEM_USAGE(&cache_root);
+}
+
 /** Log memory information about our internal DNS cache at level 'severity'. */
 void
 dump_dns_mem_usage(int severity)
 {
   /* This should never be larger than INT_MAX. */
   int hash_count = dns_cache_entry_count();
-  size_t hash_mem = sizeof(struct cached_resolve_t) * hash_count;
-  hash_mem += HT_MEM_USAGE(&cache_root);
+  size_t hash_mem = dns_cache_total_allocation();
 
   /* Print out the count and estimated size of our &cache_root.  It undercounts
      hostnames in cached reverse resolves.
@@ -2093,6 +2100,36 @@ dump_dns_mem_usage(int severity)
       (unsigned)hash_mem);
 }
 
+/* Do a round of OOM cleanup on all DNS entries. Return the amount of removed
+ * bytes. It is possible that the returned value is lower than min_remove_bytes
+ * if the caches get emptied out so the caller should be aware of this. */
+size_t
+dns_cache_handle_oom(time_t now, size_t min_remove_bytes)
+{
+  time_t time_inc = 0;
+  size_t total_bytes_removed = 0;
+  size_t current_size = dns_cache_total_allocation();
+
+  do {
+    /* If no DNS entries left, break loop. */
+    if (!dns_cache_entry_count())
+      break;
+
+    /* Get cutoff interval and remove entries. */
+    time_t cutoff = now + time_inc;
+    purge_expired_resolves(cutoff);
+
+    /* Update amount of bytes removed and array size. */
+    size_t bytes_removed = current_size - dns_cache_total_allocation();
+    current_size -= bytes_removed;
+    total_bytes_removed += bytes_removed;
+
+    time_inc += 3600; /* Increase time_inc by 1 hour. */
+  } while (total_bytes_removed < min_remove_bytes);
+
+  return total_bytes_removed;
+}
+
 #ifdef DEBUG_DNS_CACHE
 /** Exit with an assertion if the DNS cache is corrupt. */
 static void

+ 2 - 0
src/feature/relay/dns.h

@@ -38,7 +38,9 @@ void dns_launch_correctness_checks(void);
 int dns_seems_to_be_broken(void);
 int dns_seems_to_be_broken_for_ipv6(void);
 void dns_reset_correctness_checks(void);
+size_t dns_cache_total_allocation(void);
 void dump_dns_mem_usage(int severity);
+size_t dns_cache_handle_oom(time_t now, size_t min_remove_bytes);
 
 #ifdef DNS_PRIVATE
 #include "feature/relay/dns_structs.h"