Use non-exiting allocatings in the sudoers plugin.

This commit is contained in:
Todd C. Miller
2015-06-17 06:49:59 -06:00
parent 6da04821d7
commit d004b02fc6
36 changed files with 1073 additions and 810 deletions

View File

@@ -211,7 +211,7 @@ static const char *initial_keepenv_table[] = {
/*
* Initialize env based on envp.
*/
void
bool
env_init(char * const envp[])
{
char * const *ep;
@@ -220,7 +220,7 @@ env_init(char * const envp[])
if (envp == NULL) {
/* Free the old envp we allocated, if any. */
sudo_efree(env.old_envp);
free(env.old_envp);
/* Reset to initial state but keep a pointer to what we allocated. */
env.old_envp = env.envp;
@@ -235,7 +235,13 @@ env_init(char * const envp[])
env.env_len = len;
env.env_size = len + 1 + 128;
env.envp = sudo_emallocarray(env.env_size, sizeof(char *));
env.envp = reallocarray(NULL, env.env_size, sizeof(char *));
if (env.envp == NULL) {
env.env_size = 0;
env.env_len = 0;
sudo_warnx(U_("unable to allocate memory"));
debug_return_bool(false);
}
#ifdef ENV_DEBUG
memset(env.envp, 0, env.env_size * sizeof(char *));
#endif
@@ -243,11 +249,11 @@ env_init(char * const envp[])
env.envp[len] = NULL;
/* Free the old envp we allocated, if any. */
sudo_efree(env.old_envp);
free(env.old_envp);
env.old_envp = NULL;
}
debug_return;
debug_return_bool(true);
}
/*
@@ -398,7 +404,8 @@ sudo_setenv2(const char *var, const char *val, bool dupcheck, bool overwrite)
debug_decl(sudo_setenv2, SUDOERS_DEBUG_ENV)
esize = strlen(var) + 1 + strlen(val) + 1;
estring = sudo_emalloc(esize);
if ((estring = malloc(esize)) == NULL)
debug_return_int(-1);
/* Build environment string and insert it. */
if (strlcpy(estring, var, esize) >= esize ||
@@ -411,7 +418,7 @@ sudo_setenv2(const char *var, const char *val, bool dupcheck, bool overwrite)
rval = sudo_putenv(estring, dupcheck, overwrite);
}
if (rval == -1)
sudo_efree(estring);
free(estring);
debug_return_int(rval);
}
@@ -821,6 +828,16 @@ env_update_didvar(const char *ep, unsigned int *didvar)
}
}
#define CHECK_PUTENV(a, b, c) do { \
if (sudo_putenv((a), (b), (c)) == -1) \
goto bad; \
} while (0)
#define CHECK_SETENV2(a, b, c, d) do { \
if (sudo_setenv2((a), (b), (c), (d)) == -1) \
goto bad; \
} while (0)
/*
* Build a new environment and ether clear potentially dangerous
* variables from the old one or start with a clean slate.
@@ -843,9 +860,13 @@ rebuild_env(void)
didvar = 0;
env.env_len = 0;
env.env_size = 128;
sudo_efree(env.old_envp);
free(env.old_envp);
env.old_envp = env.envp;
env.envp = sudo_emallocarray(env.env_size, sizeof(char *));
env.envp = reallocarray(NULL, env.env_size, sizeof(char *));
if (env.envp == NULL) {
env.env_size = 0;
goto bad;
}
#ifdef ENV_DEBUG
memset(env.envp, 0, env.env_size * sizeof(char *));
#else
@@ -905,8 +926,7 @@ rebuild_env(void)
if (keepit) {
/* Preserve variable. */
if (sudo_putenv(*ep, false, false) == -1)
goto bad;
CHECK_PUTENV(*ep, false, false);
env_update_didvar(*ep, &didvar);
}
}
@@ -918,25 +938,25 @@ rebuild_env(void)
* on sudoers options).
*/
if (ISSET(sudo_mode, MODE_LOGIN_SHELL)) {
sudo_setenv2("SHELL", runas_pw->pw_shell,
CHECK_SETENV2("SHELL", runas_pw->pw_shell,
ISSET(didvar, DID_SHELL), true);
sudo_setenv2("LOGNAME", runas_pw->pw_name,
CHECK_SETENV2("LOGNAME", runas_pw->pw_name,
ISSET(didvar, DID_LOGNAME), true);
sudo_setenv2("USER", runas_pw->pw_name,
CHECK_SETENV2("USER", runas_pw->pw_name,
ISSET(didvar, DID_USER), true);
sudo_setenv2("USERNAME", runas_pw->pw_name,
CHECK_SETENV2("USERNAME", runas_pw->pw_name,
ISSET(didvar, DID_USERNAME), true);
} else {
if (!ISSET(didvar, DID_SHELL))
sudo_setenv2("SHELL", sudo_user.pw->pw_shell, false, true);
CHECK_SETENV2("SHELL", sudo_user.pw->pw_shell, false, true);
/* We will set LOGNAME later in the !def_set_logname case. */
if (!def_set_logname) {
if (!ISSET(didvar, DID_LOGNAME))
sudo_setenv2("LOGNAME", user_name, false, true);
CHECK_SETENV2("LOGNAME", user_name, false, true);
if (!ISSET(didvar, DID_USER))
sudo_setenv2("USER", user_name, false, true);
CHECK_SETENV2("USER", user_name, false, true);
if (!ISSET(didvar, DID_USERNAME))
sudo_setenv2("USERNAME", user_name, false, true);
CHECK_SETENV2("USERNAME", user_name, false, true);
}
}
@@ -950,10 +970,13 @@ rebuild_env(void)
*/
if (ISSET(sudo_mode, MODE_LOGIN_SHELL) || !ISSET(didvar, KEPT_MAIL)) {
cp = _PATH_MAILDIR;
if (cp[sizeof(_PATH_MAILDIR) - 2] == '/')
sudo_easprintf(&cp, "MAIL=%s%s", _PATH_MAILDIR, runas_pw->pw_name);
else
sudo_easprintf(&cp, "MAIL=%s/%s", _PATH_MAILDIR, runas_pw->pw_name);
if (cp[sizeof(_PATH_MAILDIR) - 2] == '/') {
if (asprintf(&cp, "MAIL=%s%s", _PATH_MAILDIR, runas_pw->pw_name) == -1)
goto bad;
} else {
if (asprintf(&cp, "MAIL=%s/%s", _PATH_MAILDIR, runas_pw->pw_name) == -1)
goto bad;
}
if (sudo_putenv(cp, ISSET(didvar, DID_MAIL), true) == -1) {
free(cp);
goto bad;
@@ -973,15 +996,13 @@ rebuild_env(void)
SET(didvar, DID_PATH);
else if (strncmp(*ep, "TERM=", 5) == 0)
SET(didvar, DID_TERM);
if (sudo_putenv(*ep, false, false) == -1)
goto bad;
CHECK_PUTENV(*ep, false, false);
}
}
}
/* Replace the PATH envariable with a secure one? */
if (def_secure_path && !user_is_exempt()) {
if (sudo_setenv2("PATH", def_secure_path, true, true) == -1)
goto bad;
CHECK_SETENV2("PATH", def_secure_path, true, true);
SET(didvar, DID_PATH);
}
@@ -993,58 +1014,50 @@ rebuild_env(void)
*/
if (def_set_logname && !ISSET(sudo_mode, MODE_LOGIN_SHELL)) {
if (!ISSET(didvar, KEPT_LOGNAME))
sudo_setenv2("LOGNAME", runas_pw->pw_name, true, true);
CHECK_SETENV2("LOGNAME", runas_pw->pw_name, true, true);
if (!ISSET(didvar, KEPT_USER))
sudo_setenv2("USER", runas_pw->pw_name, true, true);
CHECK_SETENV2("USER", runas_pw->pw_name, true, true);
if (!ISSET(didvar, KEPT_USERNAME))
sudo_setenv2("USERNAME", runas_pw->pw_name, true, true);
CHECK_SETENV2("USERNAME", runas_pw->pw_name, true, true);
}
/* Set $HOME to target user if not preserving user's value. */
if (reset_home)
sudo_setenv2("HOME", runas_pw->pw_dir, true, true);
CHECK_SETENV2("HOME", runas_pw->pw_dir, true, true);
/* Provide default values for $TERM and $PATH if they are not set. */
if (!ISSET(didvar, DID_TERM)) {
if (sudo_putenv("TERM=unknown", false, false) == -1)
goto bad;
}
if (!ISSET(didvar, DID_PATH)) {
if (sudo_setenv2("PATH", _PATH_STDPATH, false, true) == -1)
goto bad;
}
if (!ISSET(didvar, DID_TERM))
CHECK_PUTENV("TERM=unknown", false, false);
if (!ISSET(didvar, DID_PATH))
CHECK_SETENV2("PATH", _PATH_STDPATH, false, true);
/* Set PS1 if SUDO_PS1 is set. */
if (ps1 != NULL) {
if (sudo_putenv(ps1, true, true) == -1)
goto bad;
}
if (ps1 != NULL)
CHECK_PUTENV(ps1, true, true);
/* Add the SUDO_COMMAND envariable (cmnd + args). */
if (user_args) {
sudo_easprintf(&cp, "SUDO_COMMAND=%s %s", user_cmnd, user_args);
if (asprintf(&cp, "SUDO_COMMAND=%s %s", user_cmnd, user_args) == -1)
goto bad;
if (sudo_putenv(cp, true, true) == -1) {
sudo_efree(cp);
free(cp);
goto bad;
}
} else {
if (sudo_setenv2("SUDO_COMMAND", user_cmnd, true, true) == -1)
goto bad;
CHECK_SETENV2("SUDO_COMMAND", user_cmnd, true, true);
}
/* Add the SUDO_USER, SUDO_UID, SUDO_GID environment variables. */
if (sudo_setenv2("SUDO_USER", user_name, true, true) == -1)
goto bad;
CHECK_SETENV2("SUDO_USER", user_name, true, true);
snprintf(idbuf, sizeof(idbuf), "%u", (unsigned int) user_uid);
if (sudo_setenv2("SUDO_UID", idbuf, true, true) == -1)
goto bad;
CHECK_SETENV2("SUDO_UID", idbuf, true, true);
snprintf(idbuf, sizeof(idbuf), "%u", (unsigned int) user_gid);
if (sudo_setenv2("SUDO_GID", idbuf, true, true) == -1)
goto bad;
CHECK_SETENV2("SUDO_GID", idbuf, true, true);
debug_return_bool(true);
bad:
sudo_warn(U_("unable to rebuild the environment"));
debug_return_bool(false);
}
@@ -1177,7 +1190,11 @@ read_env_file(const char *path, int overwrite)
val_len -= 2;
}
cp = sudo_emalloc(var_len + 1 + val_len + 1);
if ((cp = malloc(var_len + 1 + val_len + 1)) == NULL) {
/* XXX - no undo on failure */
rval = false;
break;
}
memcpy(cp, var, var_len + 1); /* includes '=' */
memcpy(cp + var_len + 1, val, val_len + 1); /* includes NUL */
@@ -1193,32 +1210,43 @@ read_env_file(const char *path, int overwrite)
debug_return_bool(rval);
}
void
bool
init_envtables(void)
{
struct list_member *cur;
const char **p;
debug_decl(init_envtables, SUDOERS_DEBUG_ENV)
/* Fill in the "env_delete" list. */
for (p = initial_badenv_table; *p; p++) {
cur = sudo_ecalloc(1, sizeof(struct list_member));
cur->value = sudo_estrdup(*p);
cur = calloc(1, sizeof(struct list_member));
if (cur == NULL || (cur->value = strdup(*p)) == NULL) {
free(cur);
debug_return_bool(false);
}
SLIST_INSERT_HEAD(&def_env_delete, cur, entries);
}
/* Fill in the "env_check" list. */
for (p = initial_checkenv_table; *p; p++) {
cur = sudo_ecalloc(1, sizeof(struct list_member));
cur->value = sudo_estrdup(*p);
cur = calloc(1, sizeof(struct list_member));
if (cur == NULL || (cur->value = strdup(*p)) == NULL) {
free(cur);
debug_return_bool(false);
}
SLIST_INSERT_HEAD(&def_env_check, cur, entries);
}
/* Fill in the "env_keep" list. */
for (p = initial_keepenv_table; *p; p++) {
cur = sudo_ecalloc(1, sizeof(struct list_member));
cur->value = sudo_estrdup(*p);
cur = calloc(1, sizeof(struct list_member));
if (cur == NULL || (cur->value = strdup(*p)) == NULL) {
free(cur);
debug_return_bool(false);
}
SLIST_INSERT_HEAD(&def_env_keep, cur, entries);
}
debug_return_bool(true);
}
int