--- embedaddon/sudo/plugins/sudoers/env.c 2012/05/29 12:26:49 1.1.1.2 +++ embedaddon/sudo/plugins/sudoers/env.c 2012/10/09 09:29:52 1.1.1.3 @@ -42,6 +42,9 @@ #ifdef HAVE_UNISTD_H # include #endif /* HAVE_UNISTD_H */ +#ifdef HAVE_INTTYPES_H +# include +#endif #ifdef HAVE_LOGIN_CAP_H # include # ifndef LOGIN_SETENV @@ -50,11 +53,26 @@ #endif /* HAVE_LOGIN_CAP_H */ #include #include +#include #include #include "sudoers.h" /* + * If there is no SIZE_MAX or SIZE_T_MAX we have to assume that size_t + * could be signed (as it is on SunOS 4.x). This just means that + * emalloc2() and erealloc3() cannot allocate huge amounts on such a + * platform but that is OK since sudo doesn't need to do so anyway. + */ +#ifndef SIZE_MAX +# ifdef SIZE_T_MAX +# define SIZE_MAX SIZE_T_MAX +# else +# define SIZE_MAX INT_MAX +# endif /* SIZE_T_MAX */ +#endif /* SIZE_MAX */ + +/* * Flags used in rebuild_env() */ #undef DID_TERM @@ -229,7 +247,7 @@ env_init(char * const envp[]) memset(env.envp, 0, env.env_size * sizeof(char *)); #endif memcpy(env.envp, envp, len * sizeof(char *)); - env.envp[len] = '\0'; + env.envp[len] = NULL; /* Free the old envp we allocated, if any. */ if (env.old_envp != NULL) @@ -263,11 +281,20 @@ sudo_putenv_nodebug(char *str, bool dupcheck, bool ove bool found = false; /* Make sure there is room for the new entry plus a NULL. */ - if (env.env_len + 2 > env.env_size) { + if (env.env_size > 2 && env.env_len > env.env_size - 2) { char **nenvp; - size_t nsize = env.env_size + 128; - nenvp = env.envp ? realloc(env.envp, nsize * sizeof(char *)) : - malloc(nsize * sizeof(char *)); + size_t nsize; + + if (env.env_size > SIZE_MAX - 128) { + errorx2(1, _("internal error, %s overflow"), + "sudo_putenv_nodebug()"); + } + nsize = env.env_size + 128; + if (nsize > SIZE_MAX / sizeof(char *)) { + errorx2(1, _("internal error, %s overflow"), + "sudo_putenv_nodebug()"); + } + nenvp = realloc(env.envp, nsize * sizeof(char *)); if (nenvp == NULL) { errno = ENOMEM; return -1; @@ -289,22 +316,22 @@ sudo_putenv_nodebug(char *str, bool dupcheck, bool ove if (dupcheck) { len = (strchr(str, '=') - str) + 1; - for (ep = env.envp; !found && *ep != NULL; ep++) { + for (ep = env.envp; *ep != NULL; ep++) { if (strncmp(str, *ep, len) == 0) { if (overwrite) *ep = str; found = true; + break; } } - /* Prune out duplicate variables. */ + /* Prune out extra instances of the variable we just overwrote. */ if (found && overwrite) { - while (*ep != NULL) { + while (*++ep != NULL) { if (strncmp(str, *ep, len) == 0) { char **cur = ep; while ((*cur = *(cur + 1)) != NULL) cur++; - } else { - ep++; + ep--; } } env.env_len = ep - env.envp; @@ -332,6 +359,8 @@ sudo_putenv(char *str, bool dupcheck, bool overwrite) int rval; debug_decl(sudo_putenv, SUDO_DEBUG_ENV) + sudo_debug_printf(SUDO_DEBUG_INFO, "sudo_putenv: %s", str); + rval = sudo_putenv_nodebug(str, dupcheck, overwrite); if (rval == -1) { #ifdef ENV_DEBUG @@ -353,6 +382,7 @@ sudo_setenv2(const char *var, const char *val, bool du { char *estring; size_t esize; + int rval; debug_decl(sudo_setenv2, SUDO_DEBUG_ENV) esize = strlen(var) + 1 + strlen(val) + 1; @@ -363,9 +393,12 @@ sudo_setenv2(const char *var, const char *val, bool du strlcat(estring, "=", esize) >= esize || strlcat(estring, val, esize) >= esize) { - errorx(1, _("internal error, sudo_setenv2() overflow")); + errorx(1, _("internal error, %s overflow"), "sudo_setenv2()"); } - debug_return_int(sudo_putenv(estring, dupcheck, overwrite)); + rval = sudo_putenv(estring, dupcheck, overwrite); + if (rval == -1) + efree(estring); + debug_return_int(rval); } /* @@ -377,11 +410,12 @@ sudo_setenv_nodebug(const char *var, const char *val, { char *estring; size_t esize; + int rval = -1; esize = strlen(var) + 1 + strlen(val) + 1; if ((estring = malloc(esize)) == NULL) { errno = ENOMEM; - return -1; + goto done; } /* Build environment string and insert it. */ @@ -390,9 +424,13 @@ sudo_setenv_nodebug(const char *var, const char *val, strlcat(estring, val, esize) >= esize) { errno = EINVAL; - return -1; + goto done; } - return sudo_putenv_nodebug(estring, true, overwrite); + rval = sudo_putenv_nodebug(estring, true, overwrite); +done: + if (rval == -1) + efree(estring); + return rval; } /* @@ -407,7 +445,7 @@ sudo_setenv(const char *var, const char *val, int over rval = sudo_setenv_nodebug(var, val, overwrite); if (rval == -1) { if (errno == EINVAL) - errorx(1, _("internal error, sudo_setenv() overflow")); + errorx(1, _("internal error, %s overflow"), "sudo_setenv()"); errorx(1, _("unable to allocate memory")); } debug_return_int(rval); @@ -452,6 +490,8 @@ sudo_unsetenv(const char *name) int rval; debug_decl(sudo_unsetenv, SUDO_DEBUG_ENV) + sudo_debug_printf(SUDO_DEBUG_INFO, "sudo_unsetenv: %s", name); + rval = sudo_unsetenv_nodebug(name); debug_return_int(rval); @@ -490,6 +530,8 @@ sudo_getenv(const char *name) char *val; debug_decl(sudo_getenv, SUDO_DEBUG_ENV) + sudo_debug_printf(SUDO_DEBUG_INFO, "sudo_getenv: %s", name); + val = sudo_getenv_nodebug(name); debug_return_str(val); @@ -621,6 +663,9 @@ env_should_delete(const char *var) delete_it = matches_env_delete(var); if (!delete_it) delete_it = matches_env_check(var) == false; + + sudo_debug_printf(SUDO_DEBUG_INFO, "delete %s: %s", + var, delete_it ? "YES" : "NO"); debug_return_bool(delete_it); } @@ -638,6 +683,8 @@ env_should_keep(const char *var) if (keepit == -1) keepit = matches_env_keep(var); + sudo_debug_printf(SUDO_DEBUG_INFO, "keep %s: %s", + var, keepit ? "YES" : "NO"); debug_return_bool(keepit == true); } @@ -687,7 +734,7 @@ void rebuild_env(void) { char **old_envp, **ep, *cp, *ps1; - char idbuf[MAX_UID_T_LEN]; + char idbuf[MAX_UID_T_LEN + 1]; unsigned int didvar; bool reset_home = false; @@ -788,12 +835,15 @@ rebuild_env(void) } else { if (!ISSET(didvar, DID_SHELL)) sudo_setenv2("SHELL", sudo_user.pw->pw_shell, false, true); - if (!ISSET(didvar, DID_LOGNAME)) - sudo_setenv2("LOGNAME", user_name, false, true); - if (!ISSET(didvar, DID_USER)) - sudo_setenv2("USER", user_name, false, true); - if (!ISSET(didvar, DID_USERNAME)) - sudo_setenv2("USERNAME", user_name, 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); + if (!ISSET(didvar, DID_USER)) + sudo_setenv2("USER", user_name, false, true); + if (!ISSET(didvar, DID_USERNAME)) + sudo_setenv2("USERNAME", user_name, false, true); + } } /* If we didn't keep HOME, reset it based on target user. */ @@ -845,8 +895,8 @@ rebuild_env(void) /* * Set $USER, $LOGNAME and $USERNAME to target if "set_logname" is not * disabled. We skip this if we are running a login shell (because - * they have already been set them) or sudoedit (because we want the - * editor to find the user's startup files). + * they have already been set) or sudoedit (because we want the editor + * to find the invoking user's startup files). */ if (def_set_logname && !ISSET(sudo_mode, MODE_LOGIN_SHELL|MODE_EDIT)) { if (!ISSET(didvar, KEPT_LOGNAME))