commit 4cce58d3c22c65350fffb3c4bc4dccd73e0193d7 Author: Andrea Shepard andrea@torproject.org Date: Thu Jun 13 20:41:00 2013 -0700
Don't queue more cells as a middle relay than the spec allows to be in flight --- changes/bug9063 | 3 +++ src/or/or.h | 8 ++++++++ src/or/relay.c | 23 ++++++++++++++++++++++- 3 files changed, 33 insertions(+), 1 deletion(-)
diff --git a/changes/bug9063 b/changes/bug9063 new file mode 100644 index 0000000..af3b1a8 --- /dev/null +++ b/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.3.25. diff --git a/src/or/or.h b/src/or/or.h index 6728b86..2565777 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -539,6 +539,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? */ @@ -814,6 +816,12 @@ 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. + */ +#define ORCIRC_MAX_MIDDLE_CELLS (11*(CIRCWINDOW_START_MAX)/10) + /* Cell commands. These values are defined in tor-spec.txt. */ #define CELL_PADDING 0 #define CELL_CREATE 1 diff --git a/src/or/relay.c b/src/or/relay.c index a17c333..087459c 100644 --- a/src/or/relay.c +++ b/src/or/relay.c @@ -2532,8 +2532,10 @@ append_cell_to_circuit_queue(circuit_t *circ, or_connection_t *orconn, 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;
@@ -2541,11 +2543,30 @@ append_cell_to_circuit_queue(circuit_t *circ, or_connection_t *orconn, queue = &circ->n_conn_cells; streams_blocked = circ->streams_blocked_on_n_conn; } else { - or_circuit_t *orcirc = TO_OR_CIRCUIT(circ); + orcirc = TO_OR_CIRCUIT(circ); queue = &orcirc->p_conn_cells; streams_blocked = circ->streams_blocked_on_p_conn; }
+ /* Are we a middle circuit about to exceed ORCIRC_MAX_MIDDLE_CELLS? */ + if ((circ->n_conn != NULL) && CIRCUIT_IS_ORCIRC(circ)) { + orcirc = TO_OR_CIRCUIT(circ); + if (orcirc->p_conn) { + 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; 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); + circuit_mark_for_close(circ, END_CIRC_REASON_RESOURCELIMIT); + return; + } + } + } + cell_queue_append_packed_copy(queue, cell);
/* If we have too many cells on the circuit, we should stop reading from