summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Goulet <dgoulet@torproject.org>2023-07-31 10:57:34 -0400
committerMike Perry <mikeperry-git@torproject.org>2023-08-01 17:12:11 +0000
commit5487476fd919703b55cb1f1544d575224c9b685e (patch)
tree44672601cfa09627a20fff5180a15a0021d99f2c
parent4667195deded5e34d93ef9984ff091b2ae822fbb (diff)
downloadtor-5487476fd919703b55cb1f1544d575224c9b685e.tar.gz
tor-5487476fd919703b55cb1f1544d575224c9b685e.zip
Nullify on_circuit if last conflux leg
Signed-off-by: David Goulet <dgoulet@torproject.org>
-rw-r--r--src/core/or/conflux_pool.c44
1 files changed, 44 insertions, 0 deletions
diff --git a/src/core/or/conflux_pool.c b/src/core/or/conflux_pool.c
index 79fd6c1648..837c1da720 100644
--- a/src/core/or/conflux_pool.c
+++ b/src/core/or/conflux_pool.c
@@ -1509,6 +1509,49 @@ linked_update_stream_backpointers(circuit_t *circ)
}
}
+/** This is called when this circuit is the last leg.
+ *
+ * The "on_circuit" pointer is nullified here so it is not given back to the
+ * conflux subsytem between the circuit mark for close step and actually
+ * freeing the circuit which is when streams are destroyed.
+ *
+ * Reason is that when the connection edge inbuf is packaged in
+ * connection_edge_package_raw_inbuf(), the on_circuit pointer is used and
+ * then passed on to conflux to learn which leg to use. However, if the circuit
+ * was marked prior but not yet freed, there are no more legs remaining which
+ * leads to a linked circuit being used without legs. No bueno. */
+static void
+linked_detach_circuit(circuit_t *circ)
+{
+ tor_assert(circ);
+ tor_assert_nonfatal(circ->conflux);
+
+ if (CIRCUIT_IS_ORIGIN(circ)) {
+ origin_circuit_t *ocirc = TO_ORIGIN_CIRCUIT(circ);
+ tor_assert_nonfatal(circ->purpose == CIRCUIT_PURPOSE_CONFLUX_LINKED);
+ /* Iterate over stream list using next_stream pointer, until null */
+ for (edge_connection_t *stream = ocirc->p_streams; stream;
+ stream = stream->next_stream) {
+ /* Update the circuit pointer of each stream */
+ stream->on_circuit = NULL;
+ }
+ } else {
+ or_circuit_t *orcirc = TO_OR_CIRCUIT(circ);
+ /* Iterate over stream list using next_stream pointer, until null */
+ for (edge_connection_t *stream = orcirc->n_streams; stream;
+ stream = stream->next_stream) {
+ /* Update the circuit pointer of each stream */
+ stream->on_circuit = NULL;
+ }
+ /* Iterate over stream list using next_stream pointer, until null */
+ for (edge_connection_t *stream = orcirc->resolving_streams; stream;
+ stream = stream->next_stream) {
+ /* Update the circuit pointer of each stream */
+ stream->on_circuit = NULL;
+ }
+ }
+}
+
/** Nullify all streams of the given circuit. */
static void
linked_nullify_streams(circuit_t *circ)
@@ -1549,6 +1592,7 @@ linked_circuit_closed(circuit_t *circ)
if (CONFLUX_NUM_LEGS(circ->conflux) == 0) {
/* Last leg, remove conflux object from linked set. */
linked_pool_del(circ->conflux->nonce, is_client);
+ linked_detach_circuit(circ);
} else {
/* If there are other circuits, update streams backpointers and
* nullify the stream lists. We do not free those streams in circuit_free_.