diff --git a/changes/bug13988 b/changes/bug13988 new file mode 100644 index 000000000..e816335a3 --- /dev/null +++ b/changes/bug13988 @@ -0,0 +1,3 @@ + o Minor bugfixes (statistics): + - Increase period over which bandwidth observations are aggregated + from 15 minutes to 4 hours. Fixes bug 13988; bugfix on 0.0.8pre1. diff --git a/changes/bug14013 b/changes/bug14013 new file mode 100644 index 000000000..640cf859f --- /dev/null +++ b/changes/bug14013 @@ -0,0 +1,6 @@ + o Major bugfixes: + - When reading a hexadecimal, base-32, or base-64 encoded value + from a string, always overwrite the complete output buffer. This + prevents some bugs where we would look at (but fortunately, not + reveal) uninitialized memory on the stack. Fixes bug 14013; + bugfix on all versions of Tor. diff --git a/changes/bug14125 b/changes/bug14125 new file mode 100644 index 000000000..fe6821a33 --- /dev/null +++ b/changes/bug14125 @@ -0,0 +1,5 @@ + o Minor bugfixes (dirauth): + - Enlarge the buffer to read bw-auth generated files to avoid an + issue when parsing the file in dirserv_read_measured_bandwidths(). + Bugfix on 0.2.2.1-alpha, fixes #14125. + diff --git a/changes/bug14129 b/changes/bug14129 new file mode 100644 index 000000000..6153cd84f --- /dev/null +++ b/changes/bug14129 @@ -0,0 +1,7 @@ + o Major bugfixes (exit node stability): + + - Fix an assertion failure that could occur under high DNS load. Fixes + bug 14129; bugfix on Tor 0.0.7rc1. Found by "jowr"; diagnosed and fixed + by "cypherpunks". + + diff --git a/changes/bug14142-parse-virtual-addr b/changes/bug14142-parse-virtual-addr new file mode 100644 index 000000000..f78b7c7d8 --- /dev/null +++ b/changes/bug14142-parse-virtual-addr @@ -0,0 +1,7 @@ + o Minor bugfixes (client): + - Check for a missing option value in parse_virtual_addr_network + before asserting on the NULL in tor_addr_parse_mask_ports. + This avoids crashing on torrc lines like + Vi[rtualAddrNetworkIPv[4|6]] when no value follows the option. + Bugfix on 0.2.3 (de4cc126cbb5 on 24 November 2012), fixes #14142. + Patch by "teor". diff --git a/changes/bug14195 b/changes/bug14195 new file mode 100644 index 000000000..d2b82f31b --- /dev/null +++ b/changes/bug14195 @@ -0,0 +1,3 @@ + o Minor bugfixes (client): + - Fix a memory leak when using AutomapHostsOnResolve. + Fixes bug 14195; bugfix on 0.1.0.1-rc. diff --git a/changes/bug14220 b/changes/bug14220 new file mode 100644 index 000000000..51cfa502b --- /dev/null +++ b/changes/bug14220 @@ -0,0 +1,4 @@ + o Minor bugfixes (compilation): + - Build without warnings with the stock OpenSSL srtp.h header, + which has a duplicate declaration of SSL_get_selected_srtp_profile(). + Fixes bug 14220; this is OpenSSL's bug, not ours. diff --git a/changes/bug14261 b/changes/bug14261 new file mode 100644 index 000000000..1260ccba1 --- /dev/null +++ b/changes/bug14261 @@ -0,0 +1,5 @@ + O Minor bugfixes (directory authority): + - Allow directory authorities to fetch more data from one + another if they find themselves missing lots of votes. + Previously, they had been bumping against the 10 MB queued + data limit. Fixes bug 14261. Bugfix on 0.1.2.5-alpha. diff --git a/changes/bug15083 b/changes/bug15083 new file mode 100644 index 000000000..5cc79b5ba --- /dev/null +++ b/changes/bug15083 @@ -0,0 +1,10 @@ + o Major bugfixes (relay, stability, possible security): + - Fix a bug that could lead to a relay crashing with an assertion + failure if a buffer of exactly the wrong layout was passed + to buf_pullup() at exactly the wrong time. Fixes bug 15083; + bugfix on 0.2.0.10-alpha. Patch from 'cypherpunks'. + + - Do not assert if the 'data' pointer on a buffer is advanced to the very + end of the buffer; log a BUG message instead. Only assert if it is + past that point. Fixes bug 15083; bugfix on 0.2.0.10-alpha. + diff --git a/changes/bug15088 b/changes/bug15088 new file mode 100644 index 000000000..95878bdb3 --- /dev/null +++ b/changes/bug15088 @@ -0,0 +1,4 @@ + o Minor bugfixes (Linux seccomp2 sandbox): + - Upon receiving sighup, do not crash during attempts to call + wait4. Fixes bug 15088; bugfix on 0.2.5.1-alpha. Patch from + "sanic". diff --git a/changes/geoip-january2015 b/changes/geoip-january2015 new file mode 100644 index 000000000..67324f27f --- /dev/null +++ b/changes/geoip-january2015 @@ -0,0 +1,3 @@ + o Minor features: + - Update geoip to the January 7 2015 Maxmind GeoLite2 Country database. + diff --git a/changes/geoip6-january2015 b/changes/geoip6-january2015 new file mode 100644 index 000000000..b86fe2be5 --- /dev/null +++ b/changes/geoip6-january2015 @@ -0,0 +1,2 @@ + o Minor features: + - Update geoip6 to the January 7 2015 Maxmind GeoLite2 Country database. diff --git a/changes/ticket14128 b/changes/ticket14128 new file mode 100644 index 000000000..38b25fa7d --- /dev/null +++ b/changes/ticket14128 @@ -0,0 +1,5 @@ + o Minor features (controller): + - New "GETINFO bw-event-cache" to get information about recent bandwidth + events. Closes ticket 14128. Useful for controllers to get recent + bandwidth history after the fix for 13988. + diff --git a/changes/ticket14487 b/changes/ticket14487 new file mode 100644 index 000000000..577337ff2 --- /dev/null +++ b/changes/ticket14487 @@ -0,0 +1,3 @@ + o Directory authority IP change: + - The directory authority Faravahar has a new IP address. Closes + ticket 14487. diff --git a/src/common/crypto.c b/src/common/crypto.c index a247a87d4..f4e86683d 100644 --- a/src/common/crypto.c +++ b/src/common/crypto.c @@ -2756,6 +2756,8 @@ base64_decode(char *dest, size_t destlen, const char *src, size_t srclen) if (destlen > SIZE_T_CEILING) return -1; + memset(dest, 0, destlen); + EVP_DecodeInit(&ctx); EVP_DecodeUpdate(&ctx, (unsigned char*)dest, &len, (unsigned char*)src, srclen); @@ -2777,6 +2779,8 @@ base64_decode(char *dest, size_t destlen, const char *src, size_t srclen) if (destlen > SIZE_T_CEILING) return -1; + memset(dest, 0, destlen); + /* Iterate over all the bytes in src. Each one will add 0 or 6 bits to the * value we're decoding. Accumulate bits in n, and whenever we have * 24 bits, batch them into 3 bytes and flush those bytes to dest. @@ -2956,6 +2960,8 @@ base32_decode(char *dest, size_t destlen, const char *src, size_t srclen) tor_assert((nbits/8) <= destlen); /* We need enough space. */ tor_assert(destlen < SIZE_T_CEILING); + memset(dest, 0, destlen); + /* Convert base32 encoded chars to the 5-bit values that they represent. */ tmp = tor_malloc_zero(srclen); for (j = 0; j < srclen; ++j) { diff --git a/src/common/sandbox.c b/src/common/sandbox.c index dbbaa59d7..e43b64b91 100644 --- a/src/common/sandbox.c +++ b/src/common/sandbox.c @@ -164,6 +164,7 @@ static int filter_nopar_gen[] = { #endif SCMP_SYS(stat), SCMP_SYS(uname), + SCMP_SYS(wait4), SCMP_SYS(write), SCMP_SYS(writev), SCMP_SYS(exit_group), diff --git a/src/common/tortls.c b/src/common/tortls.c index 999d97131..d637a8e4d 100644 --- a/src/common/tortls.c +++ b/src/common/tortls.c @@ -33,6 +33,20 @@ #include #endif #endif + +#ifdef __GNUC__ +#define GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__) +#endif + +#if __GNUC__ && GCC_VERSION >= 402 +#if GCC_VERSION >= 406 +#pragma GCC diagnostic push +#endif +/* Some versions of OpenSSL declare SSL_get_selected_srtp_profile twice in + * srtp.h. Suppress the GCC warning so we can build with -Wredundant-decl. */ +#pragma GCC diagnostic ignored "-Wredundant-decls" +#endif + #include #include #include @@ -41,6 +55,14 @@ #include #include +#if __GNUC__ && GCC_VERSION >= 402 +#if GCC_VERSION >= 406 +#pragma GCC diagnostic pop +#else +#pragma GCC diagnostic warning "-Wredundant-decls" +#endif +#endif + #ifdef USE_BUFFEREVENTS #include #include diff --git a/src/common/util.c b/src/common/util.c index 2d7893b38..04cc6b12c 100644 --- a/src/common/util.c +++ b/src/common/util.c @@ -1129,6 +1129,9 @@ base16_decode(char *dest, size_t destlen, const char *src, size_t srclen) return -1; if (destlen < srclen/2 || destlen > SIZE_T_CEILING) return -1; + + memset(dest, 0, destlen); + end = src+srclen; while (srcnew_address)) { tor_free(new_address); tor_assert(!vent_needs_to_be_added); - return tor_strdup(*addrp); + return *addrp; } else { log_warn(LD_BUG, "Internal confusion: I thought that '%s' was mapped to by " diff --git a/src/or/buffers.c b/src/or/buffers.c index 033f86288..ae73c7070 100644 --- a/src/or/buffers.c +++ b/src/or/buffers.c @@ -447,7 +447,7 @@ buf_pullup(buf_t *buf, size_t bytes, int nulterminate) size_t n = bytes - dest->datalen; src = dest->next; tor_assert(src); - if (n > src->datalen) { + if (n >= src->datalen) { memcpy(CHUNK_WRITE_PTR(dest), src->data, src->datalen); dest->datalen += src->datalen; dest->next = src->next; @@ -2624,7 +2624,14 @@ assert_buf_ok(buf_t *buf) total += ch->datalen; tor_assert(ch->datalen <= ch->memlen); tor_assert(ch->data >= &ch->mem[0]); - tor_assert(ch->data < &ch->mem[0]+ch->memlen); + tor_assert(ch->data <= &ch->mem[0]+ch->memlen); + if (ch->data == &ch->mem[0]+ch->memlen) { + static int warned = 0; + if (! warned) { + log_warn(LD_BUG, "Invariant violation in buf.c related to #15083"); + warned = 1; + } + } tor_assert(ch->data+ch->datalen <= &ch->mem[0] + ch->memlen); if (!ch->next) tor_assert(ch == buf->tail); diff --git a/src/or/config.c b/src/or/config.c index 892108278..2a7237d59 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -871,7 +871,7 @@ add_default_trusted_dir_authorities(dirinfo_type_t type) "171.25.193.9:443 BD6A 8292 55CB 08E6 6FBE 7D37 4836 3586 E46B 3810", "Faravahar orport=443 " "v3ident=EFCBE720AB3A82B99F9E953CD5BF50F7EEFC7B97 " - "154.35.32.5:80 CF6D 0AAF B385 BE71 B8E1 11FC 5CFF 4B47 9237 33BC", + "154.35.175.225:80 CF6D 0AAF B385 BE71 B8E1 11FC 5CFF 4B47 9237 33BC", "longclaw orport=443 " "v3ident=23D15D965BC35114467363C165C4F724B64B4F66 " "199.254.238.52:80 74A9 1064 6BCE EFBC D2E8 74FC 1DC9 9743 0F96 8145", diff --git a/src/or/control.c b/src/or/control.c index 9378f38f4..2ff1cc844 100644 --- a/src/or/control.c +++ b/src/or/control.c @@ -1424,6 +1424,8 @@ getinfo_helper_misc(control_connection_t *conn, const char *question, (void) conn; if (!strcmp(question, "version")) { *answer = tor_strdup(get_version()); + } else if (!strcmp(question, "bw-event-cache")) { + *answer = get_bw_samples(); } else if (!strcmp(question, "config-file")) { *answer = tor_strdup(get_torrc_fname(0)); } else if (!strcmp(question, "config-defaults-file")) { @@ -2099,6 +2101,7 @@ typedef struct getinfo_item_t { * to answer them. */ static const getinfo_item_t getinfo_items[] = { ITEM("version", misc, "The current version of Tor."), + ITEM("bw-event-cache", misc, "Cached BW events for a short interval."), ITEM("config-file", misc, "Current location of the \"torrc\" file."), ITEM("config-defaults-file", misc, "Current location of the defaults file."), ITEM("config-text", misc, @@ -4133,11 +4136,29 @@ control_event_tb_empty(const char *bucket, uint32_t read_empty_time, return 0; } +/* about 5 minutes worth. */ +#define N_BW_EVENTS_TO_CACHE 300 +/* Index into cached_bw_events to next write. */ +static int next_measurement_idx = 0; +/* number of entries set in n_measurements */ +static int n_measurements = 0; +static struct cached_bw_event_s { + uint32_t n_read; + uint32_t n_written; +} cached_bw_events[N_BW_EVENTS_TO_CACHE]; + /** A second or more has elapsed: tell any interested control * connections how much bandwidth we used. */ int control_event_bandwidth_used(uint32_t n_read, uint32_t n_written) { + cached_bw_events[next_measurement_idx].n_read = n_read; + cached_bw_events[next_measurement_idx].n_written = n_written; + if (++next_measurement_idx == N_BW_EVENTS_TO_CACHE) + next_measurement_idx = 0; + if (n_measurements < N_BW_EVENTS_TO_CACHE) + ++n_measurements; + if (EVENT_IS_INTERESTING(EVENT_BANDWIDTH_USED)) { send_control_event(EVENT_BANDWIDTH_USED, ALL_FORMATS, "650 BW %lu %lu\r\n", @@ -4148,6 +4169,38 @@ control_event_bandwidth_used(uint32_t n_read, uint32_t n_written) return 0; } +STATIC char * +get_bw_samples(void) +{ + int i; + int idx = (next_measurement_idx + N_BW_EVENTS_TO_CACHE - n_measurements) + % N_BW_EVENTS_TO_CACHE; + smartlist_t *elements = smartlist_new(); + tor_assert(0 <= idx && idx < N_BW_EVENTS_TO_CACHE); + + for (i = 0; i < n_measurements; ++i) { + tor_assert(0 <= idx && idx < N_BW_EVENTS_TO_CACHE); + { + const struct cached_bw_event_s *bwe = &cached_bw_events[idx]; + + smartlist_add_asprintf(elements, "%u,%u", + (unsigned)bwe->n_read, + (unsigned)bwe->n_written); + + idx = (idx + 1) % N_BW_EVENTS_TO_CACHE; + } + } + + { + char *result = smartlist_join_strings(elements, " ", 0, NULL); + + SMARTLIST_FOREACH(elements, char *, cp, tor_free(cp)); + smartlist_free(elements); + + return result; + } +} + /** Called when we are sending a log message to the controllers: suspend * sending further log messages to the controllers until we're done. Used by * CONN_LOG_PROTECT. */ diff --git a/src/or/control.h b/src/or/control.h index 494f04b3b..869726217 100644 --- a/src/or/control.h +++ b/src/or/control.h @@ -201,6 +201,7 @@ void append_cell_stats_by_command(smartlist_t *event_parts, const uint64_t *number_to_include); void format_cell_stats(char **event_string, circuit_t *circ, cell_stats_t *cell_stats); +STATIC char *get_bw_samples(void); #endif #endif diff --git a/src/or/directory.c b/src/or/directory.c index 298271f36..50863d0c7 100644 --- a/src/or/directory.c +++ b/src/or/directory.c @@ -2183,12 +2183,15 @@ connection_dir_reached_eof(dir_connection_t *conn) */ #define MAX_DIRECTORY_OBJECT_SIZE (10*(1<<20)) +#define MAX_VOTE_DL_SIZE (MAX_DIRECTORY_OBJECT_SIZE * 5) + /** Read handler for directory connections. (That's connections to * directory servers and connections at directory servers.) */ int connection_dir_process_inbuf(dir_connection_t *conn) { + size_t max_size; tor_assert(conn); tor_assert(conn->base_.type == CONN_TYPE_DIR); @@ -2207,7 +2210,11 @@ connection_dir_process_inbuf(dir_connection_t *conn) return 0; } - if (connection_get_inbuf_len(TO_CONN(conn)) > MAX_DIRECTORY_OBJECT_SIZE) { + max_size = + (TO_CONN(conn)->purpose == DIR_PURPOSE_FETCH_STATUS_VOTE) ? + MAX_VOTE_DL_SIZE : MAX_DIRECTORY_OBJECT_SIZE; + + if (connection_get_inbuf_len(TO_CONN(conn)) > max_size) { log_warn(LD_HTTP, "Too much data received from directory connection: " "denial of service attempt, or you need to upgrade?"); connection_mark_for_close(TO_CONN(conn)); diff --git a/src/or/dirserv.c b/src/or/dirserv.c index 49fafafab..03b32cb2f 100644 --- a/src/or/dirserv.c +++ b/src/or/dirserv.c @@ -2487,7 +2487,7 @@ int dirserv_read_measured_bandwidths(const char *from_file, smartlist_t *routerstatuses) { - char line[256]; + char line[512]; FILE *fp = tor_fopen_cloexec(from_file, "r"); int applied_lines = 0; time_t file_time, now; diff --git a/src/or/dns.c b/src/or/dns.c index a9c431865..b55bf7384 100644 --- a/src/or/dns.c +++ b/src/or/dns.c @@ -558,6 +558,8 @@ purge_expired_resolves(time_t now) /* Connections should only be pending if they have no socket. */ tor_assert(!SOCKET_OK(pend->conn->base_.s)); pendconn = pend->conn; + /* Prevent double-remove */ + pendconn->base_.state = EXIT_CONN_STATE_RESOLVEFAILED; if (!pendconn->base_.marked_for_close) { connection_edge_end(pendconn, END_STREAM_REASON_TIMEOUT); circuit_detach_stream(circuit_get_by_edge_conn(pendconn), pendconn); @@ -1133,7 +1135,9 @@ connection_dns_remove(edge_connection_t *conn) return; /* more are pending */ } } - tor_assert(0); /* not reachable unless onlyconn not in pending list */ + log_warn(LD_BUG, "Connection (fd "TOR_SOCKET_T_FORMAT") was not waiting " + "for a resolve of %s, but we tried to remove it.", + conn->base_.s, escaped_safe_str(conn->base_.address)); } } diff --git a/src/or/rephist.c b/src/or/rephist.c index 72de54c0c..cedc56af0 100644 --- a/src/or/rephist.c +++ b/src/or/rephist.c @@ -1131,9 +1131,7 @@ rep_hist_load_mtbf_data(time_t now) * totals? */ #define NUM_SECS_ROLLING_MEASURE 10 /** How large are the intervals for which we track and report bandwidth use? */ -/* XXXX Watch out! Before Tor 0.2.2.21-alpha, using any other value here would - * generate an unparseable state file. */ -#define NUM_SECS_BW_SUM_INTERVAL (15*60) +#define NUM_SECS_BW_SUM_INTERVAL (4*60*60) /** How far in the past do we remember and publish bandwidth use? */ #define NUM_SECS_BW_SUM_IS_VALID (24*60*60) /** How many bandwidth usage intervals do we remember? (derived) */ diff --git a/src/test/test_relaycell.c b/src/test/test_relaycell.c index 5deb36260..9aff6ab49 100644 --- a/src/test/test_relaycell.c +++ b/src/test/test_relaycell.c @@ -104,7 +104,7 @@ test_relaycell_resolved(void *arg) tt_int_op(srm_answer_is_set, ==, 0); \ } \ tt_int_op(srm_ttl, ==, ttl); \ - tt_int_op(srm_expires, ==, expires); \ + tt_i64_op((int64_t)srm_expires, ==, (int64_t)expires); \ } while (0) (void)arg; diff --git a/src/test/test_util.c b/src/test/test_util.c index 151ec6912..225fb790f 100644 --- a/src/test/test_util.c +++ b/src/test/test_util.c @@ -3741,7 +3741,7 @@ test_util_max_mem(void *arg) } else { /* You do not have a petabyte. */ #if SIZEOF_SIZE_T == SIZEOF_UINT64_T - tt_uint_op(memory1, <, (U64_LITERAL(1)<<50)); + tt_u64_op(memory1, <, (U64_LITERAL(1)<<50)); #endif }