You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

162 lines
5.5 KiB

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