Move noexec handling to sudo front-end where it is documented as being.

This commit is contained in:
Todd C. Miller
2011-03-10 15:11:49 -05:00
parent c7a7d31905
commit a092d2fdcf
5 changed files with 83 additions and 39 deletions

View File

@@ -413,7 +413,7 @@ matches_env_keep(const char *var)
* Also adds sudo-specific variables (SUDO_*).
*/
void
rebuild_env(int noexec)
rebuild_env(void)
{
char **old_envp, **ep, *cp, *ps1;
char idbuf[MAX_UID_T_LEN];
@@ -602,30 +602,6 @@ rebuild_env(int noexec)
if (!ISSET(didvar, DID_PATH))
sudo_setenv("PATH", _PATH_STDPATH, FALSE);
/*
* Preload a noexec file? For a list of LD_PRELOAD-alikes, see
* http://www.fortran-2000.com/ArnaudRecipes/sharedlib.html
* XXX - should prepend to original value, if any
*/
if (noexec && def_noexec_file != NULL) {
#if defined(__darwin__) || defined(__APPLE__)
sudo_setenv("DYLD_INSERT_LIBRARIES", def_noexec_file, TRUE);
sudo_setenv("DYLD_FORCE_FLAT_NAMESPACE", "", TRUE);
#else
# if defined(__osf__) || defined(__sgi)
easprintf(&cp, "%s:DEFAULT", def_noexec_file);
sudo_setenv("_RLD_LIST", cp, TRUE);
efree(cp);
# else
# ifdef _AIX
sudo_setenv("LDR_PRELOAD", def_noexec_file, TRUE);
# else
sudo_setenv("LD_PRELOAD", def_noexec_file, TRUE);
# endif /* _AIX */
# endif /* __osf__ || __sgi */
#endif /* __darwin__ || __APPLE__ */
}
/* Set PS1 if SUDO_PS1 is set. */
if (ps1 != NULL)
sudo_putenv(ps1, TRUE, TRUE);

View File

@@ -433,7 +433,7 @@ sudoers_policy_main(int argc, char * const argv[], int pwflag, char *env_add[],
def_env_reset = FALSE;
/* Build a new environment that avoids any nasty bits. */
rebuild_env(def_noexec); /* XXX - move noexec bits */
rebuild_env();
/* Require a password if sudoers says so. */
if (def_authenticate) {
@@ -533,9 +533,6 @@ sudoers_policy_main(int argc, char * const argv[], int pwflag, char *env_add[],
command_info[info_len++] = estrdup("iolog_compress=true");
}
if (def_noexec)
command_info[info_len++] = estrdup("noexec=true");
log_allowed(validated);
if (ISSET(sudo_mode, MODE_CHECK))
rval = display_cmnd(snl, list_pw ? list_pw : sudo_user.pw);
@@ -646,6 +643,10 @@ sudoers_policy_main(int argc, char * const argv[], int pwflag, char *env_add[],
}
if (def_closefrom >= 0)
easprintf(&command_info[info_len++], "closefrom=%d", def_closefrom);
if (def_noexec)
command_info[info_len++] = estrdup("noexec=true");
if (def_noexec_file)
command_info[info_len++] = fmt_string("noexec_file", def_noexec_file);
#ifdef HAVE_LOGIN_CAP_H
if (lc != NULL)
command_info[info_len++] = fmt_string("login_class", lc->lc_class);

View File

@@ -123,8 +123,8 @@ struct sudo_user {
#define MODE_MASK 0x0000ffff
/* Mode flags */
#define MODE_BACKGROUND 0x00010000
#define MODE_SHELL 0x00020000
#define MODE_BACKGROUND 0x00010000 /* XXX - unused */
#define MODE_SHELL 0x00020000 /* XXX - not set but is used */
#define MODE_LOGIN_SHELL 0x00040000
#define MODE_IMPLIED_SHELL 0x00080000
#define MODE_RESET_HOME 0x00100000
@@ -295,7 +295,7 @@ void env_init(char * const envp[]);
void init_envtables(void);
void insert_env_vars(char * const envp[]);
void read_env_file(const char *, int);
void rebuild_env(int);
void rebuild_env(void);
void validate_env_vars(char * const envp[]);
/* fmt_string.c */

View File

@@ -450,6 +450,7 @@ command_info_to_details(char * const info[], struct command_details *details)
memset(details, 0, sizeof(*details));
details->closefrom = -1;
details->noexec_file = _PATH_SUDO_NOEXEC;
#define SET_STRING(s, n) \
if (strncmp(s, info[i], sizeof(s) - 1) == 0 && info[i][sizeof(s) - 1]) { \
@@ -504,6 +505,7 @@ command_info_to_details(char * const info[], struct command_details *details)
SET(details->flags, CD_NOEXEC);
break;
}
SET_STRING("noexec_file=", noexec_file)
break;
case 'p':
if (strncmp("preserve_groups=", info[i], sizeof("preserve_groups=") - 1) == 0) {
@@ -754,6 +756,75 @@ set_project(struct passwd *pw)
}
#endif /* HAVE_PROJECT_H */
/*
* Disable execution of child processes in the command we are about
* to run. On systems with privilege sets, we can remove the exec
* privilege. On other systems we use LD_PRELOAD and the like.
*/
static void
disable_execute(struct command_details *details)
{
char *cp, **ev, **nenvp;
int env_len = 0, env_size = 128;
#ifdef HAVE_PRIV_SET
/* Solaris privileges, remove PRIV_PROC_EXEC post-execve. */
if (priv_set(PRIV_OFF, PRIV_LIMIT, "PRIV_PROC_EXEC", NULL) == 0)
return;
warning("unable to remove PRIV_PROC_EXEC from PRIV_LIMIT");
#endif /* HAVE_PRIV_SET */
nenvp = emalloc2(env_size, sizeof(char *));
for (ev = details->envp; *ev != NULL; ev++) {
if (env_len + 2 > env_size) {
env_size += 128;
nenvp = erealloc3(nenvp, env_size, sizeof(char *));
}
/*
* Prune out existing preloaded libraries.
* XXX - should save and append instead of replacing.
*/
#if defined(__darwin__) || defined(__APPLE__)
if (strncmp(*ev, "DYLD_INSERT_LIBRARIES=", sizeof("DYLD_INSERT_LIBRARIES=") - 1) == 0)
continue;
if (strncmp(*ev, "DYLD_FORCE_FLAT_NAMESPACE=", sizeof("DYLD_INSERT_LIBRARIES=") - 1) == 0)
continue;
#elif defined(__osf__) || defined(__sgi)
if (strncmp(*ev, "_RLD_LIST=", sizeof("_RLD_LIST=") - 1) == 0)
continue;
#elif defined(_AIX)
if (strncmp(*ev, "LDR_PRELOAD=", sizeof("LDR_PRELOAD=") - 1) == 0)
continue;
#else
if (strncmp(*ev, "LD_PRELOAD=", sizeof("LD_PRELOAD=") - 1) == 0)
continue;
#endif
nenvp[env_len++] = *ev;
}
/*
* Preload a noexec file? For a list of LD_PRELOAD-alikes, see
* http://www.fortran-2000.com/ArnaudRecipes/sharedlib.html
* XXX - need to support 32-bit and 64-bit variants
*/
#if defined(__darwin__) || defined(__APPLE__)
nenvp[env_len++] = "DYLD_FORCE_FLAT_NAMESPACE=";
cp = fmt_string("DYLD_INSERT_LIBRARIES", details->noexec_file);
#elif defined(__osf__) || defined(__sgi)
easprintf(&cp, "_RLD_LIST=%s:DEFAULT", details->noexec_file);
#elif defined(_AIX)
cp = fmt_string("LDR_PRELOAD", details->noexec_file);
#else
cp = fmt_string("LD_PRELOAD", details->noexec_file);
#endif
if (cp == NULL)
error(1, NULL);
nenvp[env_len++] = cp;
nenvp[env_len] = NULL;
details->envp = nenvp;
}
/*
* Setup the execution environment immediately prior to the call to execve()
* Returns TRUE on success and FALSE on failure.
@@ -865,13 +936,8 @@ exec_setup(struct command_details *details, const char *ptyname, int ptyfd)
}
}
/* XXX - should do env-based noexec here too */
#ifdef HAVE_PRIV_SET
if (ISSET(details->flags, CD_NOEXEC)) {
if (priv_set(PRIV_OFF, PRIV_LIMIT, "PRIV_PROC_EXEC", NULL) == -1)
warning("unable to remove PRIV_PROC_EXEC from PRIV_LIMIT");
}
#endif /* HAVE_PRIV_SET */
if (ISSET(details->flags, CD_NOEXEC))
disable_execute(details);
#ifdef HAVE_SETRESUID
if (setresuid(details->uid, details->euid, details->euid) != 0) {

View File

@@ -139,6 +139,7 @@ struct command_details {
const char *chroot;
const char *selinux_role;
const char *selinux_type;
const char *noexec_file;
char **argv;
char **envp;
};