The FreeRADIUS server  $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
debug.c
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or modify
3  * it under the terms of the GNU General Public License as published by
4  * the Free Software Foundation; either version 2 of the License, or
5  * (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software
14  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
15  */
16 
17 /** Functions to help with debugging
18  *
19  * @file src/lib/util/debug.c
20  *
21  * @copyright 2013 The FreeRADIUS server project
22  * @copyright 2013 Arran Cudbard-Bell (a.cudbardb@freeradius.org)
23  */
24 #include <freeradius-devel/util/debug.h>
25 #include <freeradius-devel/util/hash.h>
26 #include <freeradius-devel/util/strerror.h>
27 #include <freeradius-devel/util/syserror.h>
28 
29 #include <pthread.h>
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <sys/stat.h>
33 #include <sys/wait.h>
34 
35 #if defined(HAVE_MALLOPT) && defined(HAVE_MALLOC_H)
36 # include <malloc.h>
37 #endif
38 
39 /*
40  * runtime backtrace functions are not POSIX but are included in
41  * glibc, OSX >= 10.5 and various BSDs
42  */
43 #ifdef HAVE_EXECINFO
44 # include <execinfo.h>
45 #endif
46 
47 #ifdef HAVE_SYS_PRCTL_H
48 # include <sys/prctl.h>
49 #endif
50 
51 #ifdef HAVE_SYS_PROCCTL_H
52 # include <sys/procctl.h>
53 #endif
54 
55 #ifdef HAVE_SYS_PTRACE_H
56 # include <sys/ptrace.h>
57 # if !defined(PT_ATTACH) && defined(PTRACE_ATTACH)
58 # define PT_ATTACH PTRACE_ATTACH
59 # endif
60 # if !defined(PT_DETACH) && defined(PTRACE_DETACH)
61 # define PT_DETACH PTRACE_DETACH
62 # endif
63 #endif
64 
65 #ifdef HAVE_SYS_RESOURCE_H
66 # include <sys/resource.h>
67 #endif
68 
69 #ifdef __APPLE__
70 #include <sys/sysctl.h>
71 #endif
72 
73 #ifdef HAVE_EXECINFO
74 # ifndef MAX_BT_FRAMES
75 # define MAX_BT_FRAMES 128
76 # endif
77 # ifndef MAX_BT_CBUFF
78 # define MAX_BT_CBUFF 1048576 //!< Should be a power of 2
79 # endif
80 
81 static pthread_mutex_t fr_debug_init = PTHREAD_MUTEX_INITIALIZER;
82 
83 typedef struct {
84  void *obj; //!< Memory address of the block of allocated memory.
85  void *frames[MAX_BT_FRAMES]; //!< Backtrace frame data
86  int count; //!< Number of frames stored
87 } fr_bt_info_t;
88 
89 struct fr_bt_marker {
90  void *obj; //!< Pointer to the parent object, this is our needle
91  //!< when we iterate over the contents of the circular buffer.
92  fr_fring_t *fring; //!< Where we temporarily store the backtraces
93 };
94 #endif
95 
96 static char panic_action[512]; //!< The command to execute when panicking.
97 static fr_fault_cb_t panic_cb = NULL; //!< Callback to execute whilst panicking, before the
98  //!< panic_action.
99 
100 static bool dump_core; //!< Whether we should drop a core on fatal signals.
101 
102 static int fr_fault_log_fd = STDERR_FILENO; //!< Where to write debug output.
103 
104 fr_debug_state_t fr_debug_state = DEBUGGER_STATE_UNKNOWN; //!< Whether we're attached to by a debugger.
105 
106 #ifdef HAVE_SYS_RESOURCE_H
107 static struct rlimit init_core_limit;
108 #endif
109 
110 static TALLOC_CTX *talloc_autofree_ctx;
111 
112 /*
113  * On BSD systems, ptrace(PT_DETACH) uses a third argument for
114  * resume address, with the magic value (void *)1 to resume where
115  * process stopped. Specifying NULL there leads to a crash because
116  * process resumes at address 0.
117  */
118 #if defined(HAVE_SYS_PTRACE_H)
119 # ifdef __linux__
120 # define _PTRACE(_x, _y) ptrace(_x, _y, NULL, NULL)
121 # define _PTRACE_DETACH(_x) ptrace(PT_DETACH, _x, NULL, NULL)
122 # elif !defined(__APPLE__) && !defined(__EMSCRIPTEN__) && !defined(HAVE_SYS_PROCCTL_H)
123 # define _PTRACE(_x, _y) ptrace(_x, _y, NULL, 0)
124 # define _PTRACE_DETACH(_x) ptrace(PT_DETACH, _x, (void *)1, 0)
125 #endif
126 
127 # ifdef HAVE_CAPABILITY_H
128 # include <sys/capability.h>
129 # endif
130 #endif
131 
132 #ifdef HAVE_SANITIZER_LSAN_INTERFACE_H
133 # include <sanitizer/lsan_interface.h>
134 #endif
135 
136 #ifdef HAVE_SANITIZER_LSAN_INTERFACE_H
137 static int lsan_test_pipe[2] = {-1, -1};
138 static int lsan_test_pid = -1;
139 static int lsan_state = INT_MAX;
140 static bool lsan_disable = false; //!< Explicitly disable LSAN
141 
142 /*
143  * Some versions of lsan_interface.h are broken and don't declare
144  * the prototypes of the functions properly, omitting the zero argument
145  * specifier (void), so we need to disable the warning.
146  *
147  * Observed with clang 5.
148  */
149 DIAG_OFF(missing-prototypes)
150 /** Callback for LSAN - do not rename
151  *
152  */
153 char const CC_HINT(used) *__lsan_default_suppressions(void)
154 {
155  return
156  "leak:CRYPTO_THREAD_lock_new\n" /* OpenSSL init leak - reported by heaptrack */
157 #if defined(__APPLE__)
158  "leak:*gmtsub*\n"
159  "leak:ImageLoaderMachO::doImageInit\n"
160  "leak:_st_tzset_basic\n"
161  "leak:attachCategories\n"
162  "leak:fork\n"
163  "leak:getaddrinfo\n"
164  "leak:getpwuid_r\n"
165  "leak:libSystem_atfork_child\n"
166  "leak:libsystem_notify\n"
167  "leak:load_images\n"
168  "leak:newlocale\n"
169  /* Perl >= 5.32.0 - Upstream bug, tracked by https://github.com/Perl/perl5/issues/18108 */
170  "leak:perl_construct\n"
171  "leak:realizeClassWithoutSwift\n"
172  "leak:tzset\n"
173  "leak:tzsetwall_basic\n"
174 #elif defined(__linux__)
175  "leak:*getpwnam_r*\n" /* libc startup leak - reported by heaptrack */
176  "leak:_dl_init\n" /* dl startup leak - reported by heaptrack */
177  "leak:initgroups\n" /* libc startup leak - reported by heaptrack */
178  "leak:kqueue\n"
179 #endif
180  ;
181 }
182 
183 /** Callback for LSAN - do not rename
184  *
185  * Turn off suppressions by default as it interferes with interpreting
186  * output from some of the test utilities.
187  */
188 char const CC_HINT(used) *__lsan_default_options(void)
189 {
190  return "print_suppressions=0";
191 }
192 
193 /** Callback for LSAN - do not rename
194  *
195  */
196 int CC_HINT(used) __lsan_is_turned_off(void)
197 {
198  uint8_t ret = 1;
199 
200  /* Disable LSAN explicitly - Used for tests involving fork() */
201  if (lsan_disable) return 1;
202 
203  /* Parent */
204  if (lsan_test_pid != 0) return 0;
205 
206  /* Child */
207  if (write(lsan_test_pipe[1], &ret, sizeof(ret)) < 0) {
208  fprintf(stderr, "Writing LSAN status failed: %s", fr_syserror(errno));
209  }
210  close(lsan_test_pipe[1]);
211  return 0;
212 }
213 DIAG_ON(missing-prototypes)
214 
215 /** Determine if we're running under LSAN (Leak Sanitizer)
216  *
217  * @return
218  * - 0 if we're not.
219  * - 1 if we are.
220  * - -1 if we can't tell because of an error.
221  * - -2 if we can't tell because we were compiled with support for the LSAN interface.
222  */
223 int fr_get_lsan_state(void)
224 {
225  uint8_t ret = 0;
226 
227  if (lsan_state != INT_MAX) return lsan_state;/* Use cached result */
228 
229  if (pipe(lsan_test_pipe) < 0) {
230  fr_strerror_printf("Failed opening internal pipe: %s", fr_syserror(errno));
231  return -1;
232  }
233 
234  lsan_test_pid = fork();
235  if (lsan_test_pid == -1) {
236  fr_strerror_printf("Error forking: %s", fr_syserror(errno));
237  return -1;
238  }
239 
240  /* Child */
241  if (lsan_test_pid == 0) {
242  close(lsan_test_pipe[0]); /* Close parent's side */
243  exit(EXIT_SUCCESS); /* Results in LSAN calling __lsan_is_turned_off via onexit handler */
244  }
245 
246  /* Parent */
247  close(lsan_test_pipe[1]); /* Close child's side */
248 
249  while ((read(lsan_test_pipe[0], &ret, sizeof(ret)) < 0) && (errno == EINTR));
250 
251  close(lsan_test_pipe[0]); /* Close our side (so we don't leak FDs) */
252 
253  /* Collect child */
254  waitpid(lsan_test_pid, NULL, 0);
255 
256  lsan_state = ret; /* Cache test results */
257 
258  return ret;
259 }
260 #else
262 {
263  fr_strerror_const("Not built with support for LSAN interface");
264  return -2;
265 }
266 #endif
267 
268 #if defined(HAVE_SYS_PROCCTL_H)
269 int fr_get_debug_state(void)
270 {
271  int status;
272 
273  if (procctl(P_PID, getpid(), PROC_TRACE_STATUS, &status) == -1) {
274  fr_strerror_printf("Cannot get dumpable flag: procctl(PROC_TRACE_STATUS) failed: %s", fr_syserror(errno));
275  return DEBUGGER_STATE_UNKNOWN;
276  }
277 
278  /*
279  * As FreeBSD docs say about "PROC_TRACE_STATUS":
280  *
281  * Returns the current tracing status for the specified process in the
282  * integer variable pointed to by data. If tracing is disabled, data
283  * is set to -1. If tracing is enabled, but no debugger is attached by
284  * the ptrace(2) syscall, data is set to 0. If a debugger is attached,
285  * data is set to the pid of the debugger process.
286  */
287  if (status <= 0) return DEBUGGER_STATE_NOT_ATTACHED;
288 
290 }
291 #elif defined(__APPLE__)
292 /** The ptrace_attach() method no longer works as of macOS 11.4 (we always get eperm)
293  *
294  * Apple published this helpful article here which provides the
295  * magical invocation: https://developer.apple.com/library/archive/qa/qa1361/_index.html
296  *
297  * @return
298  * - 0 if we're not.
299  * - 1 if we are.
300  * - -1
301  */
302 int fr_get_debug_state(void)
303 {
304  int ret;
305  int mib[4];
306  struct kinfo_proc info;
307  size_t size;
308 
309  /*
310  * Initialize the flags so that, if sysctl fails for some
311  * reason, we get a predictable result.
312  */
313  info.kp_proc.p_flag = 0;
314 
315  /*
316  * Initialize mib, which tells sysctl the info we want, in this case
317  * we're looking for information about a specific process ID.
318  */
319  mib[0] = CTL_KERN;
320  mib[1] = KERN_PROC;
321  mib[2] = KERN_PROC_PID;
322  mib[3] = getpid();
323 
324  /* Call sysctl */
325  size = sizeof(info);
326  ret = sysctl(mib, NUM_ELEMENTS(mib), &info, &size, NULL, 0);
327  if (ret != 0) return -1;
328 
329  /* We're being debugged if the P_TRACED flag is set */
330  return ((info.kp_proc.p_flag & P_TRACED) != 0);
331 }
332 #elif defined(HAVE_SYS_PTRACE_H) && !defined(__EMSCRIPTEN__)
333 /** Determine if we're running under a debugger by attempting to attach using pattach
334  *
335  * @return
336  * - 0 if we're not.
337  * - 1 if we are.
338  * - -1 if we can't tell because of an error.
339  * - -2 if we can't tell because we don't have the CAP_SYS_PTRACE capability.
340  */
341 int fr_get_debug_state(void)
342 {
343  int pid;
344 
345  int from_child[2] = {-1, -1};
346 
347 #ifdef HAVE_CAPABILITY_H
348  cap_flag_value_t state;
349  cap_t caps;
350 
351  /*
352  * If we're running under linux, we first need to check if we have
353  * permission to to ptrace. We do that using the capabilities
354  * functions.
355  */
356  caps = cap_get_proc();
357  if (!caps) {
358  fr_strerror_printf("Failed getting process capabilities: %s", fr_syserror(errno));
359  return DEBUGGER_STATE_UNKNOWN;
360  }
361 
362  if (cap_get_flag(caps, CAP_SYS_PTRACE, CAP_PERMITTED, &state) < 0) {
363  fr_strerror_printf("Failed getting CAP_SYS_PTRACE permitted state: %s",
364  fr_syserror(errno));
365  cap_free(caps);
366  return DEBUGGER_STATE_UNKNOWN;
367  }
368 
369  if ((state == CAP_SET) && (cap_get_flag(caps, CAP_SYS_PTRACE, CAP_EFFECTIVE, &state) < 0)) {
370  fr_strerror_printf("Failed getting CAP_SYS_PTRACE effective state: %s",
371  fr_syserror(errno));
372  cap_free(caps);
373  return DEBUGGER_STATE_UNKNOWN;
374  }
375 
376  /*
377  * We don't have permission to ptrace, so this test will always fail.
378  */
379  if (state == CAP_CLEAR) {
380  fr_strerror_printf("ptrace capability not set. If debugger detection is required run as root or: "
381  "setcap cap_sys_ptrace+ep <path_to_binary>");
382  cap_free(caps);
384  }
385  cap_free(caps);
386 #endif
387 
388  if (pipe(from_child) < 0) {
389  fr_strerror_printf("Error opening internal pipe: %s", fr_syserror(errno));
390  return DEBUGGER_STATE_UNKNOWN;
391  }
392 
393  pid = fork();
394  if (pid == -1) {
395  fr_strerror_printf("Error forking: %s", fr_syserror(errno));
396  return DEBUGGER_STATE_UNKNOWN;
397  }
398 
399  /* Child */
400  if (pid == 0) {
401  int8_t ret = DEBUGGER_STATE_NOT_ATTACHED;
402  int ppid = getppid();
403  int flags;
404 
405  /*
406  * Disable the leak checker for this forked process
407  * so we don't get spurious leaks reported.
408  */
409 #ifdef HAVE_SANITIZER_LSAN_INTERFACE_H
410  lsan_disable = true;
411 #endif
412 
413 DIAG_OFF(deprecated-declarations)
414  flags = PT_ATTACH;
415 DIAG_ON(deprecated-declarations)
416 
417  /* Close parent's side */
418  close(from_child[0]);
419 
420  /*
421  * FreeBSD is extremely picky about the order of operations here
422  * we need to attach, wait *then* write whilst the parent is still
423  * suspended, then detach, continuing the process.
424  *
425  * If we don't do it in that order the read in the parent triggers
426  * a SIGKILL.
427  */
428  errno = 0;
429  _PTRACE(flags, ppid);
430  if (errno == 0) {
431  /* Wait for the parent to stop */
432  waitpid(ppid, NULL, 0);
433 
434  /* Tell the parent what happened */
435  send_status:
436  if (write(from_child[1], &ret, sizeof(ret)) < 0) {
437  fprintf(stderr, "Writing ptrace status to parent failed: %s\n", fr_syserror(errno));
438  }
439 
440  /* Detach */
441  _PTRACE_DETACH(ppid);
442 
443 
444  /*
445  * We call _exit() instead of exit(). This means that we skip the atexit() handlers,
446  * which don't need to run in a temporary child process. Skipping them means that we
447  * avoid dirtying those pages to "clean things up", which is then immediately followed by
448  * exiting.
449  *
450  * Skipping the atexit() handlers also means that we're not worried about memory leaks
451  * because things "aren't cleaned up correctly". We're not exiting cleanly here (and
452  * don't care to exit cleanly). So just exiting with no cleanups is fine.
453  */
454  _exit(0); /* don't run the atexit() handlers. */
455  /*
456  * man ptrace says the following:
457  *
458  * EPERM The specified process cannot be traced. This could be
459  * because the tracer has insufficient privileges (the
460  * required capability is CAP_SYS_PTRACE); unprivileged
461  * processes cannot trace processes that they cannot send
462  * signals to or those running set-user-ID/set-group-ID
463  * programs, for obvious reasons. Alternatively, the process
464  * may already be being traced, or (before Linux 2.6.26) be
465  * init(1) (PID 1).
466  *
467  * In any case, we are very unlikely to be able to attach to
468  * the process from the panic action.
469  *
470  * We checked for CAP_SYS_PTRACE previously, so know that
471  * we _should_ haven been ablle to attach, so if we can't, it's
472  * likely that we're already being traced.
473  */
474  } else if (errno == EPERM) {
476  goto send_status;
477  }
478 
479  /*
480  * Unexpected error, we don't know whether we're already running
481  * under a debugger or not...
482  */
484  fprintf(stderr, "Debugger check failed to attach to parent with unexpected error: %s\n", fr_syserror(errno));
485  goto send_status;
486  /* Parent */
487  } else {
488  int8_t ret = DEBUGGER_STATE_UNKNOWN;
489 
490  /*
491  * The child writes errno (reason) if pattach failed else 0.
492  *
493  * This read may be interrupted by pattach,
494  * which is why we need the loop.
495  */
496  while ((read(from_child[0], &ret, sizeof(ret)) < 0) && (errno == EINTR));
497 
498  /* Close the pipes here (if we did it above, it might race with pattach) */
499  close(from_child[1]);
500  close(from_child[0]);
501 
502  /* Collect the status of the child */
503  waitpid(pid, NULL, 0);
504 
505  return ret;
506  }
507 }
508 #else
510 {
511  fr_strerror_const("PTRACE not available");
512 
514 }
515 #endif
516 
517 /** Should be run before using setuid or setgid to get useful results
518  *
519  * @note sets the fr_debug_state global.
520  */
522 {
524 
525 #ifndef NDEBUG
526  /*
527  * There are many reasons why this might happen with
528  * a vanilla install, so we don't want to spam users
529  * with messages they won't understand and may not
530  * want to resolve.
531  */
532  if (fr_debug_state < 0) fprintf(stderr, "Getting debug state failed: %s\n", fr_strerror());
533 #endif
534 }
535 
536 /** Return current value of debug_state
537  *
538  * @param state to translate into a humanly readable value.
539  * @return humanly readable version of debug state.
540  */
542 {
543  switch (state) {
545  return "Debug state unknown (ptrace functionality not available)";
546 
548  return "Debug state unknown (cap_sys_ptrace capability not set)";
549 
551  return "Debug state unknown";
552 
554  return "Found debugger attached";
555 
557  return "Debugger not attached";
558  }
559 
560  return "<INVALID>";
561 }
562 
563 /** Break in debugger (if were running under a debugger)
564  *
565  * If the server is running under a debugger this will raise a
566  * SIGTRAP which will pause the running process.
567  *
568  * If the server is not running under debugger then this will do nothing.
569  */
570 void fr_debug_break(bool always)
571 {
572  if (always) raise(SIGTRAP);
573 
576  fprintf(stderr, "Debugger detected, raising SIGTRAP\n");
577  fflush(stderr);
578 
579  raise(SIGTRAP);
580  }
581 }
582 
583 #ifdef HAVE_EXECINFO
584 /** Print backtrace entry for a given object
585  *
586  * @param fring to search in.
587  * @param obj pointer to original object
588  */
589 void backtrace_print(fr_fring_t *fring, void *obj)
590 {
591  fr_bt_info_t *p;
592  bool found = false;
593 
594  while ((p = fr_fring_next(fring))) {
595  if ((p->obj == obj) || !obj) {
596  found = true;
597 
598  fprintf(stderr, "Stacktrace for: %p\n", p->obj);
599  backtrace_symbols_fd(p->frames, p->count, STDERR_FILENO);
600  }
601  }
602 
603  if (!found) {
604  fprintf(stderr, "No backtrace available for %p", obj);
605  }
606 }
607 
608 /** Generate a backtrace for an object
609  *
610  * If this is the first entry being inserted
611  */
612 int fr_backtrace_do(fr_bt_marker_t *marker)
613 {
614  fr_bt_info_t *bt;
615 
616  if (!fr_cond_assert(marker->obj) || !fr_cond_assert(marker->fring)) return -1;
617 
618  bt = talloc_zero(NULL, fr_bt_info_t);
619  if (!bt) return -1;
620 
621  bt->obj = marker->obj;
622  bt->count = backtrace(bt->frames, MAX_BT_FRAMES);
623 
624  fr_fring_overwrite(marker->fring, bt);
625 
626  return 0;
627 }
628 
629 /** Inserts a backtrace marker into the provided context
630  *
631  * Allows for maximum laziness and will initialise a circular buffer if one has not already been created.
632  *
633  * Code augmentation should look something like:
634 @verbatim
635  // Create a static fringer pointer, the first call to backtrace_attach will initialise it
636  static fr_fring_t *my_obj_bt;
637 
638  my_obj_t *alloc_my_obj(TALLOC_CTX *ctx) {
639  my_obj_t *this;
640 
641  this = talloc(ctx, my_obj_t);
642 
643  // Attach backtrace marker to object
644  backtrace_attach(&my_obj_bt, this);
645 
646  return this;
647  }
648 @endverbatim
649  *
650  * Then, later when a double free occurs:
651 @verbatim
652  (gdb) call backtrace_print(&my_obj_bt, <pointer to double freed memory>)
653 @endverbatim
654  *
655  * which should print a limited backtrace to stderr. Note, this backtrace will not include any argument
656  * values, but should at least show the code path taken.
657  *
658  * @param fring this should be a pointer to a static *fr_fring_buffer.
659  * @param obj we want to generate a backtrace for.
660  */
661 fr_bt_marker_t *fr_backtrace_attach(fr_fring_t **fring, TALLOC_CTX *obj)
662 {
663  fr_bt_marker_t *marker;
664 
665  if (*fring == NULL) {
666  pthread_mutex_lock(&fr_debug_init);
667  /* Check again now we hold the mutex - eww*/
668  if (*fring == NULL) *fring = fr_fring_alloc(NULL, MAX_BT_CBUFF, true);
669  pthread_mutex_unlock(&fr_debug_init);
670  }
671 
672  marker = talloc(obj, fr_bt_marker_t);
673  if (!marker) {
674  return NULL;
675  }
676 
677  marker->obj = (void *) obj;
678  marker->fring = *fring;
679 
680  fprintf(stderr, "Backtrace attached to %s %p\n", talloc_get_name(obj), obj);
681  /*
682  * Generate the backtrace for memory allocation
683  */
684  fr_backtrace_do(marker);
685  talloc_set_destructor(marker, fr_backtrace_do);
686 
687  return marker;
688 }
689 #else
690 void backtrace_print(UNUSED fr_fring_t *fring, UNUSED void *obj)
691 {
692  fprintf(stderr, "Server built without fr_backtrace_* support, requires execinfo.h and possibly -lexecinfo\n");
693 }
695 {
696  fprintf(stderr, "Server built without fr_backtrace_* support, requires execinfo.h and possibly -lexecinfo\n");
697  abort();
698 }
699 #endif /* ifdef HAVE_EXECINFO */
700 
701 static int _panic_on_free(UNUSED char *foo)
702 {
703  fr_fault(SIGABRT);
704  return -1; /* this should make the free fail */
705 }
706 
707 /** Insert memory into the context of another talloc memory chunk which
708  * causes a panic when freed.
709  *
710  * @param ctx TALLOC_CTX to monitor for frees.
711  */
712 void fr_panic_on_free(TALLOC_CTX *ctx)
713 {
714  char *ptr;
715 
716  ptr = talloc(ctx, char);
717  talloc_set_destructor(ptr, _panic_on_free);
718 }
719 
720 /** Set the dumpable flag, also controls whether processes can PATTACH
721  *
722  * @param dumpable whether we should allow core dumping
723  */
724 #if defined(HAVE_SYS_PRCTL_H) && defined(PR_SET_DUMPABLE) && !defined(__EMSCRIPTEN__)
725 static int fr_set_pr_dumpable_flag(bool dumpable)
726 {
727  if (prctl(PR_SET_DUMPABLE, dumpable ? 1 : 0) < 0) {
728  fr_strerror_printf("Cannot re-enable core dumps: prctl(PR_SET_DUMPABLE) failed: %s",
729  fr_syserror(errno));
730  return -1;
731  }
732 
733  return 0;
734 }
735 #elif defined(HAVE_SYS_PROCCTL_H)
736 static int fr_set_pr_dumpable_flag(bool dumpable)
737 {
738  int mode = dumpable ? PROC_TRACE_CTL_ENABLE : PROC_TRACE_CTL_DISABLE;
739 
740  if (procctl(P_PID, getpid(), PROC_TRACE_CTL, &mode) == -1) {
741  fr_strerror_printf("Cannot re-enable core dumps: procctl(PROC_TRACE_CTL) failed: %s",
742  fr_syserror(errno));
743  return -1;
744  }
745 
746  return 0;
747 }
748 #else
749 static int fr_set_pr_dumpable_flag(UNUSED bool dumpable)
750 {
751  fr_strerror_const("Changing value of PR_DUMPABLE not supported on this system");
752  return -2;
753 }
754 #endif
755 
756 /** Get the processes dumpable flag
757  *
758  */
759 #if defined(HAVE_SYS_PRCTL_H) && defined(PR_GET_DUMPABLE) && !defined(__EMSCRIPTEN__)
760 static int fr_get_pr_dumpable_flag(void)
761 {
762  int ret;
763 
764  ret = prctl(PR_GET_DUMPABLE);
765  if (ret < 0) {
766  fr_strerror_printf("Cannot get dumpable flag: %s", fr_syserror(errno));
767  return -1;
768  }
769 
770  /*
771  * Linux is crazy and prctl sometimes returns 2 for disabled
772  */
773  if (ret != 1) return 0;
774  return 1;
775 }
776 #elif defined(HAVE_SYS_PROCCTL_H)
777 static int fr_get_pr_dumpable_flag(void)
778 {
779  int status;
780 
781  if (procctl(P_PID, getpid(), PROC_TRACE_CTL, &status) == -1) {
782  fr_strerror_printf("Cannot get dumpable flag: procctl(PROC_TRACE_CTL) failed: %s", fr_syserror(errno));
783  return -1;
784  }
785 
786  /*
787  * There are a few different kinds of disabled, but only
788  * one ENABLE.
789  */
790  if (status != PROC_TRACE_CTL_ENABLE) return 0;
791 
792  return 1;
793 }
794 #else
795 static int fr_get_pr_dumpable_flag(void)
796 {
797  fr_strerror_const("Getting value of PR_DUMPABLE not supported on this system");
798  return -2;
799 }
800 #endif
801 
802 
803 /** Get the current maximum for core files
804  *
805  * Do this before anything else so as to ensure it's properly initialized.
806  */
808 {
809 #ifdef HAVE_SYS_RESOURCE_H
810  if (getrlimit(RLIMIT_CORE, &init_core_limit) < 0) {
811  fr_strerror_printf("Failed to get current core limit: %s", fr_syserror(errno));
812  return -1;
813  }
814 #endif
815  return 0;
816 }
817 
818 /** Enable or disable core dumps
819  *
820  * @param allow_core_dumps whether to enable or disable core dumps.
821  */
822 int fr_set_dumpable(bool allow_core_dumps)
823 {
824  dump_core = allow_core_dumps;
825 
826 #ifdef HAVE_SYS_RESOURCE_H
827  {
828  struct rlimit current;
829 
830  /*
831  * Reset the core limits (or disable them)
832  */
833  if (getrlimit(RLIMIT_CORE, &current) < 0) {
834  fr_strerror_printf("Failed to get current core limit: %s", fr_syserror(errno));
835  return -1;
836  }
837 
838  if (allow_core_dumps) {
839  if ((current.rlim_cur != init_core_limit.rlim_cur) ||
840  (current.rlim_max != init_core_limit.rlim_max)) {
841  if (setrlimit(RLIMIT_CORE, &init_core_limit) < 0) {
842  fr_strerror_printf("Cannot update core dump limit: %s", fr_syserror(errno));
843 
844  return -1;
845  }
846  }
847  /*
848  * We've been told to disable core dumping,
849  * rlim_cur is not set to zero.
850  *
851  * Set rlim_cur to zero, but leave rlim_max
852  * set to whatever the current value is.
853  *
854  * This is because, later, we may need to
855  * re-enable core dumps to allow the debugger
856  * to attach *sigh*.
857  */
858  } else if (current.rlim_cur != 0) {
859  struct rlimit no_core;
860 
861  no_core.rlim_cur = 0;
862  no_core.rlim_max = current.rlim_max;
863 
864  if (setrlimit(RLIMIT_CORE, &no_core) < 0) {
865  fr_strerror_printf("Failed disabling core dumps: %s", fr_syserror(errno));
866 
867  return -1;
868  }
869  }
870  }
871 #endif
872  /*
873  * Macro needed so we don't emit spurious errors
874  */
875 #if defined(HAVE_SYS_PROCCTL_H) || (defined(HAVE_SYS_PRCTL_H) && defined(PR_SET_DUMPABLE))
876  if (fr_set_pr_dumpable_flag(allow_core_dumps) < 0) return -1;
877 #endif
878 
879  return 0;
880 }
881 
882 /** Reset dumpable state to previously configured value
883  *
884  * Needed after suid up/down
885  *
886  * @return
887  * - 0 on success.
888  * - -1 on failure.
889  */
891 {
892  return fr_set_dumpable(dump_core);
893 }
894 
895 /** Check to see if panic_action file is world writable
896  *
897  * @return
898  * - 0 if file is OK.
899  * - -1 if the file is world writable.
900  */
902 {
903  char const *p, *q;
904  size_t len;
905  char filename[256];
906  struct stat statbuf;
907 
908  /*
909  * Try and guess which part of the command is the binary, and check to see if
910  * it's world writable, to try and save the admin from their own stupidity.
911  *
912  * @fixme we should do this properly and take into account single and double
913  * quotes.
914  */
915  if ((q = strchr(panic_action, ' '))) {
916  /*
917  * need to use a static buffer, because allocing memory in a signal handler
918  * is a bad idea and can result in deadlock.
919  */
920  len = snprintf(filename, sizeof(filename), "%.*s", (int)(q - panic_action), panic_action);
921  if (is_truncated(len, sizeof(filename))) {
922  fr_strerror_const("Failed writing panic_action to temporary buffer (truncated)");
923  return -1;
924  }
925  p = filename;
926  } else {
927  p = panic_action;
928  }
929 
930  if (stat(p, &statbuf) == 0) {
931 #ifdef S_IWOTH
932  if ((statbuf.st_mode & S_IWOTH) != 0) {
933  fr_strerror_printf("panic_action file \"%s\" is globally writable", p);
934  return -1;
935  }
936 #endif
937  }
938 
939  return 0;
940 }
941 
942 /** Split out so it can be sprinkled throughout the server and called via a debugger
943  *
944  */
946 {
947 
948  /*
949  * Produce a simple backtrace - They're very basic but at least give us an
950  * idea of the area of the code we hit the issue in.
951  *
952  * See below in fr_fault_setup() and
953  * https://sourceware.org/bugzilla/show_bug.cgi?id=16159
954  * for why we only print backtraces in debug builds if we're using GLIBC.
955  */
956 #if defined(HAVE_EXECINFO) && (!defined(NDEBUG) || !defined(__GNUC__))
957  if (fr_fault_log_fd >= 0) {
958  size_t frame_count;
959  void *stack[MAX_BT_FRAMES];
960 
961  frame_count = backtrace(stack, MAX_BT_FRAMES);
962 
963  FR_FAULT_LOG("Backtrace of last %zu frames:", frame_count);
964 
965  backtrace_symbols_fd(stack, frame_count, fr_fault_log_fd);
966  }
967 #endif
968  return;
969 }
970 
971 /** Prints a simple backtrace (if execinfo is available) and calls panic_action if set.
972  *
973  * @param sig caught
974  */
975 NEVER_RETURNS void fr_fault(int sig)
976 {
977  char cmd[sizeof(panic_action) + 20];
978  char *out = cmd;
979  size_t left = sizeof(cmd), ret;
980 
981  char const *p = panic_action;
982  char const *q;
983 
984  int code;
985 
986  /*
987  * If a debugger is attached, we don't want to run the panic action,
988  * as it may interfere with the operation of the debugger.
989  * If something calls us directly we just raise the signal and let
990  * the debugger handle it how it wants.
991  */
993  FR_FAULT_LOG("RAISING SIGNAL: %s", strsignal(sig));
994  raise(sig);
995  }
996 
997  /*
998  * Makes the backtraces slightly cleaner
999  */
1000  memset(cmd, 0, sizeof(cmd));
1001 
1002  FR_FAULT_LOG("CAUGHT SIGNAL: %s", strsignal(sig));
1003 
1004  /*
1005  * Run the callback if one was registered
1006  */
1007  if (panic_cb && (panic_cb(sig) < 0)) goto finish;
1008 
1010 
1011  /* No panic action set... */
1012  if (panic_action[0] == '\0') {
1013  FR_FAULT_LOG("No panic action set");
1014  goto finish;
1015  }
1016 
1017  /*
1018  * Check for administrator sanity.
1019  */
1020  if (fr_fault_check_permissions() < 0) {
1021  FR_FAULT_LOG("Refusing to execute panic action: %s", fr_strerror());
1022  goto finish;
1023  }
1024 
1025  /* Substitute %p for the current PID (useful for attaching a debugger) */
1026  while ((q = strstr(p, "%p"))) {
1027  out += ret = snprintf(out, left, "%.*s%d", (int) (q - p), p, (int) getpid());
1028  if (left <= ret) {
1029  oob:
1030  FR_FAULT_LOG("Panic action too long");
1031  fr_exit_now(128 + sig);
1032  }
1033  left -= ret;
1034  p = q + 2;
1035  }
1036  if (strlen(p) >= left) goto oob;
1037  strlcpy(out, p, left);
1038 
1039  {
1040  bool disable = false;
1041 
1042  FR_FAULT_LOG("Calling: %s", cmd);
1043 
1044  /*
1045  * Here we temporarily enable the dumpable flag so if GBD or LLDB
1046  * is called in the panic_action, they can pattach to the running
1047  * process.
1048  */
1049  if (fr_get_pr_dumpable_flag() == 0) {
1050  if ((fr_set_pr_dumpable_flag(true) < 0) || !fr_get_pr_dumpable_flag()) {
1051  FR_FAULT_LOG("Failed setting dumpable flag, pattach may not work: %s", fr_strerror());
1052  } else {
1053  disable = true;
1054  }
1055  FR_FAULT_LOG("Temporarily setting PR_DUMPABLE to 1");
1056  }
1057 
1058  code = system(cmd);
1059 
1060  /*
1061  * We only want to error out here, if dumpable was originally disabled
1062  * and we managed to change the value to enabled, but failed
1063  * setting it back to disabled.
1064  */
1065  if (disable) {
1066  FR_FAULT_LOG("Resetting PR_DUMPABLE to 0");
1067  if (fr_set_pr_dumpable_flag(false) < 0) {
1068  FR_FAULT_LOG("Failed resetting dumpable flag to off: %s", fr_strerror());
1069  FR_FAULT_LOG("Exiting due to insecure process state");
1070  fr_exit_now(EXIT_FAILURE);
1071  }
1072  }
1073 
1074  FR_FAULT_LOG("Panic action exited with %i", code);
1075 
1076  fr_exit_now(128 + sig);
1077  }
1078 
1079 finish:
1080  /*
1081  * (Re-)Raise the signal, so that if we're running under
1082  * a debugger.
1083  *
1084  * This allows debuggers to function normally and catch
1085  * fatal signals.
1086  */
1087  fr_unset_signal(sig); /* Make sure we don't get into a loop */
1088  raise(sig);
1089  fr_exit_now(128 + sig); /* Function marked as noreturn */
1090 }
1091 
1092 /** Callback executed on fatal talloc error
1093  *
1094  * This is the simple version which mostly behaves the same way as the default
1095  * one, and will not call panic_action.
1096  *
1097  * @param reason string provided by talloc.
1098  */
1099 static void _fr_talloc_fault_simple(char const *reason) CC_HINT(noreturn);
1100 static void _fr_talloc_fault_simple(char const *reason)
1101 {
1102  FR_FAULT_LOG("talloc abort: %s\n", reason);
1103 
1104 #if defined(HAVE_EXECINFO) && (!defined(NDEBUG) || !defined(__GNUC__))
1105  if (fr_fault_log_fd >= 0) {
1106  size_t frame_count;
1107  void *stack[MAX_BT_FRAMES];
1108 
1109  frame_count = backtrace(stack, MAX_BT_FRAMES);
1110  FR_FAULT_LOG("Backtrace of last %zu frames:", frame_count);
1111  backtrace_symbols_fd(stack, frame_count, fr_fault_log_fd);
1112  }
1113 #endif
1114  abort();
1115 }
1116 
1117 /** Callback executed on fatal talloc error
1118  *
1119  * Translates a talloc abort into a fr_fault call.
1120  * Mostly to work around issues with some debuggers not being able to
1121  * attach after a SIGABRT has been raised.
1122  *
1123  * @param reason string provided by talloc.
1124  */
1125 static void _fr_talloc_fault(char const *reason) CC_HINT(noreturn);
1126 static void _fr_talloc_fault(char const *reason)
1127 {
1128  FR_FAULT_LOG("talloc abort: %s", reason);
1129 #ifdef SIGABRT
1130  fr_fault(SIGABRT);
1131 #endif
1132  fr_exit_now(128 + SIGABRT);
1133 }
1134 
1135 /** Wrapper to pass talloc log output to our fr_fault_log function
1136  *
1137  */
1138 static void _fr_talloc_log(char const *msg)
1139 {
1140  fr_fault_log("%s\n", msg);
1141 }
1142 
1143 /** Generate a talloc memory report for a context and print to stderr/stdout
1144  *
1145  * @param ctx to generate a report for, may be NULL in which case the root context is used.
1146  */
1147 int fr_log_talloc_report(TALLOC_CTX const *ctx)
1148 {
1149 #define TALLOC_REPORT_MAX_DEPTH 20
1150 
1151  FILE *log;
1152  int fd;
1153 
1154  fd = dup(fr_fault_log_fd);
1155  if (fd < 0) {
1156  fr_strerror_printf("Couldn't write memory report, failed to dup log fd: %s", fr_syserror(errno));
1157  return -1;
1158  }
1159  log = fdopen(fd, "w");
1160  if (!log) {
1161  close(fd);
1162  fr_strerror_printf("Couldn't write memory report, fdopen failed: %s", fr_syserror(errno));
1163  return -1;
1164  }
1165 
1166  if (!ctx) {
1167  fprintf(log, "Current state of talloced memory:\n");
1168  talloc_report_full(talloc_null_ctx(), log);
1169  } else {
1170  int i;
1171 
1172  fprintf(log, "Talloc chunk lineage:\n");
1173  fprintf(log, "%p (%s)", ctx, talloc_get_name(ctx));
1174 
1175  i = 0;
1176  while ((i < TALLOC_REPORT_MAX_DEPTH) && (ctx = talloc_parent(ctx))) {
1177  fprintf(log, " < %p (%s)", ctx, talloc_get_name(ctx));
1178  i++;
1179  }
1180  fprintf(log, "\n");
1181 
1182  i = 0;
1183  do {
1184  fprintf(log, "Talloc context level %i:\n", i++);
1185  talloc_report_full(ctx, log);
1186  } while ((ctx = talloc_parent(ctx)) &&
1187  (i < TALLOC_REPORT_MAX_DEPTH) &&
1188  (talloc_parent(ctx) != talloc_autofree_ctx) && /* Stop before we hit the autofree ctx */
1189  (talloc_parent(ctx) != talloc_null_ctx())); /* Stop before we hit NULL ctx */
1190  }
1191 
1192  fclose(log);
1193 
1194  return 0;
1195 }
1196 
1197 
1198 static int _disable_null_tracking(UNUSED bool *p)
1199 {
1200  talloc_disable_null_tracking();
1201  return 0;
1202 }
1203 
1204 /** Disable the null tracking context when a talloc chunk is freed
1205  *
1206  */
1208 {
1209  bool *marker;
1210 
1211  /*
1212  * Disable null tracking on exit, else valgrind complains
1213  */
1214  marker = talloc(ctx, bool);
1215  talloc_set_destructor(marker, _disable_null_tracking);
1216 }
1217 
1218 /** Register talloc fault handlers
1219  *
1220  * Just register the fault handlers we need to make talloc
1221  * produce useful debugging output.
1222  */
1224 {
1225  talloc_set_log_fn(_fr_talloc_log);
1226  talloc_set_abort_fn(_fr_talloc_fault_simple);
1227 }
1228 
1229 /** Registers signal handlers to execute panic_action on fatal signal
1230  *
1231  * May be called multiple time to change the panic_action/program.
1232  *
1233  * @param[in] ctx to allocate autofreeable resources in.
1234  * @param[in] cmd to execute on fault. If present %p will be substituted
1235  * for the parent PID before the command is executed, and %e
1236  * will be substituted for the currently running program.
1237  * @param program Name of program currently executing (argv[0]).
1238  * @return
1239  * - 0 on success.
1240  * - -1 on failure.
1241  */
1242 int fr_fault_setup(TALLOC_CTX *ctx, char const *cmd, char const *program)
1243 {
1244  static bool setup = false;
1245 
1246  char *out = panic_action;
1247  size_t left = sizeof(panic_action);
1248 
1249  char const *p = cmd;
1250  char const *q;
1251 
1252  if (cmd) {
1253  size_t ret;
1254 
1255  /* Substitute %e for the current program */
1256  while ((q = strstr(p, "%e"))) {
1257  out += ret = snprintf(out, left, "%.*s%s", (int) (q - p), p, program ? program : "");
1258  if (left <= ret) {
1259  oob:
1260  fr_strerror_const("Panic action too long");
1261  return -1;
1262  }
1263  left -= ret;
1264  p = q + 2;
1265  }
1266  if (strlen(p) >= left) goto oob;
1267  strlcpy(out, p, left);
1268  } else {
1269  *panic_action = '\0';
1270  }
1271 
1272  /*
1273  * Check for administrator sanity.
1274  */
1275  if (fr_fault_check_permissions() < 0) return -1;
1276 
1277  /* Unsure what the side effects of changing the signal handler mid execution might be */
1278  if (!setup) {
1279  char *env;
1280 
1281  /*
1282  * Installing signal handlers interferes with some debugging
1283  * operations. Give the developer control over whether the
1284  * signal handlers are installed or not.
1285  */
1286  env = getenv("DEBUGGER_ATTACHED");
1287  if (env && (strcmp(env, "yes") == 0)) {
1288  fr_debug_state = DEBUGGER_STATE_ATTACHED; /* i.e. disable signal handlers */
1289 
1290  } else if (env && (strcmp(env, "no") == 0)) {
1291  fr_debug_state = DEBUGGER_STATE_NOT_ATTACHED; /* i.e. enable signal handlers */
1292 
1293  /*
1294  * Figure out if we were started under a debugger
1295  */
1296  } else {
1298  }
1299 
1300  talloc_set_log_fn(_fr_talloc_log);
1301 
1302  /*
1303  * These signals can't be properly dealt with in the debugger
1304  * if we set our own signal handlers.
1305  */
1306  switch (fr_debug_state) {
1307  default:
1309 #ifdef SIGABRT
1310  if (fr_set_signal(SIGABRT, fr_fault) < 0) return -1;
1311 
1312  /*
1313  * Use this instead of abort so we get a
1314  * full backtrace with broken versions of LLDB
1315  */
1316  talloc_set_abort_fn(_fr_talloc_fault);
1317 #endif
1318 #ifdef SIGILL
1319  if (fr_set_signal(SIGILL, fr_fault) < 0) return -1;
1320 #endif
1321 #ifdef SIGFPE
1322  if (fr_set_signal(SIGFPE, fr_fault) < 0) return -1;
1323 #endif
1324 #ifdef SIGSEGV
1325  if (fr_set_signal(SIGSEGV, fr_fault) < 0) return -1;
1326 #endif
1327 #ifdef SIGALRM
1328  /*
1329  * This is used be jlibtool to terminate
1330  * processes which have been running too
1331  * long.
1332  */
1333  if (fr_set_signal(SIGALRM, fr_fault) < 0) return -1;
1334 #endif
1335  break;
1336 
1338  break;
1339  }
1340 
1341  /*
1342  * Needed for memory reports
1343  */
1345 
1346 #if defined(HAVE_MALLOPT) && !defined(NDEBUG)
1347  /*
1348  * If were using glibc malloc > 2.4 this scribbles over
1349  * uninitialised and freed memory, to make memory issues easier
1350  * to track down.
1351  */
1352 # ifdef M_PERTURB
1353  if (!getenv("TALLOC_FREE_FILL")) mallopt(M_PERTURB, 0x42);
1354 # endif
1355 # ifdef M_CHECK_ACTION
1356  mallopt(M_CHECK_ACTION, 3);
1357 # endif
1358 #endif
1359 
1360 #if defined(HAVE_EXECINFO) && defined(__GNUC__) && !defined(NDEBUG)
1361  /*
1362  * We need to pre-load lgcc_s, else we can get into a deadlock
1363  * in fr_fault, as backtrace() attempts to dlopen it.
1364  *
1365  * Apparently there's a performance impact of loading lgcc_s,
1366  * so only do it if this is a debug build.
1367  *
1368  * See: https://sourceware.org/bugzilla/show_bug.cgi?id=16159
1369  */
1370  {
1371  void *stack[10];
1372 
1373  backtrace(stack, 10);
1374  }
1375 #endif
1376  }
1377  setup = true;
1378 
1379  return 0;
1380 }
1381 
1382 /** Set a callback to be called before fr_fault()
1383  *
1384  * @param func to execute. If callback returns < 0
1385  * fr_fault will exit before running panic_action code.
1386  */
1388 {
1389  panic_cb = func;
1390 }
1391 
1392 /** Log output to the fr_fault_log_fd
1393  *
1394  * We used to support a user defined callback, which was set to a radlog
1395  * function. Unfortunately, when logging to syslog, syslog would alloc memory
1396  * which would result in a deadlock if fr_fault was triggered from within
1397  * a allocation call.
1398  *
1399  * Now we just write directly to the FD.
1400  */
1401 void fr_fault_log(char const *msg, ...)
1402 {
1403  va_list ap;
1404 
1405  if (fr_fault_log_fd < 0) return;
1406 
1407  va_start(ap, msg);
1409  va_end(ap);
1410 }
1411 
1412 /** Print data as a hex block
1413  *
1414  */
1415 void fr_fault_log_hex(uint8_t const *data, size_t data_len)
1416 {
1417  size_t i, j, len;
1418  char buffer[(0x10 * 3) + 1];
1419  char *p, *end = buffer + sizeof(buffer);
1420 
1421  for (i = 0; i < data_len; i += 0x10) {
1422  len = 0x10;
1423  if ((i + len) > data_len) len = data_len - i;
1424 
1425  for (p = buffer, j = 0; j < len; j++, p += 3) snprintf(p, end - p, "%02x ", data[i + j]);
1426 
1427  dprintf(fr_fault_log_fd, "%04x: %s\n", (int)i, buffer);
1428  }
1429 }
1430 
1431 /** Set a file descriptor to log memory reports to.
1432  *
1433  * @param fd to write output to.
1434  */
1436 {
1437  fr_fault_log_fd = fd;
1438 }
1439 
1440 /** A soft assertion which triggers the fault handler in debug builds
1441  *
1442  * @param[in] file the assertion failed in.
1443  * @param[in] line of the assertion in the file.
1444  * @param[in] expr that was evaluated.
1445  * @param[in] msg Message to print (may be NULL).
1446  * @param[in] ... Arguments for msg string.
1447  * @return the value of cond.
1448  */
1449 bool _fr_assert_fail(char const *file, int line, char const *expr, char const *msg, ...)
1450 {
1451  if (msg) {
1452  char str[256]; /* Decent compilers won't allocate this unless fmt is !NULL... */
1453  va_list ap;
1454 
1455  va_start(ap, msg);
1456  (void)vsnprintf(str, sizeof(str), msg, ap);
1457  va_end(ap);
1458 
1459 #ifndef NDEBUG
1460  FR_FAULT_LOG("ASSERT FAILED %s[%u]: %s: %s", file, line, expr, str);
1461  fr_fault(SIGABRT);
1462 #else
1463  FR_FAULT_LOG("ASSERT WOULD FAIL %s[%u]: %s: %s", file, line, expr, str);
1464  return false;
1465 #endif
1466  }
1467 
1468 #ifndef NDEBUG
1469  FR_FAULT_LOG("ASSERT FAILED %s[%u]: %s", file, line, expr);
1470  fr_fault(SIGABRT);
1471 #else
1472  FR_FAULT_LOG("ASSERT WOULD FAIL %s[%u]: %s", file, line, expr);
1473  return false;
1474 #endif
1475 }
1476 
1477 /** A fatal assertion which triggers the fault handler in debug builds or exits
1478  *
1479  * @param[in] file the assertion failed in.
1480  * @param[in] line of the assertion in the file.
1481  * @param[in] expr that was evaluated.
1482  * @param[in] msg Message to print (may be NULL).
1483  * @param[in] ... Arguments for msg string.
1484  */
1485 void _fr_assert_fatal(char const *file, int line, char const *expr, char const *msg, ...)
1486 {
1487  if (msg) {
1488  char str[256]; /* Decent compilers won't allocate this unless fmt is !NULL... */
1489  va_list ap;
1490 
1491  va_start(ap, msg);
1492  (void)vsnprintf(str, sizeof(str), msg, ap);
1493  va_end(ap);
1494 
1495  FR_FAULT_LOG("FATAL ASSERT %s[%u]: %s: %s", file, line, expr, str);
1496  } else {
1497  FR_FAULT_LOG("FATAL ASSERT %s[%u]: %s", file, line, expr);
1498  }
1499 
1500 #ifdef NDEBUG
1501  _fr_exit(file, line, 128 + SIGABRT, true);
1502 #else
1503  fr_fault(SIGABRT);
1504 #endif
1505 }
1506 
1507 /** Exit possibly printing a message about why we're exiting.
1508  *
1509  * @note Use the fr_exit(status) macro instead of calling this function directly.
1510  *
1511  * @param[in] file where fr_exit() was called.
1512  * @param[in] line where fr_exit() was called.
1513  * @param[in] status we're exiting with.
1514  * @param[in] now Exit immediately.
1515  */
1516 #ifndef NDEBUG
1517 NEVER_RETURNS void _fr_exit(char const *file, int line, int status, bool now)
1518 {
1519  if (status != EXIT_SUCCESS) {
1520  char const *error = fr_strerror();
1521 
1522  if (error && *error && (status != 0)) {
1523  FR_FAULT_LOG("%sEXIT(%i) CALLED %s[%u]. Last error was: %s", now ? "_" : "",
1524  status, file, line, error);
1525  } else {
1526  FR_FAULT_LOG("%sEXIT(%i) CALLED %s[%u]", now ? "_" : "", status, file, line);
1527  }
1528 
1529  fr_debug_break(false); /* If running under GDB we'll break here */
1530  }
1531 
1532  if (now) _Exit(status);
1533  exit(status);
1534 }
1535 #else
1536 NEVER_RETURNS void _fr_exit(UNUSED char const *file, UNUSED int line, int status, bool now)
1537 {
1538  if (status != EXIT_SUCCESS) fr_debug_break(false); /* If running under GDB we'll break here */
1539 
1540  if (now) _Exit(status);
1541  exit(status);
1542 }
1543 #endif
1544 
1545 /*
1546  * Sign a structure, but skip _signature at "offset".
1547  */
1548 static uint32_t fr_hash_struct(void const *ptr, size_t size, size_t offset)
1549 {
1550  uint32_t hash;
1551 
1552  /*
1553  * Hash entry is at the end of the structure, that's
1554  * best...
1555  */
1556  if ((size + 4) == offset) {
1557  return fr_hash(ptr, size);
1558  }
1559 
1560  hash = fr_hash(ptr, offset);
1561  return fr_hash_update(((uint8_t const *) ptr) + offset + 4, size - (offset + 4), hash);
1562 }
1563 
1564 void fr_sign_struct(void *ptr, size_t size, size_t offset)
1565 {
1566  *(uint32_t *) (((uint8_t *) ptr) + offset) = fr_hash_struct(ptr, size, offset);
1567 }
1568 
1569 void fr_verify_struct(void const *ptr, size_t size, size_t offset)
1570 {
1571  uint32_t hash;
1572 
1573  hash = fr_hash_struct(ptr, size, offset);
1574 
1575  (void) fr_cond_assert(hash == *(uint32_t const *) (((uint8_t const *) ptr) + offset));
1576 }
1577 
1578 void fr_verify_struct_member(void const *ptr, size_t len, uint32_t *signature)
1579 {
1580  uint32_t hash;
1581 
1582  hash = fr_hash(ptr, len);
1583  (void) fr_cond_assert(hash == *signature);
1584 }
vsnprintf(buffer, sizeof(buffer), fmt, args)
static int const char char buffer[256]
Definition: acutest.h:574
int const char * file
Definition: acutest.h:702
va_end(args)
log_entry msg
Definition: acutest.h:794
int const char int line
Definition: acutest.h:702
va_start(args, fmt)
#define NEVER_RETURNS
Should be placed before the function return type.
Definition: build.h:311
#define DIAG_ON(_x)
Definition: build.h:456
#define UNUSED
Definition: build.h:313
#define NUM_ELEMENTS(_t)
Definition: build.h:335
#define DIAG_OFF(_x)
Definition: build.h:455
fr_dcursor_iter_t void * current
Definition: dcursor.h:148
static int fr_fault_check_permissions(void)
Check to see if panic_action file is world writable.
Definition: debug.c:901
static char panic_action[512]
The command to execute when panicking.
Definition: debug.c:96
fr_bt_marker_t * fr_backtrace_attach(UNUSED fr_fring_t **fring, UNUSED TALLOC_CTX *obj)
Definition: debug.c:694
static int _disable_null_tracking(UNUSED bool *p)
Definition: debug.c:1198
static int _panic_on_free(UNUSED char *foo)
Definition: debug.c:701
char const * fr_debug_state_to_msg(fr_debug_state_t state)
Return current value of debug_state.
Definition: debug.c:541
void fr_disable_null_tracking_on_free(TALLOC_CTX *ctx)
Disable the null tracking context when a talloc chunk is freed.
Definition: debug.c:1207
bool _fr_assert_fail(char const *file, int line, char const *expr, char const *msg,...)
A soft assertion which triggers the fault handler in debug builds.
Definition: debug.c:1449
void fr_fault_set_log_fd(int fd)
Set a file descriptor to log memory reports to.
Definition: debug.c:1435
static bool dump_core
Whether we should drop a core on fatal signals.
Definition: debug.c:100
int fr_log_talloc_report(TALLOC_CTX const *ctx)
Generate a talloc memory report for a context and print to stderr/stdout.
Definition: debug.c:1147
int fr_set_dumpable(bool allow_core_dumps)
Enable or disable core dumps.
Definition: debug.c:822
static void _fr_talloc_fault_simple(char const *reason)
Callback executed on fatal talloc error.
Definition: debug.c:1100
void fr_verify_struct(void const *ptr, size_t size, size_t offset)
Definition: debug.c:1569
static int fr_set_pr_dumpable_flag(UNUSED bool dumpable)
Set the dumpable flag, also controls whether processes can PATTACH.
Definition: debug.c:749
static fr_fault_cb_t panic_cb
Callback to execute whilst panicking, before the panic_action.
Definition: debug.c:97
static TALLOC_CTX * talloc_autofree_ctx
Definition: debug.c:110
void fr_fault_backtrace(void)
Split out so it can be sprinkled throughout the server and called via a debugger.
Definition: debug.c:945
static uint32_t fr_hash_struct(void const *ptr, size_t size, size_t offset)
Definition: debug.c:1548
static int fr_fault_log_fd
Where to write debug output.
Definition: debug.c:102
int fr_reset_dumpable(void)
Reset dumpable state to previously configured value.
Definition: debug.c:890
int fr_fault_setup(TALLOC_CTX *ctx, char const *cmd, char const *program)
Registers signal handlers to execute panic_action on fatal signal.
Definition: debug.c:1242
void fr_verify_struct_member(void const *ptr, size_t len, uint32_t *signature)
Definition: debug.c:1578
#define TALLOC_REPORT_MAX_DEPTH
NEVER_RETURNS void fr_fault(int sig)
Prints a simple backtrace (if execinfo is available) and calls panic_action if set.
Definition: debug.c:975
void fr_sign_struct(void *ptr, size_t size, size_t offset)
Definition: debug.c:1564
int fr_get_lsan_state(void)
Definition: debug.c:261
void fr_debug_state_store(void)
Should be run before using setuid or setgid to get useful results.
Definition: debug.c:521
NEVER_RETURNS void _fr_exit(char const *file, int line, int status, bool now)
Exit possibly printing a message about why we're exiting.
Definition: debug.c:1517
void fr_talloc_fault_setup(void)
Register talloc fault handlers.
Definition: debug.c:1223
void fr_debug_break(bool always)
Break in debugger (if were running under a debugger)
Definition: debug.c:570
void fr_fault_set_cb(fr_fault_cb_t func)
Set a callback to be called before fr_fault()
Definition: debug.c:1387
void _fr_assert_fatal(char const *file, int line, char const *expr, char const *msg,...)
A fatal assertion which triggers the fault handler in debug builds or exits.
Definition: debug.c:1485
void fr_fault_log_hex(uint8_t const *data, size_t data_len)
Print data as a hex block.
Definition: debug.c:1415
int fr_set_dumpable_init(void)
Get the current maximum for core files.
Definition: debug.c:807
void fr_panic_on_free(TALLOC_CTX *ctx)
Insert memory into the context of another talloc memory chunk which causes a panic when freed.
Definition: debug.c:712
static void _fr_talloc_fault(char const *reason)
Callback executed on fatal talloc error.
Definition: debug.c:1126
static void _fr_talloc_log(char const *msg)
Wrapper to pass talloc log output to our fr_fault_log function.
Definition: debug.c:1138
static int fr_get_pr_dumpable_flag(void)
Get the processes dumpable flag.
Definition: debug.c:795
fr_debug_state_t fr_debug_state
Whether we're attached to by a debugger.
Definition: debug.c:104
void backtrace_print(UNUSED fr_fring_t *fring, UNUSED void *obj)
Definition: debug.c:690
int fr_get_debug_state(void)
Definition: debug.c:509
void fr_fault_log(char const *msg,...)
Log output to the fr_fault_log_fd.
Definition: debug.c:1401
fr_debug_state_t
Definition: debug.h:39
@ DEBUGGER_STATE_NOT_ATTACHED
We can attach, so a debugger must not be.
Definition: debug.h:43
@ DEBUGGER_STATE_UNKNOWN_NO_PTRACE
We don't have ptrace so can't check.
Definition: debug.h:40
@ DEBUGGER_STATE_UNKNOWN_NO_PTRACE_CAP
CAP_SYS_PTRACE not set for the process.
Definition: debug.h:41
@ DEBUGGER_STATE_UNKNOWN
Unknown, likely fr_get_debug_state() not called yet.
Definition: debug.h:42
@ DEBUGGER_STATE_ATTACHED
We can't attach, it's likely a debugger is already tracing.
Definition: debug.h:44
struct fr_bt_marker fr_bt_marker_t
Definition: debug.h:64
#define fr_cond_assert(_x)
Calls panic_action ifndef NDEBUG, else logs error and evaluates to value of _x.
Definition: debug.h:139
int(* fr_fault_cb_t)(int signum)
Optional callback passed to fr_fault_setup.
Definition: debug.h:63
#define FR_FAULT_LOG(_fmt,...)
Definition: debug.h:49
int fr_backtrace_do(fr_bt_marker_t *marker)
#define fr_exit_now(_x)
Exit without calling atexit() handlers, producing a log message in debug builds.
Definition: debug.h:234
void * fr_fring_next(fr_fring_t *fring)
Remove an item from the buffer.
Definition: fring.c:177
fr_fring_t * fr_fring_alloc(TALLOC_CTX *ctx, uint32_t size, bool lock)
Initialise a ring buffer with fixed element size.
Definition: fring.c:78
int fr_fring_overwrite(fr_fring_t *fring, void *in)
Insert a new item into the circular buffer, freeing the tail if we hit it.
Definition: fring.c:120
Standard thread safe circular buffer.
Definition: fring.c:36
uint32_t fr_hash_update(void const *data, size_t size, uint32_t hash)
Definition: hash.c:846
uint32_t fr_hash(void const *data, size_t size)
Definition: hash.c:812
waitpid(reap->pid_ev->pid, &status, 0)
static char * stack[MAX_STACK]
Definition: radmin.c:158
unsigned int uint32_t
Definition: merged_model.c:33
unsigned char uint8_t
Definition: merged_model.c:30
static size_t used
int fr_unset_signal(int sig)
Uninstall a signal for a specific handler.
Definition: misc.c:76
int fr_set_signal(int sig, sig_t func)
Sets a signal handler using sigaction if available, else signal.
Definition: misc.c:47
int vdprintf(int fd, char const *format, va_list args)
Definition: missing.c:210
#define is_truncated(_ret, _max)
Definition: print.h:48
static unsigned int hash(char const *username, unsigned int tablesize)
Definition: rlm_passwd.c:132
PUBLIC int snprintf(char *string, size_t length, char *format, va_alist)
Definition: snprintf.c:689
return count
Definition: module.c:163
size_t strlcpy(char *dst, char const *src, size_t siz)
Definition: strlcpy.c:34
char const * fr_syserror(int num)
Guaranteed to be thread-safe version of strerror.
Definition: syserror.c:243
void * talloc_null_ctx(void)
Retrieve the current talloc NULL ctx.
Definition: talloc.c:53
close(uq->fd)
char const * fr_strerror(void)
Get the last library error.
Definition: strerror.c:554
#define fr_strerror_printf(_fmt,...)
Log to thread local error buffer.
Definition: strerror.h:64
#define fr_strerror_const(_msg)
Definition: strerror.h:223
static fr_slen_t data
Definition: value.h:1265
static size_t char ** out
Definition: value.h:997