Commit 418c2845 authored by Andrea Shepard's avatar Andrea Shepard
Browse files

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

parent 72f775e1
Loading
Loading
Loading
Loading

changes/bug9063

0 → 100644
+3 −0
Original line number Diff line number Diff line
  o Normal bugfixes:
    - Close any circuit that has more cells queued than the spec permits.
      Fixes bug #9063; bugfix on 0.2.4.12.
+8 −0
Original line number Diff line number Diff line
@@ -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,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
+27 −1
Original line number Diff line number Diff line
@@ -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