Initialize intercept_allow_setid to true if we use ptrace(2) and seccomp(2).

This commit is contained in:
Todd C. Miller
2022-05-04 13:32:28 -06:00
parent e84fdd99fd
commit 4ab6a87b96
11 changed files with 66 additions and 43 deletions

View File

@@ -25,7 +25,7 @@
.nr BA @BAMAN@ .nr BA @BAMAN@
.nr LC @LCMAN@ .nr LC @LCMAN@
.nr PS @PSMAN@ .nr PS @PSMAN@
.TH "SUDOERS" "@mansectform@" "April 28, 2022" "Sudo @PACKAGE_VERSION@" "File Formats Manual" .TH "SUDOERS" "@mansectform@" "May 4, 2022" "Sudo @PACKAGE_VERSION@" "File Formats Manual"
.nh .nh
.if n .ad l .if n .ad l
.SH "NAME" .SH "NAME"
@@ -3314,8 +3314,11 @@ flag is enabled or the
\fIINTERCEPT\fR \fIINTERCEPT\fR
tag has been set for the command. tag has been set for the command.
This flag is This flag is
\fIon\fR \fIoff\fR
by default. by default except on Linux systems that support
seccomp(2)
filtering, where it defaults to
\fIon\fR.
.sp .sp
This setting is only supported by version 1.9.8 or higher. This setting is only supported by version 1.9.8 or higher.
.TP 18n .TP 18n

View File

@@ -24,7 +24,7 @@
.nr BA @BAMAN@ .nr BA @BAMAN@
.nr LC @LCMAN@ .nr LC @LCMAN@
.nr PS @PSMAN@ .nr PS @PSMAN@
.Dd April 28, 2022 .Dd May 4, 2022
.Dt SUDOERS @mansectform@ .Dt SUDOERS @mansectform@
.Os Sudo @PACKAGE_VERSION@ .Os Sudo @PACKAGE_VERSION@
.Sh NAME .Sh NAME
@@ -3130,8 +3130,11 @@ flag is enabled or the
.Em INTERCEPT .Em INTERCEPT
tag has been set for the command. tag has been set for the command.
This flag is This flag is
.Em on .Em off
by default. by default except on Linux systems that support
.Xr seccomp 2
filtering, where it defaults to
.Em on .
.Pp .Pp
This setting is only supported by version 1.9.8 or higher. This setting is only supported by version 1.9.8 or higher.
.It intercept_authenticate .It intercept_authenticate

View File

@@ -548,6 +548,8 @@ init_defaults(void)
#endif #endif
if ((def_rlimit_core = strdup("0,0")) == NULL) if ((def_rlimit_core = strdup("0,0")) == NULL)
goto oom; goto oom;
if (ISSET(sudo_user.flags, CAN_INTERCEPT_SETID))
def_intercept_allow_setid = true;
def_netgroup_tuple = false; def_netgroup_tuple = false;
def_sudoedit_checkdir = true; def_sudoedit_checkdir = true;
def_iolog_mode = S_IRUSR|S_IWUSR; def_iolog_mode = S_IRUSR|S_IWUSR;

View File

