Blame SOURCES/sudo-1.8.6p3-nowaitopt.patch

0e1944
From 9b1f0f16bfe7552810b4adb6b17ac3674da660f9 Mon Sep 17 00:00:00 2001
0e1944
From: Tomas Sykora <tosykora@redhat.com>
0e1944
Date: Mon, 15 Aug 2016 15:13:31 +0200
0e1944
Subject: [PATCH] Backport direct exec of command from sudo
0e1944
0e1944
Added cmnd_no_wait option
0e1944
Sudo does not run command in a new child process,
0e1944
when cmnd_no_wait is enabled.
0e1944
0e1944
!!!
0e1944
Upstream can do that too now in 1.8.17 with combination of
0e1944
pam_session, pam_setcred and use_pty option.
0e1944
They must be disabled and I/O logging must not be configured.
0e1944
See "man sudoers".
0e1944
0e1944
rebased from:
0e1944
Patch8: sudo-1.8.6p3-nowaitopt.patch
0e1944
0e1944
Resolves:
0e1944
rhbz#840980
0e1944
---
0e1944
 plugins/sudoers/def_data.c  |  4 ++++
0e1944
 plugins/sudoers/def_data.h  |  2 ++
0e1944
 plugins/sudoers/def_data.in |  3 +++
0e1944
 plugins/sudoers/policy.c    |  4 ++++
0e1944
 src/exec.c                  | 34 ++++++++++++++++++++++++++++++++++
0e1944
 src/sudo.c                  |  5 +++++
0e1944
 src/sudo.h                  |  1 +
0e1944
 7 files changed, 53 insertions(+)
0e1944
0e1944
diff --git a/plugins/sudoers/def_data.c b/plugins/sudoers/def_data.c
0e1944
index 00caa8b..d8b1ada 100644
0e1944
--- a/plugins/sudoers/def_data.c
0e1944
+++ b/plugins/sudoers/def_data.c
0e1944
@@ -435,6 +435,10 @@ struct sudo_defs_types sudo_defs_table[] = {
0e1944
 	N_("File mode to use for the I/O log files: 0%o"),
1b092f
 	NULL,
1b092f
     }, {
0e1944
+	"cmnd_no_wait", T_FLAG,
0e1944
+	N_("Don't fork and wait for the command to finish, just exec it"),
0e1944
+	NULL,
1b092f
+    }, {
1b092f
 	NULL, 0, NULL
1b092f
     }
1b092f
 };
0e1944
diff --git a/plugins/sudoers/def_data.h b/plugins/sudoers/def_data.h
0e1944
index d83d2c3..1b6be3d 100644
0e1944
--- a/plugins/sudoers/def_data.h
0e1944
+++ b/plugins/sudoers/def_data.h
0e1944
@@ -204,6 +204,8 @@
0e1944
 #define def_iolog_group         (sudo_defs_table[I_IOLOG_GROUP].sd_un.str)
0e1944
 #define I_IOLOG_MODE            102
0e1944
 #define def_iolog_mode          (sudo_defs_table[I_IOLOG_MODE].sd_un.mode)
0e1944
+#define I_CMND_NO_WAIT          103
0e1944
+#define def_cmnd_no_wait        (sudo_defs_table[I_CMND_NO_WAIT].sd_un.flag)
1b092f
 
