Failing to initialize sendme_inc when building the descriptor structure causes hidden service performance and availability issues
I believe I have found a bug with quite a serious impact in the TOR relay code, and my PI suggested that I report it.
The bug affects TOR 0.4.7.13 and 0.4.8.5 (at least).
Line numbers that are referenced are based on release-0.4.7
The details are below.
Bug:
Failing to initialize sendme_inc when building the descriptor structure causes hidden service performance and availability issues.
Details:
In hs_service.c, in the function build_service_desc_encrypted, the hidden service initializes the encrypted structure of the descriptor structure (of type hs_service_descriptor_t). In this function, the variables sendme_inc and flow_control_pv are not initialized, although they should be.
At first glance, there’s no impact, as these fields of the descriptor structure are not used when encoding the descriptor before sending it to the client. Instead, when encoding the descriptor, the correct sendme_inc and protocol version values from the consensus are used (see hs_descriptor.c line 778), so that the client receives correct values, hence there’s no impact on the sendme mechanism.
However, there’s another place where one of these fields, senme_inc, IS used by the hidden service. In the function hs_service_new_consensus_params(), in line hs_service.c line 3716, the code checks to see where sendme values have changed in the new consensus. The value of current_sendme_inc is a fixed 31. But the value of desc->desc->encrypted_data.sendme_inc is erroneously 0 (as it has never been initialized). This causes the condition to always return true. The impact of this is that all introduction points from both descriptors are immediately expired any time a new consensus is received.
Impact analysis:
According to our analysis, expiry of ALL introduction points, from both descriptors, all at once, causes an availability issue. Every time a consensus is received (roughly every hour on average), the service is not available for up to two minutes, as the descriptor cache of the clients is valid for two minutes. Until the clients load a new descriptor, the service is not available. In addition, the expiry of introduction points may lead to unnecessary hidden service descriptor uploads, which may affect the performance of both TOR clients and relays.
Fix:
We suggest the following fix.
In hs_service.c, in line 1768, add the line:
encrypted->sendme_inc=congestion_control_sendme_inc();
We have downloaded the source code and built it with the fix, and it seems to solve the problem.