瀏覽代碼

Merge commit 'origin/maint-0.2.1'

Nick Mathewson 16 年之前
父節點
當前提交
77ffd6b2a7
共有 9 個文件被更改,包括 138 次插入15 次删除
  1. 10 0
      ChangeLog
  2. 19 0
      src/common/compat.c
  3. 3 0
      src/common/compat.h
  4. 2 0
      src/common/util.c
  5. 58 8
      src/or/circuitbuild.c
  6. 38 5
      src/or/config.c
  7. 5 0
      src/or/control.c
  8. 2 1
      src/or/or.h
  9. 1 1
      src/or/routerlist.c

+ 10 - 0
ChangeLog

@@ -29,10 +29,20 @@ Changes in version 0.2.1.16-?? - 2009-??-??
   o Minor bugfixes (on 0.2.0.x):
     - Log correct error messages for DNS-related network errors on
       Windows.
+    - Don't warn users about low port and hibernation mix when they
+      provide a *ListenAddress directive to fix that. Bugfix on
+      0.2.1.15-rc.
+    - Fix a race condition that could cause crashes or memory
+      corruption when running as a server with a controller listening
+      for log messages.
 
   o Minor bugfixes (on 0.2.1.x):
     - When switching back and forth between bridge mode, do not start
       gathering GeoIP data until two hours have passed.
+    - Do not complain that the user has requested an excluded node as
+      an exit when the node is not really an exit.  This could happen
+      because the circuit was for testing, or an introduction point.
+      Fix for bug 984.
 
 
 Changes in version 0.2.1.15-rc - 2009-05-25

+ 19 - 0
src/common/compat.c

@@ -2076,6 +2076,7 @@ tor_threads_init(void)
     pthread_mutexattr_init(&attr_reentrant);
     pthread_mutexattr_settype(&attr_reentrant, PTHREAD_MUTEX_RECURSIVE);
     threads_initialized = 1;
+    set_main_thread();
   }
 }
 #elif defined(USE_WIN32_THREADS)
@@ -2168,9 +2169,27 @@ tor_threads_init(void)
 #if 0
   cond_event_tls_index = TlsAlloc();
 #endif
+  set_main_thread();
 }
 #endif
 
+/** Identity of the "main" thread */
+static unsigned long main_thread_id = -1;
+
+/** Start considering the current thread to be the 'main thread'.  This has
+ * no effect on anything besides in_main_thread(). */
+void
+set_main_thread(void)
+{
+  main_thread_id = tor_get_thread_id();
+}
+/** Return true iff called from the main thread. */
+int
+in_main_thread(void)
+{
+  return main_thread_id == tor_get_thread_id();
+}
+
 /**
  * On Windows, WSAEWOULDBLOCK is not always correct: when you see it,
  * you need to ask the socket for its actual errno.  Also, you need to

+ 3 - 0
src/common/compat.h

@@ -522,6 +522,9 @@ void tor_threads_init(void);
 #define tor_threads_init() STMT_NIL
 #endif
 
+void set_main_thread(void);
+int in_main_thread(void);
+
 #ifdef TOR_IS_MULTITHREADED
 #if 0
 typedef struct tor_cond_t tor_cond_t;

+ 2 - 0
src/common/util.c

@@ -2480,6 +2480,8 @@ start_daemon(void)
     if (fork() != 0) {
       exit(0);
     }
+    set_main_thread(); /* We are now the main thread. */
+
     return;
   }
 }

+ 58 - 8
src/or/circuitbuild.c

