tor

The Tor anonymity network
git clone https://git.dasho.dev/tor.git
Log | Files | Refs | README | LICENSE

commit adcb094cb639ab8a3a36f3dc0bf1bb4e7fcdbd2b
parent 065ebd10c2baee20f2963ac7116701d9593027a8
Author: David Goulet <dgoulet@torproject.org>
Date:   Wed,  6 Oct 2021 15:45:13 -0400

Merge branch 'tor-gitlab/mr/392' into maint-0.4.5

Diffstat:
Achanges/bug40375 | 5+++++
Msrc/feature/control/control_getinfo.c | 32+++++++++++++++-----------------
Msrc/feature/dirclient/dirclient.c | 21+++++++++++++--------
3 files changed, 33 insertions(+), 25 deletions(-)

diff --git a/changes/bug40375 b/changes/bug40375 @@ -0,0 +1,5 @@ + o Minor bugfixes (consensus handling): + - Avoid a set of bugs that could be caused by inconsistently preferring + an out-of-date consensus stored in a stale directory cache over + a more recent one stored on disk as the latest consensus. + Fixes bug 40375; bugfix on 0.3.1.1-alpha. diff --git a/src/feature/control/control_getinfo.c b/src/feature/control/control_getinfo.c @@ -353,26 +353,24 @@ getinfo_helper_current_consensus(consensus_flavor_t flavor, *errmsg = "Internal error: unrecognized flavor name."; return -1; } - if (we_want_to_fetch_flavor(get_options(), flavor)) { - /** Check from the cache */ - const cached_dir_t *consensus = dirserv_get_consensus(flavor_name); - if (consensus) { - *answer = tor_strdup(consensus->dir); - } + tor_mmap_t *mapped = networkstatus_map_cached_consensus(flavor_name); + if (mapped) { + *answer = tor_memdup_nulterm(mapped->data, mapped->size); + tor_munmap_file(mapped); } - if (!*answer) { /* try loading it from disk */ - - tor_mmap_t *mapped = networkstatus_map_cached_consensus(flavor_name); - if (mapped) { - *answer = tor_memdup_nulterm(mapped->data, mapped->size); - tor_munmap_file(mapped); - } - if (!*answer) { /* generate an error */ - *errmsg = "Could not open cached consensus. " - "Make sure FetchUselessDescriptors is set to 1."; - return -1; + if (!*answer) { /* Maybe it's in the cache? */ + if (we_want_to_fetch_flavor(get_options(), flavor)) { + const cached_dir_t *consensus = dirserv_get_consensus(flavor_name); + if (consensus) { + *answer = tor_strdup(consensus->dir); + } } } + if (!*answer) { /* generate an error */ + *errmsg = "Could not open cached consensus. " + "Make sure FetchUselessDescriptors is set to 1."; + return -1; + } return 0; } diff --git a/src/feature/dirclient/dirclient.c b/src/feature/dirclient/dirclient.c @@ -2280,18 +2280,23 @@ handle_response_fetch_consensus(dir_connection_t *conn, if (looks_like_a_consensus_diff(body, body_len)) { /* First find our previous consensus. Maybe it's in ram, maybe not. */ - cached_dir_t *cd = dirserv_get_consensus(flavname); + cached_dir_t *cd = NULL; const char *consensus_body = NULL; size_t consensus_body_len; tor_mmap_t *mapped_consensus = NULL; - if (cd) { - consensus_body = cd->dir; - consensus_body_len = cd->dir_len; + + /* We prefer the mmap'd version over the cached_dir_t version, + * since that matches the logic we used when we picked a consensus + * back in dir_consensus_request_set_additional_headers. */ + mapped_consensus = networkstatus_map_cached_consensus(flavname); + if (mapped_consensus) { + consensus_body = mapped_consensus->data; + consensus_body_len = mapped_consensus->size; } else { - mapped_consensus = networkstatus_map_cached_consensus(flavname); - if (mapped_consensus) { - consensus_body = mapped_consensus->data; - consensus_body_len = mapped_consensus->size; + cd = dirserv_get_consensus(flavname); + if (cd) { + consensus_body = cd->dir; + consensus_body_len = cd->dir_len; } } if (!consensus_body) {