summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2017-12-12 09:32:29 -0500
committerNick Mathewson <nickm@torproject.org>2017-12-12 09:32:29 -0500
commitdd5ca2505599dee6a589e228b69c4e8d4f29d7e6 (patch)
treeafea576584b3f1fb6f4692816aa302cf315eb5c4
parent706e6893d16e2097d9da4511060372c21f1cd24b (diff)
parentcf5ab5934e80c6c04825d9db83329627fe6b9729 (diff)
downloadtor-dd5ca2505599dee6a589e228b69c4e8d4f29d7e6.tar.gz
tor-dd5ca2505599dee6a589e228b69c4e8d4f29d7e6.zip
Merge branch 'maint-0.3.2' into release-0.3.2
-rw-r--r--src/or/hs_service.c50
1 files changed, 33 insertions, 17 deletions
diff --git a/src/or/hs_service.c b/src/or/hs_service.c
index 99965ddc37..dd836bf842 100644
--- a/src/or/hs_service.c
+++ b/src/or/hs_service.c
@@ -1815,6 +1815,15 @@ intro_point_should_expire(const hs_service_intro_point_t *ip,
static void
cleanup_intro_points(hs_service_t *service, time_t now)
{
+ /* List of intro points to close. We can't mark the intro circuits for close
+ * in the modify loop because doing so calls
+ * hs_service_intro_circ_has_closed() which does a digest256map_get() on the
+ * intro points map (that we are iterating over). This can't be done in a
+ * single iteration after a MAP_DEL_CURRENT, the object will still be
+ * returned leading to a use-after-free. So, we close the circuits and free
+ * the intro points after the loop if any. */
+ smartlist_t *ips_to_free = smartlist_new();
+
tor_assert(service);
/* For both descriptors, cleanup the intro points. */
@@ -1824,7 +1833,6 @@ cleanup_intro_points(hs_service_t *service, time_t now)
DIGEST256MAP_FOREACH_MODIFY(desc->intro_points.map, key,
hs_service_intro_point_t *, ip) {
const node_t *node = get_node_from_intro_point(ip);
- origin_circuit_t *ocirc = hs_circ_service_get_intro_circ(ip);
int has_expired = intro_point_should_expire(ip, now);
/* We cleanup an intro point if it has expired or if we do not know the
@@ -1845,26 +1853,34 @@ cleanup_intro_points(hs_service_t *service, time_t now)
remember_failing_intro_point(ip, desc, approx_time());
}
- /* Remove intro point from descriptor map. We'll add it to the failed
- * map if we retried it too many times. */
+ /* Remove intro point from descriptor map and add it to the list of
+ * ips to free for which we'll also try to close the intro circuit. */
MAP_DEL_CURRENT(key);
- service_intro_point_free(ip);
-
- /* XXX: Legacy code does NOT do that, it keeps the circuit open until
- * a new descriptor is uploaded and then closed all expiring intro
- * point circuit. Here, we close immediately and because we just
- * discarded the intro point, a new one will be selected, a new
- * descriptor created and uploaded. There is no difference to an
- * attacker between the timing of a new consensus and intro point
- * rotation (possibly?). */
- if (ocirc && !TO_CIRCUIT(ocirc)->marked_for_close) {
- /* After this, no new cells will be handled on the circuit. */
- circuit_mark_for_close(TO_CIRCUIT(ocirc), END_CIRC_REASON_FINISHED);
- }
- continue;
+ smartlist_add(ips_to_free, ip);
}
} DIGEST256MAP_FOREACH_END;
} FOR_EACH_DESCRIPTOR_END;
+
+ /* Go over the intro points to free and close their circuit if any. */
+ SMARTLIST_FOREACH_BEGIN(ips_to_free, hs_service_intro_point_t *, ip) {
+ /* See if we need to close the intro point circuit as well */
+
+ /* XXX: Legacy code does NOT close circuits like this: it keeps the circuit
+ * open until a new descriptor is uploaded and then closed all expiring
+ * intro point circuit. Here, we close immediately and because we just
+ * discarded the intro point, a new one will be selected, a new descriptor
+ * created and uploaded. There is no difference to an attacker between the
+ * timing of a new consensus and intro point rotation (possibly?). */
+ origin_circuit_t *ocirc = hs_circ_service_get_intro_circ(ip);
+ if (ocirc && !TO_CIRCUIT(ocirc)->marked_for_close) {
+ circuit_mark_for_close(TO_CIRCUIT(ocirc), END_CIRC_REASON_FINISHED);
+ }
+
+ /* Cleanup the intro point */
+ service_intro_point_free(ip);
+ } SMARTLIST_FOREACH_END(ip);
+
+ smartlist_free(ips_to_free);
}
/* Set the next rotation time of the descriptors for the given service for the