From 5ffabd4de4ee61fc0027b3fb82f7db22d96e661d Mon Sep 17 00:00:00 2001 From: Roger Dingledine Date: Thu, 10 May 2007 08:53:05 +0000 Subject: [PATCH] backport candidate: If a directory server runs out of space in the connection table as it's processing a begin_dir request, it will free the exit stream but leave it attached to the circuit, leading to unpredictable behavior. (Reported by seeess, fixes bug 425.) svn:r10154 --- ChangeLog | 10 ++++++++-- src/or/connection_edge.c | 28 ++++++++++++++++------------ 2 files changed, 24 insertions(+), 14 deletions(-) diff --git a/ChangeLog b/ChangeLog index e1b04c50e5..1ffaf78fe5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -29,6 +29,12 @@ Changes in version 0.2.0.1-alpha - 2007-??-?? in the network. Implements proposal 107, suggested by Kevin Bauer and Damon McCoy. + o Crash fixes: + - If a directory server runs out of space in the connection table + as it's processing a begin_dir request, it will free the exit stream + but leave it attached to the circuit, leading to unpredictable + behavior. (Reported by seeess, fixes bug 425.) + o Minor fixes (resource management): - Count the number of open sockets separately from the number of active connection_t objects. This will let us avoid underusing our @@ -40,8 +46,8 @@ Changes in version 0.2.0.1-alpha - 2007-??-?? the server), and avoids the nasty Windows socketpair() workaround. - Keep unused 4k and 16k buffers on free lists, rather than wasting 8k for every single inactive connection_t. - - Free items from the 4/16k-buffer free lists when they haven't been used - for a while. + - Free items from the 4k/16k-buffer free lists when they haven't been + used for a while. o Minor features (build): - Make autoconf search for libevent, openssl, and zlib consistently. diff --git a/src/or/connection_edge.c b/src/or/connection_edge.c index 3af8044c22..913a9eecf1 100644 --- a/src/or/connection_edge.c +++ b/src/or/connection_edge.c @@ -29,7 +29,8 @@ static smartlist_t *redirect_exit_list = NULL; static int connection_ap_handshake_process_socks(edge_connection_t *conn); static int connection_ap_process_natd(edge_connection_t *conn); -static int connection_exit_connect_dir(edge_connection_t *exit_conn); +static int connection_exit_connect_dir(edge_connection_t *exit_conn, + or_circuit_t *circ); static int hostname_is_noconnect_address(const char *address); /** An AP stream has failed/finished. If it hasn't already sent back @@ -2218,19 +2219,18 @@ connection_exit_begin_conn(cell_t *cell, circuit_t *circ) connection_free(TO_CONN(n_stream)); return 0; } - log_debug(LD_EXIT,"about to start the dns_resolve()."); - - if (rh.command == RELAY_COMMAND_BEGIN_DIR) { - if (or_circ && or_circ->p_conn && or_circ->p_conn->_base.addr) - n_stream->_base.addr = or_circ->p_conn->_base.addr; - n_stream->next_stream = TO_OR_CIRCUIT(circ)->n_streams; - n_stream->on_circuit = circ; - TO_OR_CIRCUIT(circ)->n_streams = n_stream; - return connection_exit_connect_dir(n_stream); - } n_stream->on_circuit = circ; + if (rh.command == RELAY_COMMAND_BEGIN_DIR) { + tor_assert(or_circ); + if (or_circ->p_conn && or_circ->p_conn->_base.addr) + n_stream->_base.addr = or_circ->p_conn->_base.addr; + return connection_exit_connect_dir(n_stream, or_circ); + } + + log_debug(LD_EXIT,"about to start the dns_resolve()."); + /* send it off to the gethostbyname farm */ switch (dns_resolve(n_stream)) { case 1: /* resolve worked */ @@ -2399,7 +2399,8 @@ connection_exit_connect(edge_connection_t *edge_conn) * DOCDOC no longer uses socketpair */ static int -connection_exit_connect_dir(edge_connection_t *exit_conn) +connection_exit_connect_dir(edge_connection_t *exit_conn, + or_circuit_t *circ) { dir_connection_t *dir_conn = NULL; @@ -2425,6 +2426,9 @@ connection_exit_connect_dir(edge_connection_t *exit_conn) return 0; } + exit_conn->next_stream = circ->n_streams; + circ->n_streams = exit_conn; + if (connection_add(TO_CONN(dir_conn))<0) { connection_edge_end(exit_conn, END_STREAM_REASON_RESOURCELIMIT); connection_close_immediate(TO_CONN(exit_conn));