Browse Source

Merge remote-tracking branch 'ahf-oniongit/bugs/24362'

Nick Mathewson 6 years ago
parent
commit
6c5a73f87a
7 changed files with 141 additions and 13 deletions
  1. 2 0
      changes/bug24362
  2. 14 0
      configure.ac
  3. 5 0
      doc/tor.1.txt
  4. 87 5
      src/common/log.c
  5. 5 1
      src/common/torlog.h
  6. 27 7
      src/or/config.c
  7. 1 0
      src/or/or.h

+ 2 - 0
changes/bug24362

@@ -0,0 +1,2 @@
+  o Minor features (logging, android):
+    - Added support for the Android logging subsystem. Closes ticket 24362.

+ 14 - 0
configure.ac

@@ -204,6 +204,20 @@ if test x$enable_event_tracing_debug = xyes; then
   AC_DEFINE([TOR_EVENT_TRACING_ENABLED], [1], [Compile the event tracing instrumentation])
 fi
 
+dnl Enable Android only features.
+AC_ARG_ENABLE(android,
+     AS_HELP_STRING(--enable-android, [build with Android features enabled]))
+AM_CONDITIONAL([USE_ANDROID], [test "x$enable_android" = "xyes"])
+
+if test "x$enable_android" = "xyes"; then
+  AC_DEFINE([USE_ANDROID], [1], [Compile with Android specific features enabled])
+
+  dnl Check if the Android log library is available.
+  AC_CHECK_HEADERS([android/log.h])
+  AC_SEARCH_LIBS(__android_log_write, [log])
+
+fi
+
 dnl check for the correct "ar" when cross-compiling.
 dnl   (AM_PROG_AR was new in automake 1.11.2, which we do not yet require,
 dnl    so kludge up a replacement for the case where it isn't there yet.)

+ 5 - 0
doc/tor.1.txt

@@ -727,6 +727,11 @@ GENERAL OPTIONS
     log entries are marked with "Tor-__tag__". Can not be changed while tor is
     running. (Default: none)
 
+[[AndroidIdentityTag]] **AndroidIdentityTag** __tag__::
+    When logging to Android's logging subsystem, adds a tag to the log identity
+    such that log entries are marked with "Tor-__tag__". Can not be changed while
+    tor is running. (Default: none)
+
 [[SafeLogging]] **SafeLogging** **0**|**1**|**relay**::
     Tor can scrub potentially sensitive strings from log messages (e.g.
     addresses) by replacing them with the string [scrubbed]. This way logs can

+ 87 - 5
src/common/log.c

@@ -35,6 +35,9 @@
 #define LOG_PRIVATE
 #include "torlog.h"
 #include "container.h"
+#ifdef HAVE_ANDROID_LOG_H
+#include <android/log.h>
+#endif // HAVE_ANDROID_LOG_H.
 
 /** Given a severity, yields an index into log_severity_list_t.masks to use
  * for that severity. */
@@ -58,6 +61,8 @@ typedef struct logfile_t {
   int needs_close; /**< Boolean: true if the stream gets closed on shutdown. */
   int is_temporary; /**< Boolean: close after initializing logging subsystem.*/
   int is_syslog; /**< Boolean: send messages to syslog. */
+  int is_android; /**< Boolean: send messages to Android's log subsystem. */
+  char *android_tag; /**< Identity Tag used in Android's log subsystem. */
   log_callback callback; /**< If not NULL, send messages to this function. */
   log_severity_list_t *severities; /**< Which severity of messages should we
                                     * log for each log domain? */
@@ -103,6 +108,33 @@ should_log_function_name(log_domain_mask_t domain, int severity)
   }
 }
 
+#ifdef HAVE_ANDROID_LOG_H
+/** Helper function to convert Tor's log severity into the matching
+ * Android log priority.
+ */
+static int
+severity_to_android_log_priority(int severity)
+{
+  switch (severity) {
+    case LOG_DEBUG:
+      return ANDROID_LOG_VERBOSE;
+    case LOG_INFO:
+      return ANDROID_LOG_DEBUG;
+    case LOG_NOTICE:
+      return ANDROID_LOG_INFO;
+    case LOG_WARN:
+      return ANDROID_LOG_WARN;
+    case LOG_ERR:
+      return ANDROID_LOG_ERROR;
+    default:
+      // LCOV_EXCL_START
+      raw_assert(0);
+      return 0;
+      // LCOV_EXCL_STOP
+  }
+}
+#endif // HAVE_ANDROID_LOG_H.
+
 /** A mutex to guard changes to logfiles and logging. */
 static tor_mutex_t log_mutex;
 /** True iff we have initialized log_mutex */
