Loading changes/bug21242 0 → 100644 +10 −0 Original line number Diff line number Diff line o Major bugfixes (entry guards): - Stop trying to build circuits through entry guards for which we have no descriptor yet. Also, stop crashing if we *do* accidentally try to build a circuit in such a state. Fixes bug 21242; bugfix on 0.3.0.1-alpha. o Minor features (entry guards): - Do not try to build circuits until we have descriptors for our primary entry guards. Related to fix for bug 21242. src/or/circuitbuild.c +1 −1 Original line number Diff line number Diff line Loading @@ -2369,7 +2369,7 @@ onion_extend_cpath(origin_circuit_t *circ) int client = (server_mode(get_options()) == 0); info = extend_info_from_node(r, client); /* Clients can fail to find an allowed address */ tor_assert(info || client); tor_assert_nonfatal(info || client); } } else { const node_t *r = Loading src/or/entrynodes.c +63 −1 Original line number Diff line number Diff line Loading @@ -185,6 +185,16 @@ should_apply_guardfraction(const networkstatus_t *ns) return options->UseGuardFraction; } /** Return true iff we know a descriptor for <b>guard</b> */ static int guard_has_descriptor(const entry_guard_t *guard) { const node_t *node = node_get_by_id(guard->identity); if (!node) return 0; return node_has_descriptor(node); } /** * Try to determine the correct type for a selection named "name", * if <b>type</b> is GS_TYPE_INFER. Loading Loading @@ -1436,6 +1446,7 @@ sample_reachable_filtered_entry_guards(guard_selection_t *gs, const unsigned exclude_primary = flags & SAMPLE_EXCLUDE_PRIMARY; const unsigned exclude_pending = flags & SAMPLE_EXCLUDE_PENDING; const unsigned no_update_primary = flags & SAMPLE_NO_UPDATE_PRIMARY; const unsigned need_descriptor = flags & SAMPLE_EXCLUDE_NO_DESCRIPTOR; SMARTLIST_FOREACH_BEGIN(gs->sampled_entry_guards, entry_guard_t *, guard) { entry_guard_consider_retry(guard); Loading Loading @@ -1469,6 +1480,8 @@ sample_reachable_filtered_entry_guards(guard_selection_t *gs, continue; if (exclude_pending && guard->is_pending) continue; if (need_descriptor && !guard_has_descriptor(guard)) continue; smartlist_add(reachable_filtered_sample, guard); } SMARTLIST_FOREACH_END(guard); Loading Loading @@ -1766,6 +1779,7 @@ select_entry_guard_for_circuit(guard_selection_t *gs, const entry_guard_restriction_t *rst, unsigned *state_out) { const int need_descriptor = (usage == GUARD_USAGE_TRAFFIC); tor_assert(gs); tor_assert(state_out); Loading @@ -1782,6 +1796,9 @@ select_entry_guard_for_circuit(guard_selection_t *gs, if (! entry_guard_obeys_restriction(guard, rst)) continue; if (guard->is_reachable != GUARD_REACHABLE_NO) { if (need_descriptor && BUG(!guard_has_descriptor(guard))) { continue; } *state_out = GUARD_CIRC_STATE_USABLE_ON_COMPLETION; guard->last_tried_to_connect = approx_time(); smartlist_add(usable_primary_guards, guard); Loading Loading @@ -1810,6 +1827,8 @@ select_entry_guard_for_circuit(guard_selection_t *gs, continue; entry_guard_consider_retry(guard); if (guard->is_usable_filtered_guard && ! guard->is_pending) { if (need_descriptor && !guard_has_descriptor(guard)) continue; /* not a bug */ guard->is_pending = 1; guard->last_tried_to_connect = approx_time(); *state_out = GUARD_CIRC_STATE_USABLE_IF_NO_BETTER_GUARD; Loading @@ -1825,11 +1844,15 @@ select_entry_guard_for_circuit(guard_selection_t *gs, random from {USABLE_FILTERED_GUARDS}." */ { entry_guard_t *guard; unsigned flags = 0; if (need_descriptor) flags |= SAMPLE_EXCLUDE_NO_DESCRIPTOR; guard = sample_reachable_filtered_entry_guards(gs, rst, SAMPLE_EXCLUDE_CONFIRMED | SAMPLE_EXCLUDE_PRIMARY | SAMPLE_EXCLUDE_PENDING); SAMPLE_EXCLUDE_PENDING | flags); if (guard == NULL) { log_info(LD_GUARD, "Absolutely no sampled guards were available."); return NULL; Loading Loading @@ -2057,6 +2080,8 @@ entry_guard_pick_for_circuit(guard_selection_t *gs, // XXXX prop271 check Ed ID. if (! node) goto fail; if (BUG(usage != GUARD_USAGE_DIRGUARD && !node_has_descriptor(node))) goto fail; *chosen_node_out = node; *guard_state_out = tor_malloc_zero(sizeof(circuit_guard_state_t)); Loading Loading @@ -3303,6 +3328,43 @@ guards_retry_optimistic(const or_options_t *options) return 1; } /** * Return true iff we know enough directory information to construct * circuits through all of the primary guards we'd currently use. */ int guard_selection_have_enough_dir_info_to_build_circuits(guard_selection_t *gs) { if (!gs->primary_guards_up_to_date) entry_guards_update_primary(gs); const int num_primary = get_n_primary_guards_to_use(GUARD_USAGE_TRAFFIC); int n_missing_descriptors = 0; int n_considered = 0; SMARTLIST_FOREACH_BEGIN(gs->primary_entry_guards, entry_guard_t *, guard) { entry_guard_consider_retry(guard); if (guard->is_reachable == GUARD_REACHABLE_NO) continue; n_considered++; if (!guard_has_descriptor(guard)) n_missing_descriptors++; if (n_considered >= num_primary) break; } SMARTLIST_FOREACH_END(guard); return n_missing_descriptors == 0; } /** As guard_selection_have_enough_dir_info_to_build_circuits, but uses * the default guard selection. */ int entry_guards_have_enough_dir_info_to_build_circuits(void) { return guard_selection_have_enough_dir_info_to_build_circuits( get_guard_selection_info()); } /** Free one guard selection context */ STATIC void guard_selection_free(guard_selection_t *gs) Loading src/or/entrynodes.h +6 −0 Original line number Diff line number Diff line Loading @@ -482,6 +482,7 @@ STATIC entry_guard_t *get_sampled_guard_with_id(guard_selection_t *gs, const uint8_t *rsa_id); MOCK_DECL(STATIC time_t, randomize_time, (time_t now, time_t max_backdate)); STATIC entry_guard_t *entry_guard_add_to_sample(guard_selection_t *gs, const node_t *node); STATIC entry_guard_t *entry_guards_expand_sample(guard_selection_t *gs); Loading @@ -498,6 +499,7 @@ STATIC int entry_guards_all_primary_guards_are_down(guard_selection_t *gs); #define SAMPLE_EXCLUDE_PRIMARY (1u<<1) #define SAMPLE_EXCLUDE_PENDING (1u<<2) #define SAMPLE_NO_UPDATE_PRIMARY (1u<<3) #define SAMPLE_EXCLUDE_NO_DESCRIPTOR (1u<<4) /**@}*/ STATIC entry_guard_t *sample_reachable_filtered_entry_guards( guard_selection_t *gs, Loading Loading @@ -565,6 +567,10 @@ int getinfo_helper_entry_guards(control_connection_t *conn, int entries_known_but_down(const or_options_t *options); void entries_retry_all(const or_options_t *options); int guard_selection_have_enough_dir_info_to_build_circuits( guard_selection_t *gs); int entry_guards_have_enough_dir_info_to_build_circuits(void); void entry_guards_free_all(void); double pathbias_get_close_success_count(entry_guard_t *guard); Loading src/or/nodelist.c +8 −0 Original line number Diff line number Diff line Loading @@ -43,6 +43,7 @@ #include "config.h" #include "control.h" #include "dirserv.h" #include "entrynodes.h" #include "geoip.h" #include "main.h" #include "microdesc.h" Loading Loading @@ -1991,6 +1992,13 @@ update_router_have_minimum_dir_info(void) using_md = consensus->flavor == FLAV_MICRODESC; if (! entry_guards_have_enough_dir_info_to_build_circuits()) { strlcpy(dir_info_status, "We're missing descriptors for some of our " "primary entry guards", sizeof(dir_info_status)); res = 0; goto done; } /* Check fraction of available paths */ { char *status = NULL; Loading Loading
changes/bug21242 0 → 100644 +10 −0 Original line number Diff line number Diff line o Major bugfixes (entry guards): - Stop trying to build circuits through entry guards for which we have no descriptor yet. Also, stop crashing if we *do* accidentally try to build a circuit in such a state. Fixes bug 21242; bugfix on 0.3.0.1-alpha. o Minor features (entry guards): - Do not try to build circuits until we have descriptors for our primary entry guards. Related to fix for bug 21242.
src/or/circuitbuild.c +1 −1 Original line number Diff line number Diff line Loading @@ -2369,7 +2369,7 @@ onion_extend_cpath(origin_circuit_t *circ) int client = (server_mode(get_options()) == 0); info = extend_info_from_node(r, client); /* Clients can fail to find an allowed address */ tor_assert(info || client); tor_assert_nonfatal(info || client); } } else { const node_t *r = Loading
src/or/entrynodes.c +63 −1 Original line number Diff line number Diff line Loading @@ -185,6 +185,16 @@ should_apply_guardfraction(const networkstatus_t *ns) return options->UseGuardFraction; } /** Return true iff we know a descriptor for <b>guard</b> */ static int guard_has_descriptor(const entry_guard_t *guard) { const node_t *node = node_get_by_id(guard->identity); if (!node) return 0; return node_has_descriptor(node); } /** * Try to determine the correct type for a selection named "name", * if <b>type</b> is GS_TYPE_INFER. Loading Loading @@ -1436,6 +1446,7 @@ sample_reachable_filtered_entry_guards(guard_selection_t *gs, const unsigned exclude_primary = flags & SAMPLE_EXCLUDE_PRIMARY; const unsigned exclude_pending = flags & SAMPLE_EXCLUDE_PENDING; const unsigned no_update_primary = flags & SAMPLE_NO_UPDATE_PRIMARY; const unsigned need_descriptor = flags & SAMPLE_EXCLUDE_NO_DESCRIPTOR; SMARTLIST_FOREACH_BEGIN(gs->sampled_entry_guards, entry_guard_t *, guard) { entry_guard_consider_retry(guard); Loading Loading @@ -1469,6 +1480,8 @@ sample_reachable_filtered_entry_guards(guard_selection_t *gs, continue; if (exclude_pending && guard->is_pending) continue; if (need_descriptor && !guard_has_descriptor(guard)) continue; smartlist_add(reachable_filtered_sample, guard); } SMARTLIST_FOREACH_END(guard); Loading Loading @@ -1766,6 +1779,7 @@ select_entry_guard_for_circuit(guard_selection_t *gs, const entry_guard_restriction_t *rst, unsigned *state_out) { const int need_descriptor = (usage == GUARD_USAGE_TRAFFIC); tor_assert(gs); tor_assert(state_out); Loading @@ -1782,6 +1796,9 @@ select_entry_guard_for_circuit(guard_selection_t *gs, if (! entry_guard_obeys_restriction(guard, rst)) continue; if (guard->is_reachable != GUARD_REACHABLE_NO) { if (need_descriptor && BUG(!guard_has_descriptor(guard))) { continue; } *state_out = GUARD_CIRC_STATE_USABLE_ON_COMPLETION; guard->last_tried_to_connect = approx_time(); smartlist_add(usable_primary_guards, guard); Loading Loading @@ -1810,6 +1827,8 @@ select_entry_guard_for_circuit(guard_selection_t *gs, continue; entry_guard_consider_retry(guard); if (guard->is_usable_filtered_guard && ! guard->is_pending) { if (need_descriptor && !guard_has_descriptor(guard)) continue; /* not a bug */ guard->is_pending = 1; guard->last_tried_to_connect = approx_time(); *state_out = GUARD_CIRC_STATE_USABLE_IF_NO_BETTER_GUARD; Loading @@ -1825,11 +1844,15 @@ select_entry_guard_for_circuit(guard_selection_t *gs, random from {USABLE_FILTERED_GUARDS}." */ { entry_guard_t *guard; unsigned flags = 0; if (need_descriptor) flags |= SAMPLE_EXCLUDE_NO_DESCRIPTOR; guard = sample_reachable_filtered_entry_guards(gs, rst, SAMPLE_EXCLUDE_CONFIRMED | SAMPLE_EXCLUDE_PRIMARY | SAMPLE_EXCLUDE_PENDING); SAMPLE_EXCLUDE_PENDING | flags); if (guard == NULL) { log_info(LD_GUARD, "Absolutely no sampled guards were available."); return NULL; Loading Loading @@ -2057,6 +2080,8 @@ entry_guard_pick_for_circuit(guard_selection_t *gs, // XXXX prop271 check Ed ID. if (! node) goto fail; if (BUG(usage != GUARD_USAGE_DIRGUARD && !node_has_descriptor(node))) goto fail; *chosen_node_out = node; *guard_state_out = tor_malloc_zero(sizeof(circuit_guard_state_t)); Loading Loading @@ -3303,6 +3328,43 @@ guards_retry_optimistic(const or_options_t *options) return 1; } /** * Return true iff we know enough directory information to construct * circuits through all of the primary guards we'd currently use. */ int guard_selection_have_enough_dir_info_to_build_circuits(guard_selection_t *gs) { if (!gs->primary_guards_up_to_date) entry_guards_update_primary(gs); const int num_primary = get_n_primary_guards_to_use(GUARD_USAGE_TRAFFIC); int n_missing_descriptors = 0; int n_considered = 0; SMARTLIST_FOREACH_BEGIN(gs->primary_entry_guards, entry_guard_t *, guard) { entry_guard_consider_retry(guard); if (guard->is_reachable == GUARD_REACHABLE_NO) continue; n_considered++; if (!guard_has_descriptor(guard)) n_missing_descriptors++; if (n_considered >= num_primary) break; } SMARTLIST_FOREACH_END(guard); return n_missing_descriptors == 0; } /** As guard_selection_have_enough_dir_info_to_build_circuits, but uses * the default guard selection. */ int entry_guards_have_enough_dir_info_to_build_circuits(void) { return guard_selection_have_enough_dir_info_to_build_circuits( get_guard_selection_info()); } /** Free one guard selection context */ STATIC void guard_selection_free(guard_selection_t *gs) Loading
src/or/entrynodes.h +6 −0 Original line number Diff line number Diff line Loading @@ -482,6 +482,7 @@ STATIC entry_guard_t *get_sampled_guard_with_id(guard_selection_t *gs, const uint8_t *rsa_id); MOCK_DECL(STATIC time_t, randomize_time, (time_t now, time_t max_backdate)); STATIC entry_guard_t *entry_guard_add_to_sample(guard_selection_t *gs, const node_t *node); STATIC entry_guard_t *entry_guards_expand_sample(guard_selection_t *gs); Loading @@ -498,6 +499,7 @@ STATIC int entry_guards_all_primary_guards_are_down(guard_selection_t *gs); #define SAMPLE_EXCLUDE_PRIMARY (1u<<1) #define SAMPLE_EXCLUDE_PENDING (1u<<2) #define SAMPLE_NO_UPDATE_PRIMARY (1u<<3) #define SAMPLE_EXCLUDE_NO_DESCRIPTOR (1u<<4) /**@}*/ STATIC entry_guard_t *sample_reachable_filtered_entry_guards( guard_selection_t *gs, Loading Loading @@ -565,6 +567,10 @@ int getinfo_helper_entry_guards(control_connection_t *conn, int entries_known_but_down(const or_options_t *options); void entries_retry_all(const or_options_t *options); int guard_selection_have_enough_dir_info_to_build_circuits( guard_selection_t *gs); int entry_guards_have_enough_dir_info_to_build_circuits(void); void entry_guards_free_all(void); double pathbias_get_close_success_count(entry_guard_t *guard); Loading
src/or/nodelist.c +8 −0 Original line number Diff line number Diff line Loading @@ -43,6 +43,7 @@ #include "config.h" #include "control.h" #include "dirserv.h" #include "entrynodes.h" #include "geoip.h" #include "main.h" #include "microdesc.h" Loading Loading @@ -1991,6 +1992,13 @@ update_router_have_minimum_dir_info(void) using_md = consensus->flavor == FLAV_MICRODESC; if (! entry_guards_have_enough_dir_info_to_build_circuits()) { strlcpy(dir_info_status, "We're missing descriptors for some of our " "primary entry guards", sizeof(dir_info_status)); res = 0; goto done; } /* Check fraction of available paths */ { char *status = NULL; Loading