Loading changes/bug18642 0 → 100644 +5 −0 Original line number Diff line number Diff line 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 src/core/or/relay.c +8 −0 Original line number Diff line number Diff line Loading @@ -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" Loading Loading @@ -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) { Loading @@ -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; } Loading src/feature/relay/dns.c +39 −2 Original line number Diff line number Diff line Loading @@ -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. Loading @@ -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 Loading src/feature/relay/dns.h +2 −0 Original line number Diff line number Diff line Loading @@ -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" Loading Loading
changes/bug18642 0 → 100644 +5 −0 Original line number Diff line number Diff line 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
src/core/or/relay.c +8 −0 Original line number Diff line number Diff line Loading @@ -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" Loading Loading @@ -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) { Loading @@ -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; } Loading
src/feature/relay/dns.c +39 −2 Original line number Diff line number Diff line Loading @@ -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. Loading @@ -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 Loading
src/feature/relay/dns.h +2 −0 Original line number Diff line number Diff line Loading @@ -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" Loading