[tor-commits] [stegotorus/master] Another subtle bug involving races near circuit teardown.
zwol at torproject.org
zwol at torproject.org
Fri Jul 20 23:17:06 UTC 2012
commit 4ae14e9e21d9b2848d089ba3ee150582e20744b9
Author: Zack Weinberg <zackw at panix.com>
Date: Wed Feb 1 21:19:18 2012 -0800
Another subtle bug involving races near circuit teardown.
---
src/network.cc | 3 ++-
src/protocol/chop.cc | 32 +++++++++++++++++++-------------
2 files changed, 21 insertions(+), 14 deletions(-)
diff --git a/src/network.cc b/src/network.cc
index a11cd7d..a55e539 100644
--- a/src/network.cc
+++ b/src/network.cc
@@ -423,7 +423,8 @@ upstream_flush_cb(struct bufferevent *bev, void *arg)
ckt->connected ? "" : " (not connected)",
ckt->flushing ? "" : " (not flushing)");
- if (remain == 0 && ckt->flushing && ckt->connected) {
+ if (remain == 0 && ckt->flushing && ckt->connected
+ && (!ckt->flush_timer || !evtimer_pending(ckt->flush_timer, NULL))) {
bufferevent_disable(bev, EV_WRITE);
if (bufferevent_get_enabled(bev) ||
evbuffer_get_length(bufferevent_get_input(bev)) > 0) {
diff --git a/src/protocol/chop.cc b/src/protocol/chop.cc
index 5acc010..d7da97f 100644
--- a/src/protocol/chop.cc
+++ b/src/protocol/chop.cc
@@ -784,8 +784,6 @@ chop_push_to_upstream(circuit_t *c)
static int
chop_find_or_make_circuit(conn_t *conn, uint64_t circuit_id)
{
- log_assert(conn->cfg->mode == LSN_SIMPLE_SERVER);
-
chop_config_t *cfg = static_cast<chop_config_t *>(conn->cfg);
chop_circuit_table::value_type in(circuit_id, 0);
std::pair<chop_circuit_table::iterator, bool> out = cfg->circuits.insert(in);
@@ -954,6 +952,11 @@ chop_config_t::circuit_create(size_t)
ckt->recv_crypt = decryptor::create(s2c_key, 16);
while (!ckt->circuit_id)
rng_bytes((uint8_t *)&ckt->circuit_id, sizeof(uint64_t));
+
+ chop_circuit_table::value_type in(ckt->circuit_id, 0);
+ std::pair<chop_circuit_table::iterator, bool> out = circuits.insert(in);
+ log_assert(out.second);
+ out.first->second = ckt;
}
return ckt;
}
@@ -996,17 +999,20 @@ chop_circuit_t::~chop_circuit_t()
free(p);
}
- if (this->cfg->mode == LSN_SIMPLE_SERVER) {
- /* The IDs for old circuits are preserved for a while (at present,
- indefinitely; FIXME: purge them on a timer) against the
- possibility that we'll get a junk connection for one of them
- right after we close it (same deal as the TIME_WAIT state in TCP). */
- chop_config_t *cfg = static_cast<chop_config_t *>(this->cfg);
- out = cfg->circuits.find(this->circuit_id);
- log_assert(out != cfg->circuits.end());
- log_assert(out->second == this);
- out->second = NULL;
- }
+ /* The IDs for old circuits are preserved for a while (at present,
+ indefinitely; FIXME: purge them on a timer) against the
+ possibility that we'll get a junk connection for one of them
+ right after we close it (same deal as the TIME_WAIT state in
+ TCP). Note that we can hit this case for the *client* if the
+ cover protocol includes a mandatory reply to every client
+ message and the hidden channel closed s->c before c->s: the
+ circuit will get destroyed on the client side after the c->s FIN,
+ and the mandatory reply will be to a stale circuit. */
+ chop_config_t *cfg = static_cast<chop_config_t *>(this->cfg);
+ out = cfg->circuits.find(this->circuit_id);
+ log_assert(out != cfg->circuits.end());
+ log_assert(out->second == this);
+ out->second = NULL;
}
void
More information about the tor-commits
mailing list