]> git.ipfire.org Git - thirdparty/tor.git/commitdiff
Monotonize the OOM-killer data timers
authorNick Mathewson <nickm@torproject.org>
Wed, 26 Feb 2014 14:51:30 +0000 (09:51 -0500)
committerNick Mathewson <nickm@torproject.org>
Wed, 26 Feb 2014 14:51:30 +0000 (09:51 -0500)
In a couple of places, to implement the OOM-circuit-killer defense
against sniper attacks, we have counters to remember the age of
cells or data chunks.  These timers were based on wall clock time,
which can move backwards, thus giving roll-over results for our age
calculation.  This commit creates a low-budget monotonic time, based
on ratcheting gettimeofday(), so that even in the event of a time
rollback, we don't do anything _really_ stupid.

A future version of Tor should update this function to do something
even less stupid here, like employ clock_gettime() or its kin.

src/common/compat_libevent.c
src/common/compat_libevent.h
src/or/buffers.c
src/or/circuitlist.c
src/or/relay.c

index 6655ca87d3c3b1449b7c0cf3e153b213cf14ecfb..77f8495e5c81e3bd7dea8a6fb25558febca96910 100644 (file)
@@ -724,3 +724,33 @@ tor_gettimeofday_cache_clear(void)
 }
 #endif
 
+/**
+ * As tor_gettimeofday_cached, but can never move backwards in time.
+ *
+ * The returned value may diverge from wall-clock time, since wall-clock time
+ * can trivially be adjusted backwards, and this can't.  Don't mix wall-clock
+ * time with these values in the same calculation.
+ *
+ * Depending on implementation, this function may or may not "smooth out" huge
+ * jumps forward in wall-clock time.  It may or may not keep its results
+ * advancing forward (as opposed to stalling) if the wall-clock time goes
+ * backwards.  The current implementation does neither of of these.
+ *
+ * This function is not thread-safe; do not call it outside the main thread.
+ *
+ * In future versions of Tor, this may return a time does not have its
+ * origin at the Unix epoch.
+ */
+void
+tor_gettimeofday_cached_monotonic(struct timeval *tv)
+{
+  struct timeval last_tv = { 0, 0 };
+
+  tor_gettimeofday_cached(tv);
+  if (timercmp(tv, &last_tv, <)) {
+    memcpy(tv, &last_tv, sizeof(struct timeval));
+  } else {
+    memcpy(&last_tv, tv, sizeof(struct timeval));
+  }
+}
+
index 56285ef80df9ea6bc824ff7148e147bdd5384bca..3190f13005691acff266316076b20a9da4532fac 100644 (file)
@@ -90,6 +90,7 @@ int tor_add_bufferevent_to_rate_limit_group(struct bufferevent *bev,
 
 void tor_gettimeofday_cached(struct timeval *tv);
 void tor_gettimeofday_cache_clear(void);
+void tor_gettimeofday_cached_monotonic(struct timeval *tv);
 
 #endif
 
index 352e60a9796a93a90f439b2009111de48abbc6a7..b16ee6efa736e8bc95dcc9688535ee06f09f4a50 100644 (file)
@@ -632,7 +632,7 @@ buf_add_chunk_with_capacity(buf_t *buf, size_t capacity, int capped)
     chunk = chunk_new_with_alloc_size(preferred_chunk_size(capacity));
   }
 
-  tor_gettimeofday_cached(&now);
+  tor_gettimeofday_cached_monotonic(&now);
   chunk->inserted_time = (uint32_t)tv_to_msec(&now);
 
   if (buf->tail) {
index 45fc95b5613779c9d03bf720a7ecf035aae6f54a..0534e35553894d030ecc014bb199aecc30c100db 100644 (file)
@@ -1551,7 +1551,7 @@ circuits_handle_oom(size_t current_allocation)
     mem_to_recover = current_allocation - mem_target;
   }
 
-  tor_gettimeofday_cached(&now);
+  tor_gettimeofday_cached_monotonic(&now);
   now_ms = (uint32_t)tv_to_msec(&now);
 
   /* This algorithm itself assumes that you've got enough memory slack
index e6d0f50aca0b8419c42be489988cae8375360e1d..4cbc8fa4710ae446e1111dd9cd3ada76286e6875 100644 (file)
@@ -1906,7 +1906,7 @@ cell_queue_append_packed_copy(cell_queue_t *queue, const cell_t *cell)
 {
   struct timeval now;
   packed_cell_t *copy = packed_cell_copy(cell);
-  tor_gettimeofday_cached(&now);
+  tor_gettimeofday_cached_monotonic(&now);
   copy->inserted_time = (uint32_t)tv_to_msec(&now);
 
   /* Remember the time when this cell was put in the queue. */