]> granicus.if.org Git - sudo/commitdiff
When the command sudo is running is killed by a signal, sudo will
authorTodd C. Miller <Todd.Miller@courtesan.com>
Sat, 26 Sep 2015 16:53:16 +0000 (10:53 -0600)
committerTodd C. Miller <Todd.Miller@courtesan.com>
Sat, 26 Sep 2015 16:53:16 +0000 (10:53 -0600)
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

src/sudo.c

index 64fd65787b50b44e0781808e787840f0a98a60fa..c8ae36517ffd5c42750c5556c2acf930b11b0694 100644 (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);
 }
 
 /*