Merge remote branch 'origin/maint-0.2.2'

Conflicts:
	src/or/relay.c
This commit is contained in:
Nick Mathewson
2010-11-30 19:23:40 -05:00
5 changed files with 87 additions and 7 deletions
+5
View File
@@ -0,0 +1,5 @@
o ?? bugfixes:
- Fix a bug that would cause newer streams on a given circuit to
get preference when reading bytes from the network. Fixes bug
2210. Fix by Mashael AlSabah. This bug was introduced before
the first Tor release, in svn revision r152.
+24
View File
@@ -1679,6 +1679,30 @@ tor_lookup_hostname(const char *name, uint32_t *addr)
return -1;
}
/** Initialize the insecure libc RNG. */
void
tor_init_weak_random(unsigned seed)
{
#ifdef MS_WINDOWS
srand(seed);
#else
srandom(seed);
#endif
}
/** Return a randomly chosen value in the range 0..TOR_RAND_MAX. This
* entropy will not be cryptographically strong; do not rely on it
* for anything an adversary should not be able to predict. */
long
tor_weak_random(void)
{
#ifdef MS_WINDOWS
return rand();
#else
return random();
#endif
}
/** Hold the result of our call to <b>uname</b>. */
static char uname_result[256];
/** True iff uname_result is set. */
+5
View File
@@ -487,6 +487,11 @@ typedef enum {
SOCKS5_ADDRESS_TYPE_NOT_SUPPORTED = 0x08,
} socks5_reply_status_t;
/* ===== Insecure rng */
void tor_init_weak_random(unsigned seed);
long tor_weak_random(void);
#define TOR_RAND_MAX (RAND_MAX)
/* ===== OS compatibility */
const char *get_uname(void);
+10
View File
@@ -1935,6 +1935,14 @@ crypto_dh_free(crypto_dh_env_t *dh)
OPENSSL_VERSION_NUMBER <= 0x00907fffl) || \
(OPENSSL_VERSION_NUMBER >= 0x0090803fl))
static void
seed_weak_rng(void)
{
unsigned seed;
crypto_rand((void*)&seed, sizeof(seed));
tor_init_weak_random(seed);
}
/** Seed OpenSSL's random number generator with bytes from the operating
* system. <b>startup</b> should be true iff we have just started Tor and
* have not yet allocated a bunch of fds. Return 0 on success, -1 on failure.
@@ -1985,6 +1993,7 @@ crypto_seed_rng(int startup)
}
RAND_seed(buf, sizeof(buf));
memset(buf, 0, sizeof(buf));
seed_weak_rng();
return 0;
#else
for (i = 0; filenames[i]; ++i) {
@@ -2001,6 +2010,7 @@ crypto_seed_rng(int startup)
}
RAND_seed(buf, (int)sizeof(buf));
memset(buf, 0, sizeof(buf));
seed_weak_rng();
return 0;
}
+43 -7
View File
@@ -1472,10 +1472,11 @@ circuit_resume_edge_reading_helper(edge_connection_t *first_conn,
crypt_path_t *layer_hint)
{
edge_connection_t *conn;
int n_streams, n_streams_left;
int n_packaging_streams, n_streams_left;
int packaged_this_round;
int cells_on_queue;
int cells_per_conn;
edge_connection_t *chosen_stream = NULL;
/* How many cells do we have space for? It will be the minimum of
* the number needed to exhaust the package window, and the minimum
@@ -1490,26 +1491,61 @@ circuit_resume_edge_reading_helper(edge_connection_t *first_conn,
if (CELL_QUEUE_HIGHWATER_SIZE - cells_on_queue < max_to_package)
max_to_package = CELL_QUEUE_HIGHWATER_SIZE - cells_on_queue;
/* Once we used to start listening on the streams in the order they
* appeared in the linked list. That leads to starvation on the
* streams that appeared later on the list, since the first streams
* would always get to read first. Instead, we just pick a random
* stream on the list, and enable reading for streams starting at that
* point (and wrapping around as if the list were circular). It would
* probably be better to actually remember which streams we've
* serviced in the past, but this is simple and effective. */
/* Select a stream uniformly at random from the linked list. We
* don't need cryptographic randomness here. */
{
int num_streams = 0;
for (conn = first_conn; conn; conn = conn->next_stream) {
num_streams++;
if ((tor_weak_random() % num_streams)==0)
chosen_stream = conn;
/* Invariant: chosen_stream has been chosen uniformly at random from
* among the first num_streams streams on first_conn. */
}
}
/* Count how many non-marked streams there are that have anything on
* their inbuf, and enable reading on all of the connections. */
n_streams = 0;
for (conn=first_conn; conn; conn=conn->next_stream) {
n_packaging_streams = 0;
/* Activate reading starting from the chosen stream */
for (conn=chosen_stream; conn; conn = conn->next_stream) {
/* Start reading for the streams starting from here */
if (conn->_base.marked_for_close || conn->package_window <= 0)
continue;
if (!layer_hint || conn->cpath_layer == layer_hint) {
connection_start_reading(TO_CONN(conn));
if (connection_get_inbuf_len(TO_CONN(conn)) > 0)
++n_streams;
++n_packaging_streams;
}
}
/* Go back and do the ones we skipped, circular-style */
for (conn = first_conn; conn != chosen_stream; conn = conn->next_stream) {
if (conn->_base.marked_for_close || conn->package_window <= 0)
continue;
if (!layer_hint || conn->cpath_layer == layer_hint) {
connection_start_reading(TO_CONN(conn));
if (connection_get_inbuf_len(TO_CONN(conn)) > 0)
++n_packaging_streams;
}
}
if (n_streams == 0) /* avoid divide-by-zero */
if (n_packaging_streams == 0) /* avoid divide-by-zero */
return 0;
again:
cells_per_conn = CEIL_DIV(max_to_package, n_streams);
cells_per_conn = CEIL_DIV(max_to_package, n_packaging_streams);
packaged_this_round = 0;
n_streams_left = 0;
@@ -1557,7 +1593,7 @@ circuit_resume_edge_reading_helper(edge_connection_t *first_conn,
if (packaged_this_round && packaged_this_round < max_to_package &&
n_streams_left) {
max_to_package -= packaged_this_round;
n_streams = n_streams_left;
n_packaging_streams = n_streams_left;
goto again;
}