From 8c1d8a7b156aa6b3139f1851d2303a7c99a653de Mon Sep 17 00:00:00 2001 From: "Todd C. Miller" Date: Mon, 6 Feb 2012 10:56:39 -0500 Subject: [PATCH] Make a copy of the struct passwd in exec_setup() to make sure nothing in the policy init modifies it. --- MANIFEST | 1 + compat/pw_dup.c | 104 ++++++++++++++++++++++++++++++++++++++++++++++ config.h.in | 3 ++ configure | 13 ++++++ configure.in | 2 +- include/missing.h | 3 ++ src/sudo.c | 4 +- 7 files changed, 128 insertions(+), 2 deletions(-) create mode 100644 compat/pw_dup.c diff --git a/MANIFEST b/MANIFEST index 03421d73c..03106b272 100644 --- a/MANIFEST +++ b/MANIFEST @@ -41,6 +41,7 @@ compat/mksiglist.c compat/mksiglist.h compat/mktemp.c compat/nanosleep.c +compat/pw_dup.c compat/regress/fnmatch/fnm_test.c compat/regress/fnmatch/fnm_test.in compat/regress/glob/files diff --git a/compat/pw_dup.c b/compat/pw_dup.c new file mode 100644 index 000000000..ec5659982 --- /dev/null +++ b/compat/pw_dup.c @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2000, 2002, 2012 Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Sponsored in part by the Defense Advanced Research Projects + * Agency (DARPA) and Air Force Research Laboratory, Air Force + * Materiel Command, USAF, under agreement number F39502-99-1-0512. + */ + +#include + +#include + +#include +#ifdef STDC_HEADERS +# include +# include +#else +# ifdef HAVE_STDLIB_H +# include +# endif +#endif /* STDC_HEADERS */ +#ifdef HAVE_STRING_H +# include +#endif /* HAVE_STRING_H */ +#ifdef HAVE_STRINGS_H +# include +#endif /* HAVE_STRINGS_H */ +#if defined(HAVE_MALLOC_H) && !defined(STDC_HEADERS) +# include +#endif /* HAVE_MALLOC_H && !STDC_HEADERS */ +#include + +#define PW_SIZE(name, size) \ +do { \ + if (pw->name) { \ + size = strlen(pw->name) + 1; \ + total += size; \ + } \ +} while (0) + +#define PW_COPY(name, size) \ +do { \ + if (pw->name) { \ + (void)memcpy(cp, pw->name, size); \ + newpw->name = cp; \ + cp += size; \ + } \ +} while (0) + +struct passwd * +pw_dup(const struct passwd *pw) +{ + char *cp; + size_t nsize, psize, gsize, dsize, ssize, total; +#ifdef HAVE_LOGIN_CAP_H + size_t csize; +#endif + struct passwd *newpw; + + /* Allocate in one big chunk for easy freeing */ + total = sizeof(struct passwd); + PW_SIZE(pw_name, nsize); + PW_SIZE(pw_passwd, psize); +#ifdef HAVE_LOGIN_CAP_H + PW_SIZE(pw_class, csize); +#endif + PW_SIZE(pw_gecos, gsize); + PW_SIZE(pw_dir, dsize); + PW_SIZE(pw_shell, ssize); + + if ((cp = malloc(total)) == NULL) + return (NULL); + newpw = (struct passwd *)cp; + + /* + * Copy in passwd contents and make strings relative to space + * at the end of the buffer. + */ + (void)memcpy(newpw, pw, sizeof(struct passwd)); + cp += sizeof(struct passwd); + + PW_COPY(pw_name, nsize); + PW_COPY(pw_passwd, psize); +#ifdef HAVE_LOGIN_CAP_H + PW_COPY(pw_class, csize); +#endif + PW_COPY(pw_gecos, gsize); + PW_COPY(pw_dir, dsize); + PW_COPY(pw_shell, ssize); + + return newpw; +} diff --git a/config.h.in b/config.h.in index 42da87a02..bab0510c1 100644 --- a/config.h.in +++ b/config.h.in @@ -396,6 +396,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_PTY_H +/* Define to 1 if you have the `pw_dup' function. */ +#undef HAVE_PW_DUP + /* Define to 1 if you have the `random' function. */ #undef HAVE_RANDOM diff --git a/configure b/configure index f171f6bd9..0b8e31121 100755 --- a/configure +++ b/configure @@ -17014,6 +17014,19 @@ esac fi +ac_fn_c_check_func "$LINENO" "pw_dup" "ac_cv_func_pw_dup" +if test "x$ac_cv_func_pw_dup" = xyes; then : + $as_echo "#define HAVE_PW_DUP 1" >>confdefs.h + +else + case " $LIBOBJS " in + *" pw_dup.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS pw_dup.$ac_objext" + ;; +esac + +fi + ac_fn_c_check_func "$LINENO" "strlcpy" "ac_cv_func_strlcpy" if test "x$ac_cv_func_strlcpy" = xyes; then : $as_echo "#define HAVE_STRLCPY 1" >>confdefs.h diff --git a/configure.in b/configure.in index 0dfd0a393..a3eaad998 100644 --- a/configure.in +++ b/configure.in @@ -2174,7 +2174,7 @@ SUDO_FUNC_FNMATCH([AC_DEFINE(HAVE_FNMATCH)], [AC_LIBOBJ(fnmatch) COMPAT_TEST_PROGS="${COMPAT_TEST_PROGS}${COMPAT_TEST_PROGS+ }fnm_test" ]) SUDO_FUNC_ISBLANK -AC_REPLACE_FUNCS(memrchr strlcpy strlcat setenv) +AC_REPLACE_FUNCS(memrchr pw_dup strlcpy strlcat setenv) AC_CHECK_FUNCS(nanosleep, [], [ # On Solaris, nanosleep is in librt AC_CHECK_LIB(rt, nanosleep, [REPLAY_LIBS="${REPLAY_LIBS} -lrt"], [AC_LIBOBJ(nanosleep)]) diff --git a/include/missing.h b/include/missing.h index 7ac9588cd..f05ac0de1 100644 --- a/include/missing.h +++ b/include/missing.h @@ -335,6 +335,9 @@ int mkstemps(char *, int); #ifndef HAVE_NANOSLEEP int nanosleep(const struct timespec *, struct timespec *); #endif +#ifndef HAVE_PW_DUP +struct passwd *pw_dup(const struct passwd *); +#endif #ifndef HAVE_SETENV int setenv(const char *, const char *, int); #endif diff --git a/src/sudo.c b/src/sudo.c index d80a204b0..b8875afd0 100644 --- a/src/sudo.c +++ b/src/sudo.c @@ -836,7 +836,8 @@ exec_setup(struct command_details *details, const char *ptyname, int ptyfd) #ifdef HAVE_SETAUTHDB aix_setauthdb(IDtouser(details->euid)); #endif - pw = getpwuid(details->euid); + if ((pw = getpwuid(details->euid)) != NULL && (pw = pw_dup(pw)) == NULL) + errorx(1, _("unable to allocate memory")); #ifdef HAVE_SETAUTHDB aix_restoreauthdb(); #endif @@ -994,6 +995,7 @@ exec_setup(struct command_details *details, const char *ptyname, int ptyfd) rval = true; done: + efree(pw); debug_return_bool(rval); } -- 2.40.0