mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-10 13:13:44 +01:00
Merge remote-tracking branch 'public/bug3153'
Conflicts: src/or/nodelist.c
This commit is contained in:
commit
174cbff8cf
5
changes/bug3153
Normal file
5
changes/bug3153
Normal file
@ -0,0 +1,5 @@
|
||||
o Minor features:
|
||||
- Check for and recover from inconsistency in the microdescriptor
|
||||
cache. This will make it harder for us to accidentally free a
|
||||
microdescriptor without removing it from the appropriate data
|
||||
structures. Fixes issue 3135; issue noted by wanoskarnet.
|
@ -238,6 +238,7 @@ microdescs_add_list_to_cache(microdesc_cache_t *cache,
|
||||
md->no_save = no_save;
|
||||
|
||||
HT_INSERT(microdesc_map, &cache->map, md);
|
||||
md->held_in_map = 1;
|
||||
smartlist_add(added, md);
|
||||
++cache->n_seen;
|
||||
cache->total_len_seen += md->bodylen;
|
||||
@ -266,6 +267,7 @@ microdesc_cache_clear(microdesc_cache_t *cache)
|
||||
for (entry = HT_START(microdesc_map, &cache->map); entry; entry = next) {
|
||||
microdesc_t *md = *entry;
|
||||
next = HT_NEXT_RMV(microdesc_map, &cache->map, entry);
|
||||
md->held_in_map = 0;
|
||||
microdesc_free(md);
|
||||
}
|
||||
HT_CLEAR(microdesc_map, &cache->map);
|
||||
@ -354,6 +356,7 @@ microdesc_cache_clean(microdesc_cache_t *cache, time_t cutoff, int force)
|
||||
++dropped;
|
||||
victim = *mdp;
|
||||
mdp = HT_NEXT_RMV(microdesc_map, &cache->map, mdp);
|
||||
victim->held_in_map = 0;
|
||||
bytes_dropped += victim->bodylen;
|
||||
microdesc_free(victim);
|
||||
} else {
|
||||
@ -503,7 +506,43 @@ microdesc_free(microdesc_t *md)
|
||||
{
|
||||
if (!md)
|
||||
return;
|
||||
/* Must be removed from hash table! */
|
||||
|
||||
/* Make sure that the microdesc was really removed from the appropriate data
|
||||
structures. */
|
||||
if (md->held_in_map) {
|
||||
microdesc_cache_t *cache = get_microdesc_cache();
|
||||
microdesc_t *md2 = HT_FIND(microdesc_map, &cache->map, md);
|
||||
if (md2 == md) {
|
||||
log_warn(LD_BUG, "microdesc_free() called, but md was still in "
|
||||
"microdesc_map");
|
||||
HT_REMOVE(microdesc_map, &cache->map, md);
|
||||
} else {
|
||||
log_warn(LD_BUG, "microdesc_free() called with held_in_map set, but "
|
||||
"microdesc was not in the map.");
|
||||
}
|
||||
tor_fragile_assert();
|
||||
}
|
||||
if (md->held_by_node) {
|
||||
int found=0;
|
||||
const smartlist_t *nodes = nodelist_get_list();
|
||||
SMARTLIST_FOREACH(nodes, node_t *, node, {
|
||||
if (node->md == md) {
|
||||
++found;
|
||||
node->md = NULL;
|
||||
}
|
||||
});
|
||||
if (found) {
|
||||
log_warn(LD_BUG, "microdesc_free() called, but md was still referenced "
|
||||
"%d node(s)", found);
|
||||
} else {
|
||||
log_warn(LD_BUG, "microdesc_free() called with held_by_node set, but "
|
||||
"md was not refrenced by any nodes");
|
||||
}
|
||||
tor_fragile_assert();
|
||||
}
|
||||
//tor_assert(md->held_in_map == 0);
|
||||
//tor_assert(md->held_by_node == 0);
|
||||
|
||||
if (md->onion_pkey)
|
||||
crypto_free_pk_env(md->onion_pkey);
|
||||
if (md->body && md->saved_location != SAVED_IN_CACHE)
|
||||
|
@ -158,8 +158,12 @@ nodelist_add_microdesc(microdesc_t *md)
|
||||
if (rs == NULL)
|
||||
return NULL;
|
||||
node = node_get_mutable_by_id(rs->identity_digest);
|
||||
if (node)
|
||||
if (node) {
|
||||
if (node->md)
|
||||
node->md->held_by_node = 0;
|
||||
node->md = md;
|
||||
md->held_by_node = 1;
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
@ -184,8 +188,12 @@ nodelist_set_consensus(networkstatus_t *ns)
|
||||
if (ns->flavor == FLAV_MICRODESC) {
|
||||
if (node->md == NULL ||
|
||||
tor_memneq(node->md->digest,rs->descriptor_digest,DIGEST256_LEN)) {
|
||||
if (node->md)
|
||||
node->md->held_by_node = 0;
|
||||
node->md = microdesc_cache_lookup_by_digest256(NULL,
|
||||
rs->descriptor_digest);
|
||||
if (node->md)
|
||||
node->md->held_by_node = 1;
|
||||
}
|
||||
}
|
||||
|
||||
@ -240,8 +248,10 @@ void
|
||||
nodelist_remove_microdesc(const char *identity_digest, microdesc_t *md)
|
||||
{
|
||||
node_t *node = node_get_mutable_by_id(identity_digest);
|
||||
if (node && node->md == md)
|
||||
if (node && node->md == md) {
|
||||
node->md = NULL;
|
||||
md->held_by_node = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/** Tell the nodelist that <b>ri</b> is no longer in the routerlist. */
|
||||
@ -288,6 +298,8 @@ node_free(node_t *node)
|
||||
{
|
||||
if (!node)
|
||||
return;
|
||||
if (node->md)
|
||||
node->md->held_by_node = 0;
|
||||
tor_assert(node->nodelist_idx == -1);
|
||||
tor_free(node);
|
||||
}
|
||||
@ -375,6 +387,8 @@ nodelist_assert_ok(void)
|
||||
microdesc_t *md =
|
||||
microdesc_cache_lookup_by_digest256(NULL, rs->descriptor_digest);
|
||||
tor_assert(md == node->md);
|
||||
if (md)
|
||||
tor_assert(md->held_by_node == 1);
|
||||
}
|
||||
} SMARTLIST_FOREACH_END(rs);
|
||||
}
|
||||
|
@ -1712,6 +1712,11 @@ typedef struct microdesc_t {
|
||||
saved_location_t saved_location : 3;
|
||||
/** If true, do not attempt to cache this microdescriptor on disk. */
|
||||
unsigned int no_save : 1;
|
||||
/** If true, this microdesc is attached to a node_t. */
|
||||
unsigned int held_by_node : 1;
|
||||
/** If true, this microdesc has an entry in the microdesc_map */
|
||||
unsigned int held_in_map : 1;
|
||||
|
||||
/** If saved_location == SAVED_IN_CACHE, this field holds the offset of the
|
||||
* microdescriptor in the cache. */
|
||||
off_t off;
|
||||
|
Loading…
Reference in New Issue
Block a user