diff --git a/src/exec_intercept.c b/src/exec_intercept.c index 64b53a84c..a8acb1741 100644 --- a/src/exec_intercept.c +++ b/src/exec_intercept.c @@ -72,8 +72,19 @@ intercept_setup(int fd, struct sudo_event_base *evbase, closure->listen_sock = -1; if (ISSET(details->flags, CD_USE_PTRACE)) { - /* We can perform a policy check immediately using ptrace(2). */ + /* + * We can perform a policy check immediately using ptrace(2) + * but should ignore the execve(2) of the initial command + * (and sesh for SELinux RBAC). + * + * If using fexecve(2) and the system doesn't support execveat(2), + * we may end up checking the initial command anyway. + */ closure->state = RECV_POLICY_CHECK; + if (!ISSET(details->flags, CD_FEXECVE)) + closure->initial_command++; + if (ISSET(details->flags, CD_RBAC_ENABLED)) + closure->initial_command++; } else { /* * Not using ptrace(2), use LD_PRELOAD (or its equivalent). If diff --git a/src/exec_intercept.h b/src/exec_intercept.h index 1ca417d43..0b8621530 100644 --- a/src/exec_intercept.h +++ b/src/exec_intercept.h @@ -44,6 +44,7 @@ struct intercept_closure { uint32_t off; int listen_sock; enum intercept_state state; + int initial_command; }; void intercept_closure_reset(struct intercept_closure *closure); diff --git a/src/exec_ptrace.c b/src/exec_ptrace.c index 9dcee28f7..3138810ff 100644 --- a/src/exec_ptrace.c +++ b/src/exec_ptrace.c @@ -623,6 +623,12 @@ ptrace_intercept_execve(pid_t pid, struct intercept_closure *closure) int argc, envc; debug_decl(ptrace_intercept_execve, SUDO_DEBUG_UTIL); + /* Do not check the policy if we are executing the initial command. */ + if (closure->initial_command != 0) { + closure->initial_command--; + debug_return_bool(true); + } + /* Get the current working directory and execve info. */ if (!getcwd_by_pid(pid, cwd, sizeof(cwd))) (void)strlcpy(cwd, "unknown", sizeof(cwd)); diff --git a/src/sudo.c b/src/sudo.c index 0cb6ffc98..a66ca7cb8 100644 --- a/src/sudo.c +++ b/src/sudo.c @@ -720,6 +720,7 @@ command_info_to_details(char * const info[], struct command_details *details) #ifdef HAVE_FEXECVE /* Must keep fd open during exec. */ add_preserved_fd(&details->preserved_fds, details->execfd); + SET(details->flags, CD_FEXECVE); #else /* Plugin thinks we support fexecve() but we don't. */ (void)fcntl(details->execfd, F_SETFD, FD_CLOEXEC); diff --git a/src/sudo.h b/src/sudo.h index 9d3a4b478..2c4d753ad 100644 --- a/src/sudo.h +++ b/src/sudo.h @@ -141,6 +141,7 @@ struct user_details { #define CD_OVERRIDE_UMASK 0x100000 #define CD_LOG_SUBCMDS 0x200000 #define CD_USE_PTRACE 0x400000 +#define CD_FEXECVE 0x800000 struct preserved_fd { TAILQ_ENTRY(preserved_fd) entries;