When the command sudo is running is killed by a signal, sudo will

now send itself the same signal with the default signal handler
instead of exiting.  The bash shell appears to ignore some signals,
e.g.  SIGINT, unless the command is killed by that signal.  This
makes the behavior of commands run under sudo the same as without
sudo when bash is the shell.  Bug #722
This commit is contained in:
Todd C. Miller
2015-09-26 10:53:16 -06:00
parent 7b7db55db9
commit 9486afb4e5

View File

@@ -134,7 +134,7 @@ __dso_public int main(int argc, char *argv[], char *envp[]);
int
main(int argc, char *argv[], char *envp[])
{
int nargc, ok, exitcode = 0;
int nargc, ok, status = 0;
char **nargv, **env_add;
char **user_info, **command_info, **argv_out, **user_env_out;
struct sudo_settings *settings;
@@ -283,17 +283,29 @@ main(int argc, char *argv[], char *envp[])
(void) setrlimit(RLIMIT_CORE, &corelimit);
#endif /* RLIMIT_CORE */
if (ISSET(command_details.flags, CD_SUDOEDIT)) {
exitcode = sudo_edit(&command_details);
status = sudo_edit(&command_details);
} else {
exitcode = run_command(&command_details);
status = run_command(&command_details);
}
/* The close method was called by sudo_edit/run_command. */
break;
default:
sudo_fatalx(U_("unexpected sudo mode 0x%x"), sudo_mode);
}
sudo_debug_exit_int(__func__, __FILE__, __LINE__, sudo_debug_subsys, exitcode);
exit(exitcode);
if (WIFSIGNALED(status)) {
sigaction_t sa;
memset(&sa, 0, sizeof(sa));
sigemptyset(&sa.sa_mask);
sa.sa_handler = SIG_DFL;
sigaction(SIGINT, &sa, NULL);
sudo_debug_exit_int(__func__, __FILE__, __LINE__, sudo_debug_subsys,
WTERMSIG(status) | 128);
kill(getpid(), WTERMSIG(status));
}
sudo_debug_exit_int(__func__, __FILE__, __LINE__, sudo_debug_subsys,
WEXITSTATUS(status));
exit(WEXITSTATUS(status));
}
int
@@ -1068,7 +1080,7 @@ run_command(struct command_details *details)
{
struct plugin_container *plugin;
struct command_status cstat;
int exitcode = 1;
int status = 1;
debug_decl(run_command, SUDO_DEBUG_EXEC)
cstat.type = CMD_INVALID;
@@ -1087,32 +1099,29 @@ run_command(struct command_details *details)
"calling I/O close with errno %d", cstat.val);
iolog_close(plugin, 0, cstat.val);
}
exitcode = 1;
status = 1;
break;
case CMD_WSTATUS:
/* Command ran, exited or was killed. */
if (WIFEXITED(cstat.val))
exitcode = WEXITSTATUS(cstat.val);
else if (WIFSIGNALED(cstat.val))
exitcode = WTERMSIG(cstat.val) | 128;
status = cstat.val;
#ifdef HAVE_SELINUX
if (ISSET(details->flags, CD_SUDOEDIT_COPY))
break;
#endif
sudo_debug_printf(SUDO_DEBUG_DEBUG,
"calling policy close with wait status %d", cstat.val);
policy_close(&policy_plugin, cstat.val, 0);
"calling policy close with wait status %d", status);
policy_close(&policy_plugin, status, 0);
TAILQ_FOREACH(plugin, &io_plugins, entries) {
sudo_debug_printf(SUDO_DEBUG_DEBUG,
"calling I/O close with wait status %d", cstat.val);
iolog_close(plugin, cstat.val, 0);
"calling I/O close with wait status %d", status);
iolog_close(plugin, status, 0);
}
break;
default:
sudo_warnx(U_("unexpected child termination condition: %d"), cstat.type);
break;
}
debug_return_int(exitcode);
debug_return_int(status);
}
/*