1 /*
2  * Copyright (c) 2013, 2014, 2019, 2020
3  *      Inferno Nettverk A/S, Norway.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. The above copyright notice, this list of conditions and the following
9  *    disclaimer must appear in all copies of the software, derivative works
10  *    or modified versions, and any portions thereof, aswell as in all
11  *    supporting documentation.
12  * 2. All advertising materials mentioning features or use of this software
13  *    must display the following acknowledgement:
14  *      This product includes software developed by
15  *      Inferno Nettverk A/S, Norway.
16  * 3. The name of the author may not be used to endorse or promote products
17  *    derived from this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  *
30  * Inferno Nettverk A/S requests users of this software to return to
31  *
32  *  Software Distribution Coordinator  or  sdc@inet.no
33  *  Inferno Nettverk A/S
34  *  Oslo Research Park
35  *  Gaustadall�en 21
36  *  NO-0349 Oslo
37  *  Norway
38  *
39  * any improvements or extensions that they make and grant Inferno Nettverk A/S
40  * the rights to redistribute these changes.
41  *
42  */
43 
44 #include "common.h"
45 
46 static const char rcsid[] =
47 "$Id: mother_util.c,v 1.22.4.8.6.3 2020/11/11 16:11:59 karls Exp $";
48 
49 /*
50  * signal handler functions.  Upon reception of signal, "sig" is the real
51  * signal value (> 0).  We then set a flag indicating we got a signal,
52  * but we don't do anything and return immediately.  Later we are called
53  * again, with "sig" having the value -(sig), to indicate we are not
54  * executing in the signal handler and it's safe to do whatever we
55  * need to do.
56  */
57 static void sigterm(int sig, siginfo_t *si, void *sc);
58 static void siginfo(int sig, siginfo_t *si, void *sc);
59 static void sigchld(int sig, siginfo_t *si, void *sc);
60 static void sigalrm(int sig, siginfo_t *si, void *sc);
61 static void  sighup(int sig, siginfo_t *si, void *sc);
62 
63 static void unexpecteddeath(void);
64 /*
65  * Should be called after any unexpected child death / child removal.
66  * May disable creation of further children for a while and log a warning
67  * if appropriate, or the enable creation of further children.
68  */
69 
70 void
mother_preconfigload(void)71 mother_preconfigload(void)
72 {
73 
74 }
75 
76 void
mother_postconfigload(void)77 mother_postconfigload(void)
78 {
79    const char *function = "mother_postconfigload()";
80 
81    if (pidismainmother(sockscf.state.pid))
82       shmem_idupdate(&sockscf);  /* only main mother does this. */
83 }
84 
85 void
mother_envsetup(argc,argv)86 mother_envsetup(argc, argv)
87    int argc;
88    char *argv[];
89 {
90    const char *function = "mother_envsetup()";
91    const int exitsignalv[] = {
92       SIGINT, SIGQUIT, SIGBUS, SIGSEGV, SIGTERM, SIGILL, SIGFPE
93 #ifdef SIGSYS
94       , SIGSYS
95 #endif /* SIGSYS */
96    };
97    const size_t pipetomotherfds = 2; /* fds needed for pipe to mother. */
98    const size_t exitsignalc = ELEMENTS(exitsignalv);
99    const int ignoresignalv[] = {
100       SIGPIPE
101    };
102    const size_t ignoresignalc = ELEMENTS(ignoresignalv);
103    struct sigaction sigact;
104    struct rlimit rlimit;
105 #ifdef RLIMIT_NPROC
106    struct rlimit maxproc;
107 #endif /* RLIMIT_NPROC */
108    rlim_t maxopenfd, minfd_neg, minfd_req, minfd_io, minfd;
109    size_t i, fdreserved;
110 
111    for (fdreserved = 0;
112    fdreserved < ELEMENTS(sockscf.state.reservedfdv);
113    ++fdreserved) {
114       if (sockscf.state.reservedfdv[fdreserved] == -1) {
115          if ((sockscf.state.reservedfdv[fdreserved] = makedummyfd(0, 0)) == -1)
116             serr("%s: could not reserve fd #%lu for later use",
117                  function, (unsigned long)fdreserved + 1);
118       }
119    }
120 
121    /*
122     * close any descriptor we don't need, both in case of chroot(2)
123     * and for needing every descriptor we can get.
124     */
125 
126    /* assume syslog uses one */
127    fdreserved += sockscf.log.type & LOGTYPE_SYSLOG ? 0 : 1;
128 
129    /*
130     * shmem-segments we may need to attach to temporarily in relation
131     * to doing rulespermit() and similar for a client.
132     */
133    fdreserved += 1  /* bw fd      */
134                + 1  /* session fd */
135                + 1; /* monitor fd */
136 
137    for (i = 0, maxopenfd = getmaxofiles(softlimit); (rlim_t)i < maxopenfd; ++i){
138       size_t j;
139 
140       if (descriptorisreserved((int)i)) {
141          ++fdreserved;
142          continue;
143       }
144 
145       /* sockets we listen on. */
146       for (j = 0; j < sockscf.internal.addrc; ++j) {
147          if ((int)i == sockscf.internal.addrv[j].s)
148             break;
149       }
150 
151       if (j < sockscf.internal.addrc) /* listening on this socket. */
152          continue;
153 
154       close((int)i);
155    }
156 
157    errno = 0;
158    newprocinit(); /* just in case the above closed a syslog(3) fd. */
159 
160    /*
161     * Check system limits against what we need.
162     * Enough descriptors for each child process? + 2 for the pipes from
163     * the child to mother.
164     */
165 
166    minfd_neg = (SOCKD_NEGOTIATEMAX * 1)          + pipetomotherfds + fdreserved;
167 
168    minfd_req = (SOCKD_REQUESTMAX   * FDPASS_MAX) + pipetomotherfds + fdreserved;
169 
170    minfd_io  = (SOCKD_IOMAX        * FDPASS_MAX) + pipetomotherfds + fdreserved;
171 
172    /* i/o process stays attached to bw and monitor shmem all the time. */
173    minfd_io  += SOCKD_IOMAX * (1 + 1);
174 
175 #if BAREFOOTD
176    minfd_io += MIN(10, MIN_UDPCLIENTS);
177 #endif
178 
179    slog(LOG_DEBUG,
180         "%s: minfd_negotiate: %lu, minfd_request: %lu, minfd_io: %lu",
181         function,
182         (unsigned long)minfd_neg,
183         (unsigned long)minfd_req,
184         (unsigned long)minfd_io);
185    /*
186     * need to know max number of open files so we can allocate correctly
187     * sized fd_sets.  Also, try to set both it and the max number of
188     * processes to the hard limit.
189     */
190 
191    sockscf.state.maxopenfiles = getmaxofiles(hardlimit);
192 
193    slog(LOG_DEBUG,
194         "hard limit for max number of open files is %lu, soft limit is %lu",
195         (unsigned long)sockscf.state.maxopenfiles,
196         (unsigned long)getmaxofiles(softlimit));
197 
198    if (sockscf.state.maxopenfiles == RLIM_INFINITY) {
199       sockscf.state.maxopenfiles = getmaxofiles(softlimit);
200       SASSERTX(sockscf.state.maxopenfiles != RLIM_INFINITY);
201    }
202 
203    minfd = MAX(minfd_neg, MAX(minfd_req, minfd_io));
204 
205    if (sockscf.state.maxopenfiles < minfd) {
206       slog(LOG_INFO,
207            "have only %lu file descriptors available, but need at least %lu "
208            "according to the configuration.  Trying to increase it ...",
209            (unsigned long)sockscf.state.maxopenfiles,
210            (unsigned long)minfd);
211 
212       sockscf.state.maxopenfiles = minfd;
213    }
214 
215    rlimit.rlim_cur = rlimit.rlim_max = sockscf.state.maxopenfiles;
216 
217    if (setrlimit(RLIMIT_OFILE, &rlimit) == 0)
218       slog(LOG_DEBUG, "max number of file descriptors is now %lu",
219            (unsigned long)sockscf.state.maxopenfiles);
220   else {
221       const char *problem;
222 
223       sockscf.state.maxopenfiles = getmaxofiles(hardlimit);
224 
225       if (sockscf.state.maxopenfiles      < minfd_neg)
226          problem = "SOCKD_NEGOTIATEMAX";
227       else if (sockscf.state.maxopenfiles < minfd_req)
228          problem = "SOCKD_REQUESTMAX";
229       else if (sockscf.state.maxopenfiles < minfd_io)
230          problem = "SOCKD_IOMAX";
231       else
232          SERRX(sockscf.state.maxopenfiles);
233 
234       serrx("%s: failed to increase the max number of open file descriptors "
235             "for ourselves via setrlimit(RLIMIT_OFILE) to %lu: %s.  "
236             "Increase the kernel/shell's max open files limit, or reduce "
237             "the %s value in %s's include/config.h, or we will be unable to "
238             "start up",
239             function,
240             (unsigned long)rlimit.rlim_max,
241             strerror(errno),
242             problem,
243             PRODUCT);
244    }
245 
246 #ifdef RLIMIT_NPROC
247    if (getrlimit(RLIMIT_NPROC, &maxproc) != 0)
248       swarn("getrlimit(RLIMIT_NPROC) failed");
249    else {
250       maxproc.rlim_cur = maxproc.rlim_max;
251 
252       if (setrlimit(RLIMIT_NPROC, &maxproc) != 0)
253          swarn("setrlimit(RLIMIT_NPROC, { %lu, %lu }) failed",
254                (unsigned long)rlimit.rlim_cur,
255                (unsigned long)rlimit.rlim_max);
256    }
257 #endif /* !RLIMIT_NPROC */
258 
259 
260    /*
261     * set up signal handlers.
262     */
263 
264    bzero(&sigact, sizeof(sigact));
265    sigact.sa_flags = SA_RESTART | SA_NOCLDSTOP | SA_SIGINFO;
266 
267    sigact.sa_sigaction = siginfo;
268 #if HAVE_SIGNAL_SIGINFO
269    if (sigaction(SIGINFO, &sigact, NULL) != 0)
270       serr("sigaction(SIGINFO)");
271 #endif /* HAVE_SIGNAL_SIGINFO */
272 
273    /*
274     * same handler, for systems without SIGINFO, as well as systems with
275     * broken ("more secure") signal semantics.
276     */
277    if (sigaction(SIGUSR1, &sigact, NULL) != 0)
278       serr("sigaction(SIGUSR1)");
279 
280    sigact.sa_sigaction = sighup;
281    if (sigaction(SIGHUP, &sigact, NULL) != 0)
282       serr("sigaction(SIGHUP)");
283 
284    sigact.sa_sigaction = sigchld;
285    if (sigaction(SIGCHLD, &sigact, NULL) != 0)
286       serr("sigaction(SIGCHLD)");
287 
288    sigact.sa_sigaction = sigterm;
289    for (i = 0; (size_t)i < exitsignalc; ++i)
290       if (sigaction(exitsignalv[i], &sigact, NULL) != 0)
291          serr("sigaction(%d)", exitsignalv[i]);
292 
293    sigact.sa_handler = SIG_IGN;
294    for (i = 0; (size_t)i < ignoresignalc; ++i)
295       if (sigaction(ignoresignalv[i], &sigact, NULL) != 0)
296          serr("sigaction(%d)", ignoresignalv[i]);
297 
298    sigact.sa_flags     = SA_SIGINFO;   /* want to be interrupted. */
299    sigact.sa_sigaction = sigalrm;
300    if (sigaction(SIGALRM, &sigact, NULL) != 0)
301       serr("sigaction(SIGALRM)");
302 
303    if (sockscf.option.daemon) {
304       if (daemon(1, 0) != 0)
305          serr("daemon()");
306 
307       /*
308        * leave stdout/stderr, but close stdin.
309        * Note that this needs to be done before newprocinit() (which
310        * sets up syslog-thing), as it may happen that the syslog socket
311        * is 0, and we don't want to close that.
312        */
313       close(STDIN_FILENO);
314       newprocinit(); /* for daemon(). */
315 
316       *sockscf.state.motherpidv = getpid();   /* we are the main mother. */
317    }
318 
319    if (HAVE_ENABLED_PIDFILE) {
320       const mode_t openmode  = S_IRUSR  | S_IWUSR  | S_IRGRP | S_IROTH;
321       const int    openflags = O_WRONLY | O_CREAT;
322       FILE *fp;
323       int fd;
324 
325       sockd_priv(SOCKD_PRIV_PRIVILEGED, PRIV_ON);
326       if ((fd = open(sockscf.option.pidfile, openflags, openmode)) == -1) {
327          swarn("could not open pidfile %s for writing", sockscf.option.pidfile);
328          errno = 0;
329       }
330       sockd_priv(SOCKD_PRIV_PRIVILEGED, PRIV_OFF);
331 
332       if (fd != -1) {
333          fp = fdopen(fd, "w");
334 
335          if (fp != NULL) {
336             if (fprintf(fp, "%lu\n", (unsigned long)sockscf.state.pid) == EOF)
337                swarn("failed writing pid to pidfile %s",
338                      sockscf.option.pidfile);
339             else
340                sockscf.option.pidfilewritten = 1;
341 
342             fclose(fp);
343          }
344 
345          close(fd);
346       }
347 
348    }
349 
350    enable_childcreate();
351 
352    freedescriptors(NULL, &sockscf.state.highestfdinuse);
353 }
354 
355 char *
mother_getlimitinfo(void)356 mother_getlimitinfo(void)
357 {
358    const char *function = "mother_getlimitinfo()";
359    static char buf[2048];
360    const int fds_per_proc = 2; /* two pipes */
361    const char *limiter, *prefix = "max clients calculation will not be done";
362    struct rlimit maxfd, maxproc;
363    char maxprocstr[64], maxfdstr[64];
364    unsigned long negc_proc, negc_fd, reqc_proc, reqc_fd, ioc_proc, ioc_fd,
365                  negc_limit, reqc_limit, ioc_limit,
366                  proc_free, proc_used, procs, fds_free;
367 
368    if (getrlimit(RLIMIT_NOFILE, &maxfd) != 0) {
369       swarn("%s: getrlimit(RLIMIT_NOFILE) failed", function);
370       return "";
371    }
372 
373 #ifdef RLIMIT_NPROC
374    if (getrlimit(RLIMIT_NPROC, &maxproc) != 0) {
375       swarn("%s: %s: getrlimit(RLIMIT_NPROC) failed", function, prefix);
376       return "";
377    }
378 #else /* !RLIMIT_NPROC */
379    if ((maxproc.rlim_cur = (rlim_t)sysconf(_SC_CHILD_MAX)) == (rlim_t)-1) {
380       swarn("%s: %s: sysconf(_SC_CHILD_MAX) failed", function, prefix);
381       return "";
382    }
383 
384    maxproc.rlim_max = maxproc.rlim_cur;
385 #endif /* !RLIMIT_NPROC */
386 
387    if (maxfd.rlim_cur   == RLIM_INFINITY
388    &&  maxproc.rlim_cur == RLIM_INFINITY)
389       return "no applicable environment resource limits configured";
390 
391    proc_used   = sockscf.option.serverc
392                + childcheck(-PROC_NEGOTIATE) / SOCKD_NEGOTIATEMAX
393                + childcheck(-PROC_REQUEST)   / SOCKD_REQUESTMAX
394                + childcheck(-PROC_IO)        / SOCKD_IOMAX;
395    proc_free   = maxproc.rlim_cur - proc_used;
396 
397    if (maxproc.rlim_cur == RLIM_INFINITY)
398       snprintf(maxprocstr, sizeof(maxprocstr), "no limit");
399    else
400       snprintf(maxprocstr, sizeof(maxprocstr),
401                "%lu (%lu free)",
402                (unsigned long)maxproc.rlim_cur, proc_free);
403 
404    fds_free = freedescriptors(NULL, NULL) - FDPASS_MAX;
405    if (maxfd.rlim_cur == RLIM_INFINITY)
406       snprintf(maxfdstr, sizeof(maxfdstr), "no limit");
407    else
408       snprintf(maxfdstr, sizeof(maxfdstr),
409                "%lu (%lu free)", (unsigned long)maxfd.rlim_cur, fds_free);
410 
411    /*
412     * Calculate the max number of new clients we can handle based on both
413     * the process resource limit and the fd limit.
414     */
415 
416    /*
417     * Process-based limit, disregarding any other limits.
418     * Each process can handle SOCKD_{NEGOTIATE,REQUEST,IO}MAX clients.
419     * We can create a max number of proc_free additional processes, so
420     * the number of additional clients we can handle is the number
421     * of additional clients multiplied by the number of clients each
422     * process can handle.
423     */
424    negc_proc = proc_free * SOCKD_NEGOTIATEMAX;
425    reqc_proc = proc_free * SOCKD_REQUESTMAX;
426    ioc_proc  = proc_free * SOCKD_IOMAX;
427 
428    /*
429     * FD-based limit, disregarding any other limits.
430     * With the fds we have, we can create a given number of additional
431     * processes (procs).
432     * Each process needs fds_per_proc, and an additional
433     * SOCKD_{NEGOTIATE,REQUEST,IO}MAX * <number of fds per client in this
434     * phase> fds to handle the max number of clients, meaning we can handle
435     * the following number of additional clients:
436     */
437    procs   = fds_free / fds_per_proc;
438    negc_fd = MIN(((fds_free - fds_per_proc) / 1), SOCKD_NEGOTIATEMAX)
439            * procs;
440    reqc_fd = MIN(((fds_free - fds_per_proc) / FDPASS_MAX), SOCKD_REQUESTMAX)
441            * procs;
442    ioc_fd  = MIN(((fds_free - fds_per_proc) / FDPASS_MAX), SOCKD_IOMAX)
443            * procs;
444 
445    /*
446     * Different process-types could be limited by different things, but
447     * ignore that here.
448     */
449    if (negc_proc < negc_fd
450    ||  reqc_proc < reqc_fd
451    ||  ioc_proc  < ioc_fd) {
452       limiter = "process";
453 
454       negc_limit = negc_proc;
455       reqc_limit = reqc_proc;
456       ioc_limit  = ioc_proc;
457    }
458    else {
459       limiter = "open file";
460 
461       negc_limit = negc_fd;
462       reqc_limit = reqc_fd;
463       ioc_limit  = ioc_fd;
464    }
465 
466    snprintf(buf, sizeof(buf), "max limits: processes: %s, files: %s, "
467             "%s-slots: %lu, %s-slots: %lu, %s-slots: %lu "
468             "(max clients limited by %s limit)",
469             maxprocstr,
470             maxfdstr,
471             childtype2string(PROC_NEGOTIATE),
472             negc_limit,
473             childtype2string(PROC_REQUEST),
474             reqc_limit,
475             childtype2string(PROC_IO),
476             ioc_limit,
477             limiter);
478 
479    return buf;
480 }
481 
482 void
log_rusage(childtype,pid,rusage)483 log_rusage(childtype, pid, rusage)
484    const int childtype;
485    const pid_t pid;
486    const struct rusage *rusage;
487 {
488    char prefix[256];
489 
490    if (pid == 0)
491       snprintf(prefix, sizeof(prefix),
492                "sum of resource usage for all %s processes",
493                childtype2string(childtype));
494    else
495       snprintf(prefix, sizeof(prefix),
496                "resource usage for %s-child %lu",
497                childtype2string(childtype),
498                (unsigned long)pid);
499 
500 
501    slog(LOG_DEBUG,
502         "%s\n"
503         "  ru_utime   : %ld.%06lds\n"
504         "  ru_stime   : %ld.%06lds\n"
505         "  ru_minflt  : %ld\n"
506         "  ru_majflt  : %ld\n"
507         "  ru_nswap   : %ld\n"
508         "  ru_inblock : %ld\n"
509         "  ru_oublock : %ld\n"
510         "  ru_msgsnd  : %ld\n"
511         "  ru_msgrcv  : %ld\n"
512         "  ru_nsignals: %ld\n"
513         "  ru_nvcsw   : %ld\n"
514         "  ru_nivcsw  : %ld\n",
515         prefix,
516         (long)rusage->ru_utime.tv_sec, (long)rusage->ru_utime.tv_usec,
517         (long)rusage->ru_stime.tv_sec, (long)rusage->ru_stime.tv_usec,
518         rusage->ru_minflt,
519         rusage->ru_majflt,
520         rusage->ru_nswap,
521         rusage->ru_inblock,
522         rusage->ru_oublock,
523         rusage->ru_msgsnd,
524         rusage->ru_msgrcv,
525         rusage->ru_nsignals,
526         rusage->ru_nvcsw,
527         rusage->ru_nivcsw);
528 }
529 
530 
531 
532 static void
unexpecteddeath(void)533 unexpecteddeath(void)
534 {
535    const char *function = "unexpecteddeath()";
536    const size_t maxdeaths = 10;
537 
538 
539    ++sockscf.state.unexpected_deaths;
540    time_monotonic(&sockscf.state.lastdeath_time);
541 
542    if (sockscf.state.unexpected_deaths == 1)
543       sockscf.state.firstdeath_time = sockscf.state.lastdeath_time;
544 
545    if (sockscf.state.unexpected_deaths < maxdeaths)
546       return;
547 
548    if (sockscf.state.unexpected_deaths == maxdeaths) { /* log once only. */
549       slog(LOG_ERR,
550           "%s: %lu child deaths in %ld seconds.  Not something we are "
551           "expecting so possibly something is wrong.  Locking childcount "
552           "for a while (%ld seconds), hoping things will stabilize",
553           function,
554           (unsigned long)sockscf.state.unexpected_deaths,
555           (long)socks_difftime(sockscf.state.lastdeath_time,
556                                sockscf.state.firstdeath_time),
557           (long)MAX_ADDCHILD_SECONDS);
558 
559       disable_childcreate(0, "large amount of processes suddenly died");
560       alarm(MAX_ADDCHILD_SECONDS);
561    }
562 }
563 
564 /* ARGSUSED */
565 static void
sigalrm(sig,si,sc)566 sigalrm(sig, si, sc)
567    int sig;
568    siginfo_t *si;
569    void *sc;
570 {
571    const char *function = "sigalrm()";
572    const int errno_s = errno;
573 
574    SIGNAL_PROLOGUE(sig, si, errno_s);
575 
576    enable_childcreate();
577 
578    SIGNAL_EPILOGUE(sig, si, errno_s);
579 }
580 
581 /* ARGSUSED */
582 static void
sigterm(sig,si,sc)583 sigterm(sig, si, sc)
584    int sig;
585    siginfo_t *si;
586    void *sc;
587 {
588    const char *function = "sigterm()";
589    const int errno_s = errno;
590 
591    if (sig > 0) {
592       if (SIGNALISOK(sig))
593          SIGNAL_PROLOGUE(sig, si, errno_s);
594       else {
595          /*
596           * A bad signal, something has crashed.  Can't count
597           * on it being possible to continue from here, have
598           * to exit now.
599           */
600          const char *msgv[] = { function,
601                                 ": terminating on unexpected signal ",
602                                 ltoa(sig, NULL, 0),
603                                 NULL
604                               };
605          sigset_t clearmask;
606 
607          sockscf.state.insignal = sig;
608 
609          signalslog(LOG_WARNING, msgv);
610 
611 #if HAVE_LIVEDEBUG
612          if (!sockscf.option.debug)
613             socks_flushrb();
614 #endif /* HAVE_LIVEDEBUG */
615 
616          /*
617           * Reinstall default signal handler for this signal and raise it
618           * again, assuming we will terminate and get a coredump if that is
619           * the default behavior.
620           */
621          if (signal(sig, SIG_DFL) == SIG_ERR) {
622             const char *msgv[]
623             = { function,
624                 ": failed to reinstall original handler for signal %d",
625                 ltoa(sig, NULL, 0),
626                 NULL
627               };
628 
629             signalslog(LOG_WARNING, msgv);
630          }
631 
632          bzero(&clearmask, sizeof(clearmask));
633          (void)sigprocmask(SIG_SETMASK, &clearmask, NULL);
634          raise(sig);
635 
636          return; /* need to exit this signal handler so the default can run. */
637       }
638    }
639    else
640       sig = -sig;
641 
642    slog(LOG_INFO, "%s: exiting on signal %d", function, sig);
643 
644    SIGNAL_EPILOGUE(sig, si, errno_s);
645 
646    sockdexit(EXIT_SUCCESS);
647 }
648 
649 /* ARGSUSED */
650 static void
siginfo(sig,si,sc)651 siginfo(sig, si, sc)
652    int sig;
653    siginfo_t *si;
654    void *sc;
655 {
656    const char *function = "siginfo()";
657    const int errno_s = errno;
658    unsigned long days, hours, minutes, seconds,
659                  free_negc, free_reqc, free_ioc,
660                  max_negc,  max_reqc,  max_ioc;
661    size_t clients;
662 
663    SIGNAL_PROLOGUE(sig, si, errno_s);
664 
665    clients = 0;
666    clients += (max_negc = childcheck(-PROC_NEGOTIATE));
667    clients += (max_reqc = childcheck(-PROC_REQUEST));
668    clients += (max_ioc  = childcheck(-PROC_IO));
669 
670    clients -= (free_negc = childcheck(PROC_NEGOTIATE));
671    clients -= (free_reqc = childcheck(PROC_REQUEST));
672    clients -= (free_ioc  = childcheck(PROC_IO));
673 
674    seconds = (unsigned long)socks_difftime(time_monotonic(NULL),
675                                            sockscf.stat.boot);
676    seconds2days(&seconds, &days, &hours, &minutes);
677 
678    slog(LOG_INFO, "%s v%s up %lu day%s, %lu:%.2lu, a: %lu, h: %lu c: %lu",
679          PRODUCT,
680          VERSION,
681          days,
682          days == 1 ? "" : "s",
683          hours,
684          minutes,
685          (unsigned long)sockscf.stat.accepted,
686          (unsigned long)sockscf.stat.negotiate.sendt,
687          (unsigned long)clients);
688 
689    slog(LOG_INFO, "negotiators (%lu): a: %lu, h: %lu, c: %lu, f: %lu",
690         max_negc / SOCKD_NEGOTIATEMAX,
691         (unsigned long)sockscf.stat.negotiate.sendt,
692         (unsigned long)sockscf.stat.negotiate.received,
693         max_negc - free_negc,
694         free_negc);
695 
696    slog(LOG_INFO, "requesters (%lu): a: %lu, h: %lu, c: %lu, f: %lu",
697         max_reqc / SOCKD_REQUESTMAX,
698         (unsigned long)sockscf.stat.request.sendt,
699         (unsigned long)sockscf.stat.request.received,
700         max_reqc - free_reqc,
701         free_reqc);
702 
703    slog(LOG_INFO, "iorelayers (%lu): a: %lu, h: %lu, c: %lu, f: %lu",
704         max_ioc / SOCKD_IOMAX,
705         (unsigned long)sockscf.stat.io.sendt,
706         (unsigned long)sockscf.stat.io.received,
707         max_ioc - free_ioc,
708         free_ioc);
709 
710    slog(LOG_INFO, "%s", mother_getlimitinfo());
711 
712    /*
713     * Regarding kill(2), the OpenBSD manpage says this:
714     *
715     * """
716     * Setuid and setgid processes are dealt with slightly differently.
717     * For the non-root user, to prevent attacks against such processes,
718     * some signal deliveries are not permitted and return the error
719     * EPERM.  The following signals are allowed through to this class
720     * of processes: SIGKILL, SIGINT, SIGTERM, SIGSTOP, SIGTTIN, SIGTTOU,
721     * SIGTSTP, SIGHUP, SIGUSR1, SIGUSR2.
722     * """
723     *
724     * The practical effect of this seems to be that if we use different
725     * userids, we, when running with the euid of something other than root,
726     * may not be able to send the SIGINFO signal to our own children. :-/
727     * Simlar problem exists for FreeBSD.
728     *
729     * To workaround the problem, send SIGUSR1 to the children instead of
730     * SIGINFO, as SIGUSR1 has always been treated the same way as SIGINFO
731     * by Dante due to some platforms not having the SIGINFO signal.
732     */
733 #ifdef SIGINFO
734    if (sig == SIGINFO)
735       sig = SIGUSR1;
736 #endif
737 
738    if (pidismainmother(sockscf.state.pid))   /* main mother */
739       sigserverbroadcast(sig);
740 
741    sigchildbroadcast(sig);
742 
743    SIGNAL_EPILOGUE(sig, si, errno_s);
744 }
745 
746 /* ARGSUSED */
747 static void
sighup(sig,si,sc)748 sighup(sig, si, sc)
749    int sig;
750    siginfo_t *si;
751    void *sc;
752 {
753    const char *function = "sighup()";
754    const int errno_s = errno;
755    struct config *newshmemconfig;
756    internaladdress_t oldinternal;
757    size_t i, pointersize;
758    int rc;
759 
760    SIGNAL_PROLOGUE(sig, si, errno_s);
761 
762    slog(LOG_INFO, "SIGHUP [: reloading config");
763 
764    /*
765     * Copy the current addresses on the internal interfaces so that after
766     * we have read in the new configuration, we can compare the old list
767     * against the new to know which addresses/sockets are longer in use,
768     * and stop listening on them.
769     *
770     * We can not simply clear them before reading in the new config
771     * and then start listening on them (again) after we in read the new
772     * config, as that would mean we could lose clients in the time-gap
773     * between unbinding and rebinding the addresses.
774     *
775     * This is mainly for barefootd, where adding/removing bounce-to
776     * addresses is probably not uncommon.  In the case of barefootd,
777     * we additionally have udp addresses we listen on constantly that
778     * we need to handle in a similar way.
779     *
780     * We also have a slight problem with udp rules, as we need to
781     * know if the rule existed before the reload.  If it did,
782     * we will fail when we try to bind on the internal side,
783     * and also waste time trying to set up bouncing for the same
784     * udp addresses several times.  More importantly, we will not
785     * know whether the error is expected, or if we should tell the
786     * user he is trying to use an address already in use by
787     * somebody else.
788     * The same problem occurs if we have multiple rules with the
789     * same "to:" address, which can make sense provided "from:"
790     * differs.  We then have multiple acls for the same "to:" address,
791     * but of course only one "to:" address/socket.
792     *
793     * Our solution for this is to also save the unique udp addresses we
794     * need to listen to, and compare against them upon config reload.
795     * If one of the udp address is the same as before, we consider the
796     * session to be "bounced" already, and if one of the addresses
797     * present on the old list is not present on the new list, we know
798     * we have an old session/socket to terminate.
799     */
800 
801     oldinternal.addrc      = sockscf.internal.addrc;
802     if ((oldinternal.addrv = malloc(sizeof(*oldinternal.addrv)
803                                            * oldinternal.addrc)) == NULL) {
804       swarn("%s: failed to allocate memory for saving state before "
805             "configuration reload",
806             function);
807 
808       return;
809    }
810 
811    for (i = 0; i < oldinternal.addrc; ++i)
812       oldinternal.addrv[i] = sockscf.internal.addrv[i];
813 
814    resetconfig(&sockscf, 0);
815    genericinit();
816    checkconfig();
817 
818    showconfig(&sockscf);
819 
820 #if DIAGNOSTIC
821    if (sockscf.monitor != NULL)
822       SASSERTX(sockscf.monitor->mstats == NULL);
823 
824    if (sockscf.crule != NULL)
825       SASSERTX(!SHMID_ISATTACHED(sockscf.crule));
826 
827    if (sockscf.srule != NULL)
828       SASSERTX(!SHMID_ISATTACHED(sockscf.srule));
829 #endif /* DIAGNOSTIC */
830 
831    for (i = 0; i < oldinternal.addrc; ++i) {
832       ssize_t p;
833 
834       p = addrindex_on_listenlist(sockscf.internal.addrc,
835                                   sockscf.internal.addrv,
836                                   &oldinternal.addrv[i].addr,
837                                   oldinternal.addrv[i].protocol);
838 
839       if (p >= 0) {
840          /*
841           * this socket/session should continue to exist.
842           */
843          sockscf.internal.addrv[p].s = oldinternal.addrv[i].s;
844          continue;
845       }
846 
847       /*
848        * this socket should be removed.
849        */
850 
851       if (oldinternal.addrv[i].protocol == SOCKS_TCP) {
852          close(oldinternal.addrv[i].s);
853          continue;
854       }
855 
856 #if BAREFOOTD
857       /* else; udp. */
858       slog(LOG_DEBUG, "%s: child should remove udp session for %s",
859            function,
860            sockaddr2string(&oldinternal.addrv[i].addr, NULL, 0));
861 #endif /* BAREFOOTD */
862    }
863 
864 #if BAREFOOTD
865    if (!ALL_UDP_BOUNCED()) {
866       /*
867        * Go through all rules and see if the current udp addresses
868        * to bind matches any of the old ones so we know which addresses
869        * are new and need to be bounced.  Those already bounced we should
870        * ignore.
871        */
872       rule_t *rule;
873 
874       /*
875        * Assume there are no new addresses to bounce initially.
876        */
877       sockscf.state.alludpbounced = 1;
878 
879       for (rule = sockscf.crule; rule != NULL; rule = rule->next) {
880          sockshost_t hosttobind;
881          struct sockaddr_storage addrtobind;
882 
883          if (!rule->state.protocol.udp)
884             continue;
885 
886          switch (rule->dst.atype) {
887             case SOCKS_ADDR_IPV4:
888             case SOCKS_ADDR_IPV6:
889                ruleaddr2sockshost(&rule->dst, &hosttobind, SOCKS_UDP);
890                sockshost2sockaddr(&hosttobind, &addrtobind);
891 
892                if (addrindex_on_listenlist(oldinternal.addrc,
893                                            oldinternal.addrv,
894                                            &addrtobind,
895                                            SOCKS_UDP) != -1) {
896                   slog(LOG_DEBUG,
897                        "%s: marking address %s in rule %lu as bounced; "
898                        "previously bounced",
899                        function,
900                        sockaddr2string(&addrtobind, NULL, 0),
901                        (unsigned long)rule->number);
902 
903                   rule->bounced = 1;
904                }
905                break;
906 
907             case SOCKS_ADDR_DOMAIN: {
908                size_t i;
909 
910                i = 0;
911                while (hostname2sockaddr(rule->dst.addr.domain,
912                                         i++,
913                                         &addrtobind) != NULL) {
914                   if (addrindex_on_listenlist(oldinternal.addrc,
915                                               oldinternal.addrv,
916                                               &addrtobind,
917                                               SOCKS_UDP) != -1) {
918                      slog(LOG_DEBUG,
919                           "%s: marking address %s in rule %lu "
920                           "as bounced; previously bounced",
921                           function,
922                           sockaddr2string(&addrtobind, NULL, 0),
923                           (unsigned long)rule->number);
924 
925                      rule->bounced = 1;
926                      break;
927                   }
928                }
929 
930                break;
931             }
932 
933             case SOCKS_ADDR_IFNAME: {
934                struct sockaddr_storage mask;
935                size_t i;
936 
937                i = 0;
938                while (ifname2sockaddr(rule->dst.addr.ifname,
939                                       i++,
940                                       &addrtobind,
941                                       &mask) != NULL) {
942                   if (addrindex_on_listenlist(oldinternal.addrc,
943                                               oldinternal.addrv,
944                                               &addrtobind,
945                                               SOCKS_UDP) != -1) {
946                      slog(LOG_DEBUG,
947                           "%s: marking address %s in rule %lu "
948                           "as bounced; previously bounced",
949                           function,
950                           sockaddr2string(&addrtobind, NULL, 0),
951                          (unsigned long)rule->number);
952 
953                      rule->bounced = 1;
954                      break;
955                   }
956                }
957                break;
958             }
959 
960             default:
961                SERRX(rule->dst.atype);
962          }
963 
964          if (!rule->bounced)
965             sockscf.state.alludpbounced = 0;
966       }
967    }
968 #endif /* BAREFOOTD */
969 
970    free(oldinternal.addrv);
971 
972    /* may have added addresses in new config, rebind if necessary. */
973    if (bindinternal(SOCKS_TCP) != 0)
974       serr("%s: failed to bind internal addresses", function);
975 
976    /*
977     * Now comes the tricky part: copy the config to shared memory and forward
978     * the SIGHUP to our children so they know to copy the config we put in
979     * shared memory to their own local memory.
980     *
981     * The procedure works like this:
982     * 1) We lock shmemconfigfd, copy the config to shmem (mapped by the
983     *    file referenced by shmemconfigfd), and unlock shmemconfigfd.
984     *
985     * 2) We then forward the children the SIGHUP.
986     *
987     * 3) When the children receive the SIGHUP, they lock shmemconfigfd,
988     *    copy the config, and unlock shmemconfigfd.
989     *
990     * The only reason for locking shmemconfig is so we do not update it (due
991     * to another SIGHUP) while the children try to read it (children lock it
992     * read-only, we lock it it read-write).
993     */
994 
995    socks_lock(sockscf.shmemconfigfd, 0, 0, 1, 1);
996 
997    pointersize = pointer_size(&sockscf);
998 
999    slog(LOG_DEBUG,
1000         "%s: current config is of size %lu + %lu (%lu).  Trying to mmap(2) ...",
1001         function,
1002         (unsigned long)sizeof(sockscf),
1003         (unsigned long)pointersize,
1004         (unsigned long)(sizeof(sockscf) + pointersize));
1005 
1006    if ((newshmemconfig = sockd_mmap(NULL,
1007                                     sizeof(sockscf) + pointersize,
1008                                     PROT_READ | PROT_WRITE,
1009                                     MAP_SHARED,
1010                                     sockscf.shmemconfigfd,
1011                                     1)) == MAP_FAILED) {
1012       swarn("%s: could not create shared memory segment of size %lu",
1013             function, (unsigned long)(sizeof(sockscf) + pointersize));
1014 
1015       socks_unlock(sockscf.shmemconfigfd, 0, 0);
1016       return;
1017    }
1018 
1019    /*
1020     * First shallow copy what we can.
1021     */
1022    *newshmemconfig = sockscf;
1023 
1024    /*
1025     * Then the more complicated deep copy.
1026     */
1027    if (pointer_copy(&sockscf,
1028                     0,
1029                     newshmemconfig,
1030                     (void *)((uintptr_t)newshmemconfig + sizeof(sockscf)),
1031                     pointersize) != 0) {
1032 
1033       swarn("%s: could not copy pointers to shared memory", function);
1034 
1035       munmap(newshmemconfig, sizeof(sockscf) + pointersize);
1036 
1037       socks_unlock(sockscf.shmemconfigfd, 0, 0);
1038 
1039       return;
1040    }
1041 
1042    /*
1043     * Successfully mapped new config and everything looks ok.  Now remove
1044     * the old mapping, if any.
1045     */
1046    if (sockscf.shmeminfo->config != NULL) {
1047       rc = munmap(sockscf.shmeminfo->config, sockscf.shmeminfo->configsize);
1048       SASSERTX(rc == 0);
1049    }
1050 
1051    sockscf.shmeminfo->config     = newshmemconfig;
1052    sockscf.shmeminfo->configsize = sizeof(sockscf) + pointersize;
1053 
1054    socks_unlock(sockscf.shmemconfigfd, 0, 0);
1055 
1056    slog(LOG_DEBUG,
1057         "%s: updated config in shmem.  Total size %lu. Doing compare test ...",
1058         function, (unsigned long)sockscf.shmeminfo->configsize);
1059 
1060    if ((i = compareconfigs(&sockscf, sockscf.shmeminfo->config)) == 0) {
1061       swarnx("%s: config in shmem not identical to running config", function);
1062       return;
1063    }
1064    else
1065       slog(LOG_DEBUG,
1066            "%s: shmem config identical to running config.  %lu bytes compared",
1067            function, (unsigned long)i);
1068 
1069    /*
1070     * Not necessarily necessary, but the config-change could imply we
1071     * should no longer use (and thus resolve for) ipv4 or ipv6 addresses.
1072     * Also, might be we have cached something the admin no longer wants us to
1073     * cache.  Safest to invalidate the cache too at this point.
1074     */
1075    hostcacheinvalidate();
1076 
1077 #if HAVE_LDAP
1078 
1079    /*
1080     * LDAP cache entries depend on rule configuration so old cached entries
1081     * might no longer be valid after a SIGHUP.  Need to invalidate cache
1082     * at this point.
1083     */
1084    ldapcacheinvalid();
1085 
1086 #endif /* HAVE_LDAP */
1087 
1088    time_monotonic(&sockscf.stat.configload);
1089 
1090    slog(LOG_INFO,
1091         "SIGHUP ]: config reloaded.  Broadcasting to children to do the same");
1092 
1093    sigserverbroadcast(sig);
1094    sigchildbroadcast(sig);
1095 
1096    resetprivileges();
1097 
1098    SIGNAL_EPILOGUE(sig, si, errno_s);
1099 }
1100 
1101 
1102 
1103 /* ARGSUSED */
1104 static void
sigchld(sig,si,sc)1105 sigchld(sig, si, sc)
1106    int sig;
1107    siginfo_t *si;
1108    void *sc;
1109 {
1110    const char *function = "sigchld()";
1111    const int errno_s = errno;
1112    time_t tnow;
1113    pid_t pid;
1114    int status;
1115 
1116    SIGNAL_PROLOGUE(sig, si, errno_s);
1117 
1118    if (socks_difftime(time_monotonic(&tnow), sockscf.state.firstdeath_time)
1119    >= (time_t)MAX_ADDCHILD_SECONDS) { /* enough time has passed; reset. */
1120       sockscf.state.unexpected_deaths = 0;
1121       sockscf.state.firstdeath_time   = 0;
1122       sockscf.state.lastdeath_time    = 0;
1123 
1124       enable_childcreate();
1125    }
1126 
1127    while (1) {
1128       struct rusage thisrusage;
1129       sockd_child_t *child;
1130       int isunexpected, proctype;
1131 
1132       /*
1133        * On Solaris wait4(2) expects WAIT_ANY to be 0, not -1 as it is
1134        * on other systems.  Using -1 ends up calling waitid(2) as
1135        * waitid(P_PGID, 1, ...
1136        * Not what we want, so use wait3(2) instead, as it does not have
1137        * that bug.
1138        */
1139       if ((pid = wait3(&status, WNOHANG, &thisrusage)) == -1
1140       && ERRNOISTMP(errno))
1141          continue;
1142 
1143       if (pid <= 0)
1144          break;
1145 
1146       slog(LOG_DEBUG, "%s: process %ld exited", function, (long)pid);
1147 
1148       if (pidismother(pid)) {
1149          sockscf.state.motherpidv[pidismother(pid) - 1] = 0;
1150          isunexpected = 1;
1151          proctype     = PROC_MOTHER;
1152       }
1153       else {
1154          /*
1155           * Must be a regular childprocess.
1156           * XXX merge motherprocesses into getchild() code.
1157           */
1158          struct rusage *rusage, sum;
1159 
1160          if ((child = getchild(pid)) == NULL) {
1161             /*
1162              * Note that this might be a pid from our former self also
1163              * if we failed on an internal error, fork(2)-ed process to
1164              * get the coredump and continue.  When the fork(2)-ed process
1165              * exits after generating the coredump, we will receive it's
1166              * SIGCHLD, but no account of it.  To avoid that, hopefully
1167              * never happening, problem generating a recursive error, let
1168              * this be a swarnx(), and not a SWARNX().
1169              */
1170 
1171             swarnx("%s: unknown child pid %lu exited",
1172                    function, (unsigned long)pid);
1173 
1174             continue;
1175          }
1176 
1177          if (child->exitingnormally)
1178             isunexpected = 0;
1179          else
1180             isunexpected = 1;
1181 
1182          proctype = child->type;
1183          switch (child->type) {
1184             case PROC_MONITOR:
1185                rusage = &sockscf.state.rusage_monitor;
1186                break;
1187 
1188             case PROC_NEGOTIATE:
1189                rusage = &sockscf.state.rusage_negotiate;
1190                break;
1191 
1192             case PROC_REQUEST:
1193                rusage = &sockscf.state.rusage_request;
1194                break;
1195 
1196             case PROC_IO:
1197                rusage = &sockscf.state.rusage_io;
1198                break;
1199 
1200             default:
1201                SERRX(child->type);
1202          }
1203 
1204          sum = *rusage;
1205 
1206          timeradd(&rusage->ru_utime, &thisrusage.ru_utime, &sum.ru_utime);
1207          timeradd(&rusage->ru_stime, &thisrusage.ru_stime, &sum.ru_stime);
1208          sum.ru_minflt   += thisrusage.ru_minflt;
1209          sum.ru_majflt   += thisrusage.ru_majflt;
1210          sum.ru_nswap    += thisrusage.ru_nswap;
1211          sum.ru_inblock  += thisrusage.ru_inblock;
1212          sum.ru_oublock  += thisrusage.ru_oublock;
1213          sum.ru_msgsnd   += thisrusage.ru_msgsnd;
1214          sum.ru_msgrcv   += thisrusage.ru_msgrcv;
1215          sum.ru_nsignals += thisrusage.ru_nsignals;
1216          sum.ru_nvcsw    += thisrusage.ru_nvcsw;
1217          sum.ru_nivcsw   += thisrusage.ru_nivcsw;
1218 
1219          *rusage = sum;
1220 
1221          slog(LOG_DEBUG, "%s: %s-child %lu exiting after %lds and %lu client%s",
1222               function,
1223               childtype2string(proctype),
1224               (unsigned long)pid,
1225               (long)socks_difftime(tnow, child->created),
1226               (unsigned long)child->sentc,
1227               (unsigned long)child->sentc == 1 ? "" : "s");
1228 
1229          log_rusage(child->type, pid, &thisrusage);
1230 
1231          removechild(pid);
1232       }
1233 
1234       if (isunexpected) {
1235          swarnx("%s: %s %lu exited unexpectedly %s %s",
1236                 function,
1237                 childtype2string(proctype),
1238                 (unsigned long)pid,
1239                 WIFSIGNALED(status) ? "on signal" : "",
1240                 WIFSIGNALED(status) ? signal2string(WTERMSIG(status)) : "");
1241 
1242          unexpecteddeath();
1243       }
1244    }
1245 
1246    SIGNAL_EPILOGUE(sig, si, errno_s);
1247 }
1248