@@ -1436,17 +1436,67 @@ choose_good_exit_server(uint8_t purpose, routerlist_t *dir,
 /** Log a warning if the user specified an exit for the circuit that
  * has been excluded from use by ExcludeNodes or ExcludeExitNodes. */
 static void
-warn_if_router_excluded(const extend_info_t *exit)
+warn_if_last_router_excluded(uint8_t purpose, const extend_info_t *exit)
 {
   or_options_t *options = get_options();
-  routerinfo_t *ri = router_get_by_digest(exit->identity_digest);
+  routerset_t *rs = options->ExcludeNodes;
+  const char *description;
+  int severity;
+  int domain = LD_CIRC;
 
-  if (!ri || !options->_ExcludeExitNodesUnion)
-    return;
+  switch (purpose)
+    {
+    default:
+    case CIRCUIT_PURPOSE_OR:
+    case CIRCUIT_PURPOSE_INTRO_POINT:
+    case CIRCUIT_PURPOSE_REND_POINT_WAITING:
+    case CIRCUIT_PURPOSE_REND_ESTABLISHED:
+      log_warn(LD_BUG, "Called on non-origin circuit (purpose %d)",
+               (int)purpose);
+      return;
+    case CIRCUIT_PURPOSE_C_GENERAL:
+      description = "Requested exit node";
+      rs = options->_ExcludeExitNodesUnion;
+      severity = LOG_WARN;
+      break;
+    case CIRCUIT_PURPOSE_C_INTRODUCING:
+    case CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT:
+    case CIRCUIT_PURPOSE_C_INTRODUCE_ACKED:
+      description = "Introduction point for hidden service";
+      severity = LOG_INFO;
+      break;
+    case CIRCUIT_PURPOSE_C_ESTABLISH_REND:
+    case CIRCUIT_PURPOSE_C_REND_READY:
+    case CIRCUIT_PURPOSE_C_REND_READY_INTRO_ACKED:
+    case CIRCUIT_PURPOSE_C_REND_JOINED:
+      description = "Chosen rendezvous point";
+      severity = LOG_WARN;
+      domain = LD_BUG;
+      break;
+    case CIRCUIT_PURPOSE_S_ESTABLISH_INTRO:
+      description = "Chosen introduction point";
+      severity = LOG_INFO;
+      break;
+    case CIRCUIT_PURPOSE_S_CONNECT_REND:
+    case CIRCUIT_PURPOSE_S_REND_JOINED:
+      description = "Client-selected rendezvous point";
+      severity = LOG_INFO;
+      break;
+    case CIRCUIT_PURPOSE_TESTING:
+      description = "Target for testing circuit";
+      severity = LOG_INFO;
+      break;
+    case CIRCUIT_PURPOSE_CONTROLLER:
+      rs = options->_ExcludeExitNodesUnion;
+      description = "Controller-selected circuit target";
+      severity = LOG_WARN;
+      break;
+    }
 
-  if (routerset_contains_router(options->_ExcludeExitNodesUnion, ri))
-    log_warn(LD_CIRC,"Requested exit node '%s' is in ExcludeNodes, "
-             "or ExcludeExitNodes, using anyway.",exit->nickname);
+  if (routerset_contains_extendinfo(rs, exit))
+    log_fn(severity, domain, "%s '%s' is in ExcludeNodes%s.  Using anyway.",
+           description,exit->nickname,
+           rs==options->ExcludeNodes?"":" or ExcludeExitNodes.");
 
   return;
 }
@@ -1471,7 +1521,7 @@ onion_pick_cpath_exit(origin_circuit_t *circ, extend_info_t *exit)
   }
 
   if (exit) { /* the circuit-builder pre-requested one */
-    warn_if_router_excluded(exit);
+    warn_if_last_router_excluded(circ->_base.purpose, exit);
     log_info(LD_CIRC,"Using requested exit node '%s'", exit->nickname);
     exit = extend_info_dup(exit);
   } else { /* we have to decide one */

+ 38 - 5
src/or/config.c

@@ -699,6 +699,9 @@ static int or_state_validate(or_state_t *old_options, or_state_t *options,
 static int or_state_load(void);
 static int options_init_logs(or_options_t *options, int validate_only);
 
+static int is_listening_on_low_port(uint16_t port_option,
+                                    const config_line_t *listen_options);
+
 static uint64_t config_parse_memunit(const char *s, int *ok);
 static int config_parse_interval(const char *s, int *ok);
 static void init_libevent(void);
@@ -2631,6 +2634,35 @@ options_init(or_options_t *options)
   config_init(&options_format, options);
 }
 
+/* Check if the port number given in <b>port_option</b> in combination with
+ * the specified port in <b>listen_options</b> will result in Tor actually
+ * opening a low port (meaning a port lower than 1024). Return 1 if
+ * it is, or 0 if it isn't or the concept of a low port isn't applicable for
+ * the platform we're on. */
+static int
+is_listening_on_low_port(uint16_t port_option,
+                         const config_line_t *listen_options)
+{
+#ifdef MS_WINDOWS
+  return 0; /* No port is too low for windows. */
+#else
+  const config_line_t *l;
+  uint16_t p;
+  if (port_option == 0)
+    return 0; /* We're not listening */
+  if (listen_options == NULL)
+    return (port_option < 1024);
+
+  for (l = listen_options; l; l = l->next) {
+    parse_addr_port(LOG_WARN, l->value, NULL, NULL, &p);
+    if (p<1024) {
+      return 1;
+    }
+  }
+  return 0;
+#endif
+}
+
 /** Set all vars in the configuration object <b>options</b> to their default
  * values. */
 static void
@@ -3032,17 +3064,18 @@ options_validate(or_options_t *old_options, or_options_t *options,
     REJECT("TransPort and TransListenAddress are disabled in this build.");
 #endif
 
-#ifndef MS_WINDOWS
-    if (options->AccountingMax &&
-        (options->DirPort < 1024 || options->ORPort < 1024))
-      log(LOG_WARN, LD_CONFIG,
+  if (options->AccountingMax &&
+      (is_listening_on_low_port(options->ORPort, options->ORListenAddress) ||
+       is_listening_on_low_port(options->DirPort, options->DirListenAddress)))
+  {
+    log(LOG_WARN, LD_CONFIG,
           "You have set AccountingMax to use hibernation. You have also "
           "chosen a low DirPort or OrPort. This combination can make Tor stop "
           "working when it tries to re-attach the port after a period of "
           "hibernation. Please choose a different port or turn off "
           "hibernation unless you know this combination will work on your "
           "platform.");
-#endif
+  }
 
   if (options->ExcludeExitNodes || options->ExcludeNodes) {
     options->_ExcludeExitNodesUnion = routerset_new();

+ 5 - 0
src/or/control.c

@@ -3230,6 +3230,11 @@ control_event_logmsg(int severity, uint32_t domain, const char *msg)
 {
   int event;
 
+  /* Don't even think of trying to add stuff to a buffer from a cpuworker
+   * thread. */
+  if (! in_main_thread())
+    return;
+
   if (disable_log_messages)
     return;
 

+ 2 - 1
src/or/or.h

@@ -4499,7 +4499,8 @@ int routerset_needs_geoip(const routerset_t *set);
 int routerset_contains_router(const routerset_t *set, routerinfo_t *ri);
 int routerset_contains_routerstatus(const routerset_t *set,
                                     routerstatus_t *rs);
-int routerset_contains_extendinfo(const routerset_t *set, extend_info_t *ei);
+int routerset_contains_extendinfo(const routerset_t *set,
+                                  const extend_info_t *ei);
 void routerset_get_all_routers(smartlist_t *out, const routerset_t *routerset,
                                int running_only);
 void routersets_get_disjunction(smartlist_t *target, const smartlist_t *source,

+ 1 - 1
src/or/routerlist.c

@@ -5119,7 +5119,7 @@ routerset_contains(const routerset_t *set, const tor_addr_t *addr,
 
 /** Return true iff we can tell that <b>ei</b> is a member of <b>set</b>. */
 int
-routerset_contains_extendinfo(const routerset_t *set, extend_info_t *ei)
+routerset_contains_extendinfo(const routerset_t *set, const extend_info_t *ei)
 {
   return routerset_contains(set,
                             &ei->addr,