From 8b981725798880a8bc8b1bee638e4285ffb7fe5a Mon Sep 17 00:00:00 2001 From: David Goulet Date: Fri, 11 Sep 2015 15:09:07 +0200 Subject: [PATCH] Add a rend cache failure info dup function When validating a new descriptor against our rend cache failure, we were added the failure entry to the new cache entry without duplicating. It was then freed just after the validation ending up in a very bad memory state that was making tor abort(). To fix this, a dup function has been added and used just before adding the failure entry. Fixes #17041 Signed-off-by: David Goulet --- src/or/rendcache.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/or/rendcache.c b/src/or/rendcache.c index fe9a1344f6..542d322c79 100644 --- a/src/or/rendcache.c +++ b/src/or/rendcache.c @@ -334,6 +334,17 @@ cache_failure_intro_lookup(const uint8_t *identity, const char *service_id, return 0; } +/** Allocate a new cache failure intro object and copy the content from + * entry to this newly allocated object. Return it. */ +static rend_cache_failure_intro_t * +cache_failure_intro_dup(const rend_cache_failure_intro_t *entry) +{ + rend_cache_failure_intro_t *ent_dup = + rend_cache_failure_intro_entry_new(entry->failure_type); + ent_dup->created_ts = entry->created_ts; + return ent_dup; +} + /** Add an intro point failure to the failure cache using the relay * identity and service ID service_id. Record the * failure in that object. */ @@ -383,12 +394,15 @@ validate_intro_point_failure(const rend_service_descriptor_t *desc, found = cache_failure_intro_lookup(identity, service_id, &entry); if (found) { + /* Dup here since it will be freed at the end when removing the + * original entry in the cache. */ + rend_cache_failure_intro_t *ent_dup = cache_failure_intro_dup(entry); /* This intro point is in our cache, discard it from the descriptor * because chances are that it's unusable. */ SMARTLIST_DEL_CURRENT(desc->intro_nodes, intro); rend_intro_point_free(intro); /* Keep it for our new entry. */ - digestmap_set(new_entry->intro_failures, (char *) identity, entry); + digestmap_set(new_entry->intro_failures, (char *) identity, ent_dup); continue; } } SMARTLIST_FOREACH_END(intro);