hs: circuit_expire_old_circuits_serverside() should check for RP circuits
Thanks to a single onion service operator on IRC in the #tor channel (slingamn
), armadev and I were able to identify this issue.
Any clients connecting to a single onion service and then being idle for 60 seconds would get disconnected as in the rendezvous circuit closed.
It turns out that the rendezvous point closes the service circuit through this function circuit_expire_old_circuits_serversid()
if is idle for more than 60 seconds (only for single onion service). The faulty condition is:
if (or_circ->p_chan && channel_is_client(or_circ->p_chan) &&
!circ->n_chan &&
!or_circ->n_streams && !or_circ->resolving_streams &&
channel_when_last_xmit(or_circ->p_chan) <= cutoff) {
The RP is the end of the service circuit (or_circ
), all data is spliced to the client circuit which makes it that n_streams
and n_chan
are NULL and thus validating the condition.
Also possible to hit this if channel_is_client()
is a false positive for the exit point.
The fix here is to check if the circuit being looked at is a rendezvous point and ignore it if so. The or_circ->rend_splice
should be non-NULL if so.
This needs to be backported and affects v2 and v3 hidden service.