tor

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

commit 8b238d39ece8b9cfb82cba1a61766e719a701edf
parent c75383bd668cbffb4cdb49531fd3edcbcbe3293a
Author: Nick Mathewson <nickm@torproject.org>
Date:   Tue,  4 Nov 2025 08:31:52 -0500

KeepaliveIsolateSOCKSAuth: expire based on time of last _use_.

Formerly, we expired circuits affected by KeepaliveIsolateSOCKSAuth
based on the time when a stream was last attached to them, which would
sometimes result in circuits closing immediately after their last stream
was closed.  Now, we update the "dirty timestamp" on circuits whenever a
stream is removed, so that they'll expire based on the time when they
last had a circuit.

This implements the "easy version" of proposal 368.

Closes #41157.

Diffstat:
Achanges/ticket41157 | 6++++++
Msrc/core/or/circuituse.c | 10++++++++++
2 files changed, 16 insertions(+), 0 deletions(-)

diff --git a/changes/ticket41157 b/changes/ticket41157 @@ -0,0 +1,6 @@ + o Minor features (security, reliability): + - When KeepaliveIsolateSOCKSAuth is keeping a circuit alive, + expire the circuit based on when it was last in use for any stream, + not (as we did before) based on when a stream was last attached to it. + Closes ticket 41157. Implements a minimal version of + Proposal 368. diff --git a/src/core/or/circuituse.c b/src/core/or/circuituse.c @@ -79,6 +79,8 @@ STATIC void circuit_expire_old_circuits_clientside(void); static void circuit_increment_failure_count(void); +static bool connection_ap_socks_iso_keepalive_enabled( + const entry_connection_t *); /** Check whether the hidden service destination of the stream at * <b>edge_conn</b> is the same as the destination of the circuit at @@ -1357,6 +1359,7 @@ void circuit_detach_stream(circuit_t *circ, edge_connection_t *conn) { edge_connection_t *prevconn; + bool update_dirty = false; tor_assert(circ); tor_assert(conn); @@ -1364,6 +1367,9 @@ circuit_detach_stream(circuit_t *circ, edge_connection_t *conn) if (conn->base_.type == CONN_TYPE_AP) { entry_connection_t *entry_conn = EDGE_TO_ENTRY_CONN(conn); entry_conn->may_use_optimistic_data = 0; + // When KeepAliveIsolateSOCKSAuth is in effect, we update the dirty + // time on close as well as on open. + update_dirty = connection_ap_socks_iso_keepalive_enabled(entry_conn); } conn->cpath_layer = NULL; /* don't keep a stale pointer */ conn->on_circuit = NULL; @@ -1389,6 +1395,10 @@ circuit_detach_stream(circuit_t *circ, edge_connection_t *conn) log_debug(LD_APP, "Removing stream %d from circ %u", conn->stream_id, (unsigned)circ->n_circ_id); + if (update_dirty) { + circ->timestamp_dirty = approx_time(); + } + /* If the stream was removed, and it was a rend stream, decrement the * number of streams on the circuit associated with the rend service. */