@@ -297,6 +297,12 @@ sudoers_policy_deserialize_info(void *v, struct defaults_list *defaults)
goto oom; goto oom;
continue; continue;
} }
if (MATCHES(*cur, "intercept_setid=")) {
if (parse_bool(*cur, sizeof("intercept_setid") - 1,
&sudo_user.flags, CAN_INTERCEPT_SETID) == -1)
goto bad;
continue;
}
#ifdef HAVE_SELINUX #ifdef HAVE_SELINUX
if (MATCHES(*cur, "selinux_role=")) { if (MATCHES(*cur, "selinux_role=")) {
CHECK(*cur, "selinux_role="); CHECK(*cur, "selinux_role=");

View File

@@ -145,6 +145,7 @@ struct sudo_user {
*/ */
#define RUNAS_USER_SPECIFIED 0x01 #define RUNAS_USER_SPECIFIED 0x01
#define RUNAS_GROUP_SPECIFIED 0x02 #define RUNAS_GROUP_SPECIFIED 0x02
#define CAN_INTERCEPT_SETID 0x04
/* /*
* Return values for sudoers_lookup(), also used as arguments for log_auth() * Return values for sudoers_lookup(), also used as arguments for log_auth()

View File

@@ -378,10 +378,7 @@ exec_nopty(struct command_details *details, struct command_status *cstat)
sudo_fatal("%s", U_("unable to create pipe")); sudo_fatal("%s", U_("unable to create pipe"));
if (ISSET(details->flags, CD_INTERCEPT|CD_LOG_SUBCMDS)) { if (ISSET(details->flags, CD_INTERCEPT|CD_LOG_SUBCMDS)) {
if (have_seccomp_action("trap")) { if (!ISSET(details->flags, CD_USE_PTRACE)) {
/* Kernel supports the seccomp(2) filter "trap" action. */
SET(details->flags, CD_USE_PTRACE);
} else {
/* /*
* Allocate a socketpair for communicating with sudo_intercept.so. * Allocate a socketpair for communicating with sudo_intercept.so.
* This must be inherited across exec, hence no FD_CLOEXEC. * This must be inherited across exec, hence no FD_CLOEXEC.

View File

@@ -1427,10 +1427,7 @@ exec_pty(struct command_details *details, struct command_status *cstat)
sudo_fatal("%s", U_("unable to create sockets")); sudo_fatal("%s", U_("unable to create sockets"));
if (ISSET(details->flags, CD_INTERCEPT|CD_LOG_SUBCMDS)) { if (ISSET(details->flags, CD_INTERCEPT|CD_LOG_SUBCMDS)) {
if (have_seccomp_action("trap")) { if (!ISSET(details->flags, CD_USE_PTRACE)) {
/* Kernel supports the seccomp(2) filter "trap" action. */
SET(details->flags, CD_USE_PTRACE);
} else {
/* /*
* Allocate a socketpair for communicating with sudo_intercept.so. * Allocate a socketpair for communicating with sudo_intercept.so.
* This must be inherited across exec, hence no FD_CLOEXEC. * This must be inherited across exec, hence no FD_CLOEXEC.

View File

@@ -1,7 +1,7 @@
/* /*
* SPDX-License-Identifier: ISC * SPDX-License-Identifier: ISC
* *
* Copyright (c) 1993-1996, 1998-2021 Todd C. Miller <Todd.Miller@sudo.ws> * Copyright (c) 1993-1996, 1998-2022 Todd C. Miller <Todd.Miller@sudo.ws>
* *
* Permission to use, copy, modify, and distribute this software for any * Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above
@@ -52,61 +52,36 @@ static void usage_excl(void) __attribute__((__noreturn__));
/* /*
* Mapping of command line flags to name/value settings. * Mapping of command line flags to name/value settings.
* Do not reorder, indexes must match ARG_ defines in sudo.h.
*/ */
static struct sudo_settings sudo_settings[] = { static struct sudo_settings sudo_settings[] = {
#define ARG_BSDAUTH_TYPE 0
{ "bsdauth_type" }, { "bsdauth_type" },
#define ARG_LOGIN_CLASS 1
{ "login_class" }, { "login_class" },
#define ARG_PRESERVE_ENVIRONMENT 2
{ "preserve_environment" }, { "preserve_environment" },
#define ARG_RUNAS_GROUP 3
{ "runas_group" }, { "runas_group" },
#define ARG_SET_HOME 4
{ "set_home" }, { "set_home" },
#define ARG_USER_SHELL 5
{ "run_shell" }, { "run_shell" },
#define ARG_LOGIN_SHELL 6
{ "login_shell" }, { "login_shell" },
#define ARG_IGNORE_TICKET 7
{ "ignore_ticket" }, { "ignore_ticket" },
#define ARG_PROMPT 8
{ "prompt" }, { "prompt" },
#define ARG_SELINUX_ROLE 9
{ "selinux_role" }, { "selinux_role" },
#define ARG_SELINUX_TYPE 10
{ "selinux_type" }, { "selinux_type" },
#define ARG_RUNAS_USER 11
{ "runas_user" }, { "runas_user" },
#define ARG_PROGNAME 12
{ "progname" }, { "progname" },
#define ARG_IMPLIED_SHELL 13
{ "implied_shell" }, { "implied_shell" },
#define ARG_PRESERVE_GROUPS 14
{ "preserve_groups" }, { "preserve_groups" },
#define ARG_NONINTERACTIVE 15
{ "noninteractive" }, { "noninteractive" },
#define ARG_SUDOEDIT 16
{ "sudoedit" }, { "sudoedit" },
#define ARG_CLOSEFROM 17
{ "closefrom" }, { "closefrom" },
#define ARG_NET_ADDRS 18
{ "network_addrs" }, { "network_addrs" },
#define ARG_MAX_GROUPS 19
{ "max_groups" }, { "max_groups" },
#define ARG_PLUGIN_DIR 20
{ "plugin_dir" }, { "plugin_dir" },
#define ARG_REMOTE_HOST 21
{ "remote_host" }, { "remote_host" },
#define ARG_TIMEOUT 22
{ "timeout" }, { "timeout" },
#define ARG_CHROOT 23
{ "cmnd_chroot" }, { "cmnd_chroot" },
#define ARG_CWD 24
{ "cmnd_cwd" }, { "cmnd_cwd" },
#define ARG_ASKPASS 25
{ "askpass" }, { "askpass" },
#define NUM_SETTINGS 26 { "intercept_setid" },
{ NULL } { NULL }
}; };
@@ -610,6 +585,8 @@ parse_args(int argc, char **argv, int *old_optind, int *nargc, char ***nargv,
#ifdef ENABLE_SUDO_PLUGIN_API #ifdef ENABLE_SUDO_PLUGIN_API
sudo_settings[ARG_PLUGIN_DIR].value = sudo_conf_plugin_dir_path(); sudo_settings[ARG_PLUGIN_DIR].value = sudo_conf_plugin_dir_path();
#endif #endif
if (have_seccomp_action("trap"))
sudo_settings[ARG_INTERCEPT_SETID].value = "true";
if (mode == MODE_HELP) if (mode == MODE_HELP)
help(); help();

View File

@@ -863,6 +863,12 @@ command_info_to_details(char * const info[], struct command_details *details)
} }
} }
if (ISSET(details->flags, CD_INTERCEPT|CD_LOG_SUBCMDS)) {
/* Use ptrace(2) for intercept/log_subcmds if possible. */
if (sudo_settings[ARG_INTERCEPT_SETID].value != NULL)
SET(details->flags, CD_USE_PTRACE);
}
if (!ISSET(details->flags, CD_SET_EUID)) if (!ISSET(details->flags, CD_SET_EUID))
details->cred.euid = details->cred.uid; details->cred.euid = details->cred.uid;
if (!ISSET(details->flags, CD_SET_EGID)) if (!ISSET(details->flags, CD_SET_EGID))

