commit 7cfe3b29722983fa58dca691ad64394304946f70
parent ba6db4ce97c3f654ee33b0abeb0f12ba6acc96af
Author: David Goulet <dgoulet@torproject.org>
Date: Thu, 6 Nov 2025 13:24:44 -0500
conflux: Check circuit close flag when launching a new leg
Because the returned circuit maye have been closed by the OOM handler, we must
check if it is closed to avoid accessing freed data.
We also make sure circuit_establish_circuit_conflux() never returns a closed
circuit, doubling the defenses against the C-tor maze.
Related to #41155
Signed-off-by: David Goulet <dgoulet@torproject.org>
Diffstat:
2 files changed, 20 insertions(+), 2 deletions(-)
diff --git a/src/core/or/circuitbuild.c b/src/core/or/circuitbuild.c
@@ -543,6 +543,12 @@ circuit_establish_circuit_conflux,(const uint8_t *conflux_nonce,
return NULL;
}
+ /* This can happen if the above triggered the OOM handler which in turn
+ * closed that very circuit. */
+ if (TO_CIRCUIT(circ)->marked_for_close) {
+ return NULL;
+ }
+
tor_trace(TR_SUBSYS(circuit), TR_EV(establish), circ);
return circ;
}
diff --git a/src/core/or/conflux_pool.c b/src/core/or/conflux_pool.c
@@ -1162,10 +1162,22 @@ conflux_launch_leg(const uint8_t *nonce)
origin_circuit_t *circ =
circuit_establish_circuit_conflux(nonce, CIRCUIT_PURPOSE_CONFLUX_UNLINKED,
exit, flags);
- if (!circ) {
+
+ /* The above call to establish a circuit can send us back a closed
+ * circuit if the OOM handler closes this very circuit while in that
+ * function. OOM handler runs everytime we queue a cell on a circuit which
+ * the above function does with the CREATE cell.
+ *
+ * The BUG() checks after are in the same spirit which is that there are so
+ * many things that can happen in that establish circuit function that we
+ * ought to make sure we have a valid nonce and a valid conflux object. */
+ if (!circ || TO_CIRCUIT(circ)->marked_for_close) {
+ goto err;
+ }
+ /* We think this won't happen but it might. The maze is powerful. #41155 */
+ if (BUG(!TO_CIRCUIT(circ)->conflux_pending_nonce || !unlinked->cfx)) {
goto err;
}
- tor_assert(TO_CIRCUIT(circ)->conflux_pending_nonce);
/* At this point, the unlinked object has either a new conflux_t or the one
* used by a linked set so it is fine to use the cfx from the unlinked object