Move noexec handling to sudo front-end where it is documented as being.
This commit is contained in:
@@ -413,7 +413,7 @@ matches_env_keep(const char *var)
|
|||||||
* Also adds sudo-specific variables (SUDO_*).
|
* Also adds sudo-specific variables (SUDO_*).
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
rebuild_env(int noexec)
|
rebuild_env(void)
|
||||||
{
|
{
|
||||||
char **old_envp, **ep, *cp, *ps1;
|
char **old_envp, **ep, *cp, *ps1;
|
||||||
char idbuf[MAX_UID_T_LEN];
|
char idbuf[MAX_UID_T_LEN];
|
||||||
@@ -602,30 +602,6 @@ rebuild_env(int noexec)
|
|||||||
if (!ISSET(didvar, DID_PATH))
|
if (!ISSET(didvar, DID_PATH))
|
||||||
sudo_setenv("PATH", _PATH_STDPATH, FALSE);
|
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. */
|
/* Set PS1 if SUDO_PS1 is set. */
|
||||||
if (ps1 != NULL)
|
if (ps1 != NULL)
|
||||||
sudo_putenv(ps1, TRUE, TRUE);
|
sudo_putenv(ps1, TRUE, TRUE);
|
||||||
|
@@ -433,7 +433,7 @@ sudoers_policy_main(int argc, char * const argv[], int pwflag, char *env_add[],
|
|||||||
def_env_reset = FALSE;
|
def_env_reset = FALSE;
|
||||||
|
|
||||||
/* Build a new environment that avoids any nasty bits. */
|
/* 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. */
|
/* Require a password if sudoers says so. */
|
||||||
if (def_authenticate) {
|
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");
|
command_info[info_len++] = estrdup("iolog_compress=true");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (def_noexec)
|
|
||||||
command_info[info_len++] = estrdup("noexec=true");
|
|
||||||
|
|
||||||
log_allowed(validated);
|
log_allowed(validated);
|
||||||
if (ISSET(sudo_mode, MODE_CHECK))
|
if (ISSET(sudo_mode, MODE_CHECK))
|
||||||
rval = display_cmnd(snl, list_pw ? list_pw : sudo_user.pw);
|
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)
|
if (def_closefrom >= 0)
|
||||||
easprintf(&command_info[info_len++], "closefrom=%d", def_closefrom);
|
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
|
#ifdef HAVE_LOGIN_CAP_H
|
||||||
if (lc != NULL)
|
if (lc != NULL)
|
||||||
command_info[info_len++] = fmt_string("login_class", lc->lc_class);
|
command_info[info_len++] = fmt_string("login_class", lc->lc_class);
|
||||||
|
@@ -123,8 +123,8 @@ struct sudo_user {
|
|||||||
#define MODE_MASK 0x0000ffff
|
#define MODE_MASK 0x0000ffff
|
||||||
|
|
||||||
/* Mode flags */
|
/* Mode flags */
|
||||||
#define MODE_BACKGROUND 0x00010000
|
#define MODE_BACKGROUND 0x00010000 /* XXX - unused */
|
||||||
#define MODE_SHELL 0x00020000
|
#define MODE_SHELL 0x00020000 /* XXX - not set but is used */
|
||||||
#define MODE_LOGIN_SHELL 0x00040000
|
#define MODE_LOGIN_SHELL 0x00040000
|
||||||
#define MODE_IMPLIED_SHELL 0x00080000
|
#define MODE_IMPLIED_SHELL 0x00080000
|
||||||
#define MODE_RESET_HOME 0x00100000
|
#define MODE_RESET_HOME 0x00100000
|
||||||
@@ -295,7 +295,7 @@ void env_init(char * const envp[]);
|
|||||||
void init_envtables(void);
|
void init_envtables(void);
|
||||||
void insert_env_vars(char * const envp[]);
|
void insert_env_vars(char * const envp[]);
|
||||||
void read_env_file(const char *, int);
|
void read_env_file(const char *, int);
|
||||||
void rebuild_env(int);
|
void rebuild_env(void);
|
||||||
void validate_env_vars(char * const envp[]);
|
void validate_env_vars(char * const envp[]);
|
||||||
|
|
||||||
/* fmt_string.c */
|
/* fmt_string.c */
|
||||||
|
80
src/sudo.c
80
src/sudo.c
@@ -450,6 +450,7 @@ command_info_to_details(char * const info[], struct command_details *details)
|
|||||||
|
|
||||||
memset(details, 0, sizeof(*details));
|
memset(details, 0, sizeof(*details));
|
||||||
details->closefrom = -1;
|
details->closefrom = -1;
|
||||||
|
details->noexec_file = _PATH_SUDO_NOEXEC;
|
||||||
|
|
||||||
#define SET_STRING(s, n) \
|
#define SET_STRING(s, n) \
|
||||||
if (strncmp(s, info[i], sizeof(s) - 1) == 0 && info[i][sizeof(s) - 1]) { \
|
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);
|
SET(details->flags, CD_NOEXEC);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
SET_STRING("noexec_file=", noexec_file)
|
||||||
break;
|
break;
|
||||||
case 'p':
|
case 'p':
|
||||||
if (strncmp("preserve_groups=", info[i], sizeof("preserve_groups=") - 1) == 0) {
|
if (strncmp("preserve_groups=", info[i], sizeof("preserve_groups=") - 1) == 0) {
|
||||||
@@ -754,6 +756,75 @@ set_project(struct passwd *pw)
|
|||||||
}
|
}
|
||||||
#endif /* HAVE_PROJECT_H */
|
#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()
|
* Setup the execution environment immediately prior to the call to execve()
|
||||||
* Returns TRUE on success and FALSE on failure.
|
* 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 */
|
if (ISSET(details->flags, CD_NOEXEC))
|
||||||
#ifdef HAVE_PRIV_SET
|
disable_execute(details);
|
||||||
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 */
|
|
||||||
|
|
||||||
#ifdef HAVE_SETRESUID
|
#ifdef HAVE_SETRESUID
|
||||||
if (setresuid(details->uid, details->euid, details->euid) != 0) {
|
if (setresuid(details->uid, details->euid, details->euid) != 0) {
|
||||||
|
@@ -139,6 +139,7 @@ struct command_details {
|
|||||||
const char *chroot;
|
const char *chroot;
|
||||||
const char *selinux_role;
|
const char *selinux_role;
|
||||||
const char *selinux_type;
|
const char *selinux_type;
|
||||||
|
const char *noexec_file;
|
||||||
char **argv;
|
char **argv;
|
||||||
char **envp;
|
char **envp;
|
||||||
};
|
};
|
||||||
|
Reference in New Issue
Block a user