Don't queue more cells as a middle relay than the spec allows to be in flight

This commit is contained in:
Andrea Shepard 2013-06-13 20:41:00 -07:00
parent 4835faebf5
commit 4cce58d3c2
3 changed files with 33 additions and 1 deletions

3
changes/bug9063 Normal file
View File

@ -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.

View File

@ -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

View File

@ -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