Browse Source

Merge branch 'circuit_queue_cap-0.2.4-squashed' into maint-0.2.4

Nick Mathewson 11 years ago
parent
commit
8b6d0bd99c
3 changed files with 39 additions and 1 deletions
  1. 3 0
      changes/bug9063
  2. 9 0
      src/or/or.h
  3. 27 1
      src/or/relay.c

+ 3 - 0
changes/bug9063

@@ -0,0 +1,3 @@
+  o Normal bugfixes:
+    - Close any circuit that has more cells queued than the spec permits.
+      Fixes bug #9063; bugfix on 0.2.4.12.

+ 9 - 0
src/or/or.h

@@ -541,6 +541,8 @@ typedef enum {
 #define CIRCUIT_PURPOSE_IS_ESTABLISHED_REND(p) \
   ((p) == CIRCUIT_PURPOSE_C_REND_JOINED ||     \
    (p) == CIRCUIT_PURPOSE_S_REND_JOINED)
+/** True iff the circuit_t c is actually an or_circuit_t */
+#define CIRCUIT_IS_ORCIRC(c) (((circuit_t *)(c))->magic == OR_CIRCUIT_MAGIC)
 
 /** How many circuits do we want simultaneously in-progress to handle
  * a given stream? */
@@ -818,6 +820,13 @@ typedef enum {
 /** Amount to increment a stream window when we get a stream SENDME. */
 #define STREAMWINDOW_INCREMENT 50
 
+/** Maximum number of queued cells on a circuit for which we are the
+ * midpoint before we give up and kill it.  This must be >= circwindow
+ * to avoid killing innocent circuits, and >= circwindow*2 to give
+ * leaky-pipe a chance for being useful someday.
+ */
+#define ORCIRC_MAX_MIDDLE_CELLS (21*(CIRCWINDOW_START_MAX)/10)
+
 /* Cell commands.  These values are defined in tor-spec.txt. */
 #define CELL_PADDING 0
 #define CELL_CREATE 1

+ 27 - 1
src/or/relay.c

@@ -2466,8 +2466,10 @@ append_cell_to_circuit_queue(circuit_t *circ, channel_t *chan,
                              cell_t *cell, cell_direction_t direction,
                              streamid_t fromstream)
 {
+  or_circuit_t *orcirc = NULL;
   cell_queue_t *queue;
   int streams_blocked;
+
   if (circ->marked_for_close)
     return;
 
@@ -2475,11 +2477,35 @@ append_cell_to_circuit_queue(circuit_t *circ, channel_t *chan,
     queue = &circ->n_chan_cells;
     streams_blocked = circ->streams_blocked_on_n_chan;
   } else {
-    or_circuit_t *orcirc = TO_OR_CIRCUIT(circ);
+    orcirc = TO_OR_CIRCUIT(circ);
     queue = &orcirc->p_chan_cells;
     streams_blocked = circ->streams_blocked_on_p_chan;
   }
 
+  /* Are we a middle circuit about to exceed ORCIRC_MAX_MIDDLE_CELLS? */
+  if ((circ->n_chan != NULL) && CIRCUIT_IS_ORCIRC(circ)) {
+    orcirc = TO_OR_CIRCUIT(circ);
+    if (orcirc->p_chan) {
+      if (queue->n + 1 >= ORCIRC_MAX_MIDDLE_CELLS) {
+        /* Queueing this cell would put queue over the cap */
+        log_warn(LD_CIRC,
+                 "Got a cell exceeding the cap of %u in the %s direction "
+                 "on middle circ ID %u on chan ID " U64_FORMAT
+                 "; killing the circuit.",
+                 ORCIRC_MAX_MIDDLE_CELLS,
+                 (direction == CELL_DIRECTION_OUT) ? "n" : "p",
+                 (direction == CELL_DIRECTION_OUT) ?
+                   circ->n_circ_id : orcirc->p_circ_id,
+                 U64_PRINTF_ARG(
+                   (direction == CELL_DIRECTION_OUT) ?
+                      circ->n_chan->global_identifier :
+                      orcirc->p_chan->global_identifier));
+        circuit_mark_for_close(circ, END_CIRC_REASON_RESOURCELIMIT);
+        return;
+      }
+    }
+  }
+
   cell_queue_append_packed_copy(queue, cell, chan->wide_circ_ids);
 
   /* If we have too many cells on the circuit, we should stop reading from