Annotation of embedaddon/sudo/src/exec_pty.c, revision 1.1.1.4

1.1       misho       1: /*
1.1.1.4 ! misho       2:  * Copyright (c) 2009-2013 Todd C. Miller <Todd.Miller@courtesan.com>
1.1       misho       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: #ifdef HAVE_SYS_SYSMACROS_H
                     21: # include <sys/sysmacros.h>
                     22: #endif
                     23: #include <sys/socket.h>
                     24: #include <sys/time.h>
                     25: #include <sys/wait.h>
                     26: #include <sys/ioctl.h>
                     27: #ifdef HAVE_SYS_SELECT_H
                     28: # include <sys/select.h>
                     29: #endif /* HAVE_SYS_SELECT_H */
                     30: #include <stdio.h>
                     31: #ifdef STDC_HEADERS
                     32: # include <stdlib.h>
                     33: # include <stddef.h>
                     34: #else
                     35: # ifdef HAVE_STDLIB_H
                     36: #  include <stdlib.h>
                     37: # endif
                     38: #endif /* STDC_HEADERS */
                     39: #ifdef HAVE_STRING_H
                     40: # if defined(HAVE_MEMORY_H) && !defined(STDC_HEADERS)
                     41: #  include <memory.h>
                     42: # endif
                     43: # include <string.h>
                     44: #endif /* HAVE_STRING_H */
                     45: #ifdef HAVE_STRINGS_H
                     46: # include <strings.h>
                     47: #endif /* HAVE_STRINGS_H */
                     48: #ifdef HAVE_UNISTD_H
                     49: # include <unistd.h>
                     50: #endif /* HAVE_UNISTD_H */
                     51: #if TIME_WITH_SYS_TIME
                     52: # include <time.h>
                     53: #endif
                     54: #include <errno.h>
                     55: #include <fcntl.h>
                     56: #include <signal.h>
                     57: #include <termios.h>
                     58: 
                     59: #include "sudo.h"
                     60: #include "sudo_exec.h"
                     61: #include "sudo_plugin.h"
                     62: #include "sudo_plugin_int.h"
                     63: 
                     64: #define SFD_STDIN      0
                     65: #define SFD_STDOUT     1
                     66: #define SFD_STDERR     2
                     67: #define SFD_MASTER     3
                     68: #define SFD_SLAVE      4
                     69: #define SFD_USERTTY    5
                     70: 
                     71: #define TERM_COOKED    0
                     72: #define TERM_RAW       1
                     73: 
                     74: /* Compatibility with older tty systems. */
                     75: #if !defined(TIOCGWINSZ) && defined(TIOCGSIZE)
                     76: # define TIOCGWINSZ    TIOCGSIZE
                     77: # define TIOCSWINSZ    TIOCSSIZE
                     78: # define winsize       ttysize
                     79: #endif
                     80: 
                     81: struct io_buffer {
                     82:     struct io_buffer *next;
                     83:     int len; /* buffer length (how much produced) */
                     84:     int off; /* write position (how much already consumed) */
                     85:     int rfd;  /* reader (producer) */
                     86:     int wfd; /* writer (consumer) */
1.1.1.2   misho      87:     bool (*action)(const char *buf, unsigned int len);
1.1.1.4 ! misho      88:     char buf[32 * 1024];
1.1       misho      89: };
                     90: 
                     91: static char slavename[PATH_MAX];
1.1.1.2   misho      92: static bool foreground, pipeline, tty_initialized;
1.1       misho      93: static int io_fds[6] = { -1, -1, -1, -1, -1, -1};
                     94: static int ttymode = TERM_COOKED;
1.1.1.4 ! misho      95: static pid_t ppgrp, cmnd_pgrp, mon_pgrp;
1.1       misho      96: static sigset_t ttyblock;
                     97: static struct io_buffer *iobufs;
                     98: 
                     99: static void flush_output(void);
                    100: static int exec_monitor(struct command_details *details, int backchannel);
1.1.1.4 ! misho     101: static void exec_pty(struct command_details *details,
        !           102:     struct command_status *cstat, int *errfd);
1.1       misho     103: static void sigwinch(int s);
                    104: static void sync_ttysize(int src, int dst);
1.1.1.2   misho     105: static void deliver_signal(pid_t pid, int signo, bool from_parent);
1.1       misho     106: static int safe_close(int fd);
1.1.1.2   misho     107: static void check_foreground(void);
1.1       misho     108: 
                    109: /*
1.1.1.4 ! misho     110:  * Cleanup hook for fatal()/fatalx()
1.1       misho     111:  */
1.1.1.4 ! misho     112: static void
        !           113: pty_cleanup(void)
1.1       misho     114: {
1.1.1.2   misho     115:     debug_decl(cleanup, SUDO_DEBUG_EXEC);
                    116: 
                    117:     if (!tq_empty(&io_plugins) && io_fds[SFD_USERTTY] != -1) {
                    118:        check_foreground();
                    119:        if (foreground)
                    120:            term_restore(io_fds[SFD_USERTTY], 0);
                    121:     }
1.1       misho     122: #ifdef HAVE_SELINUX
                    123:     selinux_restore_tty();
                    124: #endif
                    125:     utmp_logout(slavename, 0); /* XXX - only if CD_SET_UTMP */
1.1.1.2   misho     126: 
                    127:     debug_return;
1.1       misho     128: }
                    129: 
                    130: /*
1.1.1.3   misho     131:  * Generic handler for signals recieved by the monitor process.
                    132:  * The other end of signal_pipe is checked in the monitor event loop.
                    133:  */
                    134: #ifdef SA_SIGINFO
                    135: void
                    136: mon_handler(int s, siginfo_t *info, void *context)
                    137: {
                    138:     unsigned char signo = (unsigned char)s;
                    139: 
                    140:     /*
                    141:      * If the signal came from the command we ran, just ignore
                    142:      * it since we don't want the command to indirectly kill itself.
                    143:      * This can happen with, e.g. BSD-derived versions of reboot
                    144:      * that call kill(-1, SIGTERM) to kill all other processes.
                    145:      */
                    146:     if (info != NULL && info->si_code == SI_USER && info->si_pid == cmnd_pid)
                    147:            return;
                    148: 
                    149:     /*
                    150:      * The pipe is non-blocking, if we overflow the kernel's pipe
                    151:      * buffer we drop the signal.  This is not a problem in practice.
                    152:      */
                    153:     ignore_result(write(signal_pipe[1], &signo, sizeof(signo)));
                    154: }
                    155: #else
                    156: void
                    157: mon_handler(int s)
                    158: {
                    159:     unsigned char signo = (unsigned char)s;
                    160: 
                    161:     /*
                    162:      * The pipe is non-blocking, if we overflow the kernel's pipe
                    163:      * buffer we drop the signal.  This is not a problem in practice.
                    164:      */
                    165:     ignore_result(write(signal_pipe[1], &signo, sizeof(signo)));
                    166: }
                    167: #endif
                    168: 
                    169: /*
1.1       misho     170:  * Allocate a pty if /dev/tty is a tty.
                    171:  * Fills in io_fds[SFD_USERTTY], io_fds[SFD_MASTER], io_fds[SFD_SLAVE]
                    172:  * and slavename globals.
                    173:  */
                    174: void
                    175: pty_setup(uid_t uid, const char *tty, const char *utmp_user)
                    176: {
1.1.1.2   misho     177:     debug_decl(pty_setup, SUDO_DEBUG_EXEC);
                    178: 
1.1       misho     179:     io_fds[SFD_USERTTY] = open(_PATH_TTY, O_RDWR|O_NOCTTY, 0);
                    180:     if (io_fds[SFD_USERTTY] != -1) {
                    181:        if (!get_pty(&io_fds[SFD_MASTER], &io_fds[SFD_SLAVE],
                    182:            slavename, sizeof(slavename), uid))
1.1.1.4 ! misho     183:            fatal(_("unable to allocate pty"));
1.1       misho     184:        /* Add entry to utmp/utmpx? */
                    185:        if (utmp_user != NULL)
                    186:            utmp_login(tty, slavename, io_fds[SFD_SLAVE], utmp_user);
                    187:     }
1.1.1.2   misho     188: 
                    189:     debug_return;
1.1       misho     190: }
                    191: 
                    192: /* Call I/O plugin tty input log method. */
1.1.1.2   misho     193: static bool
1.1       misho     194: log_ttyin(const char *buf, unsigned int n)
                    195: {
                    196:     struct plugin_container *plugin;
                    197:     sigset_t omask;
1.1.1.2   misho     198:     bool rval = true;
                    199:     debug_decl(log_ttyin, SUDO_DEBUG_EXEC);
1.1       misho     200: 
                    201:     sigprocmask(SIG_BLOCK, &ttyblock, &omask);
                    202:     tq_foreach_fwd(&io_plugins, plugin) {
                    203:        if (plugin->u.io->log_ttyin) {
                    204:            if (!plugin->u.io->log_ttyin(buf, n)) {
1.1.1.2   misho     205:                rval = false;
1.1       misho     206:                break;
                    207:            }
                    208:        }
                    209:     }
                    210:     sigprocmask(SIG_SETMASK, &omask, NULL);
1.1.1.2   misho     211: 
                    212:     debug_return_bool(rval);
1.1       misho     213: }
                    214: 
                    215: /* Call I/O plugin stdin log method. */
