Add intercept_verify sudoers option to control execve(2) argument checking.

This commit is contained in:
Todd C. Miller
2022-07-29 15:22:27 -06:00
parent b80b012de0
commit 3ce19efca9
10 changed files with 99 additions and 32 deletions

View File

@@ -25,7 +25,7 @@
.nr BA @BAMAN@
.nr LC @LCMAN@
.nr PS @PSMAN@
.TH "SUDOERS" "@mansectform@" "May 31, 2022" "Sudo @PACKAGE_VERSION@" "File Formats Manual"
.TH "SUDOERS" "@mansectform@" "July 29, 2022" "Sudo @PACKAGE_VERSION@" "File Formats Manual"
.nh
.if n .ad l
.SH "NAME"
@@ -3399,6 +3399,31 @@ by default.
.sp
This setting is only supported by version 1.9.8 or higher.
.TP 18n
intercept_verify
If set,
\fBsudo\fR
will attempt to verify that a command run in intercept mode has
the expected path name and command line arguments.
The process is stopped after
execve(2)
has completed but before the new command has had a chance to run.
In the case of a path name or argument mismatch, the command will be sent a
\fRSIGKILL\fR
signal and terminated.
This flag has no effect unless the
\fIintercept\fR
flag is enabled or the
\fIINTERCEPT\fR
tag has been set for the command and the
\fIintercept_type\fR
option is set to
\fItrace\fR.
This flag is
\fIon\fR
by default.
.sp
This setting is only supported by version 1.9.12 or higher.
.TP 18n
netgroup_tuple
If set, netgroup lookups will be performed using the full netgroup
tuple: host name, user name, and domain (if one is set).

View File

@@ -25,7 +25,7 @@
.nr BA @BAMAN@
.nr LC @LCMAN@
.nr PS @PSMAN@
.Dd May 31, 2022
.Dd July 29, 2022
.Dt SUDOERS @mansectform@
.Os Sudo @PACKAGE_VERSION@
.Sh NAME
@@ -3220,6 +3220,30 @@ This flag is
by default.
.Pp
This setting is only supported by version 1.9.8 or higher.
.It intercept_verify
If set,
.Nm sudo
will attempt to verify that a command run in intercept mode has
the expected path name and command line arguments.
The process is stopped after
.Xr execve 2
has completed but before the new command has had a chance to run.
In the case of a path name or argument mismatch, the command will be sent a
.Dv SIGKILL
signal and terminated.
This flag has no effect unless the
.Em intercept
flag is enabled or the
.Em INTERCEPT
tag has been set for the command and the
.Em intercept_type
option is set to
.Em trace .
This flag is
.Em on
by default.
.Pp
This setting is only supported by version 1.9.12 or higher.
.It netgroup_tuple
If set, netgroup lookups will be performed using the full netgroup
tuple: host name, user name, and domain (if one is set).

View File

