tor

The Tor anonymity network
git clone https://git.dasho.dev/tor.git
Log | Files | Refs | README | LICENSE

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:
Achanges/bug41037 | 4++++
Msrc/core/or/conflux_pool.c | 5-----
Msrc/core/or/conflux_util.h | 5++---
Msrc/feature/control/control_fmt.c | 18+++++++++++++-----
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);