diff options
39 files changed, 269 insertions, 69 deletions
diff --git a/.travis.yml b/.travis.yml index bda1f323e5..8e258aef26 100644 --- a/.travis.yml +++ b/.travis.yml @@ -216,7 +216,7 @@ script: ## We run `make check` because that's what https://jenkins.torproject.org does. - if [[ "$DISTCHECK" == "" && "$TEST_STEM" == "" ]]; then make check; fi ## Diagnostic for bug 29437: kill stem if it hangs for 15 minutes - - if [[ "$TEST_STEM" != "" ]]; then timelimit -p -t 540 -T 30 make src/app/tor test-stem; fi + - if [[ "$TEST_STEM" != "" ]]; then make src/app/tor; timelimit -p -t 540 -s USR1 -T 30 -S ABRT python3 "$STEM_SOURCE_DIR"/run_tests.py --tor src/app/tor --integ --log notice --target RUN_ALL; fi - if [[ "$DISTCHECK" != "" && "$TEST_STEM" == "" ]]; then make distcheck DISTCHECK_CONFIGURE_FLAGS="$CONFIGURE_FLAGS"; fi ## If this build was one that produced coverage, upload it. - if [[ "$COVERAGE_OPTIONS" != "" ]]; then coveralls -b . --exclude src/test --exclude src/trunnel --gcov-options '\-p' || echo "Coverage failed"; fi @@ -230,6 +230,7 @@ after_failure: ## `make distcheck` puts it somewhere different. - if [[ "$DISTCHECK" != "" ]]; then make show-distdir-testlog || echo "make failed"; fi - if [[ "$DISTCHECK" != "" ]]; then make show-distdir-core || echo "make failed"; fi + - if [[ "$TEST_STEM" != "" ]]; then cat "$STEM_SOURCE_DIR"/test/data/tor_log || echo "cat failed"; fi before_cache: ## Delete all gcov files. diff --git a/changes/bug27199 b/changes/bug27199 new file mode 100644 index 0000000000..f9d2a422f9 --- /dev/null +++ b/changes/bug27199 @@ -0,0 +1,3 @@ + o Minor bugfixes (rust): + - Abort on panic in all build profiles, instead of potentially unwinding + into C code. Fixes bug 27199; bugfix on 0.3.3.1-alpha. diff --git a/changes/bug28269 b/changes/bug28269 new file mode 100644 index 0000000000..bdfe9e1aae --- /dev/null +++ b/changes/bug28269 @@ -0,0 +1,7 @@ + o Minor bugfixes (onion services): + - If we are launching repeated HSFETCH queries and are rate-limited, + we introduce a new controller response QUERY_RATE_LIMITED instead + of QUERY_NO_HSDIR, while keeping the latter for when onion service + directories are missing a descriptor. Previously, we returned + QUERY_NO_HSDIR for both cases. Fixes bug 28269; bugfix on + 0.3.1.1-alpha. Patch by Neel Chauhan diff --git a/changes/bug29613 b/changes/bug29613 new file mode 100644 index 0000000000..e966973255 --- /dev/null +++ b/changes/bug29613 @@ -0,0 +1,5 @@ + o Minor bugfixes (relay): + - If we are are a relay and have IPv6Exit to 1 while ExitRelay is + auto, we act as if ExitRelay is 1. Previously, we ignored IPv6Exit + if ExitRelay was 0 or auto. Fixes bug 29613; bugfix on 0.3.5.1-alpha. + Patch by Neel Chauhan. diff --git a/changes/bug30151 b/changes/bug30151 new file mode 100644 index 0000000000..8ac9a320a0 --- /dev/null +++ b/changes/bug30151 @@ -0,0 +1,5 @@ + o Minor bugfixes (tor-resolve): + - Fix a memory leak in tor-resolve that could happen if Tor gave it a + malformed SOCKS response. (Memory leaks in tor-resolve don't actually + matter, but it's good to fix them anyway.) Fixes bug 30151; bugfix on + 0.4.0.1-alpha. diff --git a/changes/diagnostic_28223_redux b/changes/diagnostic_28223_redux new file mode 100644 index 0000000000..0d7499832e --- /dev/null +++ b/changes/diagnostic_28223_redux @@ -0,0 +1,4 @@ + o Minor features (diagnostic): + - Add more diagnostic log messages in an attempt to solve + the issue of NUL bytes appearing in a microdescriptor cache. + Related to ticket 28223. diff --git a/changes/ticket27821 b/changes/ticket27821 new file mode 100644 index 0000000000..158f308fbf --- /dev/null +++ b/changes/ticket27821 @@ -0,0 +1,3 @@ + o Minor features (HTTP tunnel): + - Return an informative web page when the HTTPTunnelPort is used as an + HTTP proxy. Closes ticket 27821, patch by "eighthave". diff --git a/changes/ticket30033 b/changes/ticket30033 new file mode 100644 index 0000000000..3f66d049c8 --- /dev/null +++ b/changes/ticket30033 @@ -0,0 +1,4 @@ + o Minor features (developer tooling): + - Call pre-commit git hook from pre-push hook to make sure we're + running documentation and code style checks before pushing to remote + git repository. Implements feature 30033. diff --git a/changes/ticket30051 b/changes/ticket30051 new file mode 100644 index 0000000000..87b6d7611f --- /dev/null +++ b/changes/ticket30051 @@ -0,0 +1,5 @@ + o Minor features (developer tooling): + - Call practracker from pre-push and pre-commit git hooks to let a + developer know if they made any code style violations in their last + commit. This should help preventing code style violations appearing + upstream. Closes ticket 30051. diff --git a/changes/ticket30114 b/changes/ticket30114 new file mode 100644 index 0000000000..a80f7f4dcf --- /dev/null +++ b/changes/ticket30114 @@ -0,0 +1,3 @@ + o Minor features (git scripts): + - In git-pull-all.sh, also fetch the latest tor-github pull requests. + Implements ticket 30114. diff --git a/changes/ticket30117 b/changes/ticket30117 new file mode 100644 index 0000000000..5b6e6dabf7 --- /dev/null +++ b/changes/ticket30117 @@ -0,0 +1,4 @@ + o Testing (continuous integration): + - In Travis, tell timelimit to use stem's backtrace signals. And launch + python directly from timelimit, so python receives the signals from + timelimit, rather than make. Closes ticket 30117. diff --git a/changes/ticket30149 b/changes/ticket30149 new file mode 100644 index 0000000000..a21687ac2f --- /dev/null +++ b/changes/ticket30149 @@ -0,0 +1,3 @@ + o Code simplification and refactoring: + - Add several assertions in an attempt to fix some Coverity warnings. + Closes ticket 30149. diff --git a/changes/ticket30176 b/changes/ticket30176 new file mode 100644 index 0000000000..da23760ce5 --- /dev/null +++ b/changes/ticket30176 @@ -0,0 +1,4 @@ + o Minor features (defense in depth): + - In smartlist_remove_keeporder(), set any pointers that become + unused to NULL, in case a bug causes them to be used later. Closes + ticket 30176. Patch from Tobias Stoeckmann. diff --git a/changes/ticket30234 b/changes/ticket30234 new file mode 100644 index 0000000000..5a0076bad2 --- /dev/null +++ b/changes/ticket30234 @@ -0,0 +1,2 @@ + o Testing (continuous integration): + - In Travis, show stem's tor log after failure. Closes ticket 30234. diff --git a/doc/tor.1.txt b/doc/tor.1.txt index f992172405..cbbc3515bb 100644 --- a/doc/tor.1.txt +++ b/doc/tor.1.txt @@ -1935,13 +1935,14 @@ is non-zero): exit according to the ExitPolicy option, the ReducedExitPolicy option, or the default ExitPolicy (if no other exit policy option is specified). + + - If ExitRelay is set to 0, no traffic is allowed to - exit, and the ExitPolicy and ReducedExitPolicy options are ignored. + + If ExitRelay is set to 0, no traffic is allowed to exit, and the + ExitPolicy, ReducedExitPolicy, and IPv6Exit options are ignored. + + - If ExitRelay is set to "auto", then Tor checks the ExitPolicy and - ReducedExitPolicy options. If either is set, Tor behaves as if ExitRelay - were set to 1. If neither exit policy option is set, Tor behaves as if - ExitRelay were set to 0. (Default: auto) + If ExitRelay is set to "auto", then Tor checks the ExitPolicy, + ReducedExitPolicy, and IPv6Exit options. If at least one of these options + is set, Tor behaves as if ExitRelay were set to 1. If none of these exit + policy options are set, Tor behaves as if ExitRelay were set to 0. + (Default: auto) [[ExitPolicy]] **ExitPolicy** __policy__,__policy__,__...__:: Set an exit policy for this server. Each policy is of the form @@ -2136,8 +2137,9 @@ is non-zero): (Default: 0) [[IPv6Exit]] **IPv6Exit** **0**|**1**:: - If set, and we are an exit node, allow clients to use us for IPv6 - traffic. (Default: 0) + If set, and we are an exit node, allow clients to use us for IPv6 traffic. + When this option is set and ExitRelay is auto, we act as if ExitRelay + is 1. (Default: 0) [[MaxOnionQueueDelay]] **MaxOnionQueueDelay** __NUM__ [**msec**|**second**]:: If we have more onionskins queued for processing than we can process in diff --git a/scripts/git/git-pull-all.sh b/scripts/git/git-pull-all.sh index 0a4898a111..5d1d58e4bf 100755 --- a/scripts/git/git-pull-all.sh +++ b/scripts/git/git-pull-all.sh @@ -174,6 +174,19 @@ function fetch_origin fi } +# Fetch tor-github pull requests. No arguments. +function fetch_tor_github +{ + local cmd="git fetch tor-github" + printf " %s Fetching tor-github..." "$MARKER" + if [ $DRY_RUN -eq 0 ]; then + msg=$( eval "$cmd" 2>&1 ) + validate_ret $? "$msg" + else + printf "\\n %s\\n" "${IWTH}$cmd${CNRM}" + fi +} + ############### # Entry point # ############### @@ -188,8 +201,11 @@ while getopts "n" opt; do esac done -# First, fetch the origin. +# First, fetch tor-github. goto_repo "$ORIGIN_PATH" +fetch_tor_github + +# Then, fetch the origin. fetch_origin # Go over all configured worktree. diff --git a/scripts/git/pre-commit.git-hook b/scripts/git/pre-commit.git-hook index 65fa99f4c4..b285776c04 100755 --- a/scripts/git/pre-commit.git-hook +++ b/scripts/git/pre-commit.git-hook @@ -12,7 +12,7 @@ cd "$workdir" || exit 1 set -e -if [ ! -z "ls ./changes/*" ]; then +if [ -n "$(ls ./changes/)" ]; then python scripts/maint/lintChanges.py ./changes/* fi @@ -26,7 +26,7 @@ if [ -d src/lib ]; then src/test/*.[ch] \ src/test/*/*.[ch] \ src/tools/*.[ch] -elif [ -d src/common]; then +elif [ -d src/common ]; then # This was the layout before 0.3.5 perl scripts/maint/checkSpace.pl -C \ src/common/*/*.[ch] \ @@ -39,3 +39,7 @@ fi if test -e scripts/maint/checkIncludes.py; then python scripts/maint/checkIncludes.py fi + +if [ -e scripts/maint/practracker/practracker.py ]; then + python3 ./scripts/maint/practracker/practracker.py "$workdir" +fi diff --git a/scripts/git/pre-push.git-hook b/scripts/git/pre-push.git-hook index e7a72efa08..740180d6f6 100755 --- a/scripts/git/pre-push.git-hook +++ b/scripts/git/pre-push.git-hook @@ -27,6 +27,19 @@ ref_is_upstream_branch() { fi } +workdir=$(git rev-parse --show-toplevel) +if [ -x "$workdir/.git/hooks/pre-commit" ]; then + if ! "$workdir"/.git/hooks/pre-commit; then + exit 1 + fi +fi + +if [ -e scripts/maint/practracker/practracker.py ]; then + if ! python3 ./scripts/maint/practracker/practracker.py "$workdir"; then + exit 1 + fi +fi + # shellcheck disable=SC2034 while read -r local_ref local_sha remote_ref remote_sha do diff --git a/scripts/maint/practracker/exceptions.txt b/scripts/maint/practracker/exceptions.txt index 7d03bf27d6..1992c563ac 100644 --- a/scripts/maint/practracker/exceptions.txt +++ b/scripts/maint/practracker/exceptions.txt @@ -102,7 +102,7 @@ problem function-size /src/core/or/circuituse.c:circuit_get_open_circ_or_launch( problem function-size /src/core/or/circuituse.c:connection_ap_handshake_attach_circuit() 244 problem function-size /src/core/or/command.c:command_process_create_cell() 156 problem function-size /src/core/or/command.c:command_process_relay_cell() 132 -problem file-size /src/core/or/connection_edge.c 4550 +problem file-size /src/core/or/connection_edge.c 4575 problem include-count /src/core/or/connection_edge.c 64 problem function-size /src/core/or/connection_edge.c:connection_ap_expire_beginning() 117 problem function-size /src/core/or/connection_edge.c:connection_ap_handshake_rewrite() 192 @@ -117,7 +117,7 @@ problem include-count /src/core/or/connection_or.c 51 problem function-size /src/core/or/connection_or.c:connection_or_group_set_badness_() 105 problem function-size /src/core/or/connection_or.c:connection_or_client_learned_peer_id() 144 problem function-size /src/core/or/connection_or.c:connection_or_compute_authenticate_cell_body() 235 -problem file-size /src/core/or/policies.c 3163 +problem file-size /src/core/or/policies.c 3171 problem function-size /src/core/or/policies.c:policy_summarize() 107 problem function-size /src/core/or/protover.c:protover_all_supported() 116 problem file-size /src/core/or/relay.c 3173 @@ -187,7 +187,7 @@ problem function-size /src/feature/dirclient/dirclient.c:handle_response_fetch_c problem function-size /src/feature/dircommon/consdiff.c:gen_ed_diff() 204 problem function-size /src/feature/dircommon/consdiff.c:apply_ed_diff() 159 problem function-size /src/feature/dirparse/authcert_parse.c:authority_cert_parse_from_string() 182 -problem function-size /src/feature/dirparse/microdesc_parse.c:microdescs_parse_from_string() 154 +problem function-size /src/feature/dirparse/microdesc_parse.c:microdescs_parse_from_string() 169 problem function-size /src/feature/dirparse/ns_parse.c:routerstatus_parse_entry_from_string() 286 problem function-size /src/feature/dirparse/ns_parse.c:networkstatus_verify_bw_weights() 389 problem function-size /src/feature/dirparse/ns_parse.c:networkstatus_parse_vote_from_string() 638 @@ -218,7 +218,7 @@ problem include-count /src/feature/nodelist/networkstatus.c 61 problem function-size /src/feature/nodelist/networkstatus.c:networkstatus_check_consensus_signature() 176 problem function-size /src/feature/nodelist/networkstatus.c:networkstatus_set_current_consensus() 293 problem function-size /src/feature/nodelist/node_select.c:router_pick_directory_server_impl() 123 -problem function-size /src/feature/nodelist/node_select.c:compute_weighted_bandwidths() 205 +problem function-size /src/feature/nodelist/node_select.c:compute_weighted_bandwidths() 206 problem function-size /src/feature/nodelist/node_select.c:router_pick_trusteddirserver_impl() 114 problem function-size /src/feature/nodelist/nodelist.c:compute_frac_paths_available() 193 problem file-size /src/feature/nodelist/routerlist.c 3234 diff --git a/src/config/torrc.sample.in b/src/config/torrc.sample.in index c2ae707e93..9d514e6bda 100644 --- a/src/config/torrc.sample.in +++ b/src/config/torrc.sample.in @@ -174,13 +174,11 @@ ## Uncomment this if you want your relay to be an exit, with the default ## exit policy (or whatever exit policy you set below). -## (If ReducedExitPolicy or ExitPolicy are set, relays are exits. -## If neither exit policy option is set, relays are non-exits.) +## (If ReducedExitPolicy, ExitPolicy, or IPv6Exit are set, relays are exits. +## If none of these options are set, relays are non-exits.) #ExitRelay 1 ## Uncomment this if you want your relay to allow IPv6 exit traffic. -## You must also set ExitRelay, ReducedExitPolicy, or ExitPolicy to make your -## relay into an exit. ## (Relays do not allow any exit traffic by default.) #IPv6Exit 1 diff --git a/src/core/or/connection_edge.c b/src/core/or/connection_edge.c index 071a8c91ed..33ba723971 100644 --- a/src/core/or/connection_edge.c +++ b/src/core/or/connection_edge.c @@ -2810,6 +2810,31 @@ connection_ap_process_natd(entry_connection_t *conn) return connection_ap_rewrite_and_attach_if_allowed(conn, NULL, NULL); } +static const char HTTP_CONNECT_IS_NOT_AN_HTTP_PROXY_MSG[] = + "HTTP/1.0 405 Method Not Allowed\r\n" + "Content-Type: text/html; charset=iso-8859-1\r\n\r\n" + "<html>\n" + "<head>\n" + "<title>This is an HTTP CONNECT tunnel, not an full HTTP Proxy</title>\n" + "</head>\n" + "<body>\n" + "<h1>This is an HTTP CONNECT tunnel, not an HTTP proxy.</h1>\n" + "<p>\n" + "It appears you have configured your web browser to use this Tor port as\n" + "an HTTP proxy.\n" + "</p><p>\n" + "This is not correct: This port is configured as a CONNECT tunnel, not\n" + "an HTTP proxy. Please configure your client accordingly. You can also\n" + "use HTTPS, then the client should automatically use HTTP CONNECT." + "</p>\n" + "<p>\n" + "See <a href=\"https://www.torproject.org/documentation.html\">" + "https://www.torproject.org/documentation.html</a> for more " + "information.\n" + "</p>\n" + "</body>\n" + "</html>\n"; + /** Called on an HTTP CONNECT entry connection when some bytes have arrived, * but we have not yet received a full HTTP CONNECT request. Try to parse an * HTTP CONNECT request from the connection's inbuf. On success, set up the @@ -2850,7 +2875,7 @@ connection_ap_process_http_connect(entry_connection_t *conn) tor_assert(command); tor_assert(addrport); if (strcasecmp(command, "connect")) { - errmsg = "HTTP/1.0 405 Method Not Allowed\r\n\r\n"; + errmsg = HTTP_CONNECT_IS_NOT_AN_HTTP_PROXY_MSG; goto err; } diff --git a/src/core/or/policies.c b/src/core/or/policies.c index a6d66d36de..f59894ea8f 100644 --- a/src/core/or/policies.c +++ b/src/core/or/policies.c @@ -1164,6 +1164,15 @@ authdir_policy_badexit_address(uint32_t addr, uint16_t port) #define REJECT(arg) \ STMT_BEGIN *msg = tor_strdup(arg); goto err; STMT_END +/** Check <b>or_options</b> to determine whether or not we are using the + * default options for exit policy. Return true if so, false otherwise. */ +static int +policy_using_default_exit_options(const or_options_t *or_options) +{ + return (or_options->ExitPolicy == NULL && or_options->ExitRelay == -1 && + or_options->ReducedExitPolicy == 0 && or_options->IPv6Exit == 0); +} + /** Config helper: If there's any problem with the policy configuration * options in <b>options</b>, return -1 and set <b>msg</b> to a newly * allocated description of the error. Else return 0. */ @@ -1182,9 +1191,8 @@ validate_addr_policies(const or_options_t *options, char **msg) static int warned_about_nonexit = 0; - if (public_server_mode(options) && - !warned_about_nonexit && options->ExitPolicy == NULL && - options->ExitRelay == -1 && options->ReducedExitPolicy == 0) { + if (public_server_mode(options) && !warned_about_nonexit && + policy_using_default_exit_options(options)) { warned_about_nonexit = 1; log_notice(LD_CONFIG, "By default, Tor does not run as an exit relay. " "If you want to be an exit relay, " @@ -2141,9 +2149,9 @@ policies_parse_exit_policy_from_options(const or_options_t *or_options, int rv = 0; /* Short-circuit for non-exit relays, or for relays where we didn't specify - * ExitPolicy or ReducedExitPolicy and ExitRelay is auto. */ - if (or_options->ExitRelay == 0 || (or_options->ExitPolicy == NULL && - or_options->ExitRelay == -1 && or_options->ReducedExitPolicy == 0)) { + * ExitPolicy or ReducedExitPolicy or IPv6Exit and ExitRelay is auto. */ + if (or_options->ExitRelay == 0 || + policy_using_default_exit_options(or_options)) { append_exit_policy_string(result, "reject *4:*"); append_exit_policy_string(result, "reject *6:*"); return 0; diff --git a/src/feature/client/circpathbias.c b/src/feature/client/circpathbias.c index 1743ab5a81..e6af649ba7 100644 --- a/src/feature/client/circpathbias.c +++ b/src/feature/client/circpathbias.c @@ -176,6 +176,7 @@ pathbias_get_scale_threshold(const or_options_t *options) static double pathbias_get_scale_ratio(const or_options_t *options) { + (void) options; /* * The scale factor is the denominator for our scaling * of circuit counts for our path bias window. @@ -185,7 +186,8 @@ pathbias_get_scale_ratio(const or_options_t *options) */ int denominator = networkstatus_get_param(NULL, "pb_scalefactor", 2, 2, INT32_MAX); - (void) options; + tor_assert(denominator > 0); + /** * The mult factor is the numerator for our scaling * of circuit counts for our path bias window. It diff --git a/src/feature/dirparse/microdesc_parse.c b/src/feature/dirparse/microdesc_parse.c index 3b11e65ca0..22cc1e272e 100644 --- a/src/feature/dirparse/microdesc_parse.c +++ b/src/feature/dirparse/microdesc_parse.c @@ -160,7 +160,22 @@ microdescs_parse_from_string(const char *s, const char *eos, if (tokenize_string(area, s, start_of_next_microdesc, tokens, microdesc_token_table, flags)) { - log_warn(LD_DIR, "Unparseable microdescriptor"); + const char *location; + switch (where) { + case SAVED_NOWHERE: + location = "download or generated string"; + break; + case SAVED_IN_CACHE: + location = "cache"; + break; + case SAVED_IN_JOURNAL: + location = "journal"; + break; + default: + location = "unknown location"; + break; + } + log_warn(LD_DIR, "Unparseable microdescriptor found in %s", location); goto next; } diff --git a/src/feature/hs/hs_client.c b/src/feature/hs/hs_client.c index 38b9646c17..7aec6d80bb 100644 --- a/src/feature/hs/hs_client.c +++ b/src/feature/hs/hs_client.c @@ -424,7 +424,7 @@ pick_hsdir_v3(const ed25519_public_key_t *onion_identity_pk) /* Pick an HSDir from the responsible ones. The ownership of * responsible_hsdirs is given to this function so no need to free it. */ - hsdir_rs = hs_pick_hsdir(responsible_hsdirs, base64_blinded_pubkey); + hsdir_rs = hs_pick_hsdir(responsible_hsdirs, base64_blinded_pubkey, NULL); return hsdir_rs; } diff --git a/src/feature/hs/hs_common.c b/src/feature/hs/hs_common.c index b2227432d2..d4736c2862 100644 --- a/src/feature/hs/hs_common.c +++ b/src/feature/hs/hs_common.c @@ -1589,20 +1589,25 @@ hs_purge_last_hid_serv_requests(void) /** Given the list of responsible HSDirs in <b>responsible_dirs</b>, pick the * one that we should use to fetch a descriptor right now. Take into account * previous failed attempts at fetching this descriptor from HSDirs using the - * string identifier <b>req_key_str</b>. + * string identifier <b>req_key_str</b>. We return whether we are rate limited + * into *<b>is_rate_limited_out</b> if it is not NULL. * * Steals ownership of <b>responsible_dirs</b>. * * Return the routerstatus of the chosen HSDir if successful, otherwise return * NULL if no HSDirs are worth trying right now. */ routerstatus_t * -hs_pick_hsdir(smartlist_t *responsible_dirs, const char *req_key_str) +hs_pick_hsdir(smartlist_t *responsible_dirs, const char *req_key_str, + bool *is_rate_limited_out) { smartlist_t *usable_responsible_dirs = smartlist_new(); const or_options_t *options = get_options(); routerstatus_t *hs_dir; time_t now = time(NULL); int excluded_some; + bool rate_limited = false; + int rate_limited_count = 0; + int responsible_dirs_count = smartlist_len(responsible_dirs); tor_assert(req_key_str); @@ -1622,6 +1627,7 @@ hs_pick_hsdir(smartlist_t *responsible_dirs, const char *req_key_str) if (last + hs_hsdir_requery_period(options) >= now || !node || !node_has_preferred_descriptor(node, 0)) { SMARTLIST_DEL_CURRENT(responsible_dirs, dir); + rate_limited_count++; continue; } if (!routerset_contains_node(options->ExcludeNodes, node)) { @@ -1629,6 +1635,10 @@ hs_pick_hsdir(smartlist_t *responsible_dirs, const char *req_key_str) } } SMARTLIST_FOREACH_END(dir); + if (rate_limited_count > 0 || responsible_dirs_count > 0) { + rate_limited = rate_limited_count == responsible_dirs_count; + } + excluded_some = smartlist_len(usable_responsible_dirs) < smartlist_len(responsible_dirs); @@ -1640,9 +1650,10 @@ hs_pick_hsdir(smartlist_t *responsible_dirs, const char *req_key_str) smartlist_free(responsible_dirs); smartlist_free(usable_responsible_dirs); if (!hs_dir) { + const char *warn_str = (rate_limited) ? "we are rate limited." : + "we requested them all recently without success"; log_info(LD_REND, "Could not pick one of the responsible hidden " - "service directories, because we requested them all " - "recently without success."); + "service directories, because %s.", warn_str); if (options->StrictNodes && excluded_some) { log_warn(LD_REND, "Could not pick a hidden service directory for the " "requested hidden service: they are all either down or " @@ -1654,6 +1665,10 @@ hs_pick_hsdir(smartlist_t *responsible_dirs, const char *req_key_str) hs_lookup_last_hid_serv_request(hs_dir, req_key_str, now, 1); } + if (is_rate_limited_out != NULL) { + *is_rate_limited_out = rate_limited; + } + return hs_dir; } diff --git a/src/feature/hs/hs_common.h b/src/feature/hs/hs_common.h index abf39fa431..3009780d90 100644 --- a/src/feature/hs/hs_common.h +++ b/src/feature/hs/hs_common.h @@ -241,7 +241,8 @@ void hs_get_responsible_hsdirs(const struct ed25519_public_key_t *blinded_pk, int use_second_hsdir_index, int for_fetching, smartlist_t *responsible_dirs); routerstatus_t *hs_pick_hsdir(smartlist_t *responsible_dirs, - const char *req_key_str); + const char *req_key_str, + bool *is_rate_limited_out); time_t hs_hsdir_requery_period(const or_options_t *options); time_t hs_lookup_last_hid_serv_request(routerstatus_t *hs_dir, diff --git a/src/feature/nodelist/microdesc.c b/src/feature/nodelist/microdesc.c index b4f05b63a0..36922561a0 100644 --- a/src/feature/nodelist/microdesc.c +++ b/src/feature/nodelist/microdesc.c @@ -70,6 +70,8 @@ struct microdesc_cache_t { }; static microdesc_cache_t *get_microdesc_cache_noload(void); +static void warn_if_nul_found(const char *inp, size_t len, int64_t offset, + const char *activity); /** Helper: computes a hash of <b>md</b> to place it in a hash table. */ static inline unsigned int @@ -223,6 +225,8 @@ dump_microdescriptor(int fd, microdesc_t *md, size_t *annotation_len_out) } md->off = tor_fd_getpos(fd); + warn_if_nul_found(md->body, md->bodylen, (int64_t) md->off, + "dumping a microdescriptor"); written = write_all_to_fd(fd, md->body, md->bodylen); if (written != (ssize_t)md->bodylen) { written = written < 0 ? 0 : written; @@ -482,6 +486,27 @@ microdesc_cache_clear(microdesc_cache_t *cache) cache->bytes_dropped = 0; } +static void +warn_if_nul_found(const char *inp, size_t len, int64_t offset, + const char *activity) +{ + const char *nul_found = memchr(inp, 0, len); + if (BUG(nul_found)) { + log_warn(LD_BUG, "Found unexpected NUL while %s, offset %"PRId64 + "at position %"TOR_PRIuSZ"/%"TOR_PRIuSZ".", + activity, offset, (nul_found - inp), len); + const char *start_excerpt_at, *eos = inp + len; + if ((nul_found - inp) >= 16) + start_excerpt_at = nul_found - 16; + else + start_excerpt_at = inp; + size_t excerpt_len = MIN(32, eos - start_excerpt_at); + char tmp[65]; + base16_encode(tmp, sizeof(tmp), start_excerpt_at, excerpt_len); + log_warn(LD_BUG, " surrounding string: %s", tmp); + } +} + /** Reload the contents of <b>cache</b> from disk. If it is empty, load it * for the first time. Return 0 on success, -1 on failure. */ int @@ -499,6 +524,7 @@ microdesc_cache_reload(microdesc_cache_t *cache) mm = cache->cache_content = tor_mmap_file(cache->cache_fname); if (mm) { + warn_if_nul_found(mm->data, mm->size, 0, "scanning microdesc cache"); added = microdescs_add_to_cache(cache, mm->data, mm->data+mm->size, SAVED_IN_CACHE, 0, -1, NULL); if (added) { @@ -511,6 +537,8 @@ microdesc_cache_reload(microdesc_cache_t *cache) RFTS_IGNORE_MISSING, &st); if (journal_content) { cache->journal_len = (size_t) st.st_size; + warn_if_nul_found(journal_content, cache->journal_len, 0, + "reading microdesc journal"); added = microdescs_add_to_cache(cache, journal_content, journal_content+st.st_size, SAVED_IN_JOURNAL, 0, -1, NULL); diff --git a/src/feature/nodelist/node_select.c b/src/feature/nodelist/node_select.c index e31abb247f..93ddb066d4 100644 --- a/src/feature/nodelist/node_select.c +++ b/src/feature/nodelist/node_select.c @@ -585,6 +585,7 @@ compute_weighted_bandwidths(const smartlist_t *sl, } weight_scale = networkstatus_get_weight_scale_param(NULL); + tor_assert(weight_scale >= 1); if (rule == WEIGHT_FOR_GUARD) { Wg = networkstatus_get_bw_weight(NULL, "Wgg", -1); diff --git a/src/feature/relay/onion_queue.c b/src/feature/relay/onion_queue.c index 696905cf5e..c37745cf33 100644 --- a/src/feature/relay/onion_queue.c +++ b/src/feature/relay/onion_queue.c @@ -212,10 +212,12 @@ num_ntors_per_tap(void) #define MIN_NUM_NTORS_PER_TAP 1 #define MAX_NUM_NTORS_PER_TAP 100000 - return networkstatus_get_param(NULL, "NumNTorsPerTAP", - DEFAULT_NUM_NTORS_PER_TAP, - MIN_NUM_NTORS_PER_TAP, - MAX_NUM_NTORS_PER_TAP); + int result = networkstatus_get_param(NULL, "NumNTorsPerTAP", + DEFAULT_NUM_NTORS_PER_TAP, + MIN_NUM_NTORS_PER_TAP, + MAX_NUM_NTORS_PER_TAP); + tor_assert(result > 0); + return result; } /** Choose which onion queue we'll pull from next. If one is empty choose diff --git a/src/feature/rend/rendclient.c b/src/feature/rend/rendclient.c index 5a8b234544..f84d221b1a 100644 --- a/src/feature/rend/rendclient.c +++ b/src/feature/rend/rendclient.c @@ -469,16 +469,19 @@ directory_get_from_hs_dir(const char *desc_id, /* Automatically pick an hs dir if none given. */ if (!rs_hsdir) { + bool rate_limited = false; + /* Determine responsible dirs. Even if we can't get all we want, work with * the ones we have. If it's empty, we'll notice in hs_pick_hsdir(). */ smartlist_t *responsible_dirs = smartlist_new(); hid_serv_get_responsible_directories(responsible_dirs, desc_id); - hs_dir = hs_pick_hsdir(responsible_dirs, desc_id_base32); + hs_dir = hs_pick_hsdir(responsible_dirs, desc_id_base32, &rate_limited); if (!hs_dir) { /* No suitable hs dir can be found, stop right now. */ - control_event_hsv2_descriptor_failed(rend_query, NULL, - "QUERY_NO_HSDIR"); + const char *query_response = (rate_limited) ? "QUERY_RATE_LIMITED" : + "QUERY_NO_HSDIR"; + control_event_hsv2_descriptor_failed(rend_query, NULL, query_response); control_event_hs_descriptor_content(rend_data_get_address(rend_query), desc_id_base32, NULL, NULL); return 0; diff --git a/src/lib/fdio/fdio.c b/src/lib/fdio/fdio.c index 6c87af791d..078af6a9ba 100644 --- a/src/lib/fdio/fdio.c +++ b/src/lib/fdio/fdio.c @@ -17,12 +17,16 @@ #ifdef _WIN32 #include <windows.h> #endif +#ifdef HAVE_SYS_TYPES_H +#include <sys/types.h> +#endif #include "lib/fdio/fdio.h" #include "lib/cc/torint.h" #include "lib/err/torerr.h" #include <stdlib.h> +#include <stdio.h> /** @{ */ /** Some old versions of Unix didn't define constants for these values, diff --git a/src/lib/math/prob_distr.h b/src/lib/math/prob_distr.h index 2eb935e4a8..8fccf8d015 100644 --- a/src/lib/math/prob_distr.h +++ b/src/lib/math/prob_distr.h @@ -53,7 +53,7 @@ struct dist { * We define this conditionally to suppress false positives from * Coverity, which gets confused by the sizeof business. */ -#ifdef __COVERITY___ +#ifdef __COVERITY__ #define TYPE_CHECK_OBJ(OPS, OBJ, TYPE) 0 #else #define TYPE_CHECK_OBJ(OPS, OBJ, TYPE) \ diff --git a/src/lib/smartlist_core/smartlist_core.c b/src/lib/smartlist_core/smartlist_core.c index 5947e76271..6b0a305a93 100644 --- a/src/lib/smartlist_core/smartlist_core.c +++ b/src/lib/smartlist_core/smartlist_core.c @@ -177,6 +177,8 @@ smartlist_remove_keeporder(smartlist_t *sl, const void *element) sl->list[i++] = sl->list[j]; } } + memset(sl->list + sl->num_used, 0, + sizeof(void *) * (num_used_orig - sl->num_used)); } /** If <b>sl</b> is nonempty, remove and return the final element. Otherwise, diff --git a/src/rust/Cargo.toml b/src/rust/Cargo.toml index 83f9629660..de8693ea33 100644 --- a/src/rust/Cargo.toml +++ b/src/rust/Cargo.toml @@ -10,6 +10,17 @@ members = [ "tor_util", ] +# Can remove panic="abort" when this issue is fixed: +# https://github.com/rust-lang/rust/issues/52652 +[profile.dev] +panic = "abort" + [profile.release] debug = true panic = "abort" + +[profile.test] +panic = "abort" + +[profile.bench] +panic = "abort" diff --git a/src/test/test-network.sh b/src/test/test-network.sh index 4d56e83806..5ef995f1a4 100755 --- a/src/test/test-network.sh +++ b/src/test/test-network.sh @@ -1,4 +1,4 @@ -#!/usr/bin/env bash +#!/bin/sh # This script calls the equivalent script in chutney/tools @@ -18,32 +18,14 @@ ECHO="${ECHO:-echo}" # Output is prefixed with the name of the script myname=$(basename "$0") -# Save the arguments before we destroy them -# This might not preserve arguments with spaces in them -ORIGINAL_ARGS=( "$@" ) - # We need to find CHUTNEY_PATH, so that we can call the version of this script # in chutney/tools with the same arguments. We also need to respect --quiet. -until [ -z "$1" ] -do - case "$1" in - --chutney-path) - CHUTNEY_PATH="$2" - shift - ;; - --tor-path) - TOR_DIR="$2" - shift - ;; - --quiet) - ECHO=true - ;; - *) - # maybe chutney's test-network.sh can handle it - ;; - esac - shift -done +CHUTNEY_PATH=$(echo "$@" | awk -F '--chutney-path ' '{sub(" .*","",$2); print $2}') +TOR_DIR=$(echo "$@" | awk -F '--tor-dir ' '{sub(" .*","",$2); print $2}') + +if echo "$@" | grep -e "--quiet" > /dev/null; then + ECHO=true +fi # optional: $TOR_DIR is the tor build directory # it's used to find the location of tor binaries @@ -99,7 +81,7 @@ if [ -d "$CHUTNEY_PATH" ] && [ -x "$TEST_NETWORK" ]; then # this may fail if some arguments have spaces in them # if so, set CHUTNEY_PATH before calling test-network.sh, and spaces # will be handled correctly - exec "$TEST_NETWORK" "${ORIGINAL_ARGS[@]}" # $ORIGINAL_ARGS + exec "$TEST_NETWORK" "$@" else $ECHO "$myname: Could not find tools/test-network.sh in CHUTNEY_PATH." $ECHO "$myname: Please update your chutney using 'git pull'." diff --git a/src/test/test_containers.c b/src/test/test_containers.c index 7892a08853..67ba457975 100644 --- a/src/test/test_containers.c +++ b/src/test/test_containers.c @@ -1006,6 +1006,10 @@ test_container_smartlist_remove(void *arg) tt_ptr_op(smartlist_get(sl, 1), OP_EQ, &array[2]); tt_ptr_op(smartlist_get(sl, 2), OP_EQ, &array[1]); tt_ptr_op(smartlist_get(sl, 3), OP_EQ, &array[2]); + /* Ordinary code should never look at this pointer; we're doing it here + * to make sure that we really cleared the pointer we removed. + */ + tt_ptr_op(sl->list[4], OP_EQ, NULL); done: smartlist_free(sl); diff --git a/src/test/test_hs.c b/src/test/test_hs.c index aeb3387471..5d3327c777 100644 --- a/src/test/test_hs.c +++ b/src/test/test_hs.c @@ -323,6 +323,16 @@ test_hs_desc_event(void *arg) tt_str_op(received_msg,OP_EQ, expected_msg); tor_free(received_msg); + /* test HSDir rate limited */ + rend_query.auth_type = REND_NO_AUTH; + control_event_hsv2_descriptor_failed(&rend_query.base_, NULL, + "QUERY_RATE_LIMITED"); + expected_msg = "650 HS_DESC FAILED "STR_HS_ADDR" NO_AUTH " \ + "UNKNOWN REASON=QUERY_RATE_LIMITED\r\n"; + tt_assert(received_msg); + tt_str_op(received_msg,OP_EQ, expected_msg); + tor_free(received_msg); + /* Test invalid content with no HSDir fingerprint. */ char *exp_msg; control_event_hs_descriptor_content(rend_query.onion_address, diff --git a/src/tools/tor-resolve.c b/src/tools/tor-resolve.c index 98b3a4a74c..5d97696c18 100644 --- a/src/tools/tor-resolve.c +++ b/src/tools/tor-resolve.c @@ -424,6 +424,7 @@ do_resolve(const char *hostname, if (parsed < 2) { log_err(LD_NET, "Failed to parse SOCKS5 method selection " "message"); + socks5_server_method_free(m); goto err; } |