summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2012-08-17 16:46:11 -0400
committerNick Mathewson <nickm@torproject.org>2012-08-17 16:46:11 -0400
commit223e7cfabec5a75a7acd919210f838511e39cb16 (patch)
treece338e8c7c08578886fcd0e750fe51386999b531
parent9ed87b37d04705983b11cd995140e8864454bf5e (diff)
downloadtor-223e7cfabec5a75a7acd919210f838511e39cb16.tar.gz
tor-223e7cfabec5a75a7acd919210f838511e39cb16.zip
When iterating over connections pending DNS, skip marked ones
Failure to do this would lead to double-free cases and similar, especially when the exit's DNS was broken. See bug 6472 for full details; this is a fix for 6472. Anonymous patch from "cypherpunks" on trac.
-rw-r--r--changes/bug64724
-rw-r--r--src/or/dns.c16
2 files changed, 16 insertions, 4 deletions
diff --git a/changes/bug6472 b/changes/bug6472
new file mode 100644
index 0000000000..dcd42ebe68
--- /dev/null
+++ b/changes/bug6472
@@ -0,0 +1,4 @@
+ o Minor bugfixes:
+ - Avoid a pair of double-free and use-after-mark bugs that can
+ occur with certain timings in canceled and re-received DNS
+ requests. Fix for bug 6472; bugfix on 0.0.7rc1.
diff --git a/src/or/dns.c b/src/or/dns.c
index 3e88fad68c..78893bfbed 100644
--- a/src/or/dns.c
+++ b/src/or/dns.c
@@ -450,16 +450,17 @@ purge_expired_resolves(time_t now)
if (resolve->pending_connections) {
log_debug(LD_EXIT,
"Closing pending connections on timed-out DNS resolve!");
- tor_fragile_assert();
while (resolve->pending_connections) {
pend = resolve->pending_connections;
resolve->pending_connections = pend->next;
/* Connections should only be pending if they have no socket. */
tor_assert(!SOCKET_OK(pend->conn->_base.s));
pendconn = pend->conn;
- connection_edge_end(pendconn, END_STREAM_REASON_TIMEOUT);
- circuit_detach_stream(circuit_get_by_edge_conn(pendconn), pendconn);
- connection_free(TO_CONN(pendconn));
+ if (!pendconn->_base.marked_for_close) {
+ connection_edge_end(pendconn, END_STREAM_REASON_TIMEOUT);
+ circuit_detach_stream(circuit_get_by_edge_conn(pendconn), pendconn);
+ connection_free(TO_CONN(pendconn));
+ }
tor_free(pend);
}
}
@@ -1091,6 +1092,13 @@ dns_found_answer(const char *address, uint8_t is_reverse, uint32_t addr,
pendconn = pend->conn; /* don't pass complex things to the
connection_mark_for_close macro */
assert_connection_ok(TO_CONN(pendconn),time(NULL));
+ if (pendconn->_base.marked_for_close) {
+ /* prevent double-remove. */
+ pendconn->_base.state = EXIT_CONN_STATE_RESOLVEFAILED;
+ resolve->pending_connections = pend->next;
+ tor_free(pend);
+ continue;
+ }
tor_addr_from_ipv4h(&pendconn->_base.addr, addr);
pendconn->address_ttl = ttl;