1 /*
2 * ProFTPD - FTP server daemon
3 * Copyright (c) 2014-2020 The ProFTPD Project team
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA.
18 *
19 * As a special exemption, the ProFTPD Project team and other respective
20 * copyright holders give permission to link this program with OpenSSL, and
21 * distribute the resulting executable, without including the source code for
22 * OpenSSL in the source distribution.
23 */
24
25 /* Signal handling. */
26
27 #include "conf.h"
28 #include "privs.h"
29
30 #ifdef HAVE_EXECINFO_H
31 # include <execinfo.h>
32 #endif
33
34 #ifdef HAVE_UCONTEXT_H
35 # include <ucontext.h>
36 #endif
37
38 /* From src/main.c */
39 extern unsigned char is_master;
40 extern pid_t mpid;
41 extern int nodaemon;
42
43 int have_dead_child = FALSE;
44 volatile unsigned int recvd_signal_flags = 0;
45
46 static const char *trace_channel = "signal";
47
48 static RETSIGTYPE sig_terminate(int);
49 static void install_stacktrace_handler(void);
50
51 /* Used to capture an "unknown" signal value that causes termination. */
52 static int term_signo = 0;
53
finish_terminate(int signo)54 static void finish_terminate(int signo) {
55 int reason_code = PR_SESS_DISCONNECT_SIGNAL;
56
57 if (is_master &&
58 mpid == getpid()) {
59 PRIVS_ROOT
60
61 /* Do not need the pidfile any longer. */
62 if (ServerType == SERVER_STANDALONE &&
63 !nodaemon) {
64 pr_pidfile_remove();
65 }
66
67 /* Run any exit handlers registered in the master process here, so that
68 * they may have the benefit of root privs. More than likely these
69 * exit handlers were registered by modules' module initialization
70 * functions, which also occur under root priv conditions.
71 *
72 * If an exit handler is registered after the fork(), it won't be run here;
73 * that registration occurs in a different process space.
74 */
75 pr_event_generate("core.exit", NULL);
76 pr_event_generate("core.shutdown", NULL);
77
78 /* Remove the registered exit handlers now, so that the ensuing
79 * pr_session_end() call (outside the root privs condition) does not call
80 * the exit handlers for the master process again.
81 */
82 pr_event_unregister(NULL, "core.exit", NULL);
83 pr_event_unregister(NULL, "core.shutdown", NULL);
84
85 PRIVS_RELINQUISH
86
87 if (ServerType == SERVER_STANDALONE) {
88 pr_log_pri(PR_LOG_NOTICE, "ProFTPD " PROFTPD_VERSION_TEXT
89 " standalone mode SHUTDOWN");
90
91 /* Clean up the scoreboard */
92 PRIVS_ROOT
93 pr_delete_scoreboard();
94 PRIVS_RELINQUISH
95 }
96 }
97
98 if (signo == SIGSEGV) {
99 reason_code = PR_SESS_DISCONNECT_SEGFAULT;
100 }
101
102 pr_session_disconnect(NULL, reason_code, "Killed by signal");
103 }
104
handle_abort(void)105 static void handle_abort(void) {
106 pr_log_pri(PR_LOG_NOTICE, "ProFTPD received SIGABRT signal, no core dump");
107 finish_terminate(SIGABRT);
108 }
109
handle_chld(void)110 static void handle_chld(void) {
111 sigset_t sig_set;
112 pid_t pid;
113
114 sigemptyset(&sig_set);
115 sigaddset(&sig_set, SIGTERM);
116 sigaddset(&sig_set, SIGCHLD);
117
118 pr_alarms_block();
119
120 /* Block SIGTERM in here, so we don't create havoc with the child list
121 * while modifying it.
122 */
123 if (sigprocmask(SIG_BLOCK, &sig_set, NULL) < 0) {
124 pr_log_pri(PR_LOG_NOTICE,
125 "unable to block signal set: %s", strerror(errno));
126 }
127
128 while ((pid = waitpid(-1, NULL, WNOHANG)) > 0) {
129 if (child_remove(pid) == 0) {
130 have_dead_child = TRUE;
131 }
132 }
133
134 if (sigprocmask(SIG_UNBLOCK, &sig_set, NULL) < 0) {
135 pr_log_pri(PR_LOG_NOTICE,
136 "unable to unblock signal set: %s", strerror(errno));
137 }
138
139 pr_alarms_unblock();
140 }
141
handle_evnt(void)142 static void handle_evnt(void) {
143 pr_event_generate("core.signal.USR2", NULL);
144 }
145
handle_terminate_with_kids(void)146 static void handle_terminate_with_kids(void) {
147 /* Do not log if we are a child that has been terminated. */
148 if (is_master == TRUE) {
149
150 /* Send a SIGTERM to all our children */
151 if (child_count()) {
152 PRIVS_ROOT
153 child_signal(SIGTERM);
154 PRIVS_RELINQUISH
155 }
156
157 pr_log_pri(PR_LOG_NOTICE, "ProFTPD killed (signal %d)", term_signo);
158 }
159
160 finish_terminate(term_signo);
161 }
162
handle_terminate_without_kids(void)163 static void handle_terminate_without_kids(void) {
164 pr_log_pri(PR_LOG_WARNING, "ProFTPD terminating (signal %d)", term_signo);
165 finish_terminate(term_signo);
166 }
167
handle_stacktrace_signal(int signo,siginfo_t * info,void * ptr)168 static void handle_stacktrace_signal(int signo, siginfo_t *info, void *ptr) {
169 #ifdef HAVE_BACKTRACE
170 register int i;
171 # if defined(HAVE_UCONTEXT_H)
172 ucontext_t *uc = NULL;
173 # endif /* !HAVE_UCONTEXT_H */
174 void *trace[PR_TUNABLE_CALLER_DEPTH];
175 char **strings = NULL;
176 int tracesz;
177 #endif /* HAVE_BACKTRACE */
178
179 /* Call the "normal" signal handler. */
180 table_handling_signal(TRUE);
181
182 pr_log_pri(PR_LOG_ERR, "-----BEGIN STACK TRACE-----");
183
184 #ifdef HAVE_BACKTRACE
185 tracesz = backtrace(trace, PR_TUNABLE_CALLER_DEPTH);
186 if (tracesz < 0) {
187 pr_log_pri(PR_LOG_ERR, "backtrace(3) error: %s", strerror(errno));
188 }
189
190 # if defined(HAVE_UCONTEXT_H)
191 /* Overwrite sigaction with caller's address */
192 uc = (ucontext_t *) ptr;
193 # if defined(REG_EIP)
194 trace[1] = (void *) uc->uc_mcontext.gregs[REG_EIP];
195 # elif defined(REG_RIP)
196 trace[1] = (void *) uc->uc_mcontext.gregs[REG_RIP];
197 # endif
198 # endif /* !HAVE_UCONTEXT_H */
199
200 # ifdef HAVE_BACKTRACE_SYMBOLS
201 strings = backtrace_symbols(trace, tracesz);
202 if (strings == NULL) {
203 pr_log_pri(PR_LOG_ERR, "backtrace_symbols(3) error: %s", strerror(errno));
204 }
205 # endif /* HAVE_BACKTRACE_SYMBOLS */
206
207 if (strings != NULL) {
208 /* Skip first stack frame; it just points here. */
209 for (i = 1; i < tracesz; ++i) {
210 pr_log_pri(PR_LOG_ERR, "[%u] %s", i-1, strings[i]);
211 }
212 }
213 #else
214 pr_log_pri(PR_LOG_ERR, " backtrace(3) unavailable");
215 #endif /* HAVE_BACKTRACE */
216 pr_log_pri(PR_LOG_ERR, "-----END STACK TRACE-----");
217
218 sig_terminate(signo);
219 finish_terminate(signo);
220 }
221
handle_xcpu(void)222 static void handle_xcpu(void) {
223 pr_log_pri(PR_LOG_NOTICE, "ProFTPD CPU limit exceeded (signal %d)", SIGXCPU);
224 finish_terminate(SIGXCPU);
225 }
226
227 #ifdef SIGXFSZ
handle_xfsz(void)228 static void handle_xfsz(void) {
229 pr_log_pri(PR_LOG_NOTICE, "ProFTPD File size limit exceeded (signal %d)",
230 SIGXFSZ);
231 finish_terminate(SIGXFSZ);
232 }
233 #endif /* SIGXFSZ */
234
sig_child(int signo)235 static RETSIGTYPE sig_child(int signo) {
236 recvd_signal_flags |= RECEIVED_SIG_CHLD;
237
238 /* We make an exception here to the synchronous processing that is done
239 * for other signals; SIGCHLD is handled asynchronously. This is made
240 * necessary by two things.
241 *
242 * First, we need to support non-POSIX systems. Under POSIX, once a
243 * signal handler has been configured for a given signal, that becomes
244 * that signal's disposition, until explicitly changed later. Non-POSIX
245 * systems, on the other hand, will restore the default disposition of
246 * a signal after a custom signal handler has been configured. Thus,
247 * to properly support non-POSIX systems, a call to signal(2) is necessary
248 * as one of the last steps in our signal handlers.
249 *
250 * Second, SVR4 systems differ specifically in their semantics of signal(2)
251 * and SIGCHLD. These systems will check for any unhandled SIGCHLD
252 * signals, waiting to be reaped via wait(2) or waitpid(2), whenever
253 * the disposition of SIGCHLD is changed. This means that if our process
254 * handles SIGCHLD, but does not call wait(2) or waitpid(2), and then
255 * calls signal(2), another SIGCHLD is generated; this loop repeats,
256 * until the process runs out of stack space and terminates.
257 *
258 * Thus, in order to cover this interaction, we'll need to call handle_chld()
259 * here, asynchronously. handle_chld() does the work of reaping dead
260 * child processes, and does not seem to call any non-reentrant functions,
261 * so it should be safe.
262 */
263
264 handle_chld();
265
266 if (signal(SIGCHLD, sig_child) == SIG_ERR) {
267 pr_log_pri(PR_LOG_NOTICE,
268 "unable to install SIGCHLD (signal %d) handler: %s", SIGCHLD,
269 strerror(errno));
270 }
271 }
272
273 #ifdef PR_DEVEL_COREDUMP
prepare_core(void)274 static char *prepare_core(void) {
275 static char dir[256];
276
277 memset(dir, '\0', sizeof(dir));
278 pr_snprintf(dir, sizeof(dir)-1, "%s/proftpd-core-%lu", PR_CORE_DIR,
279 (unsigned long) getpid());
280
281 if (mkdir(dir, 0700) < 0) {
282 pr_log_pri(PR_LOG_WARNING, "unable to create directory '%s' for "
283 "coredump: %s", dir, strerror(errno));
284
285 } else {
286 chdir(dir);
287 }
288
289 return dir;
290 }
291 #endif /* PR_DEVEL_COREDUMP */
292
sig_abort(int signo)293 static RETSIGTYPE sig_abort(int signo) {
294 recvd_signal_flags |= RECEIVED_SIG_ABORT;
295
296 if (signal(SIGABRT, SIG_DFL) == SIG_ERR) {
297 pr_log_pri(PR_LOG_NOTICE,
298 "unable to install SIGABRT (signal %d) handler: %s", SIGABRT,
299 strerror(errno));
300 }
301
302 #ifdef PR_DEVEL_COREDUMP
303 pr_log_pri(PR_LOG_NOTICE, "ProFTPD received SIGABRT signal, generating core "
304 "file in %s", prepare_core());
305 pr_session_end(PR_SESS_END_FL_NOEXIT);
306 abort();
307 #endif /* PR_DEVEL_COREDUMP */
308 }
309
sig_terminate(int signo)310 static RETSIGTYPE sig_terminate(int signo) {
311 const char *signame = "(unsupported)";
312 int log_signal = TRUE, log_stacktrace = TRUE;
313
314 /* Capture the signal number for later display purposes. */
315 term_signo = signo;
316
317 /* Some terminating signals get more special treatment than others. */
318
319 switch (signo) {
320 case SIGSEGV:
321 recvd_signal_flags |= RECEIVED_SIG_SEGV;
322 signame = "SIGSEGV";
323 break;
324
325 case SIGXCPU:
326 recvd_signal_flags |= RECEIVED_SIG_XCPU;
327 signame = "SIGXCPU";
328 break;
329
330 #ifdef SIGXFSZ
331 case SIGXFSZ:
332 recvd_signal_flags |= RECEIVED_SIG_XFSZ;
333 signame = "SIGXFSZ";
334 break;
335 #endif /* SIGXFSZ */
336
337 case SIGTERM:
338 /* Since SIGTERM is more common, we do not want to log as much for it. */
339 log_signal = log_stacktrace = FALSE;
340 recvd_signal_flags |= RECEIVED_SIG_TERMINATE;
341 signame = "SIGTERM";
342 break;
343
344 #ifdef SIGBUS
345 case SIGBUS:
346 recvd_signal_flags |= RECEIVED_SIG_TERMINATE;
347 signame = "SIGBUS";
348 break;
349 #endif /* SIGBUS */
350
351 case SIGILL:
352 recvd_signal_flags |= RECEIVED_SIG_TERMINATE;
353 signame = "SIGILL";
354 break;
355
356 case SIGINT:
357 recvd_signal_flags |= RECEIVED_SIG_TERMINATE;
358 signame = "SIGINT";
359 break;
360
361 default:
362 /* Note that we do NOT want to automatically set the
363 * RECEIVED_SIG_TERMINATE here by as a fallback for unspecified signals;
364 * that flag causes the daemon to terminate all of its child processes.
365 * And not every signal should have that effect; it's on a case-by-case
366 * basis.
367 */
368 break;
369 }
370
371 if (log_signal == TRUE) {
372 /* This is probably not the safest thing to be doing, but since the
373 * process is terminating anyway, why not? It helps when knowing/logging
374 * that a segfault (or other unusual event) happened.
375 */
376 pr_trace_msg(trace_channel, 9, "handling %s (signal %d)", signame, signo);
377 pr_log_pri(PR_LOG_NOTICE, "ProFTPD terminating (signal %d)", signo);
378
379 if (!is_master) {
380 pr_log_pri(PR_LOG_INFO, "%s session closed.",
381 pr_session_get_protocol(PR_SESS_PROTO_FL_LOGOUT));
382 }
383 }
384
385 if (log_stacktrace == TRUE) {
386 install_stacktrace_handler();
387 }
388
389 /* Ignore future occurrences of this signal; we'll be terminating anyway. */
390 if (signal(signo, SIG_IGN) == SIG_ERR) {
391 pr_log_pri(PR_LOG_NOTICE,
392 "unable to install handler for signal %d: %s", signo, strerror(errno));
393 }
394 }
395
install_stacktrace_handler(void)396 static void install_stacktrace_handler(void) {
397 struct sigaction action;
398
399 memset(&action, 0, sizeof(action));
400 action.sa_sigaction = handle_stacktrace_signal;
401 action.sa_flags = SA_SIGINFO;
402
403 if (sigaction(SIGSEGV, &action, NULL) < 0) {
404 pr_log_pri(PR_LOG_NOTICE,
405 "unable to install SIGSEGV stacktrace signal handler: %s",
406 strerror(errno));
407 }
408 #ifdef SIGBUS
409 if (sigaction(SIGBUS, &action, NULL) < 0) {
410 pr_log_pri(PR_LOG_NOTICE,
411 "unable to install SIGBUS stacktrace signal handler: %s",
412 strerror(errno));
413 }
414 #endif /* SIGBUS */
415 if (sigaction(SIGXCPU, &action, NULL) < 0) {
416 pr_log_pri(PR_LOG_NOTICE,
417 "unable to install SIGXCPU stacktrace signal handler: %s",
418 strerror(errno));
419 }
420 }
421
422 /* This function is to handle the dispatching of actions based on
423 * signals received by the signal handlers, to avoid signal handler-based
424 * race conditions.
425 */
pr_signals_handle(void)426 void pr_signals_handle(void) {
427 table_handling_signal(TRUE);
428
429 if (errno == EINTR &&
430 PR_TUNABLE_EINTR_RETRY_INTERVAL > 0) {
431 struct timeval tv;
432 unsigned long interval_usecs = PR_TUNABLE_EINTR_RETRY_INTERVAL * 1000000;
433
434 tv.tv_sec = (interval_usecs / 1000000);
435 tv.tv_usec = (interval_usecs - (tv.tv_sec * 1000000));
436
437 pr_trace_msg(trace_channel, 18, "interrupted system call, "
438 "delaying for %lu %s, %lu %s",
439 (unsigned long) tv.tv_sec, tv.tv_sec != 1 ? "secs" : "sec",
440 (unsigned long) tv.tv_usec, tv.tv_usec != 1 ? "microsecs" : "microsec");
441
442 pr_timer_usleep(interval_usecs);
443
444 /* Clear the EINTR errno, now that we've dealt with it. */
445 errno = 0;
446 }
447
448 while (recvd_signal_flags) {
449 if (recvd_signal_flags & RECEIVED_SIG_ALRM) {
450 recvd_signal_flags &= ~RECEIVED_SIG_ALRM;
451 pr_trace_msg(trace_channel, 9, "handling SIGALRM (signal %d)", SIGALRM);
452 handle_alarm();
453 }
454
455 if (recvd_signal_flags & RECEIVED_SIG_CHLD) {
456 recvd_signal_flags &= ~RECEIVED_SIG_CHLD;
457 pr_trace_msg(trace_channel, 9, "handling SIGCHLD (signal %d)", SIGCHLD);
458 handle_chld();
459 }
460
461 if (recvd_signal_flags & RECEIVED_SIG_EVENT) {
462 recvd_signal_flags &= ~RECEIVED_SIG_EVENT;
463
464 /* The "event" signal is SIGUSR2 in proftpd. */
465 pr_trace_msg(trace_channel, 9, "handling SIGUSR2 (signal %d)", SIGUSR2);
466 handle_evnt();
467 }
468
469 if (recvd_signal_flags & RECEIVED_SIG_SEGV) {
470 recvd_signal_flags &= ~RECEIVED_SIG_SEGV;
471 pr_trace_msg(trace_channel, 9, "handling SIGSEGV (signal %d)", SIGSEGV);
472 handle_terminate_without_kids();
473 }
474
475 if (recvd_signal_flags & RECEIVED_SIG_TERMINATE) {
476 recvd_signal_flags &= ~RECEIVED_SIG_TERMINATE;
477 pr_trace_msg(trace_channel, 9, "handling signal %d", term_signo);
478 handle_terminate_with_kids();
479 }
480
481 if (recvd_signal_flags & RECEIVED_SIG_XCPU) {
482 recvd_signal_flags &= ~RECEIVED_SIG_XCPU;
483 pr_trace_msg(trace_channel, 9, "handling SIGXCPU (signal %d)", SIGXCPU);
484 handle_xcpu();
485 }
486
487 #ifdef SIGXFSZ
488 if (recvd_signal_flags & RECEIVED_SIG_XFSZ) {
489 recvd_signal_flags &= ~RECEIVED_SIG_XFSZ;
490 pr_trace_msg(trace_channel, 9, "handling SIGXFSZ (signal %d)", SIGXFSZ);
491 handle_xfsz();
492 }
493 #endif /* SIGXFSZ */
494
495 if (recvd_signal_flags & RECEIVED_SIG_ABORT) {
496 recvd_signal_flags &= ~RECEIVED_SIG_ABORT;
497 pr_trace_msg(trace_channel, 9, "handling SIGABRT (signal %d)", SIGABRT);
498 handle_abort();
499 }
500
501 if (recvd_signal_flags & RECEIVED_SIG_RESTART) {
502 recvd_signal_flags &= ~RECEIVED_SIG_RESTART;
503 pr_trace_msg(trace_channel, 9, "handling SIGHUP (signal %d)", SIGHUP);
504
505 /* NOTE: should this be done here, rather than using a schedule? */
506 schedule(restart_daemon, 0, NULL, NULL, NULL, NULL);
507 }
508
509 if (recvd_signal_flags & RECEIVED_SIG_EXIT) {
510 recvd_signal_flags &= ~RECEIVED_SIG_EXIT;
511 pr_trace_msg(trace_channel, 9, "handling SIGUSR1 (signal %d)", SIGUSR1);
512 pr_log_pri(PR_LOG_NOTICE, "%s", "Parent process requested shutdown");
513 pr_session_disconnect(NULL, PR_SESS_DISCONNECT_SERVER_SHUTDOWN, NULL);
514 }
515
516 if (recvd_signal_flags & RECEIVED_SIG_SHUTDOWN) {
517 recvd_signal_flags &= ~RECEIVED_SIG_SHUTDOWN;
518 pr_trace_msg(trace_channel, 9, "handling SIGUSR1 (signal %d)", SIGUSR1);
519
520 /* NOTE: should this be done here, rather than using a schedule? */
521 schedule(shutdown_end_session, 0, NULL, NULL, NULL, NULL);
522 }
523 }
524
525 table_handling_signal(FALSE);
526 }
527
528 /* sig_restart occurs in the master daemon when manually "kill -HUP"
529 * in order to re-read configuration files, and is sent to all
530 * children by the master.
531 */
sig_restart(int signo)532 static RETSIGTYPE sig_restart(int signo) {
533 recvd_signal_flags |= RECEIVED_SIG_RESTART;
534
535 if (signal(SIGHUP, sig_restart) == SIG_ERR) {
536 pr_log_pri(PR_LOG_NOTICE,
537 "unable to install SIGHUP (signal %d) handler: %s", SIGHUP,
538 strerror(errno));
539 }
540 }
541
542 /* pr_signals_handle_disconnect is called in children when the parent daemon
543 * detects that shutmsg has been created and that client sessions should be
544 * destroyed. If a file transfer is underway, the process simply dies,
545 * otherwise a function is scheduled to attempt to display the shutdown reason.
546 */
pr_signals_handle_disconnect(int signo)547 RETSIGTYPE pr_signals_handle_disconnect(int signo) {
548
549 /* If this is an anonymous session, or a transfer is in progress,
550 * perform the exit a little later...
551 */
552 if ((session.sf_flags & SF_ANON) ||
553 (session.sf_flags & SF_XFER)) {
554 recvd_signal_flags |= RECEIVED_SIG_EXIT;
555
556 } else {
557 recvd_signal_flags |= RECEIVED_SIG_SHUTDOWN;
558 }
559
560 if (signal(SIGUSR1, SIG_IGN) == SIG_ERR) {
561 pr_log_pri(PR_LOG_NOTICE,
562 "unable to install SIGUSR1 (signal %d) handler: %s", SIGUSR1,
563 strerror(errno));
564 }
565 }
566
567 /* "Events", in this case, are SIGUSR2 signals. */
pr_signals_handle_event(int signo)568 RETSIGTYPE pr_signals_handle_event(int signo) {
569 recvd_signal_flags |= RECEIVED_SIG_EVENT;
570
571 if (signal(SIGUSR2, pr_signals_handle_event) == SIG_ERR) {
572 pr_log_pri(PR_LOG_NOTICE,
573 "unable to install SIGUSR2 (signal %d) handler: %s", SIGUSR2,
574 strerror(errno));
575 }
576 }
577
init_signals(void)578 int init_signals(void) {
579 sigset_t sig_set;
580
581 /* Should the master server (only applicable in standalone mode)
582 * kill off children if we receive a signal that causes termination?
583 * Hmmmm... maybe this needs to be rethought, but I've done it in
584 * such a way as to only kill off our children if we receive a SIGTERM,
585 * meaning that the admin wants us dead (and probably our kids too).
586 */
587
588 /* The sub-pool for the child list is created the first time we fork
589 * off a child. To conserve memory, the pool and list is destroyed
590 * when our last child dies (to prevent the list from eating more and
591 * more memory on long uptimes).
592 */
593
594 sigemptyset(&sig_set);
595
596 sigaddset(&sig_set, SIGCHLD);
597 sigaddset(&sig_set, SIGINT);
598 sigaddset(&sig_set, SIGQUIT);
599 sigaddset(&sig_set, SIGILL);
600 sigaddset(&sig_set, SIGABRT);
601 sigaddset(&sig_set, SIGFPE);
602 sigaddset(&sig_set, SIGSEGV);
603 sigaddset(&sig_set, SIGALRM);
604 sigaddset(&sig_set, SIGTERM);
605 sigaddset(&sig_set, SIGHUP);
606 sigaddset(&sig_set, SIGUSR2);
607 #ifdef SIGSTKFLT
608 sigaddset(&sig_set, SIGSTKFLT);
609 #endif /* SIGSTKFLT */
610 #ifdef SIGIO
611 sigaddset(&sig_set, SIGIO);
612 #endif /* SIGIO */
613 #ifdef SIGBUS
614 sigaddset(&sig_set, SIGBUS);
615 #endif /* SIGBUS */
616
617 if (signal(SIGCHLD, sig_child) == SIG_ERR) {
618 pr_log_pri(PR_LOG_NOTICE,
619 "unable to install SIGCHLD (signal %d) handler: %s", SIGCHLD,
620 strerror(errno));
621 }
622
623 if (signal(SIGHUP, sig_restart) == SIG_ERR) {
624 pr_log_pri(PR_LOG_NOTICE,
625 "unable to install SIGHUP (signal %d) handler: %s", SIGHUP,
626 strerror(errno));
627 }
628
629 if (signal(SIGINT, sig_terminate) == SIG_ERR) {
630 pr_log_pri(PR_LOG_NOTICE,
631 "unable to install SIGINT (signal %d) handler: %s", SIGINT,
632 strerror(errno));
633 }
634
635 if (signal(SIGQUIT, sig_terminate) == SIG_ERR) {
636 pr_log_pri(PR_LOG_NOTICE,
637 "unable to install SIGQUIT (signal %d) handler: %s", SIGQUIT,
638 strerror(errno));
639 }
640
641 if (signal(SIGILL, sig_terminate) == SIG_ERR) {
642 pr_log_pri(PR_LOG_NOTICE,
643 "unable to install SIGILL (signal %d) handler: %s", SIGILL,
644 strerror(errno));
645 }
646
647 if (signal(SIGFPE, sig_terminate) == SIG_ERR) {
648 pr_log_pri(PR_LOG_NOTICE,
649 "unable to install SIGFPE (signal %d) handler: %s", SIGFPE,
650 strerror(errno));
651 }
652
653 #ifdef SIGXFSZ
654 if (signal(SIGXFSZ, sig_terminate) == SIG_ERR) {
655 pr_log_pri(PR_LOG_NOTICE,
656 "unable to install SIGXFSZ (signal %d) handler: %s", SIGXFSZ,
657 strerror(errno));
658 }
659 #endif /* SIGXFSZ */
660
661 if (signal(SIGABRT, sig_abort) == SIG_ERR) {
662 pr_log_pri(PR_LOG_NOTICE,
663 "unable to install SIGABRT (signal %d) handler: %s", SIGABRT,
664 strerror(errno));
665 }
666
667 /* Installs stacktrace handlers for SIGSEGV, SIGXCPU, and SIGBUS. */
668 install_stacktrace_handler();
669
670 /* Ignore SIGALRM; this will be changed when a timer is registered. But
671 * this will prevent SIGALRMs from killing us if we don't currently have
672 * any timers registered.
673 */
674 if (signal(SIGALRM, SIG_IGN) == SIG_ERR) {
675 pr_log_pri(PR_LOG_NOTICE,
676 "unable to install SIGALRM (signal %d) handler: %s", SIGALRM,
677 strerror(errno));
678 }
679
680 if (signal(SIGTERM, sig_terminate) == SIG_ERR) {
681 pr_log_pri(PR_LOG_NOTICE,
682 "unable to install SIGTERM (signal %d) handler: %s", SIGTERM,
683 strerror(errno));
684 }
685
686 if (signal(SIGURG, SIG_IGN) == SIG_ERR) {
687 pr_log_pri(PR_LOG_NOTICE,
688 "unable to install SIGURG (signal %d) handler: %s", SIGURG,
689 strerror(errno));
690 }
691
692 #ifdef SIGSTKFLT
693 if (signal(SIGSTKFLT, sig_terminate) == SIG_ERR) {
694 pr_log_pri(PR_LOG_NOTICE,
695 "unable to install SIGSTKFLT (signal %d) handler: %s", SIGSTKFLT,
696 strerror(errno));
697 }
698 #endif /* SIGSTKFLT */
699
700 #ifdef SIGIO
701 if (signal(SIGIO, SIG_IGN) == SIG_ERR) {
702 pr_log_pri(PR_LOG_NOTICE,
703 "unable to install SIGIO (signal %d) handler: %s", SIGIO,
704 strerror(errno));
705 }
706 #endif /* SIGIO */
707
708 if (signal(SIGUSR2, pr_signals_handle_event) == SIG_ERR) {
709 pr_log_pri(PR_LOG_NOTICE,
710 "unable to install SIGUSR2 (signal %d) handler: %s", SIGUSR2,
711 strerror(errno));
712 }
713
714 /* In case our parent left signals blocked (as happens under some
715 * poor inetd implementations)
716 */
717 if (sigprocmask(SIG_UNBLOCK, &sig_set, NULL) < 0) {
718 pr_log_pri(PR_LOG_NOTICE,
719 "unable to block signal set: %s", strerror(errno));
720 }
721
722 return 0;
723 }
724