Commit 6507ecb7 authored by David Goulet's avatar David Goulet 🐼
Browse files

hs: Fix the intro circuit max retry



Some parentheses were missing making the rend_max_intro_circs_per_period()
return a lower value than it was suppose to.

The calculation is that a service at most will open a number of intro points
that it wants which is 3 by default or HiddenServiceNumIntroductionPoints. Two
extra are launched for performance reason. Finally, this can happen twice for
two descriptors for the current and next time period.

From:
  2 * n_intro_wanted + 2

...which resulted in 8 for 3 intro points, this commit fixes it to:

  (n_intro_wanted + 2) * 2

... resulting in 12 possible intro point circuit which is the correct maximum
intro circuit allowed per period.

Last, this commit rate limits the the log message if we ever go above that
limit else over a INTRO_CIRC_RETRY_PERIOD, we can print it often!

Fixes #22159

Signed-off-by: David Goulet's avatarDavid Goulet <dgoulet@torproject.org>
parent 63fc23f8
Loading
Loading
Loading
Loading

changes/bug22159

0 → 100644
+7 −0
Original line number Diff line number Diff line
  o Minor bugfixes (hidden service):
    - A service is allowed to open a maximum number of circuits for a specific
      period of time. That value was lower than it should be (8 vs 12) in the
      normal case of 3 introduction points. Fixes bug 22159.; bugfix on
      tor-0.3.0.5-rc.
    - Rate limit the log if we ever go above the maximum number of allowed
      intro circuits. Fixes bug 22159.; bugfix on tor-0.3.1.1-alpha.
+23 −11
Original line number Diff line number Diff line
@@ -1077,16 +1077,23 @@ rend_log_intro_limit(const rend_service_t *service, int min_severity)
  }
  time_t intro_period_elapsed = time(NULL) - service->intro_period_started;
  tor_assert_nonfatal(intro_period_elapsed >= 0);
  log_fn(severity, LD_REND, "Hidden service %s %s %d intro points in the last "
         "%d seconds. Intro circuit launches are limited to %d per %d "
         "seconds.",
  {
    char *msg;
    static ratelim_t rlimit = RATELIM_INIT(INTRO_CIRC_RETRY_PERIOD);
    if ((msg = rate_limit_log(&rlimit, approx_time()))) {
      log_fn(severity, LD_REND,
             "Hidden service %s %s %d intro points in the last %d seconds. "
             "Intro circuit launches are limited to %d per %d seconds.%s",
             service->service_id,
             exceeded_limit ? "exceeded launch limit with" : "launched",
             service->n_intro_circuits_launched,
             (int)intro_period_elapsed,
             rend_max_intro_circs_per_period(service->n_intro_points_wanted),
         INTRO_CIRC_RETRY_PERIOD);
             INTRO_CIRC_RETRY_PERIOD, msg);
      rend_service_dump_stats(severity);
      tor_free(msg);
    }
  }
}

/** Replace the old value of <b>service</b>-\>desc with one that reflects
@@ -4093,7 +4100,12 @@ rend_max_intro_circs_per_period(unsigned int n_intro_points_wanted)
  /* Allow all but one of the initial connections to fail and be
   * retried. (If all fail, we *want* to wait, because something is broken.) */
  tor_assert(n_intro_points_wanted <= NUM_INTRO_POINTS_MAX);
  return (int)(2*n_intro_points_wanted + NUM_INTRO_POINTS_EXTRA);

  /* For the normal use case, 3 intro points plus 2 extra for performance and
   * allow that twice because once every 24h or so, we can do it twice for two
   * descriptors that is the current one and the next one. So (3 + 2) * 2 ==
   * 12 allowed attempts for one period. */
  return ((n_intro_points_wanted + NUM_INTRO_POINTS_EXTRA) * 2);
}

/** For every service, check how many intro points it currently has, and: