Commit 50367d06 authored by Nick Mathewson's avatar Nick Mathewson 🐚
Browse files

Merge remote-tracking branch 'tor-github/pr/352'

parents 52191064 8a83c4b6
Loading
Loading
Loading
Loading

changes/bug23512

0 → 100644
+6 −0
Original line number Diff line number Diff line
  o Major bugfix (Relay bandwidth statistics):
    - When we close relayed circuits, report the data in the circuit queues
      as being written in our relay bandwidth stats. This mitigates guard
      discovery and other attacks that close circuits for the explicit purpose
      of noticing this discrepancy in statistics. Fixes bug 23512; bugfix
      on 0.0.8pre3.
+2 −0
Original line number Diff line number Diff line
@@ -15,6 +15,8 @@
struct ed25519_public_key_t;
struct curve25519_public_key_t;

#define TLS_PER_CELL_OVERHEAD 29

#define BASE_CHAN_TO_TLS(c) (channel_tls_from_base((c)))
#define TLS_CHAN_TO_BASE(c) (channel_tls_to_base((c)))

+59 −0
Original line number Diff line number Diff line
@@ -55,6 +55,7 @@

#include "core/or/or.h"
#include "core/or/channel.h"
#include "core/or/channeltls.h"
#include "feature/client/circpathbias.h"
#include "core/or/circuitbuild.h"
#include "core/or/circuitlist.h"
@@ -2032,6 +2033,61 @@ circuit_mark_all_dirty_circs_as_unusable(void)
  SMARTLIST_FOREACH_END(circ);
}

/**
 * Report any queued cells on or_circuits as written in our bandwidth
 * totals, for the specified channel direction.
 *
 * When we close a circuit or clear its cell queues, we've read
 * data and recorded those bytes in our read statistics, but we're
 * not going to write it. This discrepancy can be used by an adversary
 * to infer information from our public relay statistics and perform
 * attacks such as guard discovery.
 *
 * This function is in the critical path of circuit_mark_for_close().
 * It must be (and is) O(1)!
 *
 * See https://trac.torproject.org/projects/tor/ticket/23512.
 */
void
circuit_synchronize_written_or_bandwidth(const circuit_t *c,
                                         circuit_channel_direction_t dir)
{
  uint64_t cells;
  uint64_t cell_size;
  uint64_t written_sync;
  const channel_t *chan = NULL;
  const or_circuit_t *or_circ;

  if (!CIRCUIT_IS_ORCIRC(c))
    return;

  or_circ = CONST_TO_OR_CIRCUIT(c);

  if (dir == CIRCUIT_N_CHAN) {
    chan = c->n_chan;
    cells = c->n_chan_cells.n;
  } else {
    chan = or_circ->p_chan;
    cells = or_circ->p_chan_cells.n;
  }

  /* If we still know the chan, determine real cell size. Otherwise,
   * assume it's a wide circid channel */
  if (chan)
    cell_size = get_cell_network_size(chan->wide_circ_ids);
  else
    cell_size = CELL_MAX_NETWORK_SIZE;

  /* The missing written bytes are the cell counts times their cell
   * size plus TLS per cell overhead */
  written_sync = cells*(cell_size+TLS_PER_CELL_OVERHEAD);

  /* Report the missing bytes as written, to avoid asymmetry.
   * We must use time() for consistency with rephist, even though on
   * some very old rare platforms, approx_time() may be faster. */
  rep_hist_note_bytes_written(written_sync, time(NULL));
}

/** Mark <b>circ</b> to be closed next time we call
 * circuit_close_all_marked(). Do any cleanup needed:
 *   - If state is onionskin_pending, remove circ from the onion_pending
@@ -2083,6 +2139,9 @@ circuit_mark_for_close_, (circuit_t *circ, int reason, int line,
    reason = END_CIRC_REASON_NONE;
  }

  circuit_synchronize_written_or_bandwidth(circ, CIRCUIT_N_CHAN);
  circuit_synchronize_written_or_bandwidth(circ, CIRCUIT_P_CHAN);

  if (reason & END_CIRC_REASON_FLAG_REMOTE)
    reason &= ~END_CIRC_REASON_FLAG_REMOTE;

+2 −0
Original line number Diff line number Diff line
@@ -209,6 +209,8 @@ origin_circuit_t *circuit_find_to_cannibalize(uint8_t purpose,
                                              extend_info_t *info, int flags);
void circuit_mark_all_unused_circs(void);
void circuit_mark_all_dirty_circs_as_unusable(void);
void circuit_synchronize_written_or_bandwidth(const circuit_t *c,
                                              circuit_channel_direction_t dir);
MOCK_DECL(void, circuit_mark_for_close_, (circuit_t *circ, int reason,
                                          int line, const char *file));
int circuit_get_cpath_len(origin_circuit_t *circ);
+12 −0
Original line number Diff line number Diff line
@@ -477,6 +477,18 @@ typedef enum {
  CELL_DIRECTION_OUT=2, /**< The cell is moving away from the origin. */
} cell_direction_t;

/**
 * An enum to allow us to specify which channel in a circuit
 * we're interested in.
 *
 * This is needed because our data structures and other fields
 * for channel delivery are disassociated from the channel.
 */
typedef enum {
  CIRCUIT_N_CHAN = 0,
  CIRCUIT_P_CHAN = 1
} circuit_channel_direction_t;

/** Initial value for both sides of a circuit transmission window when the
 * circuit is initialized.  Measured in cells. */
#define CIRCWINDOW_START 1000
Loading