From 9479bb623bde5d0ca01c68e08be047e1a77aa97b Mon Sep 17 00:00:00 2001 From: "Todd C. Miller" Date: Fri, 11 Jan 2013 14:34:09 -0500 Subject: [PATCH] Add exec_background option in plugin command info and a sudoers option to match. When set, commands are started in the background and automatically foregrounded as needed. There are issues with some ill-mannered programs (like Linux su) so this is not the default. --- doc/sudo_plugin.cat | 45 ++++++++++++++++++++++++- doc/sudo_plugin.man.in | 65 +++++++++++++++++++++++++++++++++++-- doc/sudo_plugin.mdoc.in | 64 ++++++++++++++++++++++++++++++++++-- doc/sudoers.cat | 40 ++++++++++++++++++++++- doc/sudoers.man.in | 59 ++++++++++++++++++++++++++++++++- doc/sudoers.mdoc.in | 60 ++++++++++++++++++++++++++++++++-- plugins/sudoers/def_data.c | 4 +++ plugins/sudoers/def_data.h | 2 ++ plugins/sudoers/def_data.in | 3 ++ plugins/sudoers/sudoers.c | 4 +-- src/exec_pty.c | 29 ++++------------- src/sudo.c | 9 ++++- src/sudo.h | 3 +- 13 files changed, 351 insertions(+), 36 deletions(-) diff --git a/doc/sudo_plugin.cat b/doc/sudo_plugin.cat index 7eec25a0b..e433be588 100644 --- a/doc/sudo_plugin.cat +++ b/doc/sudo_plugin.cat @@ -592,6 +592,49 @@ DDEESSCCRRIIPPTTIIOONN If not set, ssuuddoo will base the new entry on the invoking user's existing entry. + exec_background=bool + By default, ssuuddoo runs a command as the foreground + process as long as ssuuddoo itself is running in the + foreground. When _e_x_e_c___b_a_c_k_g_r_o_u_n_d is enabled and the + command is being run in a pty (due to I/O logging or + the _u_s_e___p_t_y setting), the command will be run as a + background process. Attempts to read from the + controlling terminal (or to change terminal settings) + will result in the command being suspended with the + SIGTTIN signal (or SIGTTOU in the case of terminal + settings). If this happens when ssuuddoo is a foreground + process, the command will be granted the controlling + terminal and resumed in the foreground with no user + intervention required. The advantage of initially + running the command in the background is that ssuuddoo need + not read from the terminal unless the command + explicitly requests it. Otherwise, any terminal input + must be passed to the command, whether it has required + it or not (the kernel buffers terminals so it is not + possible to tell whether the command really wants the + input). This is different from historic _s_u_d_o behavior + or when the command is not being run in a pty. + + For this to work seamlessly, the operating system must + support the automatic restarting of system calls. + Unfortunately, not all operating systems do this by + default, and even those that do may have bugs. For + example, Mac OS X fails to restart the ttccggeettaattttrr() and + ttccsseettaattttrr() system calls (this is a bug in Mac OS X). + Furthermore, because this behavior depends on the + command stopping with the SIGTTIN or SIGTTOU signals, + programs that catch these signals and suspend + themselves with a different signal (usually SIGTOP) + will not be automatically foregrounded. Some versions + of the linux su(1) command behave this way. Because of + this, a plugin should not set _e_x_e_c___b_a_c_k_g_r_o_u_n_d unless it + is explicitly enabled by the administrator and there + should be a way to enabled or disable it on a per- + command basis. + + This setting has no effect unless I/O logging is + enabled or _u_s_e___p_t_y is enabled. + Unsupported values will be ignored. argv_out @@ -1364,4 +1407,4 @@ DDIISSCCLLAAIIMMEERR file distributed with ssuuddoo or http://www.sudo.ws/sudo/license.html for complete details. -Sudo 1.8.7 November 26, 2012 Sudo 1.8.7 +Sudo 1.8.7 Janurary 11, 2013 Sudo 1.8.7 diff --git a/doc/sudo_plugin.man.in b/doc/sudo_plugin.man.in index 06bdd1457..6a07c2b2a 100644 --- a/doc/sudo_plugin.man.in +++ b/doc/sudo_plugin.man.in @@ -1,7 +1,7 @@ .\" DO NOT EDIT THIS FILE, IT IS NOT THE MASTER! .\" IT IS GENERATED AUTOMATICALLY FROM sudo_plugin.mdoc.in .\" -.\" Copyright (c) 2009-2012 Todd C. Miller +.\" Copyright (c) 2009-2013 Todd C. Miller .\" .\" Permission to use, copy, modify, and distribute this software for any .\" purpose with or without fee is hereby granted, provided that the above @@ -16,7 +16,7 @@ .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.TH "SUDO_PLUGIN" "5" "November 26, 2012" "Sudo @PACKAGE_VERSION@" "OpenBSD Programmer's Manual" +.TH "SUDO_PLUGIN" "5" "Janurary 11, 2013" "Sudo @PACKAGE_VERSION@" "OpenBSD Programmer's Manual" .nh .if n .ad l .SH "NAME" @@ -1018,6 +1018,67 @@ If not set, \fBsudo\fR will base the new entry on the invoking user's existing entry. +.TP 6n +exec_background=bool +By default, +\fBsudo\fR +runs a command as the foreground process as long as +\fBsudo\fR +itself is running in the foreground. +When +\fIexec_background\fR +is enabled and the command is being run in a pty (due to I/O logging +or the +\fIuse_pty\fR +setting), the command will be run as a background process. +Attempts to read from the controlling terminal (or to change terminal +settings) will result in the command being suspended with the +\fRSIGTTIN\fR +signal (or +\fRSIGTTOU\fR +in the case of terminal settings). +If this happens when +\fBsudo\fR +is a foreground process, the command will be granted the controlling terminal +and resumed in the foreground with no user intervention required. +The advantage of initially running the command in the background is that +\fBsudo\fR +need not read from the terminal unless the command explicitly requests it. +Otherwise, any terminal input must be passed to the command, whether it +has required it or not (the kernel buffers terminals so it is not possible +to tell whether the command really wants the input). +This is different from historic +\fIsudo\fR +behavior or when the command is not being run in a pty. +.sp +For this to work seamlessly, the operating system must support the +automatic restarting of system calls. +Unfortunately, not all operating systems do this by default, +and even those that do may have bugs. +For example, Mac OS X fails to restart the +\fBtcgetattr\fR() +and +\fBtcsetattr\fR() +system calls (this is a bug in Mac OS X). +Furthermore, because this behavior depends on the command stopping with the +\fRSIGTTIN\fR +or +\fRSIGTTOU\fR +signals, programs that catch these signals and suspend themselves +with a different signal (usually +\fRSIGTOP\fR) +will not be automatically foregrounded. +Some versions of the linux +su(1) +command behave this way. +Because of this, a plugin should not set +\fIexec_background\fR +unless it is explicitly enabled by the administrator and there should +be a way to enabled or disable it on a per-command basis. +.sp +This setting has no effect unless I/O logging is enabled or +\fIuse_pty\fR +is enabled. .PP Unsupported values will be ignored. .PP diff --git a/doc/sudo_plugin.mdoc.in b/doc/sudo_plugin.mdoc.in index 6e18b256a..e677bc400 100644 --- a/doc/sudo_plugin.mdoc.in +++ b/doc/sudo_plugin.mdoc.in @@ -1,5 +1,5 @@ .\" -.\" Copyright (c) 2009-2012 Todd C. Miller +.\" Copyright (c) 2009-2013 Todd C. Miller .\" .\" Permission to use, copy, modify, and distribute this software for any .\" purpose with or without fee is hereby granted, provided that the above @@ -14,7 +14,7 @@ .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.Dd November 26, 2012 +.Dd Janurary 11, 2013 .Dt SUDO_PLUGIN @mansectform@ .Os Sudo @PACKAGE_VERSION@ .Sh NAME @@ -900,6 +900,66 @@ If not set, .Nm sudo will base the new entry on the invoking user's existing entry. +.It exec_background=bool +By default, +.Nm sudo +runs a command as the foreground process as long as +.Nm sudo +itself is running in the foreground. +When +.Em exec_background +is enabled and the command is being run in a pty (due to I/O logging +or the +.Em use_pty +setting), the command will be run as a background process. +Attempts to read from the controlling terminal (or to change terminal +settings) will result in the command being suspended with the +.Dv SIGTTIN +signal (or +.Dv SIGTTOU +in the case of terminal settings). +If this happens when +.Nm sudo +is a foreground process, the command will be granted the controlling terminal +and resumed in the foreground with no user intervention required. +The advantage of initially running the command in the background is that +.Nm sudo +need not read from the terminal unless the command explicitly requests it. +Otherwise, any terminal input must be passed to the command, whether it +has required it or not (the kernel buffers terminals so it is not possible +to tell whether the command really wants the input). +This is different from historic +.Em sudo +behavior or when the command is not being run in a pty. +.Pp +For this to work seamlessly, the operating system must support the +automatic restarting of system calls. +Unfortunately, not all operating systems do this by default, +and even those that do may have bugs. +For example, Mac OS X fails to restart the +.Fn tcgetattr +and +.Fn tcsetattr +system calls (this is a bug in Mac OS X). +Furthermore, because this behavior depends on the command stopping with the +.Dv SIGTTIN +or +.Dv SIGTTOU +signals, programs that catch these signals and suspend themselves +with a different signal (usually +.Dv SIGTOP ) +will not be automatically foregrounded. +Some versions of the linux +.Xr su 1 +command behave this way. +Because of this, a plugin should not set +.Em exec_background +unless it is explicitly enabled by the administrator and there should +be a way to enabled or disable it on a per-command basis. +.Pp +This setting has no effect unless I/O logging is enabled or +.Em use_pty +is enabled. .El .Pp Unsupported values will be ignored. diff --git a/doc/sudoers.cat b/doc/sudoers.cat index 9b6fa2105..3476eebc5 100644 --- a/doc/sudoers.cat +++ b/doc/sudoers.cat @@ -732,6 +732,44 @@ SSUUDDOOEERRSS OOPPTTIIOONNSS This flag is _o_n by default when ssuuddoo is compiled with zzlliibb support. + exec_background By default, ssuuddoo runs a command as the foreground + process as long as ssuuddoo itself is running in the + foreground. When the _e_x_e_c___b_a_c_k_g_r_o_u_n_d flag is enabled + and the command is being run in a pty (due to I/O + logging or the _u_s_e___p_t_y flag), the command will be run + as a background process. Attempts to read from the + controlling terminal (or to change terminal settings) + will result in the command being suspended with the + SIGTTIN signal (or SIGTTOU in the case of terminal + settings). If this happens when ssuuddoo is a foreground + process, the command will be granted the controlling + terminal and resumed in the foreground with no user + intervention required. The advantage of initially + running the command in the background is that ssuuddoo need + not read from the terminal unless the command + explicitly requests it. Otherwise, any terminal input + must be passed to the command, whether it has required + it or not (the kernel buffers terminals so it is not + possible to tell whether the command really wants the + input). This is different from historic _s_u_d_o behavior + or when the command is not being run in a pty. + + For this to work seamlessly, the operating system must + support the automatic restarting of system calls. + Unfortunately, not all operating systems do this by + default, and even those that do may have bugs. For + example, Mac OS X fails to restart the ttccggeettaattttrr() and + ttccsseettaattttrr() system calls (this is a bug in Mac OS X). + Furthermore, because this behavior depends on the + command stopping with the SIGTTIN or SIGTTOU signals, + programs that catch these signals and suspend + themselves with a different signal (usually SIGTOP) + will not be automatically foregrounded. Some versions + of the linux su(1) command behave this way. + + This setting has no effect unless I/O logging is + enabled or _u_s_e___p_t_y is enabled. + env_editor If set, vviissuuddoo will use the value of the EDITOR or VISUAL environment variables before falling back on the default editor list. Note that this may create a @@ -2092,4 +2130,4 @@ DDIISSCCLLAAIIMMEERR file distributed with ssuuddoo or http://www.sudo.ws/sudo/license.html for complete details. -Sudo 1.8.6 October 23, 2012 Sudo 1.8.6 +Sudo 1.8.7 October 23, 2012 Sudo 1.8.7 diff --git a/doc/sudoers.man.in b/doc/sudoers.man.in index 2e22114c6..d1347b6de 100644 --- a/doc/sudoers.man.in +++ b/doc/sudoers.man.in @@ -1,7 +1,7 @@ .\" DO NOT EDIT THIS FILE, IT IS NOT THE MASTER! .\" IT IS GENERATED AUTOMATICALLY FROM sudoers.mdoc.in .\" -.\" Copyright (c) 1994-1996, 1998-2005, 2007-2012 +.\" Copyright (c) 1994-1996, 1998-2005, 2007-2013 .\" Todd C. Miller .\" .\" Permission to use, copy, modify, and distribute this software for any @@ -1639,6 +1639,63 @@ is compiled with \fBzlib\fR support. .TP 18n +exec_background +By default, +\fBsudo\fR +runs a command as the foreground process as long as +\fBsudo\fR +itself is running in the foreground. +When the +\fIexec_background\fR +flag is enabled and the command is being run in a pty (due to I/O logging +or the +\fIuse_pty\fR +flag), the command will be run as a background process. +Attempts to read from the controlling terminal (or to change terminal +settings) will result in the command being suspended with the +\fRSIGTTIN\fR +signal (or +\fRSIGTTOU\fR +in the case of terminal settings). +If this happens when +\fBsudo\fR +is a foreground process, the command will be granted the controlling terminal +and resumed in the foreground with no user intervention required. +The advantage of initially running the command in the background is that +\fBsudo\fR +need not read from the terminal unless the command explicitly requests it. +Otherwise, any terminal input must be passed to the command, whether it +has required it or not (the kernel buffers terminals so it is not possible +to tell whether the command really wants the input). +This is different from historic +\fIsudo\fR +behavior or when the command is not being run in a pty. +.sp +For this to work seamlessly, the operating system must support the +automatic restarting of system calls. +Unfortunately, not all operating systems do this by default, +and even those that do may have bugs. +For example, Mac OS X fails to restart the +\fBtcgetattr\fR() +and +\fBtcsetattr\fR() +system calls (this is a bug in Mac OS X). +Furthermore, because this behavior depends on the command stopping with the +\fRSIGTTIN\fR +or +\fRSIGTTOU\fR +signals, programs that catch these signals and suspend themselves +with a different signal (usually +\fRSIGTOP\fR) +will not be automatically foregrounded. +Some versions of the linux +su(1) +command behave this way. +.sp +This setting has no effect unless I/O logging is enabled or +\fIuse_pty\fR +is enabled. +.TP 18n env_editor If set, \fBvisudo\fR diff --git a/doc/sudoers.mdoc.in b/doc/sudoers.mdoc.in index b912e8ca5..5f74075cf 100644 --- a/doc/sudoers.mdoc.in +++ b/doc/sudoers.mdoc.in @@ -1,5 +1,5 @@ .\" -.\" Copyright (c) 1994-1996, 1998-2005, 2007-2012 +.\" Copyright (c) 1994-1996, 1998-2005, 2007-2013 .\" Todd C. Miller .\" .\" Permission to use, copy, modify, and distribute this software for any @@ -19,7 +19,7 @@ .\" Agency (DARPA) and Air Force Research Laboratory, Air Force .\" Materiel Command, USAF, under agreement number F39502-99-1-0512. .\" -.Dd October 23, 2012 +.Dd January 11, 2013 .Dt SUDOERS @mansectform@ .Os Sudo @PACKAGE_VERSION@ .Sh NAME @@ -1521,6 +1521,62 @@ by default when is compiled with .Sy zlib support. +.It exec_background +By default, +.Nm sudo +runs a command as the foreground process as long as +.Nm sudo +itself is running in the foreground. +When the +.Em exec_background +flag is enabled and the command is being run in a pty (due to I/O logging +or the +.Em use_pty +flag), the command will be run as a background process. +Attempts to read from the controlling terminal (or to change terminal +settings) will result in the command being suspended with the +.Dv SIGTTIN +signal (or +.Dv SIGTTOU +in the case of terminal settings). +If this happens when +.Nm sudo +is a foreground process, the command will be granted the controlling terminal +and resumed in the foreground with no user intervention required. +The advantage of initially running the command in the background is that +.Nm sudo +need not read from the terminal unless the command explicitly requests it. +Otherwise, any terminal input must be passed to the command, whether it +has required it or not (the kernel buffers terminals so it is not possible +to tell whether the command really wants the input). +This is different from historic +.Em sudo +behavior or when the command is not being run in a pty. +.Pp +For this to work seamlessly, the operating system must support the +automatic restarting of system calls. +Unfortunately, not all operating systems do this by default, +and even those that do may have bugs. +For example, Mac OS X fails to restart the +.Fn tcgetattr +and +.Fn tcsetattr +system calls (this is a bug in Mac OS X). +Furthermore, because this behavior depends on the command stopping with the +.Dv SIGTTIN +or +.Dv SIGTTOU +signals, programs that catch these signals and suspend themselves +with a different signal (usually +.Dv SIGTOP ) +will not be automatically foregrounded. +Some versions of the linux +.Xr su 1 +command behave this way. +.Pp +This setting has no effect unless I/O logging is enabled or +.Em use_pty +is enabled. .It env_editor If set, .Nm visudo diff --git a/plugins/sudoers/def_data.c b/plugins/sudoers/def_data.c index ff8f21fd7..b70a5af09 100644 --- a/plugins/sudoers/def_data.c +++ b/plugins/sudoers/def_data.c @@ -350,6 +350,10 @@ struct sudo_defs_types sudo_defs_table[] = { "limitprivs", T_STR, N_("Set of limit privileges"), NULL, + }, { + "exec_background", T_FLAG, + N_("Run commands on a pty in the background"), + NULL, }, { NULL, 0, NULL } diff --git a/plugins/sudoers/def_data.h b/plugins/sudoers/def_data.h index 774b39994..0808a6c41 100644 --- a/plugins/sudoers/def_data.h +++ b/plugins/sudoers/def_data.h @@ -162,6 +162,8 @@ #define I_PRIVS 80 #define def_limitprivs (sudo_defs_table[81].sd_un.str) #define I_LIMITPRIVS 81 +#define def_exec_background (sudo_defs_table[82].sd_un.flag) +#define I_EXEC_BACKGROUND 82 enum def_tuple { never, diff --git a/plugins/sudoers/def_data.in b/plugins/sudoers/def_data.in index 430f235bc..deb0a91fc 100644 --- a/plugins/sudoers/def_data.in +++ b/plugins/sudoers/def_data.in @@ -259,3 +259,6 @@ privs limitprivs T_STR "Set of limit privileges" +exec_background + T_FLAG + "Run commands on a pty in the background" diff --git a/plugins/sudoers/sudoers.c b/plugins/sudoers/sudoers.c index 4b6f4681e..655f887ac 100644 --- a/plugins/sudoers/sudoers.c +++ b/plugins/sudoers/sudoers.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1993-1996, 1998-2012 Todd C. Miller + * Copyright (c) 1993-1996, 1998-2013 Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -526,7 +526,7 @@ done: error_disable_setjmp(); rewind_perms(); - /* Restore signal handlers before we exec. */ + /* Restore signal handlers before we return. */ (void) sigaction(SIGINT, &saved_sa_int, NULL); (void) sigaction(SIGQUIT, &saved_sa_quit, NULL); (void) sigaction(SIGTSTP, &saved_sa_tstp, NULL); diff --git a/src/exec_pty.c b/src/exec_pty.c index cb5c11dc1..b31019722 100644 --- a/src/exec_pty.c +++ b/src/exec_pty.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009-2012 Todd C. Miller + * Copyright (c) 2009-2013 Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -78,18 +78,6 @@ # define winsize ttysize #endif -/* - * Mac OS X has a bug wrt tc[gs]etpgrp where it returns EINTR if interrupted - * by a signal (usually SIGTTOU or SIGTTIN) instead of being restarted - * automatically (via ERESTART in the kernel). On other systems we can start - * the command in the background which prevents sudo from stealing /dev/tty - * input when it doesn't need to. When the command receives SIGTTOU or SIGTTIN, - * sudo will continue it in the foreground (assuming sudo is in the foreground). - */ -#ifdef __APPLE__ -# define TCSETATTR_NO_RESTART -#endif - struct io_buffer { struct io_buffer *next; int len; /* buffer length (how much produced) */ @@ -676,9 +664,8 @@ fork_pty(struct command_details *details, int sv[], int *maxfd, sigset_t *omask) sync_ttysize(io_fds[SFD_USERTTY], io_fds[SFD_SLAVE]); } -#ifdef TCSETATTR_NO_RESTART - /* Start out in raw mode if we are not part of a pipeline. */ - if (!pipeline) { + /* Start out in raw mode unless part of a pipeline or backgrounded. */ + if (!pipeline && !ISSET(details->flags, CD_EXEC_BG)) { ttymode = TERM_RAW; do { n = term_raw(io_fds[SFD_USERTTY], 0); @@ -686,7 +673,6 @@ fork_pty(struct command_details *details, int sv[], int *maxfd, sigset_t *omask) if (!n) error(1, _("unable to set terminal to raw mode")); } -#endif } /* @@ -1111,14 +1097,13 @@ exec_monitor(struct command_details *details, int backchannel) /* Put command in its own process group. */ cmnd_pgrp = cmnd_pid; setpgid(cmnd_pid, cmnd_pgrp); -#ifdef TCSETATTR_NO_RESTART + /* Make the command the foreground process for the pty slave. */ - if (foreground) { + if (foreground && !ISSET(details->flags, CD_EXEC_BG)) { do { n = tcsetpgrp(io_fds[SFD_SLAVE], cmnd_pgrp); } while (n == -1 && errno == EINTR); } -#endif /* Wait for errno on pipe, signal on backchannel or for SIGCHLD */ maxfd = MAX(MAX(errpipe[0], signal_pipe[0]), backchannel); @@ -1311,13 +1296,11 @@ exec_pty(struct command_details *details, int *errfd) dup2(io_fds[SFD_STDERR], STDERR_FILENO) == -1) error(1, "dup2"); -#ifdef TCSETATTR_NO_RESTART /* Wait for parent to grant us the tty if we are foreground. */ - if (foreground) { + if (foreground && !ISSET(details->flags, CD_EXEC_BG)) { while (tcgetpgrp(io_fds[SFD_SLAVE]) != self) ; /* spin */ } -#endif /* We have guaranteed that the slave fd is > 2 */ if (io_fds[SFD_SLAVE] != -1) diff --git a/src/sudo.c b/src/sudo.c index d90ea1854..9c08763d6 100644 --- a/src/sudo.c +++ b/src/sudo.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009-2012 Todd C. Miller + * Copyright (c) 2009-2013 Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -543,6 +543,13 @@ command_info_to_details(char * const info[], struct command_details *details) break; } break; + case 'e': + if (strncmp("exec_background=", info[i], sizeof("exec_background=") - 1) == 0) { + if (atobool(info[i] + sizeof("exec_background=") - 1) == true) + SET(details->flags, CD_EXEC_BG); + break; + } + break; case 'l': SET_STRING("login_class=", login_class) break; diff --git a/src/sudo.h b/src/sudo.h index 1509784fb..0a5c74b44 100644 --- a/src/sudo.h +++ b/src/sudo.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1993-1996, 1998-2005, 2007-2012 + * Copyright (c) 1993-1996, 1998-2005, 2007-2013 * Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any @@ -128,6 +128,7 @@ struct user_details { #define CD_RBAC_ENABLED 0x0800 #define CD_USE_PTY 0x1000 #define CD_SET_UTMP 0x2000 +#define CD_EXEC_BG 0x4000 struct command_details { uid_t uid; -- 2.40.0