summaryrefslogtreecommitdiff
path: root/src/feature/dirclient
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2021-05-26 13:02:56 -0400
committerNick Mathewson <nickm@torproject.org>2021-05-26 13:02:56 -0400
commitd12b16614d09b303f9ef9624107b589264537341 (patch)
tree0cd377212c883b56d91150ebef7e35b2b2b9069f /src/feature/dirclient
parent4a7379b80a3d0f61d258b26f82d894da9b8cd0f5 (diff)
downloadtor-d12b16614d09b303f9ef9624107b589264537341.tar.gz
tor-d12b16614d09b303f9ef9624107b589264537341.zip
Prefer mmap()ed consensus files over cached_dir_t entries.
Cached_dir_t is a somewhat "legacy" kind of storage when used for consensus documents, and it appears that there are cases when changing our settings causes us to stop updating those entries. This can cause trouble, as @arma found out in #40375, where he changed his settings around, and consensus diff application got messed up: consensus diffs were being _requested_ based on the latest consensus, but were being (incorrectly) applied to a consensus that was no longer the latest one. This patch is a minimal fix for backporting purposes: it has Tor do the same search when applying consensus diffs as we use to request them. This should be sufficient for correct behavior. There's a similar case in GETINFO handling; I've fixed that too. Fixes #40375; bugfix on 0.3.1.1-alpha.
Diffstat (limited to 'src/feature/dirclient')
-rw-r--r--src/feature/dirclient/dirclient.c21
1 files changed, 13 insertions, 8 deletions
diff --git a/src/feature/dirclient/dirclient.c b/src/feature/dirclient/dirclient.c
index a5dd856729..b3159966d2 100644
--- a/src/feature/dirclient/dirclient.c
+++ b/src/feature/dirclient/dirclient.c
@@ -2263,18 +2263,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) {