commit 95bf19dfb13a27ccf293b6416a7a0e89eb4027c9
parent 17a6bdfe68387c992606a8aa01361d28ac785162
Author: David Goulet <dgoulet@torproject.org>
Date: Mon, 10 Nov 2025 13:26:10 -0500
Merge branch 'maint-0.4.8'
Diffstat:
4 files changed, 19 insertions(+), 13 deletions(-)
diff --git a/changes/bug41037 b/changes/bug41037
@@ -0,0 +1,4 @@
+ o Minor bugfixes (conflux fragile asserts):
+ - Fix the root cause of some conflux fragile asserts
+ when a control port listener is attached. Fixes bug 41037;
+ bugfix on 0.4.8.16.
diff --git a/src/core/or/conflux_pool.c b/src/core/or/conflux_pool.c
@@ -1461,11 +1461,6 @@ unlinked_circuit_closed(circuit_t *circ)
/* This circuit is part of set that has already been removed previously freed
* by another leg closing. */
if (!unlinked) {
- /* This circuit is not Conflux related anymore regardless of its purpose so
- * remove the pending nonce so after this function, the circuit is not
- * considered conflux with CIRCUIT_IS_CONFLUX(). */
- tor_free(circ->conflux_pending_nonce);
- circ->conflux_pending_nonce = NULL;
return;
}
diff --git a/src/core/or/conflux_util.h b/src/core/or/conflux_util.h
@@ -28,9 +28,8 @@ CIRCUIT_IS_CONFLUX(const circuit_t *circ)
tor_assert_nonfatal(circ->purpose == CIRCUIT_PURPOSE_CONFLUX_LINKED);
return true;
} else {
- /* We don't assert on purposes here because we can end up in this branch
- * with circ->conflux being NULL but for a conflux purpose. This happens in
- * the about_to_free() code path. */
+ tor_assert_nonfatal(circ->purpose != CIRCUIT_PURPOSE_CONFLUX_LINKED);
+ tor_assert_nonfatal(circ->purpose != CIRCUIT_PURPOSE_CONFLUX_UNLINKED);
return false;
}
}
diff --git a/src/feature/control/control_fmt.c b/src/feature/control/control_fmt.c
@@ -163,17 +163,25 @@ circuit_describe_status_for_controller(origin_circuit_t *circ)
/* Add conflux id and RTT info, for accurate circuit display. The RTT is
* provided to indicate the primary (preferred) circuit of a set
- * (which will have the lowest current RTT). */
- if (CIRCUIT_IS_CONFLUX(TO_CIRCUIT(circ))) {
+ * (which will have the lowest current RTT).
+ *
+ * NOTE: Because control port events can happen at arbitrary points, we
+ * must specificially check exactly what we need from the conflux object.
+ * We cannot use CIRCUIT_IS_CONFLUX() because this event may have been
+ * emitted while a set was under partial construction or teardown. */
+ if (TO_CIRCUIT(circ)->conflux || TO_CIRCUIT(circ)->conflux_pending_nonce) {
const uint8_t *nonce = conflux_get_nonce(TO_CIRCUIT(circ));
tor_assert(nonce);
- /* The conflux nonce is sensitive data. Only output half of it. */
+ /* The conflux nonce is an ephemeral cryptographic secret that if known in
+ * full, enables confirmation or data injection on a set by adding new legs
+ * at an exit from elsewhere. Only output half of it. */
smartlist_add_asprintf(descparts, "CONFLUX_ID=%s",
hex_str((const char *)nonce, DIGEST256_LEN/2));
- /* If we have a conflux object, the circ is linked and has an RTT */
- if (TO_CIRCUIT(circ)->conflux) {
+ /* If we have a conflux object that is fully linked, the circ has an RTT */
+ if (TO_CIRCUIT(circ)->conflux &&
+ TO_CIRCUIT(circ)->purpose == CIRCUIT_PURPOSE_CONFLUX_LINKED) {
uint64_t circ_rtt = conflux_get_circ_rtt(TO_CIRCUIT(circ));
if (circ_rtt) {
smartlist_add_asprintf(descparts, "CONFLUX_RTT=%" PRIu64, circ_rtt);