1 /*
2    Bacula(R) - The Network Backup Solution
3 
4    Copyright (C) 2000-2020 Kern Sibbald
5 
6    The original author of Bacula is Kern Sibbald, with contributions
7    from many others, a complete list can be found in the file AUTHORS.
8 
9    You may use this file and others of this release according to the
10    license defined in the LICENSE file, which includes the Affero General
11    Public License, v3.0 ("AGPLv3") and some additional permissions and
12    terms pursuant to its AGPLv3 Section 7.
13 
14    This notice must be preserved when any source code is
15    conveyed and/or propagated.
16 
17    Bacula(R) is a registered trademark of Kern Sibbald.
18 */
19 /*
20  *  Signal handlers for Bacula daemons
21  *
22  *   Kern Sibbald, April 2000
23  *
24  * Note, we probably should do a core dump for the serious
25  * signals such as SIGBUS, SIGPFE, ...
26  * Also, for SIGHUP and SIGUSR1, we should re-read the
27  * configuration file.  However, since this is a "general"
28  * routine, we leave it to the individual daemons to
29  * tweek their signals after calling this routine.
30  *
31  */
32 
33 #ifndef HAVE_WIN32
34 #include "bacula.h"
35 
36 #ifndef _NSIG
37 #define BA_NSIG 100
38 #else
39 #define BA_NSIG _NSIG
40 #endif
41 
42 extern char my_name[];
43 extern char fail_time[];
44 extern char *exepath;
45 extern char *exename;
46 extern bool prt_kaboom;
47 
48 static const char *sig_names[BA_NSIG+1];
49 
50 typedef void (SIG_HANDLER)(int sig);
51 static SIG_HANDLER *exit_handler;
52 
53 /* main process id */
54 static pid_t main_pid = 0;
55 
get_signal_name(int sig)56 const char *get_signal_name(int sig)
57 {
58    if (sig < 0 || sig > BA_NSIG || !sig_names[sig]) {
59       return _("Invalid signal number");
60    } else {
61       return sig_names[sig];
62    }
63 }
64 
65 /* defined in jcr.c */
66 extern void dbg_print_jcr(FILE *fp);
67 /* defined in plugins.c */
68 extern void dbg_print_plugin(FILE *fp);
69 /* defined in lockmgr.c */
70 extern void dbg_print_lock(FILE *fp);
71 
72 #define MAX_DBG_HOOK 10
73 static dbg_hook_t *dbg_hooks[MAX_DBG_HOOK];
74 static int dbg_handler_count=0;
75 
dbg_add_hook(dbg_hook_t * hook)76 void dbg_add_hook(dbg_hook_t *hook)
77 {
78    ASSERT(dbg_handler_count < MAX_DBG_HOOK);
79    dbg_hooks[dbg_handler_count++] = hook;
80 }
81 
82 /*
83  * !!! WARNING !!!
84  *
85  * This function should be used ONLY after a violent signal. We walk through the
86  * JCR chain without locking, Bacula should not be running.
87  */
dbg_print_bacula()88 static void dbg_print_bacula()
89 {
90    char buf[512];
91 
92    snprintf(buf, sizeof(buf), "%s/bacula.%d.traceback", working_directory, main_pid);
93    FILE *fp = bfopen(buf, "a+") ;
94    if (!fp) {
95       fp = stderr;
96    }
97 
98    fprintf(stderr, "LockDump: %s\n", buf);
99 
100    /* Print also BDB and RWLOCK structure
101     * Can add more info about JCR with dbg_jcr_add_hook()
102     */
103    dbg_print_lock(fp);
104    dbg_print_jcr(fp);
105    dbg_print_plugin(fp);
106 
107    for(int i=0; i < dbg_handler_count ; i++) {
108       dbg_hooks[i](fp);
109    }
110 
111    if (fp != stderr) {
112       fclose(fp);
113    }
114 }
115 
116 /*
117  * Handle signals here
118  */
signal_handler(int sig)119 extern "C" void signal_handler(int sig)
120 {
121    static int already_dead = 0;
122    int chld_status=-1;
123    utime_t now;
124 
125    Dmsg2(900, "sig=%d %s\n", sig, sig_names[sig]);
126    /* Ignore certain signals -- SIGUSR2 used to interrupt threads */
127    if (sig == SIGCHLD || sig == SIGUSR2) {
128       return;
129    }
130    /* FreeBSD seems to generate a signal of 0, which is of course undefined */
131    if (sig == 0) {
132       return;
133    }
134    /* If we come back more than once, get out fast! */
135    if (already_dead) {
136       exit(1);
137    }
138    already_dead++;
139    /* Don't use Emsg here as it may lock and thus block us */
140    if (sig == SIGTERM || sig == SIGINT) {
141        syslog(LOG_DAEMON|LOG_ERR, "Shutting down Bacula service: %s ...\n", my_name);
142    } else {
143       fprintf(stderr, _("Bacula interrupted by signal %d: %s\n"), sig, get_signal_name(sig));
144       syslog(LOG_DAEMON|LOG_ERR,
145          _("Bacula interrupted by signal %d: %s\n"), sig, get_signal_name(sig));
146       /* Edit current time for showing in the dump */
147       now = time(NULL);
148       bstrftimes(fail_time, 30, now);
149    }
150 
151 #ifdef TRACEBACK
152    if (sig != SIGTERM && sig != SIGINT) {
153       struct sigaction sigdefault;
154       static char *argv[5];
155       static char pid_buf[20];
156       static char btpath[400];
157       char buf[400];
158       pid_t pid;
159       int exelen = strlen(exepath);
160 
161       fprintf(stderr, _("Kaboom! %s, %s got signal %d - %s at %s. Attempting traceback.\n"),
162               exename, my_name, sig, get_signal_name(sig), fail_time);
163       fprintf(stderr, _("Kaboom! exepath=%s\n"), exepath);
164 
165       if (exelen + 12 > (int)sizeof(btpath)) {
166          bstrncpy(btpath, "btraceback", sizeof(btpath));
167       } else {
168          bstrncpy(btpath, exepath, sizeof(btpath));
169          if (IsPathSeparator(btpath[exelen-1])) {
170             btpath[exelen-1] = 0;
171          }
172          bstrncat(btpath, "/btraceback", sizeof(btpath));
173       }
174       if (!IsPathSeparator(exepath[exelen - 1])) {
175          strcat(exepath, "/");
176       }
177       strcat(exepath, exename);
178       if (!working_directory) {
179          working_directory = buf;
180          *buf = 0;
181       }
182       if (*working_directory == 0) {
183          strcpy((char *)working_directory, "/tmp/");
184       }
185       if (chdir(working_directory) != 0) {  /* dump in working directory */
186          berrno be;
187          Pmsg2(000, "chdir to %s failed. ERR=%s\n", working_directory,  be.bstrerror());
188          strcpy((char *)working_directory, "/tmp/");
189       }
190       unlink("./core");               /* get rid of any old core file */
191 
192       sprintf(pid_buf, "%d", (int)main_pid);
193       snprintf(buf, sizeof(buf), "%s/bacula.%s.traceback", working_directory, pid_buf);
194       unlink(buf);              /* Remove the previous backtrace file if exist */
195 
196 #ifdef DEVELOPER /* When DEVELOPER not set, this is done below */
197       /* print information about the current state into working/<file>.traceback */
198       dbg_print_bacula();
199 #endif
200 
201       Dmsg1(300, "Working=%s\n", working_directory);
202       Dmsg1(300, "btpath=%s\n", btpath);
203       Dmsg1(300, "exepath=%s\n", exepath);
204       switch (pid = fork()) {
205       case -1:                        /* error */
206          fprintf(stderr, _("Fork error: ERR=%s\n"), strerror(errno));
207          break;
208       case 0:                         /* child */
209          argv[0] = btpath;            /* path to btraceback */
210          argv[1] = exepath;           /* path to exe */
211          argv[2] = pid_buf;
212          argv[3] = (char *)working_directory;
213          argv[4] = (char *)NULL;
214          fprintf(stderr, _("Calling: %s %s %s %s\n"), btpath, exepath, pid_buf,
215             working_directory);
216          if (execv(btpath, argv) != 0) {
217             berrno be;
218             printf(_("execv: %s failed: ERR=%s\n"), btpath, be.bstrerror());
219          }
220          exit(-1);
221       default:                        /* parent */
222          break;
223       }
224 
225       /* Parent continue here, waiting for child */
226       sigdefault.sa_flags = 0;
227       sigdefault.sa_handler = SIG_DFL;
228       sigfillset(&sigdefault.sa_mask);
229 
230       sigaction(sig,  &sigdefault, NULL);
231       if (pid > 0) {
232          Dmsg0(500, "Doing waitpid\n");
233          waitpid(pid, &chld_status, 0);   /* wait for child to produce dump */
234          Dmsg0(500, "Done waitpid\n");
235       } else {
236          Dmsg0(500, "Doing sleep\n");
237          bmicrosleep(30, 0);
238       }
239       if (WEXITSTATUS(chld_status) == 0) {
240          fprintf(stderr, "%s", _("It looks like the traceback worked...\n"));
241       } else {
242          fprintf(stderr, _("The btraceback call returned %d\n"),
243                            WEXITSTATUS(chld_status));
244       }
245 
246 #ifndef DEVELOPER /* When DEVELOPER set, this is done above */
247       /* print information about the current state into working/<file>.traceback */
248       dbg_print_bacula();
249 #endif
250 
251       /* If we want it printed, do so */
252 #ifdef direct_print
253       if (prt_kaboom) {
254          FILE *fd;
255          snprintf(buf, sizeof(buf), "%s/bacula.%s.traceback", working_directory, pid_buf);
256          fd = bfopen(buf, "r");
257          if (fd != NULL) {
258             printf("\n\n ==== Traceback output ====\n\n");
259             while (fgets(buf, (int)sizeof(buf), fd) != NULL) {
260                printf("%s", buf);
261             }
262             fclose(fd);
263             printf(" ==== End traceback output ====\n\n");
264          }
265       }
266 #else
267       if (prt_kaboom) {
268          snprintf(buf, sizeof(buf), "/bin/cat %s/bacula.%s.traceback", working_directory, pid_buf);
269          fprintf(stderr, "\n\n ==== Traceback output ====\n\n");
270          system(buf);
271          fprintf(stderr, " ==== End traceback output ====\n\n");
272       }
273 #endif
274 
275    }
276 #endif
277    exit_handler(sig);
278    Dmsg0(500, "Done exit_handler\n");
279 }
280 
281 /*
282  * Init stack dump by saving main process id --
283  *   needed by debugger to attach to this program.
284  */
init_stack_dump(void)285 void init_stack_dump(void)
286 {
287    main_pid = getpid();               /* save main thread's pid */
288 }
289 
290 /*
291  * Initialize signals
292  */
init_signals(void terminate (int sig))293 void init_signals(void terminate(int sig))
294 {
295    struct sigaction sighandle;
296    struct sigaction sigignore;
297    struct sigaction sigdefault;
298 #ifdef _sys_nsig
299    int i;
300 
301    exit_handler = terminate;
302    if (BA_NSIG < _sys_nsig)
303       Emsg2(M_ABORT, 0, _("BA_NSIG too small (%d) should be (%d)\n"), BA_NSIG, _sys_nsig);
304 
305    for (i=0; i<_sys_nsig; i++)
306       sig_names[i] = _sys_siglist[i];
307 #else
308    exit_handler = terminate;
309    sig_names[0]         = _("UNKNOWN SIGNAL");
310    sig_names[SIGHUP]    = _("Hangup");
311    sig_names[SIGINT]    = _("Interrupt");
312    sig_names[SIGQUIT]   = _("Quit");
313    sig_names[SIGILL]    = _("Illegal instruction");;
314    sig_names[SIGTRAP]   = _("Trace/Breakpoint trap");
315    sig_names[SIGABRT]   = _("Abort");
316 #ifdef SIGEMT
317    sig_names[SIGEMT]    = _("EMT instruction (Emulation Trap)");
318 #endif
319 #ifdef SIGIOT
320    sig_names[SIGIOT]    = _("IOT trap");
321 #endif
322    sig_names[SIGBUS]    = _("BUS error");
323    sig_names[SIGFPE]    = _("Floating-point exception");
324    sig_names[SIGKILL]   = _("Kill, unblockable");
325    sig_names[SIGUSR1]   = _("User-defined signal 1");
326    sig_names[SIGSEGV]   = _("Segmentation violation");
327    sig_names[SIGUSR2]   = _("User-defined signal 2");
328    sig_names[SIGPIPE]   = _("Broken pipe");
329    sig_names[SIGALRM]   = _("Alarm clock");
330    sig_names[SIGTERM]   = _("Termination");
331 #ifdef SIGSTKFLT
332    sig_names[SIGSTKFLT] = _("Stack fault");
333 #endif
334    sig_names[SIGCHLD]   = _("Child status has changed");
335    sig_names[SIGCONT]   = _("Continue");
336    sig_names[SIGSTOP]   = _("Stop, unblockable");
337    sig_names[SIGTSTP]   = _("Keyboard stop");
338    sig_names[SIGTTIN]   = _("Background read from tty");
339    sig_names[SIGTTOU]   = _("Background write to tty");
340    sig_names[SIGURG]    = _("Urgent condition on socket");
341    sig_names[SIGXCPU]   = _("CPU limit exceeded");
342    sig_names[SIGXFSZ]   = _("File size limit exceeded");
343    sig_names[SIGVTALRM] = _("Virtual alarm clock");
344    sig_names[SIGPROF]   = _("Profiling alarm clock");
345    sig_names[SIGWINCH]  = _("Window size change");
346    sig_names[SIGIO]     = _("I/O now possible");
347 #ifdef SIGPWR
348    sig_names[SIGPWR]    = _("Power failure restart");
349 #endif
350 #ifdef SIGWAITING
351    sig_names[SIGWAITING] = _("No runnable lwp");
352 #endif
353 #ifdef SIGLWP
354    sig_names[SIGLWP]     = _("SIGLWP special signal used by thread library");
355 #endif
356 #ifdef SIGFREEZE
357    sig_names[SIGFREEZE] = _("Checkpoint Freeze");
358 #endif
359 #ifdef SIGTHAW
360    sig_names[SIGTHAW]   = _("Checkpoint Thaw");
361 #endif
362 #ifdef SIGCANCEL
363    sig_names[SIGCANCEL] = _("Thread Cancellation");
364 #endif
365 #ifdef SIGLOST
366    sig_names[SIGLOST]   = _("Resource Lost (e.g. record-lock lost)");
367 #endif
368 #endif
369 
370 
371 /* Now setup signal handlers */
372    sighandle.sa_flags = 0;
373    sighandle.sa_handler = signal_handler;
374    sigfillset(&sighandle.sa_mask);
375    sigignore.sa_flags = 0;
376    sigignore.sa_handler = SIG_IGN;
377    sigfillset(&sigignore.sa_mask);
378    sigdefault.sa_flags = 0;
379    sigdefault.sa_handler = SIG_DFL;
380    sigfillset(&sigdefault.sa_mask);
381 
382 
383    sigaction(SIGCHLD,   &sighandle, NULL);
384    sigaction(SIGCONT,   &sigignore, NULL);
385    sigaction(SIGPROF,   &sigignore, NULL);
386    sigaction(SIGWINCH,  &sigignore, NULL);
387    sigaction(SIGIO,     &sighandle, NULL);
388 
389    sigaction(SIGINT,    &sighandle, NULL);
390    sigaction(SIGXCPU,   &sigdefault, NULL);
391    sigaction(SIGXFSZ,   &sigdefault, NULL);
392 
393    sigaction(SIGHUP,    &sigignore, NULL);
394    sigaction(SIGQUIT,   &sighandle, NULL);
395    sigaction(SIGTRAP,   &sighandle, NULL);
396 #ifdef SIGEMT
397    sigaction(SIGEMT,    &sighandle, NULL);
398 #endif
399 #ifdef SIGIOT
400    sigaction(SIGIOT,    &sighandle, NULL);
401 #endif
402 /* sigaction(SIGKILL,   &sighandle, NULL);  cannot be trapped */
403    sigaction(SIGUSR1,   &sighandle, NULL);
404    sigaction(SIGUSR2,   &sighandle, NULL);
405    sigaction(SIGALRM,   &sighandle, NULL);
406    sigaction(SIGTERM,   &sighandle, NULL);
407 
408 /* sigaction(SIGSTOP,   &sighandle, NULL); cannot be trapped */
409    sigaction(SIGTSTP,   &sighandle, NULL);
410    sigaction(SIGTTIN,   &sighandle, NULL);
411    sigaction(SIGTTOU,   &sighandle, NULL);
412    sigaction(SIGURG,    &sighandle, NULL);
413    sigaction(SIGVTALRM, &sighandle, NULL);
414 
415 #ifdef SIGWAITING
416    sigaction(SIGWAITING,&sighandle, NULL);
417 #endif
418 #ifdef SIGLWP
419    sigaction(SIGLWP,    &sighandle, NULL);
420 #endif
421 #ifdef SIGFREEZE
422    sigaction(SIGFREEZE, &sighandle, NULL);
423 #endif
424 #ifdef SIGTHAW
425    sigaction(SIGTHAW,   &sighandle, NULL);
426 #endif
427 #ifdef SIGCANCEL
428    sigaction(SIGCANCEL, &sighandle, NULL);
429 #endif
430 #ifdef SIGLOST
431    sigaction(SIGLOST,   &sighandle, NULL);
432 #endif
433 
434 /*
435    The Android OS uses the signals below to produce a backtrace in the logs.
436    We should be able to override Android signal handlers and call them manually,
437    but so far this strategy has not worked.
438 
439    For more information, check:
440    https://programming.vip/docs/android-debuggerd-source-code-analysis.html
441    https://stackoverflow.com/questions/1083154/how-can-i-catch-sigsegv-segmentation-fault-and-get-a-stack-trace-under-jni-on
442 */
443 #ifndef __ANDROID_API__
444 sigaction(SIGILL,    &sighandle, NULL);
445 sigaction(SIGBUS,    &sighandle, NULL);
446 sigaction(SIGFPE,    &sighandle, NULL);
447 sigaction(SIGSEGV,   &sighandle, NULL);
448 sigaction(SIGPIPE,   &sigignore, NULL);
449 sigaction(SIGABRT,   &sighandle, NULL);
450 
451 #ifdef SIGSTKFLT
452    sigaction(SIGSTKFLT, &sighandle, NULL);
453 #endif
454 #endif
455 
456 }
457 #endif
458