1b092f
 enum def_tuple {
1b092f
 	never,
0e1944
diff --git a/plugins/sudoers/def_data.in b/plugins/sudoers/def_data.in
0e1944
index 9f069f1..5200fe3 100644
0e1944
--- a/plugins/sudoers/def_data.in
0e1944
+++ b/plugins/sudoers/def_data.in
0e1944
@@ -322,3 +322,6 @@ iolog_group
0e1944
 iolog_mode
0e1944
 	T_MODE
0e1944
 	"File mode to use for the I/O log files: 0%o"
0e1944
+cmnd_no_wait
0e1944
+	T_FLAG
0e1944
+	"Don't fork and wait for the command to finish, just exec it"
0e1944
diff --git a/plugins/sudoers/policy.c b/plugins/sudoers/policy.c
0e1944
index 4ee1e28..93df1dd 100644
0e1944
--- a/plugins/sudoers/policy.c
0e1944
+++ b/plugins/sudoers/policy.c
0e1944
@@ -564,6 +564,10 @@ sudoers_policy_exec_setup(char *argv[], char *envp[], mode_t cmnd_umask,
0e1944
 	if ((command_info[info_len++] = strdup("use_pty=true")) == NULL)
0e1944
 	    goto oom;
0e1944
     }
0e1944
+    if (def_cmnd_no_wait) {
0e1944
+        if ((command_info[info_len++] = strdup("cmnd_no_wait=true")) == NULL)
0e1944
+            goto oom;
0e1944
+    }
0e1944
     if (def_utmp_runas) {
0e1944
 	if ((command_info[info_len++] = sudo_new_key_val("utmp_user", runas_pw->pw_name)) == NULL)
0e1944
 	    goto oom;
0e1944
diff --git a/src/exec.c b/src/exec.c
0e1944
index 56da013..08bc86d 100644
0e1944
--- a/src/exec.c
0e1944
+++ b/src/exec.c
0e1944
@@ -384,6 +384,41 @@ sudo_execute(struct command_details *details, struct command_status *cstat)
1b092f
     }
1b092f
 
1b092f
     /*
1b092f
+     * If we don't want to wait for the command to exit, then just exec it.
1b092f
+     * THIS WILL BREAK SEVERAL THINGS including SELinux, PAM sessions and I/O
1b092f
+     * logging. Implemented because of rhbz#840980 (backwards compatibility).
1b092f
+     * In 1.8.x branch this is even harder to get back, since the nowait code
1b092f
+     * was completely removed.
1b092f
+     */
1b092f
+    if (details->flags & CD_DONTWAIT) {
1b092f
+        if (exec_setup(details, NULL, -1) == true) {
0e1944
+            restore_signals();
1b092f
+            /* headed for execve() */
1b092f
+            sudo_debug_execve(SUDO_DEBUG_INFO, details->command,
1b092f
+                              details->argv, details->envp);
1b092f
+            if (details->closefrom >= 0) {
0e1944
+                closefrom(details->closefrom);
1b092f
+            }
1b092f
+#ifdef HAVE_SELINUX
1b092f
+            if (ISSET(details->flags, CD_RBAC_ENABLED)) {
0e1944
+                selinux_execve(-1, details->command, details->argv, details->envp,
1b092f
+                               ISSET(details->flags, CD_NOEXEC));
1b092f
+            } else
1b092f
+#endif
1b092f
+            {
0e1944
+                sudo_execve(-1, details->command, details->argv, details->envp,
1b092f
+                            ISSET(details->flags, CD_NOEXEC));
1b092f
+            }
1b092f
+            sudo_debug_printf(SUDO_DEBUG_ERROR, "unable to exec %s: %s",
1b092f
+                              details->command, strerror(errno));
1b092f
+        }
1b092f
+        cstat->type = CMD_ERRNO;
1b092f
+        cstat->val = errno;
0e1944
+       return 127;
1b092f
+    }
0e1944
+
0e1944
+
1b092f
+    /*
1b092f
      * We communicate with the child over a bi-directional pair of sockets.
1b092f
      * Parent sends signal info to child and child sends back wait status.
1b092f
      */
0e1944
diff --git a/src/sudo.c b/src/sudo.c
0e1944
index 5dd090d..0606a19 100644
0e1944
--- a/src/sudo.c
0e1944
+++ b/src/sudo.c
0e1944
@@ -670,6 +670,11 @@ command_info_to_details(char * const info[], struct command_details *details)
0e1944
 			sudo_fatalx(U_("%s: %s"), info[i], U_(errstr));
1b092f
 		    break;
1b092f
 		}
1b092f
+		if (strncmp("cmnd_no_wait=", info[i], sizeof("cmnd_no_wait=") - 1) == 0) {
0e1944
+                    if (sudo_strtobool(info[i] + sizeof("cmnd_no_wait=") - 1) == true)
0e1944
+                        SET(details->flags, CD_DONTWAIT);
0e1944
+                    break;
0e1944
+                }
1b092f
 		break;
0e1944
 	    case 'e':
0e1944
 		SET_FLAG("exec_background=", CD_EXEC_BG)
0e1944
diff --git a/src/sudo.h b/src/sudo.h
0e1944
index 3ac2c9d..f07ba11 100644
0e1944
--- a/src/sudo.h
0e1944
+++ b/src/sudo.h
0e1944
@@ -130,6 +130,7 @@ struct user_details {
0e1944
 #define CD_SUDOEDIT_FOLLOW	0x10000
0e1944
 #define CD_SUDOEDIT_CHECKDIR	0x20000
0e1944
 #define CD_SET_GROUPS		0x40000
0e1944
+#define CD_DONTWAIT		0x80000
1b092f
 
0e1944
 struct preserved_fd {
0e1944
     TAILQ_ENTRY(preserved_fd) entries;
0e1944
-- 
0e1944
2.7.4
0e1944