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:
@@ -1111,6 +1111,7 @@ DDEESSCCRRIIPPTTIIOONN
|
|||||||
++oo SIGALRM
|
++oo SIGALRM
|
||||||
++oo SIGHUP
|
++oo SIGHUP
|
||||||
++oo SIGINT
|
++oo SIGINT
|
||||||
|
++oo SIGPIPE
|
||||||
++oo SIGQUIT
|
++oo SIGQUIT
|
||||||
++oo SIGTERM
|
++oo SIGTERM
|
||||||
++oo SIGTSTP
|
++oo SIGTSTP
|
||||||
@@ -1121,7 +1122,8 @@ DDEESSCCRRIIPPTTIIOONN
|
|||||||
call the plugin's cclloossee() function with an exit status of 128 plus the
|
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
|
value of the signal that was received. This allows for consistent
|
||||||
logging of commands killed by a signal for plugins that log such
|
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
|
A plugin may temporarily install its own signal handlers but must restore
|
||||||
the original handler before the plugin function returns.
|
the original handler before the plugin function returns.
|
||||||
|
@@ -1978,6 +1978,9 @@ executed:
|
|||||||
\fRSIGINT\fR
|
\fRSIGINT\fR
|
||||||
.TP 4n
|
.TP 4n
|
||||||
\fB\(bu\fR
|
\fB\(bu\fR
|
||||||
|
\fRSIGPIPE\fR
|
||||||
|
.TP 4n
|
||||||
|
\fB\(bu\fR
|
||||||
\fRSIGQUIT\fR
|
\fRSIGQUIT\fR
|
||||||
.TP 4n
|
.TP 4n
|
||||||
\fB\(bu\fR
|
\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
|
for plugins that log such information in their
|
||||||
\fBclose\fR()
|
\fBclose\fR()
|
||||||
function.
|
function.
|
||||||
|
An exception to this is
|
||||||
|
\fRSIGPIPE\fR,
|
||||||
|
which is ignored until the command is executed.
|
||||||
.PP
|
.PP
|
||||||
A plugin may temporarily install its own signal handlers but must
|
A plugin may temporarily install its own signal handlers but must
|
||||||
restore the original handler before the plugin function returns.
|
restore the original handler before the plugin function returns.
|
||||||
|
@@ -1735,6 +1735,8 @@ executed:
|
|||||||
.It
|
.It
|
||||||
.Dv SIGINT
|
.Dv SIGINT
|
||||||
.It
|
.It
|
||||||
|
.Dv SIGPIPE
|
||||||
|
.It
|
||||||
.Dv SIGQUIT
|
.Dv SIGQUIT
|
||||||
.It
|
.It
|
||||||
.Dv SIGTERM
|
.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
|
for plugins that log such information in their
|
||||||
.Fn close
|
.Fn close
|
||||||
function.
|
function.
|
||||||
|
An exception to this is
|
||||||
|
.Ev SIGPIPE ,
|
||||||
|
which is ignored until the command is executed.
|
||||||
.Pp
|
.Pp
|
||||||
A plugin may temporarily install its own signal handlers but must
|
A plugin may temporarily install its own signal handlers but must
|
||||||
restore the original handler before the plugin function returns.
|
restore the original handler before the plugin function returns.
|
||||||
|
@@ -2975,17 +2975,10 @@ sudo_ldap_open(struct sudo_nss *nss)
|
|||||||
{
|
{
|
||||||
LDAP *ld;
|
LDAP *ld;
|
||||||
int rc = -1;
|
int rc = -1;
|
||||||
sigaction_t sa, saved_sa_pipe;
|
|
||||||
bool ldapnoinit = false;
|
bool ldapnoinit = false;
|
||||||
struct sudo_ldap_handle *handle;
|
struct sudo_ldap_handle *handle;
|
||||||
debug_decl(sudo_ldap_open, SUDOERS_DEBUG_LDAP)
|
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())
|
if (!sudo_ldap_read_config())
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
@@ -3071,7 +3064,6 @@ sudo_ldap_open(struct sudo_nss *nss)
|
|||||||
nss->handle = handle;
|
nss->handle = handle;
|
||||||
|
|
||||||
done:
|
done:
|
||||||
(void) sigaction(SIGPIPE, &saved_sa_pipe, NULL);
|
|
||||||
debug_return_int(rc == LDAP_SUCCESS ? 0 : -1);
|
debug_return_int(rc == LDAP_SUCCESS ? 0 : -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -542,7 +542,6 @@ send_mail(const char *fmt, ...)
|
|||||||
const char *timestr;
|
const char *timestr;
|
||||||
int fd, pfd[2], status;
|
int fd, pfd[2], status;
|
||||||
pid_t pid, rv;
|
pid_t pid, rv;
|
||||||
sigaction_t sa;
|
|
||||||
struct stat sb;
|
struct stat sb;
|
||||||
va_list ap;
|
va_list ap;
|
||||||
#ifndef NO_ROOT_MAILER
|
#ifndef NO_ROOT_MAILER
|
||||||
@@ -619,13 +618,6 @@ send_mail(const char *fmt, ...)
|
|||||||
sudo_endgrent();
|
sudo_endgrent();
|
||||||
closefrom(STDERR_FILENO + 1);
|
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) {
|
if (pipe(pfd) == -1) {
|
||||||
mysyslog(LOG_ERR, _("unable to open pipe: %m"));
|
mysyslog(LOG_ERR, _("unable to open pipe: %m"));
|
||||||
sudo_debug_printf(SUDO_DEBUG_ERROR, "unable to open pipe: %s",
|
sudo_debug_printf(SUDO_DEBUG_ERROR, "unable to open pipe: %s",
|
||||||
|
@@ -30,6 +30,7 @@
|
|||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
|
||||||
#include "sudo.h"
|
#include "sudo.h"
|
||||||
|
#include "sudo_exec.h"
|
||||||
|
|
||||||
int signal_pipe[2];
|
int signal_pipe[2];
|
||||||
|
|
||||||
@@ -151,6 +152,13 @@ init_signals(void)
|
|||||||
break;
|
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;
|
debug_return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -188,10 +188,13 @@ main(int argc, char *argv[], char *envp[])
|
|||||||
/* Make sure we are setuid root. */
|
/* Make sure we are setuid root. */
|
||||||
sudo_check_suid(argc > 0 ? argv[0] : "sudo");
|
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) sigemptyset(&mask);
|
||||||
(void) sigprocmask(SIG_SETMASK, &mask, NULL);
|
(void) sigprocmask(SIG_SETMASK, &mask, NULL);
|
||||||
save_signals();
|
|
||||||
|
|
||||||
/* Parse the rest of sudo.conf. */
|
/* Parse the rest of sudo.conf. */
|
||||||
sudo_conf_read(NULL, SUDO_CONF_ALL & ~SUDO_CONF_DEBUG);
|
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"));
|
sudo_fatalx(U_("unable to initialize policy plugin"));
|
||||||
}
|
}
|
||||||
|
|
||||||
init_signals();
|
|
||||||
|
|
||||||
switch (sudo_mode & MODE_MASK) {
|
switch (sudo_mode & MODE_MASK) {
|
||||||
case MODE_VERSION:
|
case MODE_VERSION:
|
||||||
policy_show_version(&policy_plugin, !user_details.uid);
|
policy_show_version(&policy_plugin, !user_details.uid);
|
||||||
|
@@ -85,7 +85,7 @@ tgetpass(const char *prompt, int timeout, int flags,
|
|||||||
struct sudo_conv_callback *callback)
|
struct sudo_conv_callback *callback)
|
||||||
{
|
{
|
||||||
sigaction_t sa, savealrm, saveint, savehup, savequit, saveterm;
|
sigaction_t sa, savealrm, saveint, savehup, savequit, saveterm;
|
||||||
sigaction_t savetstp, savettin, savettou, savepipe;
|
sigaction_t savetstp, savettin, savettou;
|
||||||
char *pass;
|
char *pass;
|
||||||
static const char *askpass;
|
static const char *askpass;
|
||||||
static char buf[SUDO_CONV_REPL_MAX + 1];
|
static char buf[SUDO_CONV_REPL_MAX + 1];
|
||||||
@@ -168,10 +168,6 @@ restart:
|
|||||||
(void) sigaction(SIGTTIN, &sa, &savettin);
|
(void) sigaction(SIGTTIN, &sa, &savettin);
|
||||||
(void) sigaction(SIGTTOU, &sa, &savettou);
|
(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 (prompt) {
|
||||||
if (write(output, prompt, strlen(prompt)) == -1)
|
if (write(output, prompt, strlen(prompt)) == -1)
|
||||||
goto restore;
|
goto restore;
|
||||||
@@ -198,7 +194,6 @@ restore:
|
|||||||
(void) sigaction(SIGTSTP, &savetstp, NULL);
|
(void) sigaction(SIGTSTP, &savetstp, NULL);
|
||||||
(void) sigaction(SIGTTIN, &savettin, NULL);
|
(void) sigaction(SIGTTIN, &savettin, NULL);
|
||||||
(void) sigaction(SIGTTOU, &savettou, NULL);
|
(void) sigaction(SIGTTOU, &savettou, NULL);
|
||||||
(void) sigaction(SIGPIPE, &savepipe, NULL);
|
|
||||||
|
|
||||||
/* Restore old tty settings. */
|
/* Restore old tty settings. */
|
||||||
if (!ISSET(flags, TGP_ECHO)) {
|
if (!ISSET(flags, TGP_ECHO)) {
|
||||||
@@ -252,7 +247,6 @@ static char *
|
|||||||
sudo_askpass(const char *askpass, const char *prompt)
|
sudo_askpass(const char *askpass, const char *prompt)
|
||||||
{
|
{
|
||||||
static char buf[SUDO_CONV_REPL_MAX + 1], *pass;
|
static char buf[SUDO_CONV_REPL_MAX + 1], *pass;
|
||||||
sigaction_t sa, saved_sa_pipe;
|
|
||||||
int pfd[2], status;
|
int pfd[2], status;
|
||||||
pid_t child;
|
pid_t child;
|
||||||
debug_decl(sudo_askpass, SUDO_DEBUG_CONV)
|
debug_decl(sudo_askpass, SUDO_DEBUG_CONV)
|
||||||
@@ -286,18 +280,10 @@ sudo_askpass(const char *askpass, const char *prompt)
|
|||||||
_exit(255);
|
_exit(255);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Ignore SIGPIPE in case child exits prematurely */
|
/* Get response from child (askpass). */
|
||||||
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 */
|
|
||||||
(void) close(pfd[1]);
|
(void) close(pfd[1]);
|
||||||
pass = getln(pfd[0], buf, sizeof(buf), 0);
|
pass = getln(pfd[0], buf, sizeof(buf), 0);
|
||||||
(void) close(pfd[0]);
|
(void) close(pfd[0]);
|
||||||
(void) sigaction(SIGPIPE, &saved_sa_pipe, NULL);
|
|
||||||
|
|
||||||
/* Wait for child to exit. */
|
/* Wait for child to exit. */
|
||||||
for (;;) {
|
for (;;) {
|
||||||
|
Reference in New Issue
Block a user