torerr.c 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. /* Copyright (c) 2001, Matej Pfajfar.
  2. * Copyright (c) 2001-2004, Roger Dingledine.
  3. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
  4. * Copyright (c) 2007-2018, The Tor Project, Inc. */
  5. /* See LICENSE for licensing information */
  6. /**
  7. * \file torerr.c
  8. *
  9. * \brief Handling code for unrecoverable emergencies, at a lower level
  10. * than the logging code.
  11. */
  12. #include "orconfig.h"
  13. #include <stdarg.h>
  14. #include <stdlib.h>
  15. #include <string.h>
  16. #include <stdio.h>
  17. #ifdef HAVE_SYS_TIME_H
  18. #include <sys/time.h>
  19. #endif
  20. #ifdef HAVE_TIME_H
  21. #include <time.h>
  22. #endif
  23. #ifdef HAVE_UNISTD_H
  24. #include <unistd.h>
  25. #endif
  26. #ifdef HAVE_SYS_TYPES_H
  27. #include <sys/types.h>
  28. #endif
  29. #include "lib/err/torerr.h"
  30. #include "lib/err/backtrace.h"
  31. /** Array of fds to log crash-style warnings to. */
  32. static int sigsafe_log_fds[TOR_SIGSAFE_LOG_MAX_FDS] = { STDERR_FILENO };
  33. /** The number of elements used in sigsafe_log_fds */
  34. static int n_sigsafe_log_fds = 1;
  35. /** Log granularity in milliseconds. */
  36. static int log_granularity = 1000;
  37. /** Write <b>s</b> to each element of sigsafe_log_fds. Return 0 on success, -1
  38. * on failure. */
  39. static int
  40. tor_log_err_sigsafe_write(const char *s)
  41. {
  42. int i;
  43. ssize_t r;
  44. size_t len = strlen(s);
  45. int err = 0;
  46. for (i=0; i < n_sigsafe_log_fds; ++i) {
  47. r = write(sigsafe_log_fds[i], s, len);
  48. err += (r != (ssize_t)len);
  49. }
  50. return err ? -1 : 0;
  51. }
  52. /** Given a list of string arguments ending with a NULL, writes them
  53. * to our logs and to stderr (if possible). This function is safe to call
  54. * from within a signal handler. */
  55. void
  56. tor_log_err_sigsafe(const char *m, ...)
  57. {
  58. va_list ap;
  59. const char *x;
  60. char timebuf[33];
  61. time_t now = time(NULL);
  62. if (!m)
  63. return;
  64. if (log_granularity >= 2000) {
  65. int g = log_granularity / 1000;
  66. now -= now % g;
  67. }
  68. timebuf[0] = now < 0 ? '-' : ' ';
  69. if (now < 0) now = -now;
  70. timebuf[1] = '\0';
  71. format_dec_number_sigsafe(now, timebuf+1, sizeof(timebuf)-1);
  72. tor_log_err_sigsafe_write("\n=========================================="
  73. "================== T=");
  74. tor_log_err_sigsafe_write(timebuf);
  75. tor_log_err_sigsafe_write("\n");
  76. tor_log_err_sigsafe_write(m);
  77. va_start(ap, m);
  78. while ((x = va_arg(ap, const char*))) {
  79. tor_log_err_sigsafe_write(x);
  80. }
  81. va_end(ap);
  82. }
  83. /** Set *<b>out</b> to a pointer to an array of the fds to log errors to from
  84. * inside a signal handler or other emergency condition. Return the number of
  85. * elements in the array. */
  86. int
  87. tor_log_get_sigsafe_err_fds(const int **out)
  88. {
  89. *out = sigsafe_log_fds;
  90. return n_sigsafe_log_fds;
  91. }
  92. /**
  93. * Update the list of fds that get errors from inside a signal handler or
  94. * other emergency condition. Ignore any beyond the first
  95. * TOR_SIGSAFE_LOG_MAX_FDS.
  96. */
  97. void
  98. tor_log_set_sigsafe_err_fds(const int *fds, int n)
  99. {
  100. if (n > TOR_SIGSAFE_LOG_MAX_FDS) {
  101. n = TOR_SIGSAFE_LOG_MAX_FDS;
  102. }
  103. memcpy(sigsafe_log_fds, fds, n * sizeof(int));
  104. n_sigsafe_log_fds = n;
  105. }
  106. /**
  107. * Set the granularity (in ms) to use when reporting fatal errors outside
  108. * the logging system.
  109. */
  110. void
  111. tor_log_sigsafe_err_set_granularity(int ms)
  112. {
  113. log_granularity = ms;
  114. }
  115. /**
  116. * Log an emergency assertion failure message.
  117. *
  118. * This kind of message is safe to send from within a log handler,
  119. * a signal handler, or other emergency situation.
  120. */
  121. void
  122. tor_raw_assertion_failed_msg_(const char *file, int line, const char *expr,
  123. const char *msg)
  124. {
  125. char linebuf[16];
  126. format_dec_number_sigsafe(line, linebuf, sizeof(linebuf));
  127. tor_log_err_sigsafe("INTERNAL ERROR: Raw assertion failed at ",
  128. file, ":", linebuf, ": ", expr, NULL);
  129. if (msg) {
  130. tor_log_err_sigsafe_write(msg);
  131. tor_log_err_sigsafe_write("\n");
  132. }
  133. dump_stack_symbols_to_error_fds();
  134. }
  135. /* As format_{hex,dex}_number_sigsafe, but takes a <b>radix</b> argument
  136. * in range 2..16 inclusive. */
  137. static int
  138. format_number_sigsafe(unsigned long x, char *buf, int buf_len,
  139. unsigned int radix)
  140. {
  141. unsigned long tmp;
  142. int len;
  143. char *cp;
  144. /* NOT tor_assert. This needs to be safe to run from within a signal
  145. * handler, and from within the 'tor_assert() has failed' code. Not even
  146. * raw_assert(), since raw_assert() calls this function on failure. */
  147. if (radix < 2 || radix > 16)
  148. return 0;
  149. /* Count how many digits we need. */
  150. tmp = x;
  151. len = 1;
  152. while (tmp >= radix) {
  153. tmp /= radix;
  154. ++len;
  155. }
  156. /* Not long enough */
  157. if (!buf || len >= buf_len)
  158. return 0;
  159. cp = buf + len;
  160. *cp = '\0';
  161. do {
  162. unsigned digit = (unsigned) (x % radix);
  163. if (cp <= buf) {
  164. /* Not tor_assert(); see above. */
  165. abort();
  166. }
  167. --cp;
  168. *cp = "0123456789ABCDEF"[digit];
  169. x /= radix;
  170. } while (x);
  171. /* NOT tor_assert; see above. */
  172. if (cp != buf) {
  173. abort(); // LCOV_EXCL_LINE
  174. }
  175. return len;
  176. }
  177. /**
  178. * Helper function to output hex numbers from within a signal handler.
  179. *
  180. * Writes the nul-terminated hexadecimal digits of <b>x</b> into a buffer
  181. * <b>buf</b> of size <b>buf_len</b>, and return the actual number of digits
  182. * written, not counting the terminal NUL.
  183. *
  184. * If there is insufficient space, write nothing and return 0.
  185. *
  186. * This accepts an unsigned int because format_helper_exit_status() needs to
  187. * call it with a signed int and an unsigned char, and since the C standard
  188. * does not guarantee that an int is wider than a char (an int must be at
  189. * least 16 bits but it is permitted for a char to be that wide as well), we
  190. * can't assume a signed int is sufficient to accommodate an unsigned char.
  191. * Thus, format_helper_exit_status() will still need to emit any require '-'
  192. * on its own.
  193. *
  194. * For most purposes, you'd want to use tor_snprintf("%x") instead of this
  195. * function; it's designed to be used in code paths where you can't call
  196. * arbitrary C functions.
  197. */
  198. int
  199. format_hex_number_sigsafe(unsigned long x, char *buf, int buf_len)
  200. {
  201. return format_number_sigsafe(x, buf, buf_len, 16);
  202. }
  203. /** As format_hex_number_sigsafe, but format the number in base 10. */
  204. int
  205. format_dec_number_sigsafe(unsigned long x, char *buf, int buf_len)
  206. {
  207. return format_number_sigsafe(x, buf, buf_len, 10);
  208. }