File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / sudo / src / exec.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Feb 21 16:23:02 2012 UTC (12 years, 4 months ago) by misho
Branches: sudo, MAIN
CVS tags: v1_8_3p2, HEAD
sudo

    1: /*
    2:  * Copyright (c) 2009-2011 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 <sys/param.h>
   21: #ifdef HAVE_SYS_SYSMACROS_H
   22: # include <sys/sysmacros.h>
   23: #endif
   24: #include <sys/socket.h>
   25: #include <sys/stat.h>
   26: #include <sys/time.h>
   27: #include <sys/wait.h>
   28: #include <sys/ioctl.h>
   29: #ifdef HAVE_SYS_SELECT_H
   30: # include <sys/select.h>
   31: #endif /* HAVE_SYS_SELECT_H */
   32: #include <stdio.h>
   33: #ifdef STDC_HEADERS
   34: # include <stdlib.h>
   35: # include <stddef.h>
   36: #else
   37: # ifdef HAVE_STDLIB_H
   38: #  include <stdlib.h>
   39: # endif
   40: #endif /* STDC_HEADERS */
   41: #ifdef HAVE_STRING_H
   42: # include <string.h>
   43: #endif /* HAVE_STRING_H */
   44: #ifdef HAVE_STRINGS_H
   45: # include <strings.h>
   46: #endif /* HAVE_STRINGS_H */
   47: #ifdef HAVE_UNISTD_H
   48: # include <unistd.h>
   49: #endif /* HAVE_UNISTD_H */
   50: #if TIME_WITH_SYS_TIME
   51: # include <time.h>
   52: #endif
   53: #ifdef HAVE_SETLOCALE
   54: # include <locale.h>
   55: #endif
   56: #include <errno.h>
   57: #include <fcntl.h>
   58: #include <signal.h>
   59: #include <termios.h>
   60: 
   61: #include "sudo.h"
   62: #include "sudo_exec.h"
   63: #include "sudo_plugin.h"
   64: #include "sudo_plugin_int.h"
   65: 
   66: /* Shared with exec_pty.c for use with handler(). */
   67: int signal_pipe[2];
   68: 
   69: /* We keep a tailq of signals to forward to child. */
   70: struct sigforward {
   71:     struct sigforward *prev, *next;
   72:     int signo;
   73: };
   74: TQ_DECLARE(sigforward)
   75: static struct sigforward_list sigfwd_list;
   76: 
   77: static int handle_signals(int fd, pid_t child, int log_io,
   78:     struct command_status *cstat);
   79: static void forward_signals(int fd);
   80: static void schedule_signal(int signo);
   81: 
   82: /*
   83:  * Like execve(2) but falls back to running through /bin/sh
   84:  * ala execvp(3) if we get ENOEXEC.
   85:  */
   86: int
   87: my_execve(const char *path, char *const argv[], char *const envp[])
   88: {
   89:     execve(path, argv, envp);
   90:     if (errno == ENOEXEC) {
   91: 	int argc;
   92: 	char **nargv;
   93: 
   94: 	for (argc = 0; argv[argc] != NULL; argc++)
   95: 	    continue;
   96: 	nargv = emalloc2(argc + 2, sizeof(char *));
   97: 	nargv[0] = "sh";
   98: 	nargv[1] = (char *)path;
   99: 	memcpy(nargv + 2, argv + 1, argc * sizeof(char *));
  100: 	execve(_PATH_BSHELL, nargv, envp);
  101: 	efree(nargv);
  102:     }
  103:     return -1;
  104: }
  105: 
  106: /*
  107:  * Fork and execute a command, returns the child's pid.
  108:  * Sends errno back on sv[1] if execve() fails.
  109:  */
  110: static int fork_cmnd(struct command_details *details, int sv[2])
  111: {
  112:     struct command_status cstat;
  113:     sigaction_t sa;
  114:     pid_t child;
  115: 
  116:     zero_bytes(&sa, sizeof(sa));
  117:     sigemptyset(&sa.sa_mask);
  118:     sa.sa_flags = SA_INTERRUPT; /* do not restart syscalls */
  119:     sa.sa_handler = handler;
  120:     sigaction(SIGCONT, &sa, NULL);
  121: 
  122:     child = fork();
  123:     switch (child) {
  124:     case -1:
  125: 	error(1, _("unable to fork"));
  126: 	break;
  127:     case 0:
  128: 	/* child */
  129: 	close(sv[0]);
  130: 	close(signal_pipe[0]);
  131: 	close(signal_pipe[1]);
  132: 	fcntl(sv[1], F_SETFD, FD_CLOEXEC);
  133: 	restore_signals();
  134: 	if (exec_setup(details, NULL, -1) == TRUE) {
  135: 	    /* headed for execve() */
  136: 	    if (details->closefrom >= 0)
  137: 		closefrom(details->closefrom);
  138: #ifdef HAVE_SELINUX
  139: 	    if (ISSET(details->flags, CD_RBAC_ENABLED))
  140: 		selinux_execve(details->command, details->argv, details->envp);
  141: 	    else
  142: #endif
  143: 		my_execve(details->command, details->argv, details->envp);
  144: 	}
  145: 	cstat.type = CMD_ERRNO;
  146: 	cstat.val = errno;
  147: 	send(sv[1], &cstat, sizeof(cstat), 0);
  148: 	_exit(1);
  149:     }
  150:     return child;
  151: }
  152: 
  153: static struct signal_state {
  154:     int signo;
  155:     sigaction_t sa;
  156: } saved_signals[] = {
  157:     { SIGALRM },
  158:     { SIGCHLD },
  159:     { SIGCONT },
  160:     { SIGHUP },
  161:     { SIGINT },
  162:     { SIGPIPE },
  163:     { SIGQUIT },
  164:     { SIGTERM },
  165:     { SIGTSTP },
  166:     { SIGTTIN },
  167:     { SIGTTOU },
  168:     { SIGUSR1 },
  169:     { SIGUSR2 },
  170:     { -1 }
  171: };
  172: 
  173: /*
  174:  * Save signal handler state so it can be restored before exec.
  175:  */
  176: void
  177: save_signals(void)
  178: {
  179:     struct signal_state *ss;
  180: 
  181:     for (ss = saved_signals; ss->signo != -1; ss++)
  182: 	sigaction(ss->signo, NULL, &ss->sa);
  183: }
  184: 
  185: /*
  186:  * Restore signal handlers to initial state.
  187:  */
  188: void
  189: restore_signals(void)
  190: {
  191:     struct signal_state *ss;
  192: 
  193:     for (ss = saved_signals; ss->signo != -1; ss++)
  194: 	sigaction(ss->signo, &ss->sa, NULL);
  195: }
  196: 
  197: /*
  198:  * Execute a command, potentially in a pty with I/O loggging.
  199:  * This is a little bit tricky due to how POSIX job control works and
  200:  * we fact that we have two different controlling terminals to deal with.
  201:  */
  202: int
  203: sudo_execve(struct command_details *details, struct command_status *cstat)
  204: {
  205:     int maxfd, n, nready, sv[2], log_io = FALSE;
  206:     const char *utmp_user = NULL;
  207:     fd_set *fdsr, *fdsw;
  208:     sigaction_t sa;
  209:     pid_t child;
  210: 
  211:     /* If running in background mode, fork and exit. */
  212:     if (ISSET(details->flags, CD_BACKGROUND)) {
  213: 	switch (fork()) {
  214: 	    case -1:
  215: 		cstat->type = CMD_ERRNO;
  216: 		cstat->val = errno;
  217: 		return -1;
  218: 	    case 0:
  219: 		/* child continues without controlling terminal */
  220: 		(void)setpgid(0, 0);
  221: 		break;
  222: 	    default:
  223: 		/* parent exits (but does not flush buffers) */
  224: 		_exit(0);
  225: 	}
  226:     }
  227: 
  228:     /*
  229:      * If we have an I/O plugin or the policy plugin has requested one, we
  230:      * need to allocate a pty.  It is OK to set log_io in the pty-only case
  231:      * as the io plugin tailqueue will be empty and no I/O logging will occur.
  232:      */
  233:     if (!tq_empty(&io_plugins) || ISSET(details->flags, CD_USE_PTY)) {
  234: 	log_io = TRUE;
  235: 	if (ISSET(details->flags, CD_SET_UTMP))
  236: 	    utmp_user = details->utmp_user ? details->utmp_user : user_details.username;
  237: 	sudo_debug(8, "allocate pty for I/O logging");
  238: 	pty_setup(details->euid, user_details.tty, utmp_user);
  239:     }
  240: 
  241:     /*
  242:      * We communicate with the child over a bi-directional pair of sockets.
  243:      * Parent sends signal info to child and child sends back wait status.
  244:      */
  245:     if (socketpair(PF_UNIX, SOCK_DGRAM, 0, sv) == -1)
  246: 	error(1, _("unable to create sockets"));
  247: 
  248:     /*
  249:      * We use a pipe to atomically handle signal notification within
  250:      * the select() loop.
  251:      */
  252:     if (pipe_nonblock(signal_pipe) != 0)
  253: 	error(1, _("unable to create pipe"));
  254: 
  255:     zero_bytes(&sa, sizeof(sa));
  256:     sigemptyset(&sa.sa_mask);
  257: 
  258:     /*
  259:      * Signals for forward to the child process (excluding SIGALRM and SIGCHLD).
  260:      * Note: HP-UX select() will not be interrupted if SA_RESTART set.
  261:      */
  262:     sa.sa_flags = SA_INTERRUPT; /* do not restart syscalls */
  263:     sa.sa_handler = handler;
  264:     sigaction(SIGALRM, &sa, NULL);
  265:     sigaction(SIGCHLD, &sa, NULL);
  266:     sigaction(SIGHUP, &sa, NULL);
  267:     sigaction(SIGINT, &sa, NULL);
  268:     sigaction(SIGPIPE, &sa, NULL);
  269:     sigaction(SIGQUIT, &sa, NULL);
  270:     sigaction(SIGTERM, &sa, NULL);
  271:     sigaction(SIGUSR1, &sa, NULL);
  272:     sigaction(SIGUSR2, &sa, NULL);
  273: 
  274:     /* Max fd we will be selecting on. */
  275:     maxfd = MAX(sv[0], signal_pipe[0]);
  276: 
  277:     /*
  278:      * Child will run the command in the pty, parent will pass data
  279:      * to and from pty.  Adjusts maxfd as needed.
  280:      */
  281:     if (log_io)
  282: 	child = fork_pty(details, sv, &maxfd);
  283:     else
  284: 	child = fork_cmnd(details, sv);
  285:     close(sv[1]);
  286: 
  287:     /* Set command timeout if specified. */
  288:     if (ISSET(details->flags, CD_SET_TIMEOUT))
  289: 	alarm(details->timeout);
  290: 
  291: #ifdef HAVE_SETLOCALE
  292:     /*
  293:      * I/O logging must be in the C locale for floating point numbers
  294:      * to be logged consistently.
  295:      */
  296:     setlocale(LC_ALL, "C");
  297: #endif
  298: 
  299:     /*
  300:      * In the event loop we pass input from user tty to master
  301:      * and pass output from master to stdout and IO plugin.
  302:      */
  303:     fdsr = (fd_set *)emalloc2(howmany(maxfd + 1, NFDBITS), sizeof(fd_mask));
  304:     fdsw = (fd_set *)emalloc2(howmany(maxfd + 1, NFDBITS), sizeof(fd_mask));
  305:     for (;;) {
  306: 	zero_bytes(fdsw, howmany(maxfd + 1, NFDBITS) * sizeof(fd_mask));
  307: 	zero_bytes(fdsr, howmany(maxfd + 1, NFDBITS) * sizeof(fd_mask));
  308: 
  309: 	FD_SET(signal_pipe[0], fdsr);
  310: 	FD_SET(sv[0], fdsr);
  311: 	if (!tq_empty(&sigfwd_list))
  312: 	    FD_SET(sv[0], fdsw);
  313: 	if (log_io)
  314: 	    fd_set_iobs(fdsr, fdsw); /* XXX - better name */
  315: 	nready = select(maxfd + 1, fdsr, fdsw, NULL, NULL);
  316: 	if (nready == -1) {
  317: 	    if (errno == EINTR)
  318: 		continue;
  319: 	    error(1, _("select failed"));
  320: 	}
  321: 	if (FD_ISSET(sv[0], fdsw)) {
  322: 	    forward_signals(sv[0]);
  323: 	}
  324: 	if (FD_ISSET(signal_pipe[0], fdsr)) {
  325: 	    n = handle_signals(signal_pipe[0], child, log_io, cstat);
  326: 	    if (n == 0) {
  327: 		/* Child has exited, cstat is set, we are done. */
  328: 		goto done;
  329: 	    }
  330: 	    if (n == -1) {
  331: 		/* Error reading signal_pipe[0], should not happen. */
  332: 		break;
  333: 	    }
  334: 	    /* Restart event loop so signals get sent to child immediately. */
  335: 	    continue;
  336: 	}
  337: 	if (FD_ISSET(sv[0], fdsr)) {
  338: 	    /* read child status */
  339: 	    n = recv(sv[0], cstat, sizeof(*cstat), 0);
  340: 	    if (n == -1) {
  341: 		if (errno == EINTR)
  342: 		    continue;
  343: 		/*
  344: 		 * If not logging I/O we will receive ECONNRESET when
  345: 		 * the command is executed.  It is safe to ignore this.
  346: 		 */
  347: 		if (log_io && errno != EAGAIN) {
  348: 		    cstat->type = CMD_ERRNO;
  349: 		    cstat->val = errno;
  350: 		    break;
  351: 		}
  352: 	    }
  353: 	    if (cstat->type == CMD_WSTATUS) {
  354: 		if (WIFSTOPPED(cstat->val)) {
  355: 		    /* Suspend parent and tell child how to resume on return. */
  356: 		    sudo_debug(8, "child stopped, suspending parent");
  357: 		    n = suspend_parent(WSTOPSIG(cstat->val));
  358: 		    schedule_signal(n);
  359: 		    continue;
  360: 		} else {
  361: 		    /* Child exited or was killed, either way we are done. */
  362: 		    break;
  363: 		}
  364: 	    } else if (cstat->type == CMD_ERRNO) {
  365: 		/* Child was unable to execute command or broken pipe. */
  366: 		break;
  367: 	    }
  368: 	}
  369: 
  370: 	if (perform_io(fdsr, fdsw, cstat) != 0) {
  371: 	    /* I/O error, kill child if still alive and finish. */
  372: 	    schedule_signal(SIGKILL);
  373: 	    forward_signals(sv[0]);
  374: 	    break;
  375: 	}
  376:     }
  377: 
  378:     if (log_io) {
  379: 	/* Flush any remaining output and free pty-related memory. */
  380: 	pty_close(cstat);
  381:    }
  382: 
  383: #ifdef HAVE_SELINUX
  384:     if (ISSET(details->flags, CD_RBAC_ENABLED)) {
  385: 	/* This is probably not needed in log_io mode. */
  386: 	if (selinux_restore_tty() != 0)
  387: 	    warningx(_("unable to restore tty label"));
  388:     }
  389: #endif
  390: 
  391: done:
  392:     efree(fdsr);
  393:     efree(fdsw);
  394:     while (!tq_empty(&sigfwd_list)) {
  395: 	struct sigforward *sigfwd = tq_first(&sigfwd_list);
  396: 	tq_remove(&sigfwd_list, sigfwd);
  397: 	efree(sigfwd);
  398:     }
  399: 
  400:     return cstat->type == CMD_ERRNO ? -1 : 0;
  401: }
  402: 
  403: /*
  404:  * Read signals on fd written to by handler().
  405:  * Returns -1 on error, 0 on child exit, else 1.
  406:  */
  407: static int
  408: handle_signals(int fd, pid_t child, int log_io, struct command_status *cstat)
  409: {
  410:     unsigned char signo;
  411:     ssize_t nread;
  412:     int status;
  413:     pid_t pid;
  414: 
  415:     for (;;) {
  416: 	/* read signal pipe */
  417: 	nread = read(signal_pipe[0], &signo, sizeof(signo));
  418: 	if (nread <= 0) {
  419: 	    /* It should not be possible to get EOF but just in case. */
  420: 	    if (nread == 0)
  421: 		errno = ECONNRESET;
  422: 	    /* Restart if interrupted by signal so the pipe doesn't fill. */
  423: 	    if (errno == EINTR)
  424: 		continue;
  425: 	    /* If pipe is empty, we are done. */
  426: 	    if (errno == EAGAIN)
  427: 		break;
  428: 	    sudo_debug(9, "error reading signal pipe %s", strerror(errno));
  429: 	    cstat->type = CMD_ERRNO;
  430: 	    cstat->val = errno;
  431: 	    return -1;
  432: 	}
  433: 	sudo_debug(9, "received signal %d", signo);
  434: 	if (signo == SIGCHLD) {
  435: 	    /*
  436: 	     * If logging I/O, child is the intermediate process,
  437: 	     * otherwise it is the command itself.
  438: 	     */
  439: 	    do {
  440: 		pid = waitpid(child, &status, WUNTRACED|WNOHANG);
  441: 	    } while (pid == -1 && errno == EINTR);
  442: 	    if (pid == child) {
  443: 		/* If not logging I/O and child has exited we are done. */
  444: 		if (!log_io) {
  445: 		    if (WIFSTOPPED(status)) {
  446: 			/*
  447: 			 * Save the controlling terminal's process group
  448: 			 * so we can restore it after we resume.
  449: 			 */
  450: 			pid_t saved_pgrp = (pid_t)-1;
  451: 			int fd = open(_PATH_TTY, O_RDWR|O_NOCTTY, 0);
  452: 			if (fd != -1)
  453: 			    saved_pgrp = tcgetpgrp(fd);
  454: 			if (kill(getpid(), WSTOPSIG(status)) != 0) {
  455: 			    warning("kill(%d, %d)", (int)getpid(),
  456: 				WSTOPSIG(status));
  457: 			}
  458: 			if (fd != -1) {
  459: 			    if (saved_pgrp != (pid_t)-1)
  460: 				(void)tcsetpgrp(fd, saved_pgrp);
  461: 			    close(fd);
  462: 			}
  463: 		    } else {
  464: 			/* Child has exited, we are done. */
  465: 			cstat->type = CMD_WSTATUS;
  466: 			cstat->val = status;
  467: 			return 0;
  468: 		    }
  469: 		}
  470: 		/* Else we get ECONNRESET on sv[0] if child dies. */
  471: 	    }
  472: 	} else {
  473: 	    if (log_io) {
  474: 		/* Schedule signo to be forwared to the child. */
  475: 		schedule_signal(signo);
  476: 	    } else {
  477: 		/* Nothing listening on sv[0], send directly. */
  478: 		if (signo == SIGALRM)
  479: 		    terminate_child(child, FALSE);
  480: 		else if (kill(child, signo) != 0)
  481: 		    warning("kill(%d, %d)", (int)child, signo);
  482: 	    }
  483: 	}
  484:     }
  485:     return 1;
  486: }
  487: 
  488: /*
  489:  * Forward signals in sigfwd_list to child listening on fd.
  490:  */
  491: static void
  492: forward_signals(int sock)
  493: {
  494:     struct sigforward *sigfwd;
  495:     struct command_status cstat;
  496:     ssize_t nsent;
  497: 
  498:     while (!tq_empty(&sigfwd_list)) {
  499: 	sigfwd = tq_first(&sigfwd_list);
  500: 	sudo_debug(9, "sending signal %d to child over backchannel",
  501: 	    sigfwd->signo);
  502: 	cstat.type = CMD_SIGNO;
  503: 	cstat.val = sigfwd->signo;
  504: 	do {
  505: 	    nsent = send(sock, &cstat, sizeof(cstat), 0);
  506: 	} while (nsent == -1 && errno == EINTR);
  507: 	tq_remove(&sigfwd_list, sigfwd);
  508: 	efree(sigfwd);
  509: 	if (nsent != sizeof(cstat)) {
  510: 	    if (errno == EPIPE) {
  511: 		/* Other end of socket gone, empty out sigfwd_list. */
  512: 		while (!tq_empty(&sigfwd_list)) {
  513: 		    sigfwd = tq_first(&sigfwd_list);
  514: 		    tq_remove(&sigfwd_list, sigfwd);
  515: 		    efree(sigfwd);
  516: 		}
  517: 	    }
  518: 	    break;
  519: 	}
  520:     }
  521: }
  522: 
  523: /*
  524:  * Schedule a signal to be forwared.
  525:  */
  526: static void
  527: schedule_signal(int signo)
  528: {
  529:     struct sigforward *sigfwd;
  530: 
  531:     sigfwd = emalloc(sizeof(*sigfwd));
  532:     sigfwd->prev = sigfwd;
  533:     sigfwd->next = NULL;
  534:     sigfwd->signo = signo;
  535:     tq_append(&sigfwd_list, sigfwd);
  536: }
  537: 
  538: /*
  539:  * Generic handler for signals passed from parent -> child.
  540:  * The other end of signal_pipe is checked in the main event loop.
  541:  */
  542: void
  543: handler(int s)
  544: {
  545:     unsigned char signo = (unsigned char)s;
  546: 
  547:     /*
  548:      * The pipe is non-blocking, if we overflow the kernel's pipe
  549:      * buffer we drop the signal.  This is not a problem in practice.
  550:      */
  551:     if (write(signal_pipe[1], &signo, sizeof(signo)) == -1)
  552: 	/* shut up glibc */;
  553: }
  554: 
  555: /*
  556:  * Open a pipe and make both ends non-blocking.
  557:  * Returns 0 on success and -1 on error.
  558:  */
  559: int
  560: pipe_nonblock(int fds[2])
  561: {
  562:     int flags, rval;
  563: 
  564:     rval = pipe(fds);
  565:     if (rval != -1) {
  566: 	flags = fcntl(fds[0], F_GETFL, 0);
  567: 	if (flags != -1 && !ISSET(flags, O_NONBLOCK))
  568: 	    rval = fcntl(fds[0], F_SETFL, flags | O_NONBLOCK);
  569: 	if (rval != -1) {
  570: 	    flags = fcntl(fds[1], F_GETFL, 0);
  571: 	    if (flags != -1 && !ISSET(flags, O_NONBLOCK))
  572: 		rval = fcntl(fds[1], F_SETFL, flags | O_NONBLOCK);
  573: 	}
  574: 	if (rval == -1) {
  575: 	    close(fds[0]);
  576: 	    close(fds[1]);
  577: 	}
  578:     }
  579: 
  580:     return rval;
  581: }

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