File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / sudo / src / signal.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Sun Jun 15 16:12:55 2014 UTC (10 years ago) by misho
Branches: sudo, MAIN
CVS tags: v1_8_10p3_0, v1_8_10p3, HEAD
sudo v 1.8.10p3

    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(U_("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>