[tor-commits] [tor/release-0.2.9] Merge branch 'ticket25122_029_02' into ticket24902_029_05

nickm at torproject.org nickm at torproject.org
Fri Feb 16 14:56:20 UTC 2018


commit 475218c108ad84aa302f0daec013faab9ff778f2
Merge: 33d9889a2 e758d659a
Author: David Goulet <dgoulet at torproject.org>
Date:   Fri Feb 2 14:55:01 2018 -0500

    Merge branch 'ticket25122_029_02' into ticket24902_029_05

 changes/ticket25122 |   4 ++
 src/or/geoip.c      | 148 ++++++++++++++++++++++++++++++++++++++++++++++++++--
 src/or/geoip.h      |   2 +
 src/or/relay.c      |  16 ++++--
 src/test/test.c     |  18 +++++++
 5 files changed, 180 insertions(+), 8 deletions(-)

diff --cc src/or/geoip.c
index 4e4f6e639,76fca43f6..20dad5f15
--- a/src/or/geoip.c
+++ b/src/or/geoip.c
@@@ -516,9 -574,7 +557,10 @@@ clientmap_entry_free(clientmap_entry_t 
    if (!ent)
      return;
  
 +  /* This entry is about to be freed so pass it to the DoS subsystem to see if
 +   * any actions can be taken about it. */
 +  dos_geoip_entry_about_to_free(ent);
+   geoip_decrement_client_history_cache_size(clientmap_entry_size(ent));
  
    tor_free(ent->transport_name);
    tor_free(ent);
@@@ -573,13 -651,13 +640,9 @@@ geoip_note_client_seen(geoip_client_act
              safe_str_client(fmt_addr((addr))),
              transport_name ? transport_name : "<no transport>");
  
 -  tor_addr_copy(&lookup.addr, addr);
 -  lookup.action = (int)action;
 -  lookup.transport_name = (char*) transport_name;
 -  ent = HT_FIND(clientmap, &client_history, &lookup);
 -
 +  ent = geoip_lookup_client(addr, transport_name, action);
    if (! ent) {
-     ent = tor_malloc_zero(sizeof(clientmap_entry_t));
-     tor_addr_copy(&ent->addr, addr);
-     if (transport_name)
-       ent->transport_name = tor_strdup(transport_name);
-     ent->action = (int)action;
+     ent = clientmap_entry_new(action, addr, transport_name);
      HT_INSERT(clientmap, &client_history, ent);
    }
    if (now / 60 <= (int)MAX_LAST_SEEN_IN_MINUTES && now >= 0)
@@@ -621,25 -699,81 +684,100 @@@ geoip_remove_old_clients(time_t cutoff
                            &cutoff);
  }
  
 +/* Return a client entry object matching the given address, transport name and
 + * geoip action from the clientmap. NULL if not found. The transport_name can
 + * be NULL. */
 +clientmap_entry_t *
 +geoip_lookup_client(const tor_addr_t *addr, const char *transport_name,
 +                    geoip_client_action_t action)
 +{
 +  clientmap_entry_t lookup;
 +
 +  tor_assert(addr);
 +
 +  /* We always look for a client connection with no transport. */
 +  tor_addr_copy(&lookup.addr, addr);
 +  lookup.action = action;
 +  lookup.transport_name = (char *) transport_name;
 +
 +  return HT_FIND(clientmap, &client_history, &lookup);
 +}
 +
+ /* Cleanup client entries older than the cutoff. Used for the OOM. Return the
+  * number of bytes freed. If 0 is returned, nothing was freed. */
+ static size_t
+ oom_clean_client_entries(time_t cutoff)
+ {
+   size_t bytes = 0;
+   clientmap_entry_t **ent, **ent_next;
+ 
+   for (ent = HT_START(clientmap, &client_history); ent; ent = ent_next) {
+     clientmap_entry_t *entry = *ent;
+     if (entry->last_seen_in_minutes < (cutoff / 60)) {
+       ent_next = HT_NEXT_RMV(clientmap, &client_history, ent);
+       bytes += clientmap_entry_size(entry);
+       clientmap_entry_free(entry);
+     } else {
+       ent_next = HT_NEXT(clientmap, &client_history, ent);
+     }
+   }
+   return bytes;
+ }
+ 
+ /* Below this minimum lifetime, the OOM won't cleanup any entries. */
+ #define GEOIP_CLIENT_CACHE_OOM_MIN_CUTOFF (4 * 60 * 60)
+ /* The OOM moves the cutoff by that much every run. */
+ #define GEOIP_CLIENT_CACHE_OOM_STEP (15 * 50)
+ 
+ /* Cleanup the geoip client history cache called from the OOM handler. Return
+  * the amount of bytes removed. This can return a value below or above
+  * min_remove_bytes but will stop as oon as the min_remove_bytes has been
+  * reached. */
+ size_t
+ geoip_client_cache_handle_oom(time_t now, size_t min_remove_bytes)
+ {
+   time_t k;
+   size_t bytes_removed = 0;
+ 
+   /* Our OOM handler called with 0 bytes to remove is a code flow error. */
+   tor_assert(min_remove_bytes != 0);
+ 
+   /* Set k to the initial cutoff of an entry. We then going to move it by step
+    * to try to remove as much as we can. */
+   k = WRITE_STATS_INTERVAL;
+ 
+   do {
+     time_t cutoff;
+ 
+     /* If k has reached the minimum lifetime, we have to stop else we might
+      * remove every single entries which would be pretty bad for the DoS
+      * mitigation subsystem if by just filling the geoip cache, it was enough
+      * to trigger the OOM and clean every single entries. */
+     if (k <= GEOIP_CLIENT_CACHE_OOM_MIN_CUTOFF) {
+       break;
+     }
+ 
+     cutoff = now - k;
+     bytes_removed += oom_clean_client_entries(cutoff);
+     k -= GEOIP_CLIENT_CACHE_OOM_STEP;
+   } while (bytes_removed < min_remove_bytes);
+ 
+   return bytes_removed;
+ }
+ 
+ /* Return the total size in bytes of the client history cache. */
+ size_t
+ geoip_client_cache_total_allocation(void)
+ {
+   size_t bytes = 0;
+   clientmap_entry_t **ent;
+ 
+   HT_FOREACH(ent, clientmap, &client_history) {
+     bytes += clientmap_entry_size(*ent);
+   }
+   return bytes;
+ }
+ 
  /** How many responses are we giving to clients requesting v3 network
   * statuses? */
  static uint32_t ns_v3_responses[GEOIP_NS_RESPONSE_NUM];
diff --cc src/or/geoip.h
index aa0fca50f,42d0c1cfd..c8ea9f85e
--- a/src/or/geoip.h
+++ b/src/or/geoip.h
@@@ -57,9 -33,8 +57,11 @@@ void geoip_note_client_seen(geoip_clien
                              const tor_addr_t *addr, const char *transport_name,
                              time_t now);
  void geoip_remove_old_clients(time_t cutoff);
 +clientmap_entry_t *geoip_lookup_client(const tor_addr_t *addr,
 +                                       const char *transport_name,
 +                                       geoip_client_action_t action);
+ size_t geoip_client_cache_total_allocation(void);
+ size_t geoip_client_cache_handle_oom(time_t now, size_t min_remove_bytes);
  
  void geoip_note_ns_response(geoip_ns_response_t response);
  char *geoip_get_transport_history(void);





More information about the tor-commits mailing list