circ: Don't cannibalize a circuit if the guard state is unusable

Tor preemptiely builds circuits and they can be cannibalized later in their
lifetime. A Guard node can become unusable (from our guard state) but we can
still have circuits using that node opened. It is important to not pick those
circuits for any usage through the cannibalization process.

Fixes #24469

Signed-off-by: David Goulet <dgoulet@torproject.org>
This commit is contained in:
David Goulet 2018-01-31 15:23:45 -05:00
parent a846fd267e
commit fb93c6fc51
4 changed files with 29 additions and 0 deletions

4
changes/bug24469 Normal file
View File

@ -0,0 +1,4 @@
o Minor bugfixes (circuit, cannibalization):
- Don't cannibalize circuits for which we don't know the first hop which
can happen if our Guard relay went off the consensus after the circuit
was created preemptively. Fixes bug 24469; bugfix on 0.0.6.

View File

@ -1803,6 +1803,13 @@ circuit_find_to_cannibalize(uint8_t purpose_to_produce, extend_info_t *info,
goto next; goto next;
} }
/* Ignore any circuits for which we can't use the Guard. It is possible
* that the Guard was removed from the samepled set after the circuit
* was created so avoid using it. */
if (!entry_guard_could_succeed(circ->guard_state)) {
goto next;
}
if ((!need_uptime || circ->build_state->need_uptime) && if ((!need_uptime || circ->build_state->need_uptime) &&
(!need_capacity || circ->build_state->need_capacity) && (!need_capacity || circ->build_state->need_capacity) &&
(internal == circ->build_state->is_internal) && (internal == circ->build_state->is_internal) &&

View File

@ -3307,6 +3307,22 @@ entry_guards_update_state(or_state_t *state)
entry_guards_dirty = 0; entry_guards_dirty = 0;
} }
/** Return true iff the circuit's guard can succeed that is can be used. */
int
entry_guard_could_succeed(const circuit_guard_state_t *guard_state)
{
if (!guard_state) {
return 0;
}
entry_guard_t *guard = entry_guard_handle_get(guard_state->guard);
if (!guard || BUG(guard->in_selection == NULL)) {
return 0;
}
return 1;
}
/** /**
* Format a single entry guard in the format expected by the controller. * Format a single entry guard in the format expected by the controller.
* Return a newly allocated string. * Return a newly allocated string.

View File

@ -386,6 +386,8 @@ void entry_guards_note_internet_connectivity(guard_selection_t *gs);
int update_guard_selection_choice(const or_options_t *options); int update_guard_selection_choice(const or_options_t *options);
int entry_guard_could_succeed(const circuit_guard_state_t *guard_state);
MOCK_DECL(int,num_bridges_usable,(int use_maybe_reachable)); MOCK_DECL(int,num_bridges_usable,(int use_maybe_reachable));
#ifdef ENTRYNODES_PRIVATE #ifdef ENTRYNODES_PRIVATE