@@ -401,6 +433,16 @@ pending_log_message_free_(pending_log_message_t *msg)
   tor_free(msg);
 }
 
+/** Helper function: returns true iff the log file, given in <b>lf</b>, is
+ * handled externally via the system log API, the Android logging API, or is an
+ * external callback function. */
+static inline int
+logfile_is_external(logfile_t *lf)
+{
+  raw_assert(lf);
+  return lf->is_syslog || lf->is_android || lf->callback;
+}
+
 /** Return true iff <b>lf</b> would like to receive a message with the
  * specified <b>severity</b> in the specified <b>domain</b>.
  */
@@ -411,7 +453,7 @@ logfile_wants_message(const logfile_t *lf, int severity,
   if (! (lf->severities->masks[SEVERITY_MASK_IDX(severity)] & domain)) {
     return 0;
   }
-  if (! (lf->fd >= 0 || lf->is_syslog || lf->callback)) {
+  if (! (lf->fd >= 0 || logfile_is_external(lf))) {
     return 0;
   }
   if (lf->seems_dead) {
@@ -454,6 +496,11 @@ logfile_deliver(logfile_t *lf, const char *buf, size_t msg_len,
     syslog(severity, "%s", msg_after_prefix);
 #endif /* defined(MAXLINE) */
 #endif /* defined(HAVE_SYSLOG_H) */
+  } else if (lf->is_android) {
+#ifdef HAVE_ANDROID_LOG_H
+    int priority = severity_to_android_log_priority(severity);
+    __android_log_write(priority, lf->android_tag, msg_after_prefix);
+#endif // HAVE_ANDROID_LOG_H.
   } else if (lf->callback) {
     if (domain & LD_NOCB) {
       if (!*callbacks_deferred && pending_cb_messages) {
@@ -646,8 +693,8 @@ tor_log_update_sigsafe_err_fds(void)
      /* Don't try callback to the control port, or syslogs: We can't
       * do them from a signal handler. Don't try stdout: we always do stderr.
       */
-    if (lf->is_temporary || lf->is_syslog ||
-        lf->callback || lf->seems_dead || lf->fd < 0)
+    if (lf->is_temporary || logfile_is_external(lf)
+        || lf->seems_dead || lf->fd < 0)
       continue;
     if (lf->severities->masks[SEVERITY_MASK_IDX(LOG_ERR)] &
         (LD_BUG|LD_GENERAL)) {
@@ -683,7 +730,7 @@ tor_log_get_logfile_names(smartlist_t *out)
   LOCK_LOGS();
 
   for (lf = logfiles; lf; lf = lf->next) {
-    if (lf->is_temporary || lf->is_syslog || lf->callback)
+    if (lf->is_temporary || logfile_is_external(lf))
       continue;
     if (lf->filename == NULL)
       continue;
@@ -732,6 +779,7 @@ log_free_(logfile_t *victim)
     return;
   tor_free(victim->severities);
   tor_free(victim->filename);
+  tor_free(victim->android_tag);
   tor_free(victim);
 }
 
@@ -1151,6 +1199,39 @@ add_syslog_log(const log_severity_list_t *severity,
 }
 #endif /* defined(HAVE_SYSLOG_H) */
 
+#ifdef HAVE_ANDROID_LOG_H
+/**
+ * Add a log handler to send messages to the Android platform log facility.
+ */
+int
+add_android_log(const log_severity_list_t *severity,
+                const char *android_tag)
+{
+  logfile_t *lf = NULL;
+
+  lf = tor_malloc_zero(sizeof(logfile_t));
+  lf->fd = -1;
+  lf->severities = tor_memdup(severity, sizeof(log_severity_list_t));
+  lf->filename = tor_strdup("<android>");
+  lf->is_android = 1;
+
+  if (android_tag == NULL)
+    lf->android_tag = tor_strdup("Tor");
+  else {
+    char buf[256];
+    tor_snprintf(buf, sizeof(buf), "Tor-%s", android_tag);
+    lf->android_tag = tor_strdup(buf);
+  }
+
+  LOCK_LOGS();
+  lf->next = logfiles;
+  logfiles = lf;
+  log_global_min_severity_ = get_min_log_level();
+  UNLOCK_LOGS();
+  return 0;
+}
+#endif // HAVE_ANDROID_LOG_H.
+
 /** If <b>level</b> is a valid log severity, return the corresponding
  * numeric value.  Otherwise, return -1. */
 int
@@ -1318,7 +1399,8 @@ parse_log_severity_config(const char **cfg_ptr,
     if (!strcasecmpstart(cfg, "file") ||
         !strcasecmpstart(cfg, "stderr") ||
         !strcasecmpstart(cfg, "stdout") ||
-        !strcasecmpstart(cfg, "syslog")) {
+        !strcasecmpstart(cfg, "syslog") ||
+        !strcasecmpstart(cfg, "android")) {
       goto done;
     }
     if (got_an_unqualified_range > 1)

+ 5 - 1
src/common/torlog.h

@@ -146,7 +146,11 @@ int add_file_log(const log_severity_list_t *severity, const char *filename,
 #ifdef HAVE_SYSLOG_H
 int add_syslog_log(const log_severity_list_t *severity,
                    const char* syslog_identity_tag);
-#endif
+#endif // HAVE_SYSLOG_H.
+#ifdef HAVE_ANDROID_LOG_H
+int add_android_log(const log_severity_list_t *severity,
+                    const char *android_identity_tag);
+#endif // HAVE_ANDROID_LOG_H.
 int add_callback_log(const log_severity_list_t *severity, log_callback cb);
 void logs_set_domain_logging(int enabled);
 int get_min_log_level(void);

+ 27 - 7
src/or/config.c

@@ -403,6 +403,7 @@ static config_var_t option_vars_[] = {
   V(LogTimeGranularity,          MSEC_INTERVAL, "1 second"),
   V(TruncateLogFile,             BOOL,     "0"),
   V(SyslogIdentityTag,           STRING,   NULL),
+  V(AndroidIdentityTag,          STRING,   NULL),
   V(LongLivedPorts,              CSV,
         "21,22,706,1863,5050,5190,5222,5223,6523,6667,6697,8300"),
   VAR("MapAddress",              LINELIST, AddressMap,           NULL),
@@ -4692,6 +4693,12 @@ options_transition_allowed(const or_options_t *old,
     return -1;
   }
 
+  if (!opt_streq(old->AndroidIdentityTag, new_val->AndroidIdentityTag)) {
+    *msg = tor_strdup("While Tor is running, changing "
+                      "AndroidIdentityTag is not allowed.");
+    return -1;
+  }
+
   if ((old->HardwareAccel != new_val->HardwareAccel)
       || !opt_streq(old->AccelName, new_val->AccelName)
       || !opt_streq(old->AccelDir, new_val->AccelDir)) {
@@ -5732,16 +5739,29 @@ options_init_logs(const or_options_t *old_options, or_options_t *options,
       }
       goto cleanup;
     }
-    if (smartlist_len(elts) == 1 &&
-        !strcasecmp(smartlist_get(elts,0), "syslog")) {
+    if (smartlist_len(elts) == 1) {
+      if (!strcasecmp(smartlist_get(elts,0), "syslog")) {
 #ifdef HAVE_SYSLOG_H
-      if (!validate_only) {
-        add_syslog_log(severity, options->SyslogIdentityTag);
-      }
+        if (!validate_only) {
+          add_syslog_log(severity, options->SyslogIdentityTag);
+        }
 #else
-      log_warn(LD_CONFIG, "Syslog is not supported on this system. Sorry.");
+        log_warn(LD_CONFIG, "Syslog is not supported on this system. Sorry.");
 #endif /* defined(HAVE_SYSLOG_H) */
-      goto cleanup;
+        goto cleanup;
+      }
+
+      if (!strcasecmp(smartlist_get(elts, 0), "android")) {
+#ifdef HAVE_ANDROID_LOG_H
+        if (!validate_only) {
+          add_android_log(severity, options->AndroidIdentityTag);
+        }
+#else
+        log_warn(LD_CONFIG, "Android logging is not supported"
+                            " on this system. Sorry.");
+#endif // HAVE_ANDROID_LOG_H.
+        goto cleanup;
+      }
     }
 
     if (smartlist_len(elts) == 2 &&

+ 1 - 0
src/or/or.h

@@ -3639,6 +3639,7 @@ typedef struct {
   int TruncateLogFile; /**< Boolean: Should we truncate the log file
                             before we start writing? */
   char *SyslogIdentityTag; /**< Identity tag to add for syslog logging. */
+  char *AndroidIdentityTag; /**< Identity tag to add for Android logging. */
 
   char *DebugLogFile; /**< Where to send verbose log messages. */
   char *DataDirectory_option; /**< Where to store long-term data, as