Annotation of embedaddon/sudo/src/signal.c, revision 1.1

1.1     ! misho       1: /*
        !             2:  * Copyright (c) 2009-2013 Todd C. Miller <Todd.Miller@courtesan.com>
        !             3:  *
        !             4:  * Permission to use, copy, modify, and distribute this software for any
        !             5:  * purpose with or without fee is hereby granted, provided that the above
        !             6:  * copyright notice and this permission notice appear in all copies.
        !             7:  *
        !             8:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
        !             9:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
        !            10:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
        !            11:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
        !            12:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
        !            13:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
        !            14:  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
        !            15:  */
        !            16: 
        !            17: #include <config.h>
        !            18: 
        !            19: #include <sys/types.h>
        !            20: #include <stdio.h>
        !            21: #ifdef STDC_HEADERS
        !            22: # include <stdlib.h>
        !            23: # include <stddef.h>
        !            24: #else
        !            25: # ifdef HAVE_STDLIB_H
        !            26: #  include <stdlib.h>
        !            27: # endif
        !            28: #endif /* STDC_HEADERS */
        !            29: #ifdef HAVE_STRING_H
        !            30: # include <string.h>
        !            31: #endif /* HAVE_STRING_H */
        !            32: #ifdef HAVE_STRINGS_H
        !            33: # include <strings.h>
        !            34: #endif /* HAVE_STRINGS_H */
        !            35: #ifdef HAVE_UNISTD_H
        !            36: # include <unistd.h>
        !            37: #endif /* HAVE_UNISTD_H */
        !            38: #include <errno.h>
        !            39: #include <signal.h>
        !            40: 
        !            41: #include "sudo.h"
        !            42: 
        !            43: int signal_pipe[2];
        !            44: 
        !            45: static struct signal_state {
        !            46:     int signo;
        !            47:     int restore;
        !            48:     sigaction_t sa;
        !            49: } saved_signals[] = {
        !            50:     { SIGALRM },       /* SAVED_SIGALRM */
        !            51:     { SIGCHLD },       /* SAVED_SIGCHLD */
        !            52:     { SIGCONT },       /* SAVED_SIGCONT */
        !            53:     { SIGHUP },                /* SAVED_SIGHUP */
        !            54:     { SIGINT },                /* SAVED_SIGINT */
        !            55:     { SIGPIPE },       /* SAVED_SIGPIPE */
        !            56:     { SIGQUIT },       /* SAVED_SIGQUIT */
        !            57:     { SIGTERM },       /* SAVED_SIGTERM */
        !            58:     { SIGTSTP },       /* SAVED_SIGTSTP */
        !            59:     { SIGTTIN },       /* SAVED_SIGTTIN */
        !            60:     { SIGTTOU },       /* SAVED_SIGTTOU */
        !            61:     { SIGUSR1 },       /* SAVED_SIGUSR1 */
        !            62:     { SIGUSR2 },       /* SAVED_SIGUSR2 */
        !            63:     { -1 }
        !            64: };
        !            65: 
        !            66: /*
        !            67:  * Save signal handler state so it can be restored before exec.
        !            68:  */
        !            69: void
        !            70: save_signals(void)
        !            71: {
        !            72:     struct signal_state *ss;
        !            73:     debug_decl(save_signals, SUDO_DEBUG_MAIN)
        !            74: 
        !            75:     for (ss = saved_signals; ss->signo != -1; ss++)
        !            76:        sigaction(ss->signo, NULL, &ss->sa);
        !            77: 
        !            78:     debug_return;
        !            79: }
        !            80: 
        !            81: /*
        !            82:  * Restore signal handlers to initial state for exec.
        !            83:  */
        !            84: void
        !            85: restore_signals(void)
        !            86: {
        !            87:     struct signal_state *ss;
        !            88:     debug_decl(restore_signals, SUDO_DEBUG_MAIN)
        !            89: 
        !            90:     for (ss = saved_signals; ss->signo != -1; ss++) {
        !            91:        if (ss->restore)
        !            92:            sigaction(ss->signo, &ss->sa, NULL);
        !            93:     }
        !            94: 
        !            95:     debug_return;
        !            96: }
        !            97: 
        !            98: static void
        !            99: sudo_handler(int signo)
        !           100: {
        !           101:     /*
        !           102:      * The pipe is non-blocking, if we overflow the kernel's pipe
        !           103:      * buffer we drop the signal.  This is not a problem in practice.
        !           104:      */
        !           105:     ignore_result(write(signal_pipe[1], &signo, sizeof(signo)));
        !           106: }
        !           107: 
        !           108: /*
        !           109:  * Trap tty-generated (and other) signals so we can't be killed before
        !           110:  * calling the policy close function.  The signal pipe will be drained
        !           111:  * in sudo_execute() before running the command and new handlers will
        !           112:  * be installed in the parent.
        !           113:  */
        !           114: void
        !           115: init_signals(void)
        !           116: {
        !           117:     struct sigaction sa;
        !           118:     struct signal_state *ss;
        !           119:     debug_decl(init_signals, SUDO_DEBUG_MAIN)
        !           120: 
        !           121:     /*
        !           122:      * We use a pipe to atomically handle signal notification within
        !           123:      * the select() loop without races (we may not have pselect()).
        !           124:      */
        !           125:     if (pipe_nonblock(signal_pipe) != 0)
        !           126:        fatal(_("unable to create pipe"));
        !           127: 
        !           128:     memset(&sa, 0, sizeof(sa));
        !           129:     sigfillset(&sa.sa_mask);
        !           130:     sa.sa_flags = SA_RESTART;
        !           131:     sa.sa_handler = sudo_handler;
        !           132: 
        !           133:     for (ss = saved_signals; ss->signo > 0; ss++) {
        !           134:        switch (ss->signo) {
        !           135:            case SIGCHLD:
        !           136:            case SIGCONT:
        !           137:            case SIGPIPE:
        !           138:            case SIGTTIN:
        !           139:            case SIGTTOU:
        !           140:                /* Don't install these until exec time. */
        !           141:                break;
        !           142:            default:
        !           143:                if (ss->sa.sa_handler != SIG_IGN)
        !           144:                    sigaction(ss->signo, &sa, NULL);
        !           145:                break;
        !           146:        }
        !           147:     }
        !           148:     debug_return;
        !           149: }
        !           150: 
        !           151: /*
        !           152:  * Like sigaction() but sets restore flag in saved_signals[]
        !           153:  * if needed.
        !           154:  */
        !           155: int
        !           156: sudo_sigaction(int signo, struct sigaction *sa, struct sigaction *osa)
        !           157: {
        !           158:     struct signal_state *ss;
        !           159:     int rval;
        !           160:     debug_decl(sudo_sigaction, SUDO_DEBUG_MAIN)
        !           161: 
        !           162:     for (ss = saved_signals; ss->signo > 0; ss++) {
        !           163:        if (ss->signo == signo) {
        !           164:            /* If signal was or now is ignored, restore old handler on exec. */
        !           165:            if (ss->sa.sa_handler == SIG_IGN || sa->sa_handler == SIG_IGN) {
        !           166:                sudo_debug_printf(SUDO_DEBUG_INFO,
        !           167:                    "will restore signal %d on exec", signo);
        !           168:                ss->restore = true;
        !           169:            }
        !           170:            break;
        !           171:        }
        !           172:     }
        !           173:     rval = sigaction(signo, sa, osa);
        !           174: 
        !           175:     debug_return_int(rval);
        !           176: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>