From 4ab1d1c0c44a887417b04fc75b1b11bf246f2bb5 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Sat, 15 Jun 2019 16:47:16 -0400 Subject: Fix memleak when failing to parse a CSV_INTERVAL. Fixes bug 30894; bugfix on 0.3.4.1-alpha --- changes/bug30894 | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 changes/bug30894 (limited to 'changes') diff --git a/changes/bug30894 b/changes/bug30894 new file mode 100644 index 0000000000..64c14c4e6d --- /dev/null +++ b/changes/bug30894 @@ -0,0 +1,4 @@ + o Minor bugfixes (memory leaks): + - Fix a trivial memory leak when parsing an invalid value + from a download schedule in the configuration. Fixes bug + 30894; bugfix on 0.3.4.1-alpha. -- cgit v1.2.3-54-g00ecf From e3f3478032921a8b6af07a655fd2ea520d3ff463 Mon Sep 17 00:00:00 2001 From: David Goulet Date: Tue, 18 Jun 2019 13:32:45 -0400 Subject: guard: Ignore marked for close circuit when changing state to open When we consider all circuits in "waiting for guard" state to be promoted to an "open" state, we were considering all circuits, even the one marked for close. This ultiamtely triggers a "circuit_has_opened()" called on the circuit that is marked for close which then leads to possible undesirable behaviors within a subsystem. For instance, the HS subsystem would be unable to find the authentication key of the introduction point circuit leading to a BUG() warning and a duplicate mark for close on the circuit. This commit also adds a unit test to make sure we never select marked for close circuits when upgrading its guard state from waiting for guard to open. Fixes #30871 Signed-off-by: David Goulet --- changes/ticket30871 | 6 ++++++ src/feature/client/entrynodes.c | 4 ++++ src/test/test_circuitbuild.c | 47 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 57 insertions(+) create mode 100644 changes/ticket30871 (limited to 'changes') diff --git a/changes/ticket30871 b/changes/ticket30871 new file mode 100644 index 0000000000..81c076bb02 --- /dev/null +++ b/changes/ticket30871 @@ -0,0 +1,6 @@ + o Major bugfixes (circuit build, guard): + - When considering upgrading circuits from "waiting for guard" to "open", + always ignore the ones that are mark for close. Else, we can end up in + the situation where a subsystem is notified of that circuit opening but + still marked for close leading to undesirable behavior. Fixes bug 30871; + bugfix on 0.3.0.1-alpha. diff --git a/src/feature/client/entrynodes.c b/src/feature/client/entrynodes.c index e543289ce0..d191f58367 100644 --- a/src/feature/client/entrynodes.c +++ b/src/feature/client/entrynodes.c @@ -2611,6 +2611,10 @@ entry_guards_upgrade_waiting_circuits(guard_selection_t *gs, entry_guard_t *guard = entry_guard_handle_get(state->guard); if (!guard || guard->in_selection != gs) continue; + if (TO_CIRCUIT(circ)->marked_for_close) { + /* Don't consider any marked for close circuits. */ + continue; + } smartlist_add(all_circuits, circ); } SMARTLIST_FOREACH_END(circ); diff --git a/src/test/test_circuitbuild.c b/src/test/test_circuitbuild.c index 275f1eced2..538f20781f 100644 --- a/src/test/test_circuitbuild.c +++ b/src/test/test_circuitbuild.c @@ -4,6 +4,8 @@ /* See LICENSE for licensing information */ #define CIRCUITBUILD_PRIVATE +#define CIRCUITLIST_PRIVATE +#define ENTRYNODES_PRIVATE #include "core/or/or.h" #include "test/test.h" @@ -13,7 +15,11 @@ #include "core/or/circuitbuild.h" #include "core/or/circuitlist.h" +#include "core/or/cpath_build_state_st.h" #include "core/or/extend_info_st.h" +#include "core/or/origin_circuit_st.h" + +#include "feature/client/entrynodes.h" /* Dummy nodes smartlist for testing */ static smartlist_t dummy_nodes; @@ -126,10 +132,51 @@ test_new_route_len_unhandled_exit(void *arg) UNMOCK(count_acceptable_nodes); } +static void +test_upgrade_from_guard_wait(void *arg) +{ + circuit_t *circ = NULL; + origin_circuit_t *orig_circ = NULL; + entry_guard_t *guard = NULL; + smartlist_t *list = NULL; + + (void) arg; + + circ = dummy_origin_circuit_new(0); + orig_circ = TO_ORIGIN_CIRCUIT(circ); + tt_assert(orig_circ); + + orig_circ->build_state = tor_malloc_zero(sizeof(cpath_build_state_t)); + + circuit_set_state(circ, CIRCUIT_STATE_GUARD_WAIT); + + /* Put it in guard wait state. */ + guard = tor_malloc_zero(sizeof(*guard)); + guard->in_selection = get_guard_selection_info(); + + orig_circ->guard_state = + circuit_guard_state_new(guard, GUARD_CIRC_STATE_WAITING_FOR_BETTER_GUARD, + NULL); + + /* Mark the circuit for close. */ + circuit_mark_for_close(circ, END_CIRC_REASON_TORPROTOCOL); + tt_int_op(circ->marked_for_close, OP_NE, 0); + + /* We shouldn't pick the mark for close circuit. */ + list = circuit_find_circuits_to_upgrade_from_guard_wait(); + tt_assert(!list); + + done: + circuit_free(circ); + entry_guard_free_(guard); +} + struct testcase_t circuitbuild_tests[] = { { "noexit", test_new_route_len_noexit, 0, NULL, NULL }, { "safe_exit", test_new_route_len_safe_exit, 0, NULL, NULL }, { "unsafe_exit", test_new_route_len_unsafe_exit, 0, NULL, NULL }, { "unhandled_exit", test_new_route_len_unhandled_exit, 0, NULL, NULL }, + { "upgrade_from_guard_wait", test_upgrade_from_guard_wait, TT_FORK, + NULL, NULL }, END_OF_TESTCASES }; -- cgit v1.2.3-54-g00ecf From a9379d6750d025d8bfe54a79c26e89eb45393f3a Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Fri, 19 Jul 2019 09:49:52 -0400 Subject: Set 'routerlist' global to NULL before freeing it. There is other code that uses this value, and some of it is apparently reachable from inside router_dir_info_changed(), which routerlist_free() apparently calls. (ouch!) This is a minimal fix to try to resolve the issue without causing other problems. Fixes bug 31003. I'm calling this a bugfix on 0.1.2.2-alpha, where the call to router_dir_info_changed() was added to routerlist_free(). --- changes/bug31003 | 4 ++++ src/feature/nodelist/routerlist.c | 12 ++++++------ 2 files changed, 10 insertions(+), 6 deletions(-) create mode 100644 changes/bug31003 (limited to 'changes') diff --git a/changes/bug31003 b/changes/bug31003 new file mode 100644 index 0000000000..6c75163380 --- /dev/null +++ b/changes/bug31003 @@ -0,0 +1,4 @@ + o Minor bugfixes (crash on exit): + - Avoid a set of possible code paths that could use try to use freed memory + in routerlist_free() while Tor was exiting. Fixes bug 31003; bugfix on + 0.1.2.2-alpha. diff --git a/src/feature/nodelist/routerlist.c b/src/feature/nodelist/routerlist.c index 4a99427cd6..61af09742d 100644 --- a/src/feature/nodelist/routerlist.c +++ b/src/feature/nodelist/routerlist.c @@ -954,20 +954,18 @@ routerlist_free_(routerlist_t *rl) smartlist_free(rl->routers); smartlist_free(rl->old_routers); if (rl->desc_store.mmap) { - int res = tor_munmap_file(routerlist->desc_store.mmap); + int res = tor_munmap_file(rl->desc_store.mmap); if (res != 0) { log_warn(LD_FS, "Failed to munmap routerlist->desc_store.mmap"); } } if (rl->extrainfo_store.mmap) { - int res = tor_munmap_file(routerlist->extrainfo_store.mmap); + int res = tor_munmap_file(rl->extrainfo_store.mmap); if (res != 0) { log_warn(LD_FS, "Failed to munmap routerlist->extrainfo_store.mmap"); } } tor_free(rl); - - router_dir_info_changed(); } /** Log information about how much memory is being used for routerlist, @@ -1426,8 +1424,10 @@ routerlist_reparse_old(routerlist_t *rl, signed_descriptor_t *sd) void routerlist_free_all(void) { - routerlist_free(routerlist); - routerlist = NULL; + routerlist_t *rl = routerlist; + routerlist = NULL; // Prevent internals of routerlist_free() from using + // routerlist. + routerlist_free(rl); dirlist_free_all(); if (warned_nicknames) { SMARTLIST_FOREACH(warned_nicknames, char *, cp, tor_free(cp)); -- cgit v1.2.3-54-g00ecf