diff --git a/NEWS b/NEWS index 991c0cd33..54c95375e 100644 --- a/NEWS +++ b/NEWS @@ -69,6 +69,11 @@ What's new in Sudo 1.9.0 The list output also now includes the host name if one is present in the log file. + * For "sudo -i", if the target user's home directory does not + exist, sudo will now warn about the problem but run the command + in the current working directory. Previously, this was a fatal + error. Debian bug #598519 + What's new in Sudo 1.8.31p1 * Sudo once again ignores a failure to restore the RLIMIT_CORE diff --git a/doc/sudo_plugin.man.in b/doc/sudo_plugin.man.in index 27656a562..26c2d31a9 100644 --- a/doc/sudo_plugin.man.in +++ b/doc/sudo_plugin.man.in @@ -16,7 +16,7 @@ .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" -.TH "SUDO_PLUGIN" "5" "February 10, 2020" "Sudo @PACKAGE_VERSION@" "File Formats Manual" +.TH "SUDO_PLUGIN" "5" "March 31, 2020" "Sudo @PACKAGE_VERSION@" "File Formats Manual" .nh .if n .ad l .SH "NAME" @@ -886,6 +886,21 @@ Fully qualified path to the command to be executed. .TP 6n cwd=string The current working directory to change to when executing the command. +If +\fBsudo\fR +is unable to change to the new working directory, the command will +not be run unless +\fIcwd_optional\fR +is also set (see below). +.TP 6n +cwd_optional=bool +If enabled, +\fBsudo\fR +will treat an inability to change to the new working directory as a +non-fatal error. +This setting has no effect unless +\fIcwd\fR +is also set. .TP 6n exec_background=bool By default, diff --git a/doc/sudo_plugin.mdoc.in b/doc/sudo_plugin.mdoc.in index 01e1f3472..c83bf27d3 100644 --- a/doc/sudo_plugin.mdoc.in +++ b/doc/sudo_plugin.mdoc.in @@ -15,7 +15,7 @@ .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" -.Dd February 10, 2020 +.Dd March 31, 2020 .Dt SUDO_PLUGIN @mansectform@ .Os Sudo @PACKAGE_VERSION@ .Sh NAME @@ -789,6 +789,20 @@ or higher. Fully qualified path to the command to be executed. .It cwd=string The current working directory to change to when executing the command. +If +.Nm sudo +is unable to change to the new working directory, the command will +not be run unless +.Em cwd_optional +is also set (see below). +.It cwd_optional=bool +If enabled, +.Nm sudo +will treat an inability to change to the new working directory as a +non-fatal error. +This setting has no effect unless +.Em cwd +is also set. .It exec_background=bool By default, .Nm sudo diff --git a/plugins/sudoers/policy.c b/plugins/sudoers/policy.c index f185711e0..782c60a7e 100644 --- a/plugins/sudoers/policy.c +++ b/plugins/sudoers/policy.c @@ -564,7 +564,7 @@ sudoers_policy_exec_setup(char *argv[], char *envp[], mode_t cmnd_umask, debug_return_bool(true); /* nothing to do */ /* Increase the length of command_info as needed, it is *not* checked. */ - command_info = calloc(52, sizeof(char *)); + command_info = calloc(53, sizeof(char *)); if (command_info == NULL) goto oom; @@ -619,6 +619,8 @@ sudoers_policy_exec_setup(char *argv[], char *envp[], mode_t cmnd_umask, /* Set cwd to run user's homedir. */ if ((command_info[info_len++] = sudo_new_key_val("cwd", runas_pw->pw_dir)) == NULL) goto oom; + if ((command_info[info_len++] = strdup("cwd_optional=true")) == NULL) + goto oom; } if ((command_info[info_len++] = sudo_new_key_val("runas_user", runas_pw->pw_name)) == NULL) goto oom; diff --git a/src/exec.c b/src/exec.c index 5337599a0..a97c76049 100644 --- a/src/exec.c +++ b/src/exec.c @@ -214,12 +214,15 @@ exec_setup(struct command_details *details, int errfd) * specifies a different cwd. Must be done after uid change. */ if (details->cwd != NULL) { - if (details->chroot || user_details.cwd == NULL || + if (details->chroot != NULL || user_details.cwd == NULL || strcmp(details->cwd, user_details.cwd) != 0) { /* Note: cwd is relative to the new root, if any. */ - if (chdir(details->cwd) != 0) { + if (chdir(details->cwd) == -1) { sudo_warn(U_("unable to change directory to %s"), details->cwd); - goto done; + if (!details->cwd_optional) + goto done; + if (details->chroot != NULL) + sudo_warnx(U_("starting from %s"), "/"); } } } diff --git a/src/sudo.c b/src/sudo.c index 4f086170a..a7c25404d 100644 --- a/src/sudo.c +++ b/src/sudo.c @@ -678,6 +678,15 @@ command_info_to_details(char * const info[], struct command_details *details) SET_STRING("chroot=", chroot) SET_STRING("command=", command) SET_STRING("cwd=", cwd) + if (strncmp("cwd_optional=", info[i], sizeof("cwd_optional=") - 1) == 0) { + cp = info[i] + sizeof("cwd_optional=") - 1; + details->cwd_optional = sudo_strtobool(cp); + if (details->cwd_optional == -1) { + errno = EINVAL; + sudo_fatal("%s", info[i]); + } + break; + } if (strncmp("closefrom=", info[i], sizeof("closefrom=") - 1) == 0) { cp = info[i] + sizeof("closefrom=") - 1; details->closefrom = sudo_strtonum(cp, 0, INT_MAX, &errstr); diff --git a/src/sudo.h b/src/sudo.h index ef804d3bd..282d9cea5 100644 --- a/src/sudo.h +++ b/src/sudo.h @@ -157,6 +157,7 @@ struct command_details { int closefrom; int flags; int execfd; + int cwd_optional; struct preserved_fd_list preserved_fds; struct passwd *pw; GETGROUPS_T *groups;