tor

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

commit 194e2dd2c269d535e1ea287acf015bc114c30bf0
parent 247869a84f79e354b035354b885f0bc8bfb8a010
Author: David Goulet <dgoulet@torproject.org>
Date:   Thu, 30 Oct 2025 12:19:24 -0400

conflux: Close all legs if sequence numbers are incoherent

When switching to a new leg, if the sequence number of sent cells on the
previous leg is larger then the leg we want to switch on, we consider an
incoherent state so close the set.

Signed-off-by: David Goulet <dgoulet@torproject.org>

Diffstat:
Msrc/core/or/conflux.c | 16++++++++++++++--
Msrc/core/or/conflux_pool.c | 2+-
Msrc/core/or/conflux_pool.h | 2++
3 files changed, 17 insertions(+), 3 deletions(-)

diff --git a/src/core/or/conflux.c b/src/core/or/conflux.c @@ -507,8 +507,20 @@ conflux_decide_circ_for_send(conflux_t *cfx, uint64_t relative_seq = cfx->prev_leg->last_seq_sent - cfx->curr_leg->last_seq_sent; - tor_assert(cfx->prev_leg->last_seq_sent >= - cfx->curr_leg->last_seq_sent); + if (cfx->curr_leg->last_seq_sent > cfx->prev_leg->last_seq_sent) { + /* Having incoherent sequence numbers, log warn about it but rate limit + * it to every hour so we avoid redundent report. */ + static ratelim_t rlimit = RATELIM_INIT(60 * 60); + log_fn_ratelim(&rlimit, LOG_WARN, LD_BUG, + "Current conflux leg last_seq_sent=%"PRIu64 + " is above previous leg at %" PRIu64 ". Closing set.", + cfx->curr_leg->last_seq_sent, + cfx->prev_leg->last_seq_sent); + conflux_mark_all_for_close(cfx->nonce, CIRCUIT_IS_ORIGIN(new_circ), + END_CIRC_REASON_TORPROTOCOL); + return NULL; + } + conflux_send_switch_command(cfx->curr_leg->circ, relative_seq); cfx->curr_leg->last_seq_sent = cfx->prev_leg->last_seq_sent; } diff --git a/src/core/or/conflux_pool.c b/src/core/or/conflux_pool.c @@ -675,7 +675,7 @@ unlinked_close_or_free(unlinked_circuits_t *unlinked) /** Upon an error condition or a close of an in-use circuit, we must close all * linked and unlinked circuits associated with a set. When the last leg of * each set is closed, the set is removed from the pool. */ -static void +void conflux_mark_all_for_close(const uint8_t *nonce, bool is_client, int reason) { /* It is possible that for a nonce we have both an unlinked set and a linked diff --git a/src/core/or/conflux_pool.h b/src/core/or/conflux_pool.h @@ -16,6 +16,8 @@ void conflux_pool_free_all(void); origin_circuit_t *conflux_get_circ_for_conn(const entry_connection_t *conn, time_t now); +void conflux_mark_all_for_close(const uint8_t *nonce, bool is_client, + int reason); void conflux_predict_new(time_t now);