View File

@@ -75,6 +75,35 @@
#define MODE_NONINTERACTIVE 0x00800000 #define MODE_NONINTERACTIVE 0x00800000
#define MODE_LONG_LIST 0x01000000 #define MODE_LONG_LIST 0x01000000
/* Indexes into sudo_settings[] args, must match parse_args.c. */
#define ARG_BSDAUTH_TYPE 0
#define ARG_LOGIN_CLASS 1
#define ARG_PRESERVE_ENVIRONMENT 2
#define ARG_RUNAS_GROUP 3
#define ARG_SET_HOME 4
#define ARG_USER_SHELL 5
#define ARG_LOGIN_SHELL 6
#define ARG_IGNORE_TICKET 7
#define ARG_PROMPT 8
#define ARG_SELINUX_ROLE 9
#define ARG_SELINUX_TYPE 10
#define ARG_RUNAS_USER 11
#define ARG_PROGNAME 12
#define ARG_IMPLIED_SHELL 13
#define ARG_PRESERVE_GROUPS 14
#define ARG_NONINTERACTIVE 15
#define ARG_SUDOEDIT 16
#define ARG_CLOSEFROM 17
#define ARG_NET_ADDRS 18
#define ARG_MAX_GROUPS 19
#define ARG_PLUGIN_DIR 20
#define ARG_REMOTE_HOST 21
#define ARG_TIMEOUT 22
#define ARG_CHROOT 23
#define ARG_CWD 24
#define ARG_ASKPASS 25
#define ARG_INTERCEPT_SETID 26
/* /*
* Flags for tgetpass() * Flags for tgetpass()
*/ */
@@ -308,4 +337,7 @@ void unlimit_sudo(void);
int serialize_rlimits(char **info, size_t info_max); int serialize_rlimits(char **info, size_t info_max);
bool parse_policy_rlimit(const char *str); bool parse_policy_rlimit(const char *str);
/* exec_ptrace.c */
bool have_seccomp_action(const char *action);
#endif /* SUDO_SUDO_H */ #endif /* SUDO_SUDO_H */

View File

@@ -146,7 +146,6 @@ char **sudo_preload_dso(char *envp[], const char *dso_file, int intercept_fd);
/* exec_ptrace.c */ /* exec_ptrace.c */
bool exec_ptrace_handled(pid_t pid, int status, void *intercept); bool exec_ptrace_handled(pid_t pid, int status, void *intercept);
bool have_seccomp_action(const char *action);
bool set_exec_filter(void); bool set_exec_filter(void);
int exec_ptrace_seize(pid_t child); int exec_ptrace_seize(pid_t child);