Make a copy of the struct passwd in exec_setup() to make sure nothing
authorTodd C. Miller <Todd.Miller@courtesan.com>
Mon, 6 Feb 2012 15:56:39 +0000 (10:56 -0500)
committerTodd C. Miller <Todd.Miller@courtesan.com>
Mon, 6 Feb 2012 15:56:39 +0000 (10:56 -0500)
in the policy init modifies it.

MANIFEST
compat/pw_dup.c [new file with mode: 0644]
config.h.in
configure
configure.in
include/missing.h
src/sudo.c

index 03421d73c446a38b0d6136542ee269d60367e38b..03106b2728cd24e6cb0589adf9f63c31d85c4b8e 100644 (file)
--- 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 (file)
index 0000000..ec56599
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2000, 2002, 2012 Todd C. Miller <Todd.Miller@courtesan.com>
+ *
+ * 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 <config.h>
+
+#include <sys/types.h>
+
+#include <stdio.h>
+#ifdef STDC_HEADERS
+# include <stdlib.h>
+# include <stddef.h>
+#else
+# ifdef HAVE_STDLIB_H
+#  include <stdlib.h>
+# endif
+#endif /* STDC_HEADERS */
+#ifdef HAVE_STRING_H
+# include <string.h>
+#endif /* HAVE_STRING_H */
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif /* HAVE_STRINGS_H */
+#if defined(HAVE_MALLOC_H) && !defined(STDC_HEADERS)
+# include <malloc.h>
+#endif /* HAVE_MALLOC_H && !STDC_HEADERS */
+#include <pwd.h>
+
+#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;
+}
index 42da87a028e73db516b511cf90d86491c97fc324..bab0510c1d12779b22294208f69548c019ab66bc 100644 (file)
 /* Define to 1 if you have the <pty.h> 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
 
index f171f6bd9f650e0a43e1e771d98dddabc1b367c6..0b8e311212302d847a6efe7d1e88679209240e24 100755 (executable)
--- 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
index 0dfd0a3935ce0ec525652dcfb5047a79d1a89ef2..a3eaad998686a61aa065ca774086b998c1d01c5c 100644 (file)
@@ -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)])
index 7ac9588cd903b6fec0c600a807029c49dc4366c9..f05ac0de12ad7a569d483d0663a642322f60e17e 100644 (file)
@@ -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
index d80a204b08e9375f663b03f5ce9ba3c0dcf91835..b8875afd0641f78cb611592aad7e117a8f354235 100644 (file)
@@ -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);
 }