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