1.1.1.2   misho     216: static bool
1.1       misho     217: log_stdin(const char *buf, unsigned int n)
                    218: {
                    219:     struct plugin_container *plugin;
                    220:     sigset_t omask;
1.1.1.2   misho     221:     bool rval = true;
                    222:     debug_decl(log_stdin, SUDO_DEBUG_EXEC);
1.1       misho     223: 
                    224:     sigprocmask(SIG_BLOCK, &ttyblock, &omask);
                    225:     tq_foreach_fwd(&io_plugins, plugin) {
                    226:        if (plugin->u.io->log_stdin) {
                    227:            if (!plugin->u.io->log_stdin(buf, n)) {
1.1.1.2   misho     228:                rval = false;
1.1       misho     229:                break;
                    230:            }
                    231:        }
                    232:     }
                    233:     sigprocmask(SIG_SETMASK, &omask, NULL);
1.1.1.2   misho     234: 
                    235:     debug_return_bool(rval);
1.1       misho     236: }
                    237: 
                    238: /* Call I/O plugin tty output log method. */
1.1.1.2   misho     239: static bool
1.1       misho     240: log_ttyout(const char *buf, unsigned int n)
                    241: {
                    242:     struct plugin_container *plugin;
                    243:     sigset_t omask;
1.1.1.2   misho     244:     bool rval = true;
                    245:     debug_decl(log_ttyout, SUDO_DEBUG_EXEC);
1.1       misho     246: 
                    247:     sigprocmask(SIG_BLOCK, &ttyblock, &omask);
                    248:     tq_foreach_fwd(&io_plugins, plugin) {
                    249:        if (plugin->u.io->log_ttyout) {
                    250:            if (!plugin->u.io->log_ttyout(buf, n)) {
1.1.1.2   misho     251:                rval = false;
1.1       misho     252:                break;
                    253:            }
                    254:        }
                    255:     }
                    256:     sigprocmask(SIG_SETMASK, &omask, NULL);
1.1.1.2   misho     257: 
                    258:     debug_return_bool(rval);
1.1       misho     259: }
                    260: 
                    261: /* Call I/O plugin stdout log method. */
1.1.1.2   misho     262: static bool
1.1       misho     263: log_stdout(const char *buf, unsigned int n)
                    264: {
                    265:     struct plugin_container *plugin;
                    266:     sigset_t omask;
1.1.1.2   misho     267:     bool rval = true;
                    268:     debug_decl(log_stdout, SUDO_DEBUG_EXEC);
1.1       misho     269: 
                    270:     sigprocmask(SIG_BLOCK, &ttyblock, &omask);
                    271:     tq_foreach_fwd(&io_plugins, plugin) {
                    272:        if (plugin->u.io->log_stdout) {
                    273:            if (!plugin->u.io->log_stdout(buf, n)) {
1.1.1.2   misho     274:                rval = false;
1.1       misho     275:                break;
                    276:            }
                    277:        }
                    278:     }
                    279:     sigprocmask(SIG_SETMASK, &omask, NULL);
1.1.1.2   misho     280: 
                    281:     debug_return_bool(rval);
1.1       misho     282: }
                    283: 
                    284: /* Call I/O plugin stderr log method. */
1.1.1.2   misho     285: static bool
1.1       misho     286: log_stderr(const char *buf, unsigned int n)
                    287: {
                    288:     struct plugin_container *plugin;
                    289:     sigset_t omask;
1.1.1.2   misho     290:     bool rval = true;
                    291:     debug_decl(log_stderr, SUDO_DEBUG_EXEC);
1.1       misho     292: 
                    293:     sigprocmask(SIG_BLOCK, &ttyblock, &omask);
                    294:     tq_foreach_fwd(&io_plugins, plugin) {
                    295:        if (plugin->u.io->log_stderr) {
                    296:            if (!plugin->u.io->log_stderr(buf, n)) {
1.1.1.2   misho     297:                rval = false;
1.1       misho     298:                break;
                    299:            }
                    300:        }
                    301:     }
                    302:     sigprocmask(SIG_SETMASK, &omask, NULL);
1.1.1.2   misho     303: 
                    304:     debug_return_bool(rval);
1.1       misho     305: }
                    306: 
                    307: /*
                    308:  * Check whether we are running in the foregroup.
                    309:  * Updates the foreground global and does lazy init of the
                    310:  * the pty slave as needed.
                    311:  */
                    312: static void
                    313: check_foreground(void)
                    314: {
1.1.1.2   misho     315:     debug_decl(check_foreground, SUDO_DEBUG_EXEC);
                    316: 
1.1       misho     317:     if (io_fds[SFD_USERTTY] != -1) {
                    318:        foreground = tcgetpgrp(io_fds[SFD_USERTTY]) == ppgrp;
                    319:        if (foreground && !tty_initialized) {
                    320:            if (term_copy(io_fds[SFD_USERTTY], io_fds[SFD_SLAVE])) {
1.1.1.2   misho     321:                tty_initialized = true;
1.1       misho     322:                sync_ttysize(io_fds[SFD_USERTTY], io_fds[SFD_SLAVE]);
                    323:            }
                    324:        }
                    325:     }
1.1.1.2   misho     326: 
                    327:     debug_return;
1.1       misho     328: }
                    329: 
                    330: /*
                    331:  * Suspend sudo if the underlying command is suspended.
1.1.1.3   misho     332:  * Returns SIGCONT_FG if the command should be resumed in the
1.1       misho     333:  * foreground or SIGCONT_BG if it is a background process.
                    334:  */
                    335: int
                    336: suspend_parent(int signo)
                    337: {
1.1.1.3   misho     338:     char signame[SIG2STR_MAX];
1.1       misho     339:     sigaction_t sa, osa;
1.1.1.4 ! misho     340:     int n, rval = 0;
1.1.1.2   misho     341:     debug_decl(suspend_parent, SUDO_DEBUG_EXEC);
1.1       misho     342: 
                    343:     switch (signo) {
                    344:     case SIGTTOU:
                    345:     case SIGTTIN:
                    346:        /*
1.1.1.4 ! misho     347:         * If sudo is already the foreground process, just resume the command
        !           348:         * in the foreground.  If not, we'll suspend sudo and resume later.
1.1       misho     349:         */
                    350:        if (!foreground)
                    351:            check_foreground();
                    352:        if (foreground) {
                    353:            if (ttymode != TERM_RAW) {
                    354:                do {
                    355:                    n = term_raw(io_fds[SFD_USERTTY], 0);
                    356:                } while (!n && errno == EINTR);
                    357:                ttymode = TERM_RAW;
                    358:            }
1.1.1.3   misho     359:            rval = SIGCONT_FG; /* resume command in foreground */
1.1       misho     360:            break;
                    361:        }
                    362:        /* FALLTHROUGH */
                    363:     case SIGSTOP:
                    364:     case SIGTSTP:
                    365:        /* Flush any remaining output before suspending. */
                    366:        flush_output();
                    367: 
                    368:        /* Restore original tty mode before suspending. */
1.1.1.4 ! misho     369:        if (ttymode != TERM_COOKED) {
1.1       misho     370:            do {
                    371:                n = term_restore(io_fds[SFD_USERTTY], 0);
                    372:            } while (!n && errno == EINTR);
                    373:        }
                    374: 
1.1.1.3   misho     375:        if (sig2str(signo, signame) == -1)
                    376:            snprintf(signame, sizeof(signame), "%d", signo);
                    377: 
                    378:        /* Suspend self and continue command when we resume. */
1.1.1.4 ! misho     379:        if (signo != SIGSTOP) {
        !           380:            memset(&sa, 0, sizeof(sa));
        !           381:            sigemptyset(&sa.sa_mask);
        !           382:            sa.sa_flags = SA_RESTART;
        !           383:            sa.sa_handler = SIG_DFL;
        !           384:            sudo_sigaction(signo, &sa, &osa);
        !           385:        }
1.1.1.3   misho     386:        sudo_debug_printf(SUDO_DEBUG_INFO, "kill parent SIG%s", signame);
1.1       misho     387:        if (killpg(ppgrp, signo) != 0)
1.1.1.3   misho     388:            warning("killpg(%d, SIG%s)", (int)ppgrp, signame);
1.1       misho     389: 
                    390:        /* Check foreground/background status on resume. */
                    391:        check_foreground();
                    392: 
                    393:        /*
1.1.1.4 ! misho     394:         * We always resume the command in the foreground if sudo itself
        !           395:         * is the foreground process.  This helps work around poorly behaved
        !           396:         * programs that catch SIGTTOU/SIGTTIN but suspend themselves with
        !           397:         * SIGSTOP.  At worst, sudo will go into the background but upon
        !           398:         * resume the command will be runnable.  Otherwise, we can get into
        !           399:         * a situation where the command will immediately suspend itself.
1.1       misho     400:         */
1.1.1.2   misho     401:        sudo_debug_printf(SUDO_DEBUG_INFO, "parent is in %s, ttymode %d -> %d",
1.1.1.4 ! misho     402:            foreground ? "foreground" : "background", ttymode,
        !           403:            foreground ? TERM_RAW : TERM_COOKED);
1.1       misho     404: 
1.1.1.4 ! misho     405:        if (foreground) {
        !           406:            /* Foreground process, set tty to raw mode. */
        !           407:            do {
        !           408:                n = term_raw(io_fds[SFD_USERTTY], 0);
        !           409:            } while (!n && errno == EINTR);
        !           410:            ttymode = TERM_RAW;
        !           411:        } else {
        !           412:            /* Background process, no access to tty. */
        !           413:            ttymode = TERM_COOKED;
1.1       misho     414:        }
                    415: 
1.1.1.4 ! misho     416:        if (signo != SIGSTOP)
        !           417:            sudo_sigaction(signo, &osa, NULL);
1.1       misho     418:        rval = ttymode == TERM_RAW ? SIGCONT_FG : SIGCONT_BG;
                    419:        break;
                    420:     }
                    421: 
1.1.1.2   misho     422:     debug_return_int(rval);
1.1       misho     423: }
                    424: 
                    425: /*
1.1.1.3   misho     426:  * Kill command with increasing urgency.
1.1       misho     427:  */
                    428: void
1.1.1.3   misho     429: terminate_command(pid_t pid, bool use_pgrp)
1.1       misho     430: {
1.1.1.3   misho     431:     debug_decl(terminate_command, SUDO_DEBUG_EXEC);
1.1.1.2   misho     432: 
1.1       misho     433:     /*
                    434:      * Note that SIGCHLD will interrupt the sleep()
                    435:      */
                    436:     if (use_pgrp) {
1.1.1.2   misho     437:        sudo_debug_printf(SUDO_DEBUG_INFO, "killpg %d SIGHUP", (int)pid);
1.1       misho     438:        killpg(pid, SIGHUP);
1.1.1.2   misho     439:        sudo_debug_printf(SUDO_DEBUG_INFO, "killpg %d SIGTERM", (int)pid);
1.1       misho     440:        killpg(pid, SIGTERM);
                    441:        sleep(2);
1.1.1.2   misho     442:        sudo_debug_printf(SUDO_DEBUG_INFO, "killpg %d SIGKILL", (int)pid);
1.1       misho     443:        killpg(pid, SIGKILL);
                    444:     } else {
1.1.1.2   misho     445:        sudo_debug_printf(SUDO_DEBUG_INFO, "kill %d SIGHUP", (int)pid);
1.1       misho     446:        kill(pid, SIGHUP);
1.1.1.2   misho     447:        sudo_debug_printf(SUDO_DEBUG_INFO, "kill %d SIGTERM", (int)pid);
1.1       misho     448:        kill(pid, SIGTERM);
                    449:        sleep(2);
1.1.1.2   misho     450:        sudo_debug_printf(SUDO_DEBUG_INFO, "kill %d SIGKILL", (int)pid);
1.1       misho     451:        kill(pid, SIGKILL);
                    452:     }
1.1.1.2   misho     453: 
                    454:     debug_return;
1.1       misho     455: }
                    456: 
                    457: static struct io_buffer *
1.1.1.2   misho     458: io_buf_new(int rfd, int wfd, bool (*action)(const char *, unsigned int),
1.1       misho     459:     struct io_buffer *head)
                    460: {
                    461:     struct io_buffer *iob;
1.1.1.2   misho     462:     debug_decl(io_buf_new, SUDO_DEBUG_EXEC);
1.1       misho     463: 
1.1.1.2   misho     464:     iob = ecalloc(1, sizeof(*iob));
1.1       misho     465:     iob->rfd = rfd;
                    466:     iob->wfd = wfd;
                    467:     iob->action = action;
                    468:     iob->next = head;
1.1.1.2   misho     469: 
                    470:     debug_return_ptr(iob);
1.1       misho     471: }
                    472: 
                    473: /*
                    474:  * Read/write iobufs depending on fdsr and fdsw.
                    475:  * Returns the number of errors.
                    476:  */
                    477: int
                    478: perform_io(fd_set *fdsr, fd_set *fdsw, struct command_status *cstat)
                    479: {
                    480:     struct io_buffer *iob;
                    481:     int n, errors = 0;
1.1.1.2   misho     482:     debug_decl(perform_io, SUDO_DEBUG_EXEC);
1.1       misho     483: 
                    484:     for (iob = iobufs; iob; iob = iob->next) {
                    485:        if (iob->rfd != -1 && FD_ISSET(iob->rfd, fdsr)) {
                    486:            do {
                    487:                n = read(iob->rfd, iob->buf + iob->len,
                    488:                    sizeof(iob->buf) - iob->len);
                    489:            } while (n == -1 && errno == EINTR);
                    490:            switch (n) {
                    491:                case -1:
1.1.1.2   misho     492:                    if (errno != EAGAIN) {
                    493:                        /* treat read error as fatal and close the fd */
                    494:                        sudo_debug_printf(SUDO_DEBUG_ERROR,
                    495:                            "error reading fd %d: %s", iob->rfd,
                    496:                            strerror(errno));
                    497:                        safe_close(iob->rfd);
                    498:                        iob->rfd = -1;
1.1       misho     499:                    }
1.1.1.2   misho     500:                    break;
1.1       misho     501:                case 0:
                    502:                    /* got EOF or pty has gone away */
1.1.1.2   misho     503:                    sudo_debug_printf(SUDO_DEBUG_INFO,
                    504:                        "read EOF from fd %d", iob->rfd);
1.1       misho     505:                    safe_close(iob->rfd);
                    506:                    iob->rfd = -1;
                    507:                    break;
                    508:                default:
1.1.1.2   misho     509:                    sudo_debug_printf(SUDO_DEBUG_INFO,
                    510:                        "read %d bytes from fd %d", n, iob->rfd);
1.1       misho     511:                    if (!iob->action(iob->buf + iob->len, n))
1.1.1.3   misho     512:                        terminate_command(cmnd_pid, true);
1.1       misho     513:                    iob->len += n;
                    514:                    break;
                    515:            }
                    516:        }
                    517:        if (iob->wfd != -1 && FD_ISSET(iob->wfd, fdsw)) {
                    518:            do {
                    519:                n = write(iob->wfd, iob->buf + iob->off,
                    520:                    iob->len - iob->off);
                    521:            } while (n == -1 && errno == EINTR);
                    522:            if (n == -1) {
1.1.1.2   misho     523:                if (errno == EPIPE || errno == ENXIO || errno == EIO || errno == EBADF) {
                    524:                    sudo_debug_printf(SUDO_DEBUG_INFO,
                    525:                        "unable to write %d bytes to fd %d",
                    526:                            iob->len - iob->off, iob->wfd);
1.1       misho     527:                    /* other end of pipe closed or pty revoked */
                    528:                    if (iob->rfd != -1) {
                    529:                        safe_close(iob->rfd);
                    530:                        iob->rfd = -1;
                    531:                    }
                    532:                    safe_close(iob->wfd);
                    533:                    iob->wfd = -1;
                    534:                    continue;
                    535:                }
1.1.1.2   misho     536:                if (errno != EAGAIN) {
1.1       misho     537:                    errors++;
1.1.1.2   misho     538:                    sudo_debug_printf(SUDO_DEBUG_ERROR,
                    539:                        "error writing fd %d: %s", iob->wfd, strerror(errno));
                    540:                }
1.1       misho     541:            } else {
1.1.1.2   misho     542:                sudo_debug_printf(SUDO_DEBUG_INFO,
                    543:                    "wrote %d bytes to fd %d", n, iob->wfd);
1.1       misho     544:                iob->off += n;
                    545:            }
                    546:        }
                    547:     }
                    548:     if (errors && cstat != NULL) {
                    549:        cstat->type = CMD_ERRNO;
                    550:        cstat->val = errno;
                    551:     }
1.1.1.2   misho     552:     debug_return_int(errors);
1.1       misho     553: }
                    554: 
                    555: /*
                    556:  * Fork a monitor process which runs the actual command as its own child
                    557:  * process with std{in,out,err} hooked up to the pty or pipes as appropriate.
                    558:  * Returns the child pid.
                    559:  */
                    560: int
1.1.1.3   misho     561: fork_pty(struct command_details *details, int sv[], int *maxfd, sigset_t *omask)
1.1       misho     562: {
                    563:     struct command_status cstat;
                    564:     struct io_buffer *iob;
                    565:     int io_pipe[3][2], n;
                    566:     sigaction_t sa;
1.1.1.3   misho     567:     sigset_t mask;
                    568:     pid_t child;
1.1.1.2   misho     569:     debug_decl(fork_pty, SUDO_DEBUG_EXEC);
1.1.1.4 ! misho     570: 
1.1       misho     571:     ppgrp = getpgrp(); /* parent's pgrp, so child can signal us */
1.1.1.4 ! misho     572: 
        !           573:     memset(&sa, 0, sizeof(sa));
1.1       misho     574:     sigemptyset(&sa.sa_mask);
1.1.1.4 ! misho     575: 
1.1       misho     576:     if (io_fds[SFD_USERTTY] != -1) {
                    577:        sa.sa_flags = SA_RESTART;
                    578:        sa.sa_handler = sigwinch;
1.1.1.4 ! misho     579:        sudo_sigaction(SIGWINCH, &sa, NULL);
1.1       misho     580:     }
                    581: 
                    582:     /* So we can block tty-generated signals */
                    583:     sigemptyset(&ttyblock);
                    584:     sigaddset(&ttyblock, SIGINT);
                    585:     sigaddset(&ttyblock, SIGQUIT);
                    586:     sigaddset(&ttyblock, SIGTSTP);
                    587:     sigaddset(&ttyblock, SIGTTIN);
                    588:     sigaddset(&ttyblock, SIGTTOU);
                    589: 
                    590:     /*
                    591:      * Setup stdin/stdout/stderr for child, to be duped after forking.
                    592:      * In background mode there is no stdin.
                    593:      */
                    594:     if (!ISSET(details->flags, CD_BACKGROUND))
                    595:        io_fds[SFD_STDIN] = io_fds[SFD_SLAVE];
                    596:     io_fds[SFD_STDOUT] = io_fds[SFD_SLAVE];
                    597:     io_fds[SFD_STDERR] = io_fds[SFD_SLAVE];
                    598: 
                    599:     if (io_fds[SFD_USERTTY] != -1) {
                    600:        /* Read from /dev/tty, write to pty master */
                    601:        if (!ISSET(details->flags, CD_BACKGROUND)) {
                    602:            iobufs = io_buf_new(io_fds[SFD_USERTTY], io_fds[SFD_MASTER],
                    603:                log_ttyin, iobufs);
                    604:        }
                    605: 
                    606:        /* Read from pty master, write to /dev/tty */
                    607:        iobufs = io_buf_new(io_fds[SFD_MASTER], io_fds[SFD_USERTTY],
                    608:            log_ttyout, iobufs);
                    609: 
                    610:        /* Are we the foreground process? */
                    611:        foreground = tcgetpgrp(io_fds[SFD_USERTTY]) == ppgrp;
                    612:     }
                    613: 
                    614:     /*
                    615:      * If either stdin, stdout or stderr is not a tty we use a pipe
                    616:      * to interpose ourselves instead of duping the pty fd.
                    617:      */
                    618:     memset(io_pipe, 0, sizeof(io_pipe));
                    619:     if (io_fds[SFD_STDIN] == -1 || !isatty(STDIN_FILENO)) {
1.1.1.2   misho     620:        sudo_debug_printf(SUDO_DEBUG_INFO, "stdin not a tty, creating a pipe");
                    621:        pipeline = true;
1.1       misho     622:        if (pipe(io_pipe[STDIN_FILENO]) != 0)
1.1.1.4 ! misho     623:            fatal(_("unable to create pipe"));
1.1       misho     624:        iobufs = io_buf_new(STDIN_FILENO, io_pipe[STDIN_FILENO][1],
                    625:            log_stdin, iobufs);
                    626:        io_fds[SFD_STDIN] = io_pipe[STDIN_FILENO][0];
                    627:     }
                    628:     if (io_fds[SFD_STDOUT] == -1 || !isatty(STDOUT_FILENO)) {
1.1.1.2   misho     629:        sudo_debug_printf(SUDO_DEBUG_INFO, "stdout not a tty, creating a pipe");
                    630:        pipeline = true;
1.1       misho     631:        if (pipe(io_pipe[STDOUT_FILENO]) != 0)
1.1.1.4 ! misho     632:            fatal(_("unable to create pipe"));
1.1       misho     633:        iobufs = io_buf_new(io_pipe[STDOUT_FILENO][0], STDOUT_FILENO,
                    634:            log_stdout, iobufs);
                    635:        io_fds[SFD_STDOUT] = io_pipe[STDOUT_FILENO][1];
                    636:     }
                    637:     if (io_fds[SFD_STDERR] == -1 || !isatty(STDERR_FILENO)) {
1.1.1.2   misho     638:        sudo_debug_printf(SUDO_DEBUG_INFO, "stderr not a tty, creating a pipe");
1.1       misho     639:        if (pipe(io_pipe[STDERR_FILENO]) != 0)
1.1.1.4 ! misho     640:            fatal(_("unable to create pipe"));
1.1       misho     641:        iobufs = io_buf_new(io_pipe[STDERR_FILENO][0], STDERR_FILENO,
                    642:            log_stderr, iobufs);
                    643:        io_fds[SFD_STDERR] = io_pipe[STDERR_FILENO][1];
                    644:     }
                    645: 
1.1.1.4 ! misho     646:     /* We don't want to receive SIGTTIN/SIGTTOU, getting EIO is preferable. */
        !           647:     sa.sa_handler = SIG_IGN;
        !           648:     sudo_sigaction(SIGTTIN, &sa, NULL);
        !           649:     sudo_sigaction(SIGTTOU, &sa, NULL);
        !           650: 
1.1       misho     651:     /* Job control signals to relay from parent to child. */
1.1.1.4 ! misho     652:     sigfillset(&sa.sa_mask);
1.1       misho     653:     sa.sa_flags = SA_INTERRUPT; /* do not restart syscalls */
1.1.1.3   misho     654: #ifdef SA_SIGINFO
                    655:     sa.sa_flags |= SA_SIGINFO;
                    656:     sa.sa_sigaction = handler;
                    657: #else
1.1       misho     658:     sa.sa_handler = handler;
1.1.1.3   misho     659: #endif
1.1.1.4 ! misho     660:     sudo_sigaction(SIGTSTP, &sa, NULL);
1.1.1.2   misho     661: 
1.1       misho     662:     if (foreground) {
                    663:        /* Copy terminal attrs from user tty -> pty slave. */
                    664:        if (term_copy(io_fds[SFD_USERTTY], io_fds[SFD_SLAVE])) {
1.1.1.2   misho     665:            tty_initialized = true;
1.1       misho     666:            sync_ttysize(io_fds[SFD_USERTTY], io_fds[SFD_SLAVE]);
                    667:        }
                    668: 
1.1.1.4 ! misho     669:        /* Start out in raw mode unless part of a pipeline or backgrounded. */
        !           670:        if (!pipeline && !ISSET(details->flags, CD_EXEC_BG)) {
1.1       misho     671:            ttymode = TERM_RAW;
                    672:            do {
                    673:                n = term_raw(io_fds[SFD_USERTTY], 0);
                    674:            } while (!n && errno == EINTR);
                    675:            if (!n)
1.1.1.4 ! misho     676:                fatal(_("unable to set terminal to raw mode"));
1.1       misho     677:        }
                    678:     }
                    679: 
1.1.1.2   misho     680:     /*
                    681:      * The policy plugin's session init must be run before we fork
                    682:      * or certain pam modules won't be able to track their state.
                    683:      */
                    684:     if (policy_init_session(details) != true)
1.1.1.4 ! misho     685:        fatalx(_("policy plugin failed session initialization"));
1.1.1.2   misho     686: 
1.1.1.3   misho     687:     /*
                    688:      * Block some signals until cmnd_pid is set in the parent to avoid a
                    689:      * race between exec of the command and receipt of a fatal signal from it.
                    690:      */
                    691:     sigemptyset(&mask);
                    692:     sigaddset(&mask, SIGTERM);
                    693:     sigaddset(&mask, SIGHUP);
                    694:     sigaddset(&mask, SIGINT);
                    695:     sigaddset(&mask, SIGQUIT);
                    696:     sigprocmask(SIG_BLOCK, &mask, omask);
                    697: 
1.1.1.2   misho     698:     child = sudo_debug_fork();
1.1       misho     699:     switch (child) {
                    700:     case -1:
1.1.1.4 ! misho     701:        fatal(_("unable to fork"));
1.1       misho     702:        break;
                    703:     case 0:
                    704:        /* child */
                    705:        close(sv[0]);
                    706:        close(signal_pipe[0]);
                    707:        close(signal_pipe[1]);
                    708:        fcntl(sv[1], F_SETFD, FD_CLOEXEC);
1.1.1.3   misho     709:        sigprocmask(SIG_SETMASK, omask, NULL);
1.1.1.4 ! misho     710:        /* Close the other end of the stdin/stdout/stderr pipes and exec. */
        !           711:        if (io_pipe[STDIN_FILENO][1])
        !           712:            close(io_pipe[STDIN_FILENO][1]);
        !           713:        if (io_pipe[STDOUT_FILENO][0])
        !           714:            close(io_pipe[STDOUT_FILENO][0]);
        !           715:        if (io_pipe[STDERR_FILENO][0])
        !           716:            close(io_pipe[STDERR_FILENO][0]);
        !           717:        exec_monitor(details, sv[1]);
1.1       misho     718:        cstat.type = CMD_ERRNO;
                    719:        cstat.val = errno;
1.1.1.3   misho     720:        ignore_result(send(sv[1], &cstat, sizeof(cstat), 0));
1.1       misho     721:        _exit(1);
                    722:     }
                    723: 
                    724:     /* Close the other end of the stdin/stdout/stderr pipes. */
                    725:     if (io_pipe[STDIN_FILENO][0])
                    726:        close(io_pipe[STDIN_FILENO][0]);
                    727:     if (io_pipe[STDOUT_FILENO][1])
                    728:        close(io_pipe[STDOUT_FILENO][1]);
1.1.1.4 ! misho     729:     if (io_pipe[STDERR_FILENO][1])
1.1       misho     730:        close(io_pipe[STDERR_FILENO][1]);
                    731: 
                    732:     for (iob = iobufs; iob; iob = iob->next) {
                    733:        /* Determine maxfd */
                    734:        if (iob->rfd > *maxfd)
                    735:            *maxfd = iob->rfd;
                    736:        if (iob->wfd > *maxfd)
                    737:            *maxfd = iob->wfd;
                    738: 
                    739:        /* Set non-blocking mode. */
                    740:        n = fcntl(iob->rfd, F_GETFL, 0);
                    741:        if (n != -1 && !ISSET(n, O_NONBLOCK))
                    742:            (void) fcntl(iob->rfd, F_SETFL, n | O_NONBLOCK);
                    743:        n = fcntl(iob->wfd, F_GETFL, 0);
                    744:        if (n != -1 && !ISSET(n, O_NONBLOCK))
                    745:            (void) fcntl(iob->wfd, F_SETFL, n | O_NONBLOCK);
                    746:     }
                    747: 
1.1.1.2   misho     748:     debug_return_int(child);
1.1       misho     749: }
                    750: 
                    751: void
                    752: pty_close(struct command_status *cstat)
                    753: {
                    754:     int n;
1.1.1.2   misho     755:     debug_decl(pty_close, SUDO_DEBUG_EXEC);
1.1       misho     756: 
                    757:     /* Flush any remaining output (the plugin already got it) */
                    758:     if (io_fds[SFD_USERTTY] != -1) {
                    759:        n = fcntl(io_fds[SFD_USERTTY], F_GETFL, 0);
                    760:        if (n != -1 && ISSET(n, O_NONBLOCK)) {
                    761:            CLR(n, O_NONBLOCK);
                    762:            (void) fcntl(io_fds[SFD_USERTTY], F_SETFL, n);
                    763:        }
                    764:     }
                    765:     flush_output();
                    766: 
                    767:     if (io_fds[SFD_USERTTY] != -1) {
1.1.1.2   misho     768:        check_foreground();
                    769:        if (foreground) {
                    770:            do {
                    771:                n = term_restore(io_fds[SFD_USERTTY], 0);
                    772:            } while (!n && errno == EINTR);
                    773:        }
1.1       misho     774:     }
                    775: 
                    776:     /* If child was signalled, write the reason to stdout like the shell. */
                    777:     if (cstat->type == CMD_WSTATUS && WIFSIGNALED(cstat->val)) {
                    778:        int signo = WTERMSIG(cstat->val);
                    779:        if (signo && signo != SIGINT && signo != SIGPIPE) {
                    780:            const char *reason = strsignal(signo);
                    781:            n = io_fds[SFD_USERTTY] != -1 ?
                    782:                io_fds[SFD_USERTTY] : STDOUT_FILENO;
                    783:            if (write(n, reason, strlen(reason)) != -1) {
                    784:                if (WCOREDUMP(cstat->val)) {
1.1.1.2   misho     785:                    ignore_result(write(n, " (core dumped)", 14));
1.1       misho     786:                }
1.1.1.2   misho     787:                ignore_result(write(n, "\n", 1));
1.1       misho     788:            }
                    789:        }
                    790:     }
                    791:     utmp_logout(slavename, cstat->type == CMD_WSTATUS ? cstat->val : 0); /* XXX - only if CD_SET_UTMP */
1.1.1.2   misho     792:     debug_return;
1.1       misho     793: }
                    794: 
                    795: /*
                    796:  * Fill in fdsr and fdsw based on the io buffers list.
                    797:  * Called prior to select().
                    798:  */
                    799: void
                    800: fd_set_iobs(fd_set *fdsr, fd_set *fdsw)
                    801: {
                    802:     struct io_buffer *iob;
1.1.1.2   misho     803:     debug_decl(fd_set_iobs, SUDO_DEBUG_EXEC);
1.1       misho     804: 
                    805:     for (iob = iobufs; iob; iob = iob->next) {
                    806:        if (iob->rfd == -1 && iob->wfd == -1)
                    807:            continue;
                    808:        if (iob->off == iob->len) {
                    809:            iob->off = iob->len = 0;
                    810:            /* Forward the EOF from reader to writer. */
                    811:            if (iob->rfd == -1) {
                    812:                safe_close(iob->wfd);
                    813:                iob->wfd = -1;
                    814:            }
                    815:        }
                    816:        /* Don't read/write /dev/tty if we are not in the foreground. */
                    817:        if (iob->rfd != -1 &&
                    818:            (ttymode == TERM_RAW || iob->rfd != io_fds[SFD_USERTTY])) {
                    819:            if (iob->len != sizeof(iob->buf))
                    820:                FD_SET(iob->rfd, fdsr);
                    821:        }
                    822:        if (iob->wfd != -1 &&
                    823:            (foreground || iob->wfd != io_fds[SFD_USERTTY])) {
                    824:            if (iob->len > iob->off)
                    825:                FD_SET(iob->wfd, fdsw);
                    826:        }
                    827:     }
1.1.1.2   misho     828:     debug_return;
1.1       misho     829: }
                    830: 
                    831: static void
1.1.1.2   misho     832: deliver_signal(pid_t pid, int signo, bool from_parent)
1.1       misho     833: {
1.1.1.3   misho     834:     char signame[SIG2STR_MAX];
1.1       misho     835:     int status;
1.1.1.2   misho     836:     debug_decl(deliver_signal, SUDO_DEBUG_EXEC);
1.1       misho     837: 
1.1.1.4 ! misho     838:     if (signo == SIGCONT_FG)
        !           839:        strlcpy(signame, "CONT_FG", sizeof(signame));
        !           840:     else if (signo == SIGCONT_BG)
        !           841:        strlcpy(signame, "CONT_BG", sizeof(signame));
        !           842:     else if (sig2str(signo, signame) == -1)
1.1.1.3   misho     843:        snprintf(signame, sizeof(signame), "%d", signo);
                    844: 
1.1       misho     845:     /* Handle signal from parent. */
1.1.1.3   misho     846:     sudo_debug_printf(SUDO_DEBUG_INFO, "received SIG%s%s",
                    847:        signame, from_parent ? " from parent" : "");
1.1       misho     848:     switch (signo) {
                    849:     case SIGALRM:
1.1.1.3   misho     850:        terminate_command(pid, true);
1.1       misho     851:        break;
                    852:     case SIGCONT_FG:
                    853:        /* Continue in foreground, grant it controlling tty. */
                    854:        do {
1.1.1.3   misho     855:            status = tcsetpgrp(io_fds[SFD_SLAVE], cmnd_pgrp);
1.1       misho     856:        } while (status == -1 && errno == EINTR);
                    857:        killpg(pid, SIGCONT);
                    858:        break;
                    859:     case SIGCONT_BG:
                    860:        /* Continue in background, I take controlling tty. */
                    861:        do {
1.1.1.4 ! misho     862:            status = tcsetpgrp(io_fds[SFD_SLAVE], mon_pgrp);
1.1       misho     863:        } while (status == -1 && errno == EINTR);
                    864:        killpg(pid, SIGCONT);
                    865:        break;
                    866:     case SIGKILL:
                    867:        _exit(1); /* XXX */
                    868:        /* NOTREACHED */
                    869:     default:
1.1.1.3   misho     870:        /* Relay signal to command. */
1.1       misho     871:        killpg(pid, signo);
                    872:        break;
                    873:     }
1.1.1.2   misho     874:     debug_return;
1.1       misho     875: }
                    876: 
                    877: /*
                    878:  * Send status to parent over socketpair.
                    879:  * Return value is the same as send(2).
                    880:  */
                    881: static int
                    882: send_status(int fd, struct command_status *cstat)
                    883: {
                    884:     int n = -1;
1.1.1.2   misho     885:     debug_decl(send_status, SUDO_DEBUG_EXEC);
1.1       misho     886: 
                    887:     if (cstat->type != CMD_INVALID) {
1.1.1.2   misho     888:        sudo_debug_printf(SUDO_DEBUG_INFO,
                    889:            "sending status message to parent: [%d, %d]",
                    890:            cstat->type, cstat->val);
1.1       misho     891:        do {
                    892:            n = send(fd, cstat, sizeof(*cstat), 0);
                    893:        } while (n == -1 && errno == EINTR);
                    894:        if (n != sizeof(*cstat)) {
1.1.1.2   misho     895:            sudo_debug_printf(SUDO_DEBUG_ERROR,
                    896:                "unable to send status to parent: %s", strerror(errno));
1.1       misho     897:        }
                    898:        cstat->type = CMD_INVALID; /* prevent re-sending */
                    899:     }
1.1.1.2   misho     900:     debug_return_int(n);
1.1       misho     901: }
                    902: 
                    903: /*
1.1.1.3   misho     904:  * Wait for command status after receiving SIGCHLD.
                    905:  * If the command was stopped, the status is send back to the parent.
1.1       misho     906:  * Otherwise, cstat is filled in but not sent.
1.1.1.3   misho     907:  * Returns true if command is still alive, else false.
1.1       misho     908:  */
1.1.1.2   misho     909: static bool
1.1       misho     910: handle_sigchld(int backchannel, struct command_status *cstat)
                    911: {
1.1.1.2   misho     912:     bool alive = true;
                    913:     int status;
1.1       misho     914:     pid_t pid;
1.1.1.2   misho     915:     debug_decl(handle_sigchld, SUDO_DEBUG_EXEC);
1.1       misho     916: 
1.1.1.3   misho     917:     /* read command status */
1.1       misho     918:     do {
1.1.1.3   misho     919:        pid = waitpid(cmnd_pid, &status, WUNTRACED|WNOHANG);
1.1       misho     920:     } while (pid == -1 && errno == EINTR);
1.1.1.3   misho     921:     if (pid == cmnd_pid) {
1.1       misho     922:        if (cstat->type != CMD_ERRNO) {
1.1.1.3   misho     923:            char signame[SIG2STR_MAX];
                    924: 
1.1       misho     925:            cstat->type = CMD_WSTATUS;
                    926:            cstat->val = status;
                    927:            if (WIFSTOPPED(status)) {
1.1.1.3   misho     928:                if (sig2str(WSTOPSIG(status), signame) == -1)
                    929:                    snprintf(signame, sizeof(signame), "%d", WSTOPSIG(status));
                    930:                sudo_debug_printf(SUDO_DEBUG_INFO,
                    931:                    "command stopped, SIG%s", signame);
1.1.1.4 ! misho     932:                /* Saved the foreground pgid so we can restore it later. */
1.1       misho     933:                do {
1.1.1.4 ! misho     934:                    pid = tcgetpgrp(io_fds[SFD_SLAVE]);
        !           935:                } while (pid == -1 && errno == EINTR);
        !           936:                if (pid != mon_pgrp)
        !           937:                    cmnd_pgrp = pid;
1.1       misho     938:                if (send_status(backchannel, cstat) == -1)
                    939:                    return alive; /* XXX */
                    940:            } else if (WIFSIGNALED(status)) {
1.1.1.3   misho     941:                if (sig2str(WTERMSIG(status), signame) == -1)
                    942:                    snprintf(signame, sizeof(signame), "%d", WTERMSIG(status));
                    943:                sudo_debug_printf(SUDO_DEBUG_INFO,
                    944:                    "command killed, SIG%s", signame);
1.1       misho     945:            } else {
1.1.1.2   misho     946:                sudo_debug_printf(SUDO_DEBUG_INFO, "command exited: %d",
                    947:                    WEXITSTATUS(status));
1.1       misho     948:            }
                    949:        }
                    950:        if (!WIFSTOPPED(status))
1.1.1.2   misho     951:            alive = false;
1.1       misho     952:     }
1.1.1.2   misho     953:     debug_return_bool(alive);
1.1       misho     954: }
                    955: 
                    956: /*
                    957:  * Monitor process that creates a new session with the controlling tty,
                    958:  * resets signal handlers and forks a child to call exec_pty().
                    959:  * Waits for status changes from the command and relays them to the
                    960:  * parent and relays signals from the parent to the command.
                    961:  * Returns an error if fork(2) fails, else calls _exit(2).
                    962:  */
                    963: static int
                    964: exec_monitor(struct command_details *details, int backchannel)
                    965: {
                    966:     struct command_status cstat;
                    967:     struct timeval tv;
                    968:     fd_set *fdsr;
                    969:     sigaction_t sa;
1.1.1.4 ! misho     970:     int errpipe[2], maxfd, n;
1.1.1.2   misho     971:     bool alive = true;
1.1       misho     972:     unsigned char signo;
1.1.1.2   misho     973:     debug_decl(exec_monitor, SUDO_DEBUG_EXEC);
1.1       misho     974: 
                    975:     /* Close unused fds. */
                    976:     if (io_fds[SFD_MASTER] != -1)
                    977:        close(io_fds[SFD_MASTER]);
                    978:     if (io_fds[SFD_USERTTY] != -1)
                    979:        close(io_fds[SFD_USERTTY]);
                    980: 
                    981:     /*
                    982:      * We use a pipe to atomically handle signal notification within
                    983:      * the select() loop.
                    984:      */
                    985:     if (pipe_nonblock(signal_pipe) != 0)
1.1.1.4 ! misho     986:        fatal(_("unable to create pipe"));
1.1       misho     987: 
                    988:     /* Reset SIGWINCH and SIGALRM. */
1.1.1.4 ! misho     989:     memset(&sa, 0, sizeof(sa));
1.1       misho     990:     sigemptyset(&sa.sa_mask);
                    991:     sa.sa_flags = SA_RESTART;
                    992:     sa.sa_handler = SIG_DFL;
1.1.1.4 ! misho     993:     sudo_sigaction(SIGWINCH, &sa, NULL);
        !           994:     sudo_sigaction(SIGALRM, &sa, NULL);
1.1       misho     995: 
                    996:     /* Ignore any SIGTTIN or SIGTTOU we get. */
                    997:     sa.sa_handler = SIG_IGN;
1.1.1.4 ! misho     998:     sudo_sigaction(SIGTTIN, &sa, NULL);
        !           999:     sudo_sigaction(SIGTTOU, &sa, NULL);
        !          1000: 
        !          1001:     /* Block all signals in mon_handler(). */
        !          1002:     sigfillset(&sa.sa_mask);
1.1       misho    1003: 
                   1004:     /* Note: HP-UX select() will not be interrupted if SA_RESTART set */
                   1005:     sa.sa_flags = SA_INTERRUPT;
1.1.1.3   misho    1006: #ifdef SA_SIGINFO
                   1007:     sa.sa_flags |= SA_SIGINFO;
                   1008:     sa.sa_sigaction = mon_handler;
                   1009: #else
                   1010:     sa.sa_handler = mon_handler;
                   1011: #endif
1.1.1.4 ! misho    1012:     sudo_sigaction(SIGCHLD, &sa, NULL);
1.1       misho    1013: 
1.1.1.2   misho    1014:     /* Catch common signals so we can cleanup properly. */
                   1015:     sa.sa_flags = SA_RESTART;
1.1.1.3   misho    1016: #ifdef SA_SIGINFO
                   1017:     sa.sa_flags |= SA_SIGINFO;
                   1018:     sa.sa_sigaction = mon_handler;
                   1019: #else
                   1020:     sa.sa_handler = mon_handler;
                   1021: #endif
1.1.1.4 ! misho    1022:     sudo_sigaction(SIGHUP, &sa, NULL);
        !          1023:     sudo_sigaction(SIGINT, &sa, NULL);
        !          1024:     sudo_sigaction(SIGQUIT, &sa, NULL);
        !          1025:     sudo_sigaction(SIGTERM, &sa, NULL);
        !          1026:     sudo_sigaction(SIGTSTP, &sa, NULL);
        !          1027:     sudo_sigaction(SIGUSR1, &sa, NULL);
        !          1028:     sudo_sigaction(SIGUSR2, &sa, NULL);
1.1.1.2   misho    1029: 
1.1       misho    1030:     /*
                   1031:      * Start a new session with the parent as the session leader
                   1032:      * and the slave pty as the controlling terminal.
1.1.1.3   misho    1033:      * This allows us to be notified when the command has been suspended.
1.1       misho    1034:      */
                   1035:     if (setsid() == -1) {
                   1036:        warning("setsid");
                   1037:        goto bad;
                   1038:     }
                   1039:     if (io_fds[SFD_SLAVE] != -1) {
                   1040: #ifdef TIOCSCTTY
                   1041:        if (ioctl(io_fds[SFD_SLAVE], TIOCSCTTY, NULL) != 0)
1.1.1.4 ! misho    1042:            fatal(_("unable to set controlling tty"));
1.1       misho    1043: #else
                   1044:        /* Set controlling tty by reopening slave. */
                   1045:        if ((n = open(slavename, O_RDWR)) >= 0)
                   1046:            close(n);
                   1047: #endif
                   1048:     }
                   1049: 
1.1.1.4 ! misho    1050:     mon_pgrp = getpgrp();      /* save a copy of our process group */
        !          1051: 
1.1       misho    1052:     /*
                   1053:      * If stdin/stdout is not a tty, start command in the background
                   1054:      * since it might be part of a pipeline that reads from /dev/tty.
                   1055:      * In this case, we rely on the command receiving SIGTTOU or SIGTTIN
                   1056:      * when it needs access to the controlling tty.
                   1057:      */
                   1058:     if (pipeline)
1.1.1.2   misho    1059:        foreground = false;
1.1       misho    1060: 
                   1061:     /* Start command and wait for it to stop or exit */
                   1062:     if (pipe(errpipe) == -1)
1.1.1.4 ! misho    1063:        fatal(_("unable to create pipe"));
1.1.1.3   misho    1064:     cmnd_pid = sudo_debug_fork();
                   1065:     if (cmnd_pid == -1) {
1.1       misho    1066:        warning(_("unable to fork"));
                   1067:        goto bad;
                   1068:     }
1.1.1.3   misho    1069:     if (cmnd_pid == 0) {
1.1       misho    1070:        /* We pass errno back to our parent via pipe on exec failure. */
                   1071:        close(backchannel);
                   1072:        close(signal_pipe[0]);
                   1073:        close(signal_pipe[1]);
                   1074:        close(errpipe[0]);
                   1075:        fcntl(errpipe[1], F_SETFD, FD_CLOEXEC);
                   1076:        restore_signals();
                   1077: 
                   1078:        /* setup tty and exec command */
1.1.1.4 ! misho    1079:        exec_pty(details, &cstat, &errpipe[1]);
1.1.1.2   misho    1080:        ignore_result(write(errpipe[1], &cstat, sizeof(cstat)));
1.1       misho    1081:        _exit(1);
                   1082:     }
                   1083:     close(errpipe[1]);
                   1084: 
1.1.1.3   misho    1085:     /* Send the command's pid to main sudo process. */
                   1086:     cstat.type = CMD_PID;
                   1087:     cstat.val = cmnd_pid;
                   1088:     ignore_result(send(backchannel, &cstat, sizeof(cstat), 0));
                   1089: 
1.1       misho    1090:     /* If any of stdin/stdout/stderr are pipes, close them in parent. */
                   1091:     if (io_fds[SFD_STDIN] != io_fds[SFD_SLAVE])
                   1092:        close(io_fds[SFD_STDIN]);
                   1093:     if (io_fds[SFD_STDOUT] != io_fds[SFD_SLAVE])
                   1094:        close(io_fds[SFD_STDOUT]);
                   1095:     if (io_fds[SFD_STDERR] != io_fds[SFD_SLAVE])
                   1096:        close(io_fds[SFD_STDERR]);
                   1097: 
1.1.1.4 ! misho    1098:     /* Put command in its own process group. */
1.1.1.3   misho    1099:     cmnd_pgrp = cmnd_pid;
                   1100:     setpgid(cmnd_pid, cmnd_pgrp);
1.1.1.4 ! misho    1101: 
        !          1102:     /* Make the command the foreground process for the pty slave. */
        !          1103:     if (foreground && !ISSET(details->flags, CD_EXEC_BG)) {
1.1       misho    1104:        do {
1.1.1.4 ! misho    1105:            n = tcsetpgrp(io_fds[SFD_SLAVE], cmnd_pgrp);
        !          1106:        } while (n == -1 && errno == EINTR);
1.1       misho    1107:     }
                   1108: 
                   1109:     /* Wait for errno on pipe, signal on backchannel or for SIGCHLD */
                   1110:     maxfd = MAX(MAX(errpipe[0], signal_pipe[0]), backchannel);
1.1.1.2   misho    1111:     fdsr = ecalloc(howmany(maxfd + 1, NFDBITS), sizeof(fd_mask));
                   1112:     memset(&cstat, 0, sizeof(cstat));
1.1       misho    1113:     tv.tv_sec = 0;
                   1114:     tv.tv_usec = 0;
                   1115:     for (;;) {
                   1116:        /* Check for signal on backchannel or errno on errpipe. */
                   1117:        FD_SET(backchannel, fdsr);
                   1118:        FD_SET(signal_pipe[0], fdsr);
                   1119:        if (errpipe[0] != -1)
                   1120:            FD_SET(errpipe[0], fdsr);
                   1121:        maxfd = MAX(MAX(errpipe[0], signal_pipe[0]), backchannel);
                   1122: 
                   1123:        /* If command exited we just poll, there may be data on errpipe. */
                   1124:        n = select(maxfd + 1, fdsr, NULL, NULL, alive ? NULL : &tv);
                   1125:        if (n <= 0) {
                   1126:            if (n == 0)
                   1127:                goto done;
1.1.1.2   misho    1128:            if (errno == EINTR || errno == ENOMEM)
1.1       misho    1129:                continue;
1.1.1.2   misho    1130:            warning("monitor: %s", _("select failed"));
                   1131:            break;
1.1       misho    1132:        }
                   1133: 
                   1134:        if (FD_ISSET(signal_pipe[0], fdsr)) {
                   1135:            n = read(signal_pipe[0], &signo, sizeof(signo));
                   1136:            if (n == -1) {
                   1137:                if (errno == EINTR || errno == EAGAIN)
                   1138:                    continue;
                   1139:                warning(_("error reading from signal pipe"));
                   1140:                goto done;
                   1141:            }
                   1142:            /*
                   1143:             * Handle SIGCHLD specially and deliver other signals
1.1.1.3   misho    1144:             * directly to the command.
1.1       misho    1145:             */
1.1.1.2   misho    1146:            if (signo == SIGCHLD) {
                   1147:                if (!handle_sigchld(backchannel, &cstat))
                   1148:                    alive = false;
                   1149:            } else {
1.1.1.3   misho    1150:                deliver_signal(cmnd_pid, signo, false);
1.1.1.2   misho    1151:            }
1.1       misho    1152:            continue;
                   1153:        }
                   1154:        if (errpipe[0] != -1 && FD_ISSET(errpipe[0], fdsr)) {
                   1155:            /* read errno or EOF from command pipe */
                   1156:            n = read(errpipe[0], &cstat, sizeof(cstat));
                   1157:            if (n == -1) {
                   1158:                if (errno == EINTR)
                   1159:                    continue;
                   1160:                warning(_("error reading from pipe"));
                   1161:                goto done;
                   1162:            }
                   1163:            /* Got errno or EOF, either way we are done with errpipe. */
                   1164:            FD_CLR(errpipe[0], fdsr);
                   1165:            close(errpipe[0]);
                   1166:            errpipe[0] = -1;
                   1167:        }
                   1168:        if (FD_ISSET(backchannel, fdsr)) {
                   1169:            struct command_status cstmp;
                   1170: 
                   1171:            /* read command from backchannel, should be a signal */
                   1172:            n = recv(backchannel, &cstmp, sizeof(cstmp), 0);
                   1173:            if (n == -1) {
                   1174:                if (errno == EINTR)
                   1175:                    continue;
                   1176:                warning(_("error reading from socketpair"));
                   1177:                goto done;
                   1178:            }
                   1179:            if (cstmp.type != CMD_SIGNO) {
                   1180:                warningx(_("unexpected reply type on backchannel: %d"),
                   1181:                    cstmp.type);
                   1182:                continue;
                   1183:            }
1.1.1.3   misho    1184:            deliver_signal(cmnd_pid, cstmp.val, true);
1.1       misho    1185:        }
                   1186:     }
                   1187: 
                   1188: done:
                   1189:     if (alive) {
                   1190:        /* XXX An error occurred, should send an error back. */
1.1.1.3   misho    1191:        kill(cmnd_pid, SIGKILL);
1.1       misho    1192:     } else {
                   1193:        /* Send parent status. */
                   1194:        send_status(backchannel, &cstat);
                   1195:     }
1.1.1.2   misho    1196:     sudo_debug_exit_int(__func__, __FILE__, __LINE__, sudo_debug_subsys, 1);
1.1       misho    1197:     _exit(1);
                   1198: 
                   1199: bad:
1.1.1.2   misho    1200:     debug_return_int(errno);
1.1       misho    1201: }
                   1202: 
                   1203: /*
                   1204:  * Flush any output buffered in iobufs or readable from the fds.
                   1205:  * Does not read from /dev/tty.
                   1206:  */
                   1207: static void
                   1208: flush_output(void)
                   1209: {
                   1210:     struct io_buffer *iob;
                   1211:     struct timeval tv;
                   1212:     fd_set *fdsr, *fdsw;
                   1213:     int nready, nwriters, maxfd = -1;
1.1.1.2   misho    1214:     debug_decl(flush_output, SUDO_DEBUG_EXEC);
1.1       misho    1215: 
                   1216:     /* Determine maxfd */
                   1217:     for (iob = iobufs; iob; iob = iob->next) {
                   1218:        if (iob->rfd > maxfd)
                   1219:            maxfd = iob->rfd;
                   1220:        if (iob->wfd > maxfd)
                   1221:            maxfd = iob->wfd;
                   1222:     }
                   1223:     if (maxfd == -1)
1.1.1.2   misho    1224:        debug_return;
1.1       misho    1225: 
1.1.1.2   misho    1226:     fdsr = emalloc2(howmany(maxfd + 1, NFDBITS), sizeof(fd_mask));
                   1227:     fdsw = emalloc2(howmany(maxfd + 1, NFDBITS), sizeof(fd_mask));
1.1       misho    1228:     for (;;) {
1.1.1.2   misho    1229:        memset(fdsw, 0, howmany(maxfd + 1, NFDBITS) * sizeof(fd_mask));
                   1230:        memset(fdsr, 0, howmany(maxfd + 1, NFDBITS) * sizeof(fd_mask));
1.1       misho    1231: 
                   1232:        nwriters = 0;
                   1233:        for (iob = iobufs; iob; iob = iob->next) {
                   1234:            /* Don't read from /dev/tty while flushing. */
                   1235:            if (io_fds[SFD_USERTTY] != -1 && iob->rfd == io_fds[SFD_USERTTY])
                   1236:                continue;
                   1237:            if (iob->rfd == -1 && iob->wfd == -1)
                   1238:                continue;
                   1239:            if (iob->off == iob->len) {
                   1240:                iob->off = iob->len = 0;
                   1241:                /* Forward the EOF from reader to writer. */
                   1242:                if (iob->rfd == -1) {
                   1243:                    safe_close(iob->wfd);
                   1244:                    iob->wfd = -1;
                   1245:                }
                   1246:            }
                   1247:            if (iob->rfd != -1) {
                   1248:                if (iob->len != sizeof(iob->buf))
                   1249:                    FD_SET(iob->rfd, fdsr);
                   1250:            }
                   1251:            if (iob->wfd != -1) {
                   1252:                if (iob->len > iob->off) {
                   1253:                    nwriters++;
                   1254:                    FD_SET(iob->wfd, fdsw);
                   1255:                }
                   1256:            }
                   1257:        }
                   1258: 
                   1259:        /* Don't sleep in select if there are no buffers that need writing. */
                   1260:        tv.tv_sec = 0;
                   1261:        tv.tv_usec = 0;
                   1262:        nready = select(maxfd + 1, fdsr, fdsw, NULL, nwriters ? NULL : &tv);
                   1263:        if (nready <= 0) {
                   1264:            if (nready == 0)
                   1265:                break; /* all I/O flushed */
1.1.1.2   misho    1266:            if (errno == EINTR || errno == ENOMEM)
1.1       misho    1267:                continue;
1.1.1.2   misho    1268:            warning(_("select failed"));
1.1       misho    1269:        }
1.1.1.2   misho    1270:        if (perform_io(fdsr, fdsw, NULL) != 0 || nready == -1)
1.1       misho    1271:            break;
                   1272:     }
                   1273:     efree(fdsr);
                   1274:     efree(fdsw);
1.1.1.2   misho    1275:     debug_return;
1.1       misho    1276: }
                   1277: 
                   1278: /*
                   1279:  * Sets up std{in,out,err} and executes the actual command.
                   1280:  * Returns only if execve() fails.
                   1281:  */
                   1282: static void
1.1.1.4 ! misho    1283: exec_pty(struct command_details *details,
        !          1284:     struct command_status *cstat, int *errfd)
1.1       misho    1285: {
                   1286:     pid_t self = getpid();
1.1.1.2   misho    1287:     debug_decl(exec_pty, SUDO_DEBUG_EXEC);
1.1       misho    1288: 
1.1.1.4 ! misho    1289:     /* Register cleanup function */
        !          1290:     fatal_callback_register(pty_cleanup);
        !          1291: 
1.1.1.3   misho    1292:     /* Set command process group here too to avoid a race. */
1.1       misho    1293:     setpgid(0, self);
                   1294: 
                   1295:     /* Wire up standard fds, note that stdout/stderr may be pipes. */
                   1296:     if (dup2(io_fds[SFD_STDIN], STDIN_FILENO) == -1 ||
                   1297:        dup2(io_fds[SFD_STDOUT], STDOUT_FILENO) == -1 ||
                   1298:        dup2(io_fds[SFD_STDERR], STDERR_FILENO) == -1)
1.1.1.4 ! misho    1299:        fatal("dup2");
1.1       misho    1300: 
                   1301:     /* Wait for parent to grant us the tty if we are foreground. */
1.1.1.4 ! misho    1302:     if (foreground && !ISSET(details->flags, CD_EXEC_BG)) {
1.1       misho    1303:        while (tcgetpgrp(io_fds[SFD_SLAVE]) != self)
                   1304:            ; /* spin */
                   1305:     }
                   1306: 
                   1307:     /* We have guaranteed that the slave fd is > 2 */
                   1308:     if (io_fds[SFD_SLAVE] != -1)
                   1309:        close(io_fds[SFD_SLAVE]);
                   1310:     if (io_fds[SFD_STDIN] != io_fds[SFD_SLAVE])
                   1311:        close(io_fds[SFD_STDIN]);
                   1312:     if (io_fds[SFD_STDOUT] != io_fds[SFD_SLAVE])
                   1313:        close(io_fds[SFD_STDOUT]);
                   1314:     if (io_fds[SFD_STDERR] != io_fds[SFD_SLAVE])
                   1315:        close(io_fds[SFD_STDERR]);
                   1316: 
1.1.1.4 ! misho    1317:     /* Execute command; only returns on error. */
        !          1318:     exec_cmnd(details, cstat, errfd);
1.1.1.2   misho    1319: 
                   1320:     debug_return;
1.1       misho    1321: }
                   1322: 
                   1323: /*
                   1324:  * Propagates tty size change signals to pty being used by the command.
                   1325:  */
                   1326: static void
                   1327: sync_ttysize(int src, int dst)
                   1328: {
                   1329: #ifdef TIOCGWINSZ
                   1330:     struct winsize wsize;
                   1331:     pid_t pgrp;
1.1.1.2   misho    1332:     debug_decl(sync_ttysize, SUDO_DEBUG_EXEC);
1.1       misho    1333: 
                   1334:     if (ioctl(src, TIOCGWINSZ, &wsize) == 0) {
                   1335:            ioctl(dst, TIOCSWINSZ, &wsize);
                   1336:            if ((pgrp = tcgetpgrp(dst)) != -1)
                   1337:                killpg(pgrp, SIGWINCH);
                   1338:     }
1.1.1.2   misho    1339: 
                   1340:     debug_return;
1.1       misho    1341: #endif
                   1342: }
                   1343: 
                   1344: /*
                   1345:  * Handler for SIGWINCH in parent.
                   1346:  */
                   1347: static void
                   1348: sigwinch(int s)
                   1349: {
                   1350:     int serrno = errno;
                   1351: 
                   1352:     sync_ttysize(io_fds[SFD_USERTTY], io_fds[SFD_SLAVE]);
                   1353:     errno = serrno;
                   1354: }
                   1355: 
                   1356: /*
                   1357:  * Only close the fd if it is not /dev/tty or std{in,out,err}.
                   1358:  * Return value is the same as send(2).
                   1359:  */
                   1360: static int
                   1361: safe_close(int fd)
                   1362: {
1.1.1.2   misho    1363:     debug_decl(safe_close, SUDO_DEBUG_EXEC);
                   1364: 
1.1       misho    1365:     /* Avoid closing /dev/tty or std{in,out,err}. */
                   1366:     if (fd < 3 || fd == io_fds[SFD_USERTTY]) {
                   1367:        errno = EINVAL;
1.1.1.2   misho    1368:        debug_return_int(-1);
1.1       misho    1369:     }
1.1.1.2   misho    1370:     debug_return_int(close(fd));
1.1       misho    1371: }

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