Ignore SIGPIPE for the duration of sudo and not just in a few select

places.  We have no control over what nss, PAM modules or sudo
plugins might do so ignoring SIGPIPE is safest.
This commit is contained in:
Todd C. Miller
2016-04-22 16:36:36 -06:00
parent 70cf5674b5
commit b4309d4aea
8 changed files with 29 additions and 37 deletions

View File

@@ -1111,6 +1111,7 @@ DDEESSCCRRIIPPTTIIOONN
++oo SIGALRM
++oo SIGHUP
++oo SIGINT
++oo SIGPIPE
++oo SIGQUIT
++oo SIGTERM
++oo SIGTSTP
@@ -1121,7 +1122,8 @@ DDEESSCCRRIIPPTTIIOONN
call the plugin's cclloossee() function with an exit status of 128 plus the
value of the signal that was received. This allows for consistent
logging of commands killed by a signal for plugins that log such
information in their cclloossee() function.
information in their cclloossee() function. An exception to this is SIGPIPE,
which is ignored until the command is executed.
A plugin may temporarily install its own signal handlers but must restore
the original handler before the plugin function returns.

View File

@@ -1978,6 +1978,9 @@ executed:
\fRSIGINT\fR
.TP 4n
\fB\(bu\fR
\fRSIGPIPE\fR
.TP 4n
\fB\(bu\fR
\fRSIGQUIT\fR
.TP 4n
\fB\(bu\fR
@@ -2003,6 +2006,9 @@ This allows for consistent logging of commands killed by a signal
for plugins that log such information in their
\fBclose\fR()
function.
An exception to this is
\fRSIGPIPE\fR,
which is ignored until the command is executed.
.PP
A plugin may temporarily install its own signal handlers but must
restore the original handler before the plugin function returns.

View File

@@ -1735,6 +1735,8 @@ executed:
.It
.Dv SIGINT
.It
.Dv SIGPIPE
.It
.Dv SIGQUIT
.It
.Dv SIGTERM
@@ -1756,6 +1758,9 @@ This allows for consistent logging of commands killed by a signal
for plugins that log such information in their
.Fn close
function.
An exception to this is
.Ev SIGPIPE ,
which is ignored until the command is executed.
.Pp
A plugin may temporarily install its own signal handlers but must
restore the original handler before the plugin function returns.

View File

@@ -2975,17 +2975,10 @@ sudo_ldap_open(struct sudo_nss *nss)
{
LDAP *ld;
int rc = -1;
sigaction_t sa, saved_sa_pipe;
bool ldapnoinit = false;
struct sudo_ldap_handle *handle;
debug_decl(sudo_ldap_open, SUDOERS_DEBUG_LDAP)
/* Ignore SIGPIPE if we cannot bind to the server. */
memset(&sa, 0, sizeof(sa));
sigemptyset(&sa.sa_mask);
sa.sa_handler = SIG_IGN;
(void) sigaction(SIGPIPE, &sa, &saved_sa_pipe);
if (!sudo_ldap_read_config())
goto done;
@@ -3071,7 +3064,6 @@ sudo_ldap_open(struct sudo_nss *nss)
nss->handle = handle;
done:
(void) sigaction(SIGPIPE, &saved_sa_pipe, NULL);
debug_return_int(rc == LDAP_SUCCESS ? 0 : -1);
}

View File

@@ -542,7 +542,6 @@ send_mail(const char *fmt, ...)
const char *timestr;
int fd, pfd[2], status;
pid_t pid, rv;
sigaction_t sa;
struct stat sb;
va_list ap;
#ifndef NO_ROOT_MAILER
@@ -619,13 +618,6 @@ send_mail(const char *fmt, ...)
sudo_endgrent();
closefrom(STDERR_FILENO + 1);
/* Ignore SIGPIPE in case mailer exits prematurely (or is missing). */
memset(&sa, 0, sizeof(sa));
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_INTERRUPT;
sa.sa_handler = SIG_IGN;
(void) sigaction(SIGPIPE, &sa, NULL);
if (pipe(pfd) == -1) {
mysyslog(LOG_ERR, _("unable to open pipe: %m"));
sudo_debug_printf(SUDO_DEBUG_ERROR, "unable to open pipe: %s",

View File

@@ -30,6 +30,7 @@
#include <signal.h>
#include "sudo.h"
#include "sudo_exec.h"
int signal_pipe[2];
@@ -151,6 +152,13 @@ init_signals(void)
break;
}
}
/* Ignore SIGPIPE until exec. */
if (saved_signals[SAVED_SIGPIPE].sa.sa_handler != SIG_IGN) {
sa.sa_handler = SIG_IGN;
if (sigaction(SIGPIPE, &sa, NULL) != 0)
sudo_warn(U_("unable to set handler for signal %d"), SIGPIPE);
}
debug_return;
}

View File

@@ -188,10 +188,13 @@ main(int argc, char *argv[], char *envp[])
/* Make sure we are setuid root. */
sudo_check_suid(argc > 0 ? argv[0] : "sudo");
/* Reset signal mask and save signal state. */
/* Save original signal state and setup default signal handlers. */
save_signals();
init_signals();
/* Reset signal mask to the default value (unblock). */
(void) sigemptyset(&mask);
(void) sigprocmask(SIG_SETMASK, &mask, NULL);
save_signals();
/* Parse the rest of sudo.conf. */
sudo_conf_read(NULL, SUDO_CONF_ALL & ~SUDO_CONF_DEBUG);
@@ -230,8 +233,6 @@ main(int argc, char *argv[], char *envp[])
sudo_fatalx(U_("unable to initialize policy plugin"));
}
init_signals();
switch (sudo_mode & MODE_MASK) {
case MODE_VERSION:
policy_show_version(&policy_plugin, !user_details.uid);

View File

@@ -85,7 +85,7 @@ tgetpass(const char *prompt, int timeout, int flags,
struct sudo_conv_callback *callback)
{
sigaction_t sa, savealrm, saveint, savehup, savequit, saveterm;
sigaction_t savetstp, savettin, savettou, savepipe;
sigaction_t savetstp, savettin, savettou;
char *pass;
static const char *askpass;
static char buf[SUDO_CONV_REPL_MAX + 1];
@@ -168,10 +168,6 @@ restart:
(void) sigaction(SIGTTIN, &sa, &savettin);
(void) sigaction(SIGTTOU, &sa, &savettou);
/* Ignore SIGPIPE in case stdin is a pipe and TGP_STDIN is set */
sa.sa_handler = SIG_IGN;
(void) sigaction(SIGPIPE, &sa, &savepipe);
if (prompt) {
if (write(output, prompt, strlen(prompt)) == -1)
goto restore;
@@ -198,7 +194,6 @@ restore:
(void) sigaction(SIGTSTP, &savetstp, NULL);
(void) sigaction(SIGTTIN, &savettin, NULL);
(void) sigaction(SIGTTOU, &savettou, NULL);
(void) sigaction(SIGPIPE, &savepipe, NULL);
/* Restore old tty settings. */
if (!ISSET(flags, TGP_ECHO)) {
@@ -252,7 +247,6 @@ static char *
sudo_askpass(const char *askpass, const char *prompt)
{
static char buf[SUDO_CONV_REPL_MAX + 1], *pass;
sigaction_t sa, saved_sa_pipe;
int pfd[2], status;
pid_t child;
debug_decl(sudo_askpass, SUDO_DEBUG_CONV)
@@ -286,18 +280,10 @@ sudo_askpass(const char *askpass, const char *prompt)
_exit(255);
}
/* Ignore SIGPIPE in case child exits prematurely */
memset(&sa, 0, sizeof(sa));
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_INTERRUPT;
sa.sa_handler = SIG_IGN;
(void) sigaction(SIGPIPE, &sa, &saved_sa_pipe);
/* Get response from child (askpass) and restore SIGPIPE handler */
/* Get response from child (askpass). */
(void) close(pfd[1]);
pass = getln(pfd[0], buf, sizeof(buf), 0);
(void) close(pfd[0]);
(void) sigaction(SIGPIPE, &saved_sa_pipe, NULL);
/* Wait for child to exit. */
for (;;) {