1 #include "log.h"
2
3 #include <execinfo.h>
4 #include <openssl/bio.h>
5 #include <openssl/err.h>
6 #include <pthread.h>
7 #include <signal.h>
8 #include <syslog.h>
9 #include <time.h>
10 #include <unistd.h>
11
12 #include "config.h"
13 #include "thread_var.h"
14
15 struct level {
16 char const *label;
17 char const *color;
18 FILE *stream;
19 };
20
21 static struct level DBG = { "DBG", "\x1B[36m" }; /* Cyan */
22 static struct level INF = { "INF", "\x1B[37m" }; /* White */
23 static struct level WRN = { "WRN", "\x1B[33m" }; /* Yellow */
24 static struct level ERR = { "ERR", "\x1B[31m" }; /* Red */
25 static struct level CRT = { "CRT", "\x1B[35m" }; /* Purple */
26 static struct level UNK = { "UNK", "" };
27 #define COLOR_RESET "\x1B[0m"
28
29 struct log_config {
30 bool fprintf_enabled; /* Print on the standard streams? */
31 bool syslog_enabled; /* Print on syslog? */
32
33 uint8_t level;
34 char const *prefix;
35 bool color;
36 int facility;
37 };
38
39 /* Configuration for the operation logs. */
40 static struct log_config op_config;
41 /* Configuration for the validation logs. */
42 static struct log_config val_config;
43
44 /*
45 * Note: Normally, fprintf and syslog would have separate locks.
46 *
47 * However, fprintf and syslog are rarely enabled at the same time, so I don't
48 * think it's worth it. So I'm reusing the lock.
49 *
50 * "log" + "lock" = "logck"
51 */
52 static pthread_mutex_t logck;
53
54 /**
55 * Important: -rdynamic needs to be enabled, otherwise this does not print
56 * function names. See LDFLAGS_DEBUG in Makefile.am.
57 * Also: Only non-static functions will be labeled.
58 *
59 * The first printed entry is probably not meaningful. (But I'm printing
60 * everything anyway due to paranoia.)
61 *
62 * @title is allowed to be NULL. If you need locking, do it outside. (And be
63 * aware that pthread_mutex_lock() can return error codes, which shouldn't
64 * prevent critical stack traces from printing.)
65 */
66 void
print_stack_trace(char const * title)67 print_stack_trace(char const *title)
68 {
69 #define STACK_SIZE 64
70
71 void *array[STACK_SIZE];
72 size_t size;
73 char **strings;
74 size_t i;
75 int fp;
76
77 size = backtrace(array, STACK_SIZE);
78 strings = backtrace_symbols(array, size);
79
80 if (op_config.fprintf_enabled) {
81 if (title != NULL)
82 fprintf(ERR.stream, "%s\n", title);
83 fprintf(ERR.stream, "Stack trace:\n");
84 for (i = 0; i < size; i++)
85 fprintf(ERR.stream, " %s\n", strings[i]);
86 fprintf(ERR.stream, "(End of stack trace)\n");
87 }
88
89 if (op_config.syslog_enabled) {
90 fp = LOG_ERR | op_config.facility;
91 if (title != NULL)
92 syslog(fp, "%s", title);
93 syslog(fp, "Stack trace:");
94 for (i = 0; i < size; i++)
95 syslog(fp, " %s", strings[i]);
96 syslog(fp, "(End of stack trace)");
97 }
98
99 free(strings);
100 }
101
init_config(struct log_config * cfg,bool unit_tests)102 static void init_config(struct log_config *cfg, bool unit_tests)
103 {
104 cfg->fprintf_enabled = true;
105 cfg->syslog_enabled = !unit_tests;
106 cfg->level = LOG_DEBUG;
107 cfg->prefix = NULL;
108 cfg->color = false;
109 cfg->facility = LOG_DAEMON;
110 }
111
112 static void
sigsegv_handler(int signum)113 sigsegv_handler(int signum)
114 {
115 /*
116 * IMPORTANT: See https://stackoverflow.com/questions/29982643
117 * I went with rationalcoder's answer, because I think not printing
118 * stack traces on segfaults is a nice way of ending up committing
119 * suicide.
120 *
121 * Here's a list of legal functions:
122 * https://stackoverflow.com/a/16891799/1735458
123 * (Man, I wish POSIX standards were easier to link to.)
124 */
125
126 #define STACK_SIZE 64
127 void *array[STACK_SIZE];
128 size_t size;
129
130 size = backtrace(array, STACK_SIZE);
131 backtrace_symbols_fd(array, size, STDERR_FILENO);
132
133 /* Trigger default handler. */
134 signal(signum, SIG_DFL);
135 kill(getpid(), signum);
136 }
137
138 /*
139 * Register better handlers for some signals.
140 *
141 * Remember to enable -rdynamic (See print_stack_trace()).
142 */
143 static void
register_signal_handlers(void)144 register_signal_handlers(void)
145 {
146 struct sigaction action;
147 void* dummy;
148
149 /*
150 * Make sure libgcc is loaded; otherwise backtrace() might allocate
151 * during a signal handler. (Which is illegal.)
152 */
153 dummy = NULL;
154 backtrace(&dummy, 1);
155
156 /* Register the segmentation fault handler */
157 memset(&action, 0, sizeof(action));
158 action.sa_handler = sigsegv_handler;
159 sigemptyset(&action.sa_mask);
160 action.sa_flags = 0;
161 if (sigaction(SIGSEGV, &action, NULL) == -1) {
162 /*
163 * Not fatal; it just means we will not print stack traces on
164 * Segmentation Faults.
165 */
166 pr_op_errno(errno, "SIGSEGV handler registration failure");
167 }
168
169 /*
170 * SIGPIPE can be triggered by any I/O function. libcurl is particularly
171 * tricky:
172 *
173 * > libcurl makes an effort to never cause such SIGPIPEs to trigger,
174 * > but some operating systems have no way to avoid them and even on
175 * > those that have there are some corner cases when they may still
176 * > happen
177 * (Documentation of CURLOPT_NOSIGNAL)
178 *
179 * All SIGPIPE means is "the peer closed the connection for some reason,
180 * fuck you."
181 * Which is a normal I/O error, and should be handled by the normal
182 * error propagation logic, not by a signal handler.
183 * So, ignore SIGPIPE.
184 *
185 * https://github.com/NICMx/FORT-validator/issues/49
186 */
187 if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) {
188 /*
189 * Not fatal. It just means that, if a broken pipe happens, we
190 * will die silently.
191 * But they're somewhat rare, so whatever.
192 */
193 pr_op_errno(errno, "SIGPIPE handler registration failure");
194 }
195 }
196
197 int
log_setup(bool unit_tests)198 log_setup(bool unit_tests)
199 {
200 /*
201 * Remember not to use any actual logging functions until logging has
202 * been properly initialized.
203 */
204
205 int error;
206
207 DBG.stream = stdout;
208 INF.stream = stdout;
209 WRN.stream = stderr;
210 ERR.stream = stderr;
211 CRT.stream = stderr;
212 UNK.stream = stdout;
213
214 if (unit_tests)
215 openlog("fort", LOG_CONS | LOG_PID, LOG_DAEMON);
216
217 init_config(&op_config, unit_tests);
218 init_config(&val_config, unit_tests);
219
220 error = pthread_mutex_init(&logck, NULL);
221 if (error) {
222 fprintf(ERR.stream, "pthread_mutex_init() returned %d: %s\n",
223 error, strerror(abs(error)));
224 if (!unit_tests)
225 syslog(LOG_ERR | op_config.facility,
226 "pthread_mutex_init() returned %d: %s",
227 error, strerror(abs(error)));
228 return error;
229 }
230
231 if (!unit_tests)
232 register_signal_handlers();
233
234 return 0;
235 }
236
237 static void
log_disable_syslog(void)238 log_disable_syslog(void)
239 {
240 if (op_config.syslog_enabled || val_config.syslog_enabled) {
241 closelog();
242 op_config.syslog_enabled = false;
243 val_config.syslog_enabled = false;
244 }
245 }
246
247 void
log_start(void)248 log_start(void)
249 {
250 if (config_get_val_log_enabled()) {
251 switch (config_get_val_log_output()) {
252 case SYSLOG:
253 pr_op_info("Syslog log output configured; disabling validation logging on standard streams.");
254 pr_op_info("(Validation Logs will be sent to syslog only.)");
255 val_config.fprintf_enabled = false;
256 break;
257 case CONSOLE:
258 pr_op_info("Console log output configured; disabling validation logging on syslog.");
259 pr_op_info("(Validation Logs will be sent to the standard streams only.)");
260 val_config.syslog_enabled = false;
261 break;
262 }
263 } else {
264 pr_op_info("Disabling validation logging on syslog.");
265 pr_op_info("Disabling validation logging on standard streams.");
266 val_config.fprintf_enabled = false;
267 val_config.syslog_enabled = false;
268 }
269
270 if (config_get_op_log_enabled()) {
271 switch (config_get_op_log_output()) {
272 case SYSLOG:
273 pr_op_info("Syslog log output configured; disabling operation logging on standard streams.");
274 pr_op_info("(Operation Logs will be sent to syslog only.)");
275 op_config.fprintf_enabled = false;
276 break;
277 case CONSOLE:
278 pr_op_info("Console log output configured; disabling operation logging on syslog.");
279 pr_op_info("(Operation Logs will be sent to the standard streams only.)");
280 if (val_config.syslog_enabled)
281 op_config.syslog_enabled = false;
282 else
283 log_disable_syslog();
284 break;
285 }
286 } else {
287 pr_op_info("Disabling operation logging on syslog.");
288 pr_op_info("Disabling operation logging on standard streams.");
289 op_config.fprintf_enabled = false;
290 if (val_config.syslog_enabled)
291 op_config.syslog_enabled = false;
292 else
293 log_disable_syslog();
294 }
295
296 op_config.level = config_get_op_log_level();
297 op_config.prefix = config_get_op_log_tag();
298 op_config.color = config_get_op_log_color_output();
299 op_config.facility = config_get_op_log_facility();
300 val_config.level = config_get_val_log_level();
301 val_config.prefix = config_get_val_log_tag();
302 val_config.color = config_get_val_log_color_output();
303 val_config.facility = config_get_val_log_facility();
304 }
305
306 void
log_teardown(void)307 log_teardown(void)
308 {
309 log_disable_syslog();
310 pthread_mutex_destroy(&logck);
311 }
312
313 void
log_flush(void)314 log_flush(void)
315 {
316 if (op_config.fprintf_enabled || val_config.fprintf_enabled) {
317 fflush(stdout);
318 fflush(stderr);
319 }
320 }
321
322 bool
log_val_enabled(unsigned int level)323 log_val_enabled(unsigned int level)
324 {
325 return val_config.level >= level;
326 }
327
328 bool
log_op_enabled(unsigned int level)329 log_op_enabled(unsigned int level)
330 {
331 return op_config.level >= level;
332 }
333
334 static struct level const *
level2struct(int level)335 level2struct(int level)
336 {
337 switch (level) {
338 case LOG_CRIT:
339 return &CRT;
340 case LOG_ERR:
341 return &ERR;
342 case LOG_WARNING:
343 return &WRN;
344 case LOG_INFO:
345 return &INF;
346 case LOG_DEBUG:
347 return &DBG;
348 }
349
350 return &UNK;
351 }
352
353 static void
lock_mutex(void)354 lock_mutex(void)
355 {
356 int error;
357
358 error = pthread_mutex_lock(&logck);
359 if (error) {
360 /*
361 * Despite being supposed to be impossible, failing to lock the
362 * mutex is not fatal; it just means we might log some mixed
363 * messages, which is better than dying.
364 *
365 * Furthermore, this might have been called while logging
366 * another critical. We must absolutely not get in the way of
367 * that critical's print.
368 */
369 print_stack_trace(strerror(error));
370 }
371 }
372
373 static void
unlock_mutex(void)374 unlock_mutex(void)
375 {
376 int error;
377
378 error = pthread_mutex_unlock(&logck);
379 if (error)
380 print_stack_trace(strerror(error)); /* Same as above. */
381 }
382
383 static void
__vfprintf(int level,struct log_config * cfg,char const * format,va_list args)384 __vfprintf(int level, struct log_config *cfg, char const *format, va_list args)
385 {
386 char time_buff[20];
387 struct level const *lvl;
388 time_t now;
389 struct tm stm_buff;
390 char const *file_name;
391
392 lvl = level2struct(level);
393
394 lock_mutex();
395
396 if (cfg->color)
397 fprintf(lvl->stream, "%s", lvl->color);
398
399 now = time(0);
400 if (now != ((time_t) -1)) {
401 localtime_r(&now, &stm_buff);
402 strftime(time_buff, sizeof(time_buff), "%b %e %T", &stm_buff);
403 fprintf(lvl->stream, "%s ", time_buff);
404 }
405
406 fprintf(lvl->stream, "%s", lvl->label);
407 if (cfg->prefix)
408 fprintf(lvl->stream, " [%s]", cfg->prefix);
409 fprintf(lvl->stream, ": ");
410
411 file_name = fnstack_peek();
412 if (file_name != NULL)
413 fprintf(lvl->stream, "%s: ", file_name);
414
415 vfprintf(lvl->stream, format, args);
416
417 if (cfg->color)
418 fprintf(lvl->stream, COLOR_RESET);
419 fprintf(lvl->stream, "\n");
420
421 /* Force flush */
422 if (lvl->stream == stdout)
423 fflush(lvl->stream);
424
425 unlock_mutex();
426 }
427
428 #define MSG_LEN 1024
429
430 static void
__syslog(int level,struct log_config * cfg,const char * format,va_list args)431 __syslog(int level, struct log_config *cfg, const char *format, va_list args)
432 {
433 static char msg[MSG_LEN];
434 char const *file_name;
435 struct level const *lvl;
436
437 file_name = fnstack_peek();
438 lvl = level2struct(level);
439
440 lock_mutex();
441
442 /* Can't use vsyslog(); it's not portable. */
443 vsnprintf(msg, MSG_LEN, format, args);
444 if (file_name != NULL) {
445 if (cfg->prefix != NULL)
446 syslog(level | cfg->facility, "%s [%s]: %s: %s",
447 lvl->label, cfg->prefix, file_name, msg);
448 else
449 syslog(level | cfg->facility, "%s: %s: %s",
450 lvl->label, file_name, msg);
451 } else {
452 if (cfg->prefix != NULL)
453 syslog(level | cfg->facility, "%s [%s]: %s",
454 lvl->label, cfg->prefix, msg);
455 else
456 syslog(level | cfg->facility, "%s: %s",
457 lvl->label, msg);
458 }
459
460 unlock_mutex();
461 }
462
463 #define PR_SIMPLE(lvl, config) \
464 do { \
465 va_list args; \
466 \
467 if (lvl > config.level) \
468 break; \
469 \
470 if (config.syslog_enabled) { \
471 va_start(args, format); \
472 __syslog(lvl, &config, format, args); \
473 va_end(args); \
474 } \
475 \
476 if (config.fprintf_enabled) { \
477 va_start(args, format); \
478 __vfprintf(lvl, &config, format, args); \
479 va_end(args); \
480 } \
481 } while (0)
482
483 void
pr_op_debug(const char * format,...)484 pr_op_debug(const char *format, ...)
485 {
486 PR_SIMPLE(LOG_DEBUG, op_config);
487 }
488
489 void
pr_op_info(const char * format,...)490 pr_op_info(const char *format, ...)
491 {
492 PR_SIMPLE(LOG_INFO, op_config);
493 }
494
495 /**
496 * Always returs 0. (So you can interrupt whatever you're doing without failing
497 * validation.)
498 */
499 int
pr_op_warn(const char * format,...)500 pr_op_warn(const char *format, ...)
501 {
502 PR_SIMPLE(LOG_WARNING, op_config);
503 return 0;
504 }
505
506 int
__pr_op_err(int error,const char * format,...)507 __pr_op_err(int error, const char *format, ...)
508 {
509 PR_SIMPLE(LOG_ERR, op_config);
510 lock_mutex();
511 print_stack_trace(NULL);
512 unlock_mutex();
513 return error;
514 }
515
516 void
pr_val_debug(const char * format,...)517 pr_val_debug(const char *format, ...)
518 {
519 PR_SIMPLE(LOG_DEBUG, val_config);
520 }
521
522 void
pr_val_info(const char * format,...)523 pr_val_info(const char *format, ...)
524 {
525 PR_SIMPLE(LOG_INFO, val_config);
526 }
527
528 /**
529 * Always returs 0. (So you can interrupt whatever you're doing without failing
530 * validation.)
531 */
532 int
pr_val_warn(const char * format,...)533 pr_val_warn(const char *format, ...)
534 {
535 PR_SIMPLE(LOG_WARNING, val_config);
536 return 0;
537 }
538
539 int
__pr_val_err(int error,const char * format,...)540 __pr_val_err(int error, const char *format, ...)
541 {
542 PR_SIMPLE(LOG_ERR, val_config);
543 return error;
544 }
545
546 struct crypto_cb_arg {
547 unsigned int stack_size;
548 int (*error_fn)(int, const char *, ...);
549 };
550
551 static int
log_crypto_error(const char * str,size_t len,void * _arg)552 log_crypto_error(const char *str, size_t len, void *_arg)
553 {
554 struct crypto_cb_arg *arg = _arg;
555 arg->error_fn(0, "-> %s", str);
556 arg->stack_size++;
557 return 1;
558 }
559
560 static int
crypto_err(struct log_config * cfg,int (* error_fn)(int,const char *,...))561 crypto_err(struct log_config *cfg, int (*error_fn)(int, const char *, ...))
562 {
563 struct crypto_cb_arg arg;
564
565 error_fn(0, "libcrypto error stack:");
566
567 arg.stack_size = 0;
568 arg.error_fn = error_fn;
569 ERR_print_errors_cb(log_crypto_error, &arg);
570 if (arg.stack_size == 0)
571 error_fn(0, " <Empty>");
572 else
573 error_fn(0, "End of libcrypto stack.");
574
575 return -EINVAL;
576 }
577
578 /**
579 * This is like pr_err() and pr_errno(), except meant to log an error made
580 * during a libcrypto routine.
581 *
582 * This differs from usual printf-like functions:
583 *
584 * - It returns -EINVAL, not bytes written.
585 * - It prints a newline.
586 * - Also prints the cryptolib's error message stack.
587 *
588 * Always appends a newline at the end.
589 */
590 int
op_crypto_err(const char * format,...)591 op_crypto_err(const char *format, ...)
592 {
593 PR_SIMPLE(LOG_ERR, op_config);
594 return crypto_err(&op_config, __pr_op_err);
595 }
596
597 /**
598 * This is like pr_err() and pr_errno(), except meant to log an error made
599 * during a libcrypto routine.
600 *
601 * This differs from usual printf-like functions:
602 *
603 * - It returns -EINVAL, not bytes written.
604 * - It prints a newline.
605 * - Also prints the cryptolib's error message stack.
606 *
607 * Always appends a newline at the end.
608 */
609 int
val_crypto_err(const char * format,...)610 val_crypto_err(const char *format, ...)
611 {
612 PR_SIMPLE(LOG_ERR, val_config);
613 return crypto_err(&val_config, __pr_val_err);
614 }
615
616 int
pr_enomem(void)617 pr_enomem(void)
618 {
619 static char const *ENOMEM_MSG = "Out of memory.\n";
620 ssize_t garbage;
621
622 /*
623 * I'm not using PR_SIMPLE and friends, because those allocate.
624 * We want to minimize allocations after a memory allocation failure.
625 */
626
627 if (LOG_ERR > op_config.level)
628 return -ENOMEM;
629
630 if (op_config.fprintf_enabled) {
631 lock_mutex();
632 /*
633 * write() is AS-Safe, which implies it doesn't allocate,
634 * unlike printf().
635 */
636 garbage = write(STDERR_FILENO, ENOMEM_MSG, strlen(ENOMEM_MSG));
637 unlock_mutex();
638 garbage++;
639 }
640
641 if (op_config.syslog_enabled) {
642 lock_mutex();
643 /* This allocates, but I don't think I have more options. */
644 syslog(LOG_ERR | op_config.facility, "Out of memory.");
645 unlock_mutex();
646 }
647
648 return -ENOMEM;
649 }
650
651 __dead void
pr_crit(const char * format,...)652 pr_crit(const char *format, ...)
653 {
654 PR_SIMPLE(LOG_ERR, op_config);
655 print_stack_trace(NULL);
656 exit(-1);
657 }
658
659 /**
660 * Prints the [format, ...] error message using the configured logging severity
661 * of the @id incidence.
662 */
663 int
incidence(enum incidence_id id,const char * format,...)664 incidence(enum incidence_id id, const char *format, ...)
665 {
666 enum incidence_action action;
667
668 action = incidence_get_action(id);
669 switch (action) {
670 case INAC_IGNORE:
671 return 0;
672 case INAC_WARN:
673 PR_SIMPLE(LOG_WARNING, val_config);
674 return 0;
675 case INAC_ERROR:
676 PR_SIMPLE(LOG_ERR, val_config);
677 return -EINVAL;
678 }
679
680 pr_crit("Unknown incidence action: %u", action);
681 }
682