For ptrace intercept mode, do not do a policy check for the initial command.
We can skip the policy check for the execve(2) of the initial command since it has already been check. Otherwise, we would log the command twice. When using fexecve(2) due to a digest check, there should be no need to skip the initial command since it will be executed via execveat(2) not execve(2). However, on older kernels without execveat(2), glibc will emulate fexecve(2) using /proc which will result in the extra log entry.
This commit is contained in:
@@ -72,8 +72,19 @@ intercept_setup(int fd, struct sudo_event_base *evbase,
|
|||||||
closure->listen_sock = -1;
|
closure->listen_sock = -1;
|
||||||
|
|
||||||
if (ISSET(details->flags, CD_USE_PTRACE)) {
|
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;
|
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 {
|
} else {
|
||||||
/*
|
/*
|
||||||
* Not using ptrace(2), use LD_PRELOAD (or its equivalent). If
|
* Not using ptrace(2), use LD_PRELOAD (or its equivalent). If
|
||||||
|
@@ -44,6 +44,7 @@ struct intercept_closure {
|
|||||||
uint32_t off;
|
uint32_t off;
|
||||||
int listen_sock;
|
int listen_sock;
|
||||||
enum intercept_state state;
|
enum intercept_state state;
|
||||||
|
int initial_command;
|
||||||
};
|
};
|
||||||
|
|
||||||
void intercept_closure_reset(struct intercept_closure *closure);
|
void intercept_closure_reset(struct intercept_closure *closure);
|
||||||
|
@@ -623,6 +623,12 @@ ptrace_intercept_execve(pid_t pid, struct intercept_closure *closure)
|
|||||||
int argc, envc;
|
int argc, envc;
|
||||||
debug_decl(ptrace_intercept_execve, SUDO_DEBUG_UTIL);
|
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. */
|
/* Get the current working directory and execve info. */
|
||||||
if (!getcwd_by_pid(pid, cwd, sizeof(cwd)))
|
if (!getcwd_by_pid(pid, cwd, sizeof(cwd)))
|
||||||
(void)strlcpy(cwd, "unknown", sizeof(cwd));
|
(void)strlcpy(cwd, "unknown", sizeof(cwd));
|
||||||
|
@@ -720,6 +720,7 @@ command_info_to_details(char * const info[], struct command_details *details)
|
|||||||
#ifdef HAVE_FEXECVE
|
#ifdef HAVE_FEXECVE
|
||||||
/* Must keep fd open during exec. */
|
/* Must keep fd open during exec. */
|
||||||
add_preserved_fd(&details->preserved_fds, details->execfd);
|
add_preserved_fd(&details->preserved_fds, details->execfd);
|
||||||
|
SET(details->flags, CD_FEXECVE);
|
||||||
#else
|
#else
|
||||||
/* Plugin thinks we support fexecve() but we don't. */
|
/* Plugin thinks we support fexecve() but we don't. */
|
||||||
(void)fcntl(details->execfd, F_SETFD, FD_CLOEXEC);
|
(void)fcntl(details->execfd, F_SETFD, FD_CLOEXEC);
|
||||||
|
@@ -141,6 +141,7 @@ struct user_details {
|
|||||||
#define CD_OVERRIDE_UMASK 0x100000
|
#define CD_OVERRIDE_UMASK 0x100000
|
||||||
#define CD_LOG_SUBCMDS 0x200000
|
#define CD_LOG_SUBCMDS 0x200000
|
||||||
#define CD_USE_PTRACE 0x400000
|
#define CD_USE_PTRACE 0x400000
|
||||||
|
#define CD_FEXECVE 0x800000
|
||||||
|
|
||||||
struct preserved_fd {
|
struct preserved_fd {
|
||||||
TAILQ_ENTRY(preserved_fd) entries;
|
TAILQ_ENTRY(preserved_fd) entries;
|
||||||
|
Reference in New Issue
Block a user