@@ -667,6 +667,10 @@ struct sudo_defs_types sudo_defs_table[] = {
"intercept_type", T_TUPLE,
N_("The mechanism used by the intercept and log_subcmds options: %s"),
def_data_intercept_type,
}, {
"intercept_verify", T_FLAG,
N_("Whether to verify the command and arguments after execution"),
NULL,
}, {
"apparmor_profile", T_STR,
N_("AppArmor profile to use in the new security context: %s"),

View File

@@ -308,7 +308,9 @@
#define def_passprompt_regex (sudo_defs_table[I_PASSPROMPT_REGEX].sd_un.list)
#define I_INTERCEPT_TYPE 153
#define def_intercept_type (sudo_defs_table[I_INTERCEPT_TYPE].sd_un.tuple)
#define I_APPARMOR_PROFILE 154
#define I_INTERCEPT_VERIFY 154
#define def_intercept_verify (sudo_defs_table[I_INTERCEPT_VERIFY].sd_un.flag)
#define I_APPARMOR_PROFILE 155
#define def_apparmor_profile (sudo_defs_table[I_APPARMOR_PROFILE].sd_un.str)
enum def_tuple {

View File

@@ -479,6 +479,9 @@ intercept_type
T_TUPLE
"The mechanism used by the intercept and log_subcmds options: %s"
dso trace
intercept_verify
T_FLAG
"Whether to verify the command and arguments after execution"
apparmor_profile
T_STR
"AppArmor profile to use in the new security context: %s"

View File

@@ -549,6 +549,7 @@ init_defaults(void)
if ((def_rlimit_core = strdup("0,0")) == NULL)
goto oom;
def_intercept_type = dso;
def_intercept_verify = true;
def_netgroup_tuple = false;
def_sudoedit_checkdir = true;
def_iolog_mode = S_IRUSR|S_IWUSR;

View File

@@ -636,7 +636,7 @@ sudoers_policy_store_result(bool accepted, char *argv[], char *envp[],
}
/* Increase the length of command_info as needed, it is *not* checked. */
command_info = calloc(71, sizeof(char *));
command_info = calloc(72, sizeof(char *));
if (command_info == NULL)
goto oom;
@@ -812,6 +812,10 @@ sudoers_policy_store_result(bool accepted, char *argv[], char *envp[],
if ((command_info[info_len++] = strdup("use_ptrace=true")) == NULL)
goto oom;
}
if (def_intercept_verify) {
if ((command_info[info_len++] = strdup("intercept_verify=true")) == NULL)
goto oom;
}
if (def_noexec) {
if ((command_info[info_len++] = strdup("noexec=true")) == NULL)
goto oom;

View File

@@ -1532,12 +1532,14 @@ ptrace_intercept_execve(pid_t pid, struct intercept_closure *closure)
}
}
if (closure->state == POLICY_ACCEPT) {
if (ISSET(closure->details->flags, CD_INTERCEPT_VERIFY)) {
/* Verify execve(2) args post-exec. */
if (!ptrace_verify_post_exec(pid, &regs, closure)) {
if (errno != ESRCH)
kill(pid, SIGKILL);
}
}
}
break;
default:
/* If rejected, fake the syscall and set return to EACCES */

View File

@@ -734,6 +734,7 @@ command_info_to_details(char * const info[], struct command_details *details)
break;
case 'i':
SET_FLAG("intercept=", CD_INTERCEPT)
SET_FLAG("intercept_verify=", CD_INTERCEPT_VERIFY)
break;
case 'l':
SET_STRING("login_class=", login_class)

View File

@@ -149,30 +149,31 @@ struct user_details {
int ts_cols;
};
#define CD_SET_UID 0x000001
#define CD_SET_EUID 0x000002
#define CD_SET_GID 0x000004
#define CD_SET_EGID 0x000008
#define CD_PRESERVE_GROUPS 0x000010
#define CD_INTERCEPT 0x000020
#define CD_NOEXEC 0x000040
#define CD_SET_PRIORITY 0x000080
#define CD_SET_UMASK 0x000100
#define CD_SET_TIMEOUT 0x000200
#define CD_SUDOEDIT 0x000400
#define CD_BACKGROUND 0x000800
#define CD_RBAC_ENABLED 0x001000
#define CD_USE_PTY 0x002000
#define CD_SET_UTMP 0x004000
#define CD_EXEC_BG 0x008000
#define CD_SUDOEDIT_FOLLOW 0x010000
#define CD_SUDOEDIT_CHECKDIR 0x020000
#define CD_SET_GROUPS 0x040000
#define CD_LOGIN_SHELL 0x080000
#define CD_OVERRIDE_UMASK 0x100000
#define CD_LOG_SUBCMDS 0x200000
#define CD_USE_PTRACE 0x400000
#define CD_FEXECVE 0x800000
#define CD_SET_UID 0x00000001
#define CD_SET_EUID 0x00000002
#define CD_SET_GID 0x00000004
#define CD_SET_EGID 0x00000008
#define CD_PRESERVE_GROUPS 0x00000010
#define CD_INTERCEPT 0x00000020
#define CD_NOEXEC 0x00000040
#define CD_SET_PRIORITY 0x00000080
#define CD_SET_UMASK 0x00000100
#define CD_SET_TIMEOUT 0x00000200
#define CD_SUDOEDIT 0x00000400
#define CD_BACKGROUND 0x00000800
#define CD_RBAC_ENABLED 0x00001000
#define CD_USE_PTY 0x00002000
#define CD_SET_UTMP 0x00004000
#define CD_EXEC_BG 0x00008000
#define CD_SUDOEDIT_FOLLOW 0x00010000
#define CD_SUDOEDIT_CHECKDIR 0x00020000
#define CD_SET_GROUPS 0x00040000
#define CD_LOGIN_SHELL 0x00080000
#define CD_OVERRIDE_UMASK 0x00100000
#define CD_LOG_SUBCMDS 0x00200000
#define CD_USE_PTRACE 0x00400000
#define CD_FEXECVE 0x00800000
#define CD_INTERCEPT_VERIFY 0x01000000
struct preserved_fd {
TAILQ_ENTRY(preserved_fd) entries;