Check for LD_PRELOAD variants in configure instead of checkign cpp

symbols.  In disable_execute(), compute the length of the new envp
and allocate it once instead of reallocating on demand.  Also append
old value of LD_PRELOAD (if any) to the new value.
This commit is contained in:
Todd C. Miller
2012-02-21 13:26:02 -05:00
parent 6fb0090db9
commit 22f4f10a3a
4 changed files with 156 additions and 42 deletions

View File

@@ -745,6 +745,19 @@
/* The syslog priority sudo will use for successful attempts. */ /* The syslog priority sudo will use for successful attempts. */
#undef PRI_SUCCESS #undef PRI_SUCCESS
/* The default value of preloaded objects (if any). */
#undef RTLD_PRELOAD_DEFAULT
/* The delimiter to use when defining multiple preloaded objects. */
#undef RTLD_PRELOAD_DELIM
/* An extra environment variable that is required to enable preloading (if
any). */
#undef RTLD_PRELOAD_ENABLE_VAR
/* The environment variable that controls preloading of dynamic objects. */
#undef RTLD_PRELOAD_VAR
/* The user sudo should run commands as by default. */ /* The user sudo should run commands as by default. */
#undef RUNAS_DEFAULT #undef RUNAS_DEFAULT

50
configure vendored
View File

@@ -2946,6 +2946,11 @@ shadow_libs=
shadow_libs_optional= shadow_libs_optional=
CONFIGURE_ARGS="$@" CONFIGURE_ARGS="$@"
RTLD_PRELOAD_VAR="LD_PRELOAD"
RTLD_PRELOAD_ENABLE_VAR=
RTLD_PRELOAD_DELIM=":"
RTLD_PRELOAD_DEFAULT=
@@ -13728,6 +13733,9 @@ fi
case "$host" in case "$host" in
*-*-sunos4*) *-*-sunos4*)
# LD_PRELOAD is space-delimited
RTLD_PRELOAD_DELIM=" "
# getcwd(3) opens a pipe to getpwd(1)!?! # getcwd(3) opens a pipe to getpwd(1)!?!
BROKEN_GETCWD=1 BROKEN_GETCWD=1
@@ -13739,6 +13747,9 @@ case "$host" in
shadow_funcs="getpwanam issecure" shadow_funcs="getpwanam issecure"
;; ;;
*-*-solaris2*) *-*-solaris2*)
# LD_PRELOAD is space-delimited
RTLD_PRELOAD_DELIM=" "
# To get the crypt(3) prototype (so we pass -Wall) # To get the crypt(3) prototype (so we pass -Wall)
OSDEFS="${OSDEFS} -D__EXTENSIONS__" OSDEFS="${OSDEFS} -D__EXTENSIONS__"
# AFS support needs -lucb # AFS support needs -lucb
@@ -13855,6 +13866,8 @@ done
# LDR_PRELOAD is only supported in AIX 5.3 and later # LDR_PRELOAD is only supported in AIX 5.3 and later
if test $OSMAJOR -lt 5; then if test $OSMAJOR -lt 5; then
with_noexec=no with_noexec=no
else
RTLD_PRELOAD_VAR="LDR_PRELOAD"
fi fi
# AIX-specific functions # AIX-specific functions
@@ -14056,6 +14069,9 @@ $as_echo "yes, fixing locally" >&6; }
fi fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
# ":DEFAULT" must be appended to _RLD_LIST
RTLD_PRELOAD_VAR="_RLD_LIST"
RTLD_PRELOAD_DEFAULT="DEFAULT"
: ${mansectsu='8'} : ${mansectsu='8'}
: ${mansectform='4'} : ${mansectform='4'}
;; ;;
@@ -14122,6 +14138,9 @@ if test "x$ac_cv_lib_sun_getpwnam" = xyes; then :
fi fi
fi fi
# ":DEFAULT" must be appended to _RLD_LIST
RTLD_PRELOAD_VAR="_RLD_LIST"
RTLD_PRELOAD_DEFAULT="DEFAULT"
: ${mansectsu='1m'} : ${mansectsu='1m'}
: ${mansectform='4'} : ${mansectform='4'}
;; ;;
@@ -14313,11 +14332,15 @@ done
CHECKSHADOW="false" CHECKSHADOW="false"
test -z "$with_pam" && AUTH_EXCL_DEF="PAM" test -z "$with_pam" && AUTH_EXCL_DEF="PAM"
: ${with_logincap='yes'} : ${with_logincap='yes'}
RTLD_PRELOAD_VAR="DYLD_INSERT_LIBRARIES"
RTLD_PRELOAD_ENABLE_VAR="DYLD_FORCE_FLAT_NAMESPACE"
;; ;;
*-*-nextstep*) *-*-nextstep*)
# lockf() on is broken on the NeXT -- use flock instead # lockf() on is broken on the NeXT -- use flock instead
ac_cv_func_lockf=no ac_cv_func_lockf=no
ac_cv_func_flock=yes ac_cv_func_flock=yes
RTLD_PRELOAD_VAR="DYLD_INSERT_LIBRARIES"
RTLD_PRELOAD_ENABLE_VAR="DYLD_FORCE_FLAT_NAMESPACE"
;; ;;
*-*-*sysv4*) *-*-*sysv4*)
: ${mansectsu='1m'} : ${mansectsu='1m'}
@@ -14333,6 +14356,29 @@ done
;; ;;
esac esac
if test -n "$with_noexec"; then
cat >>confdefs.h <<EOF
#define RTLD_PRELOAD_VAR "$RTLD_PRELOAD_VAR"
EOF
cat >>confdefs.h <<EOF
#define RTLD_PRELOAD_DELIM "$RTLD_PRELOAD_DELIM"
EOF
if test -n "$RTLD_PRELOAD_DEFAULT"; then
cat >>confdefs.h <<EOF
#define RTLD_PRELOAD_DEFAULT "$RTLD_PRELOAD_DEFAULT"
EOF
fi
if test -n "$RTLD_PRELOAD_ENABLE_VAR"; then
cat >>confdefs.h <<EOF
#define RTLD_PRELOAD_ENABLE_VAR "$RTLD_PRELOAD_ENABLE_VAR"
EOF
fi
fi
AUTH_REG=${AUTH_REG# } AUTH_REG=${AUTH_REG# }
AUTH_EXCL=${AUTH_EXCL# } AUTH_EXCL=${AUTH_EXCL# }
if test -n "$AUTH_EXCL"; then if test -n "$AUTH_EXCL"; then
@@ -22313,6 +22359,10 @@ fi

View File

@@ -184,6 +184,14 @@ shadow_libs=
shadow_libs_optional= shadow_libs_optional=
CONFIGURE_ARGS="$@" CONFIGURE_ARGS="$@"
dnl
dnl LD_PRELOAD equivalents
dnl
RTLD_PRELOAD_VAR="LD_PRELOAD"
RTLD_PRELOAD_ENABLE_VAR=
RTLD_PRELOAD_DELIM=":"
RTLD_PRELOAD_DEFAULT=
dnl dnl
dnl libc replacement functions live in compat dnl libc replacement functions live in compat
dnl dnl
@@ -1465,6 +1473,9 @@ fi
case "$host" in case "$host" in
*-*-sunos4*) *-*-sunos4*)
# LD_PRELOAD is space-delimited
RTLD_PRELOAD_DELIM=" "
# getcwd(3) opens a pipe to getpwd(1)!?! # getcwd(3) opens a pipe to getpwd(1)!?!
BROKEN_GETCWD=1 BROKEN_GETCWD=1
@@ -1476,6 +1487,9 @@ case "$host" in
shadow_funcs="getpwanam issecure" shadow_funcs="getpwanam issecure"
;; ;;
*-*-solaris2*) *-*-solaris2*)
# LD_PRELOAD is space-delimited
RTLD_PRELOAD_DELIM=" "
# To get the crypt(3) prototype (so we pass -Wall) # To get the crypt(3) prototype (so we pass -Wall)
OSDEFS="${OSDEFS} -D__EXTENSIONS__" OSDEFS="${OSDEFS} -D__EXTENSIONS__"
# AFS support needs -lucb # AFS support needs -lucb
@@ -1538,6 +1552,8 @@ case "$host" in
# LDR_PRELOAD is only supported in AIX 5.3 and later # LDR_PRELOAD is only supported in AIX 5.3 and later
if test $OSMAJOR -lt 5; then if test $OSMAJOR -lt 5; then
with_noexec=no with_noexec=no
else
RTLD_PRELOAD_VAR="LDR_PRELOAD"
fi fi
# AIX-specific functions # AIX-specific functions
@@ -1671,6 +1687,9 @@ case "$host" in
]], [[exit(0);]])], [AC_MSG_RESULT(no)], [AC_MSG_RESULT([yes, fixing locally]) ]], [[exit(0);]])], [AC_MSG_RESULT(no)], [AC_MSG_RESULT([yes, fixing locally])
sed 's:<acl.h>:<sys/acl.h>:g' < /usr/include/prot.h > prot.h sed 's:<acl.h>:<sys/acl.h>:g' < /usr/include/prot.h > prot.h
]) ])
# ":DEFAULT" must be appended to _RLD_LIST
RTLD_PRELOAD_VAR="_RLD_LIST"
RTLD_PRELOAD_DEFAULT="DEFAULT"
: ${mansectsu='8'} : ${mansectsu='8'}
: ${mansectform='4'} : ${mansectform='4'}
;; ;;
@@ -1698,6 +1717,9 @@ case "$host" in
if test "$OSMAJOR" -le 4; then if test "$OSMAJOR" -le 4; then
AC_CHECK_LIB(sun, getpwnam, [LIBS="${LIBS} -lsun"]) AC_CHECK_LIB(sun, getpwnam, [LIBS="${LIBS} -lsun"])
fi fi
# ":DEFAULT" must be appended to _RLD_LIST
RTLD_PRELOAD_VAR="_RLD_LIST"
RTLD_PRELOAD_DEFAULT="DEFAULT"
: ${mansectsu='1m'} : ${mansectsu='1m'}
: ${mansectform='4'} : ${mansectform='4'}
;; ;;
@@ -1840,11 +1862,15 @@ case "$host" in
CHECKSHADOW="false" CHECKSHADOW="false"
test -z "$with_pam" && AUTH_EXCL_DEF="PAM" test -z "$with_pam" && AUTH_EXCL_DEF="PAM"
: ${with_logincap='yes'} : ${with_logincap='yes'}
RTLD_PRELOAD_VAR="DYLD_INSERT_LIBRARIES"
RTLD_PRELOAD_ENABLE_VAR="DYLD_FORCE_FLAT_NAMESPACE"
;; ;;
*-*-nextstep*) *-*-nextstep*)
# lockf() on is broken on the NeXT -- use flock instead # lockf() on is broken on the NeXT -- use flock instead
ac_cv_func_lockf=no ac_cv_func_lockf=no
ac_cv_func_flock=yes ac_cv_func_flock=yes
RTLD_PRELOAD_VAR="DYLD_INSERT_LIBRARIES"
RTLD_PRELOAD_ENABLE_VAR="DYLD_FORCE_FLAT_NAMESPACE"
;; ;;
*-*-*sysv4*) *-*-*sysv4*)
: ${mansectsu='1m'} : ${mansectsu='1m'}
@@ -1860,6 +1886,20 @@ case "$host" in
;; ;;
esac esac
dnl
dnl Library preloading to support NOEXEC
dnl
if test -n "$with_noexec"; then
SUDO_DEFINE_UNQUOTED(RTLD_PRELOAD_VAR, "$RTLD_PRELOAD_VAR")
SUDO_DEFINE_UNQUOTED(RTLD_PRELOAD_DELIM, "$RTLD_PRELOAD_DELIM")
if test -n "$RTLD_PRELOAD_DEFAULT"; then
SUDO_DEFINE_UNQUOTED(RTLD_PRELOAD_DEFAULT, "$RTLD_PRELOAD_DEFAULT")
fi
if test -n "$RTLD_PRELOAD_ENABLE_VAR"; then
SUDO_DEFINE_UNQUOTED(RTLD_PRELOAD_ENABLE_VAR, "$RTLD_PRELOAD_ENABLE_VAR")
fi
fi
dnl dnl
dnl Check for mixing mutually exclusive and regular auth methods dnl Check for mixing mutually exclusive and regular auth methods
dnl dnl
@@ -3308,6 +3348,10 @@ AH_TEMPLATE(HAVE_STRUCT_UTMP_UT_EXIT, [Define to 1 if `ut_exit' is a member of `
AH_TEMPLATE(HAVE_STRUCT_UTMPX_UT_EXIT, [Define to 1 if `ut_exit' is a member of `struct utmpx'.]) AH_TEMPLATE(HAVE_STRUCT_UTMPX_UT_EXIT, [Define to 1 if `ut_exit' is a member of `struct utmpx'.])
AH_TEMPLATE(HAVE___FUNC__, [Define to 1 if the compiler supports the C99 __func__ variable.]) AH_TEMPLATE(HAVE___FUNC__, [Define to 1 if the compiler supports the C99 __func__ variable.])
AH_TEMPLATE(SUDO_KRB5_INSTANCE, [An instance string to append to the username (separated by a slash) for Kerberos V authentication]) AH_TEMPLATE(SUDO_KRB5_INSTANCE, [An instance string to append to the username (separated by a slash) for Kerberos V authentication])
AH_TEMPLATE(RTLD_PRELOAD_VAR, [The environment variable that controls preloading of dynamic objects.])
AH_TEMPLATE(RTLD_PRELOAD_ENABLE_VAR, [An extra environment variable that is required to enable preloading (if any).])
AH_TEMPLATE(RTLD_PRELOAD_DELIM, [The delimiter to use when defining multiple preloaded objects.])
AH_TEMPLATE(RTLD_PRELOAD_DEFAULT, [The default value of preloaded objects (if any).])
dnl dnl
dnl Bits to copy verbatim into config.h.in dnl Bits to copy verbatim into config.h.in

View File

@@ -53,9 +53,12 @@ static char * const *
disable_execute(char *const envp[]) disable_execute(char *const envp[])
{ {
#ifdef _PATH_SUDO_NOEXEC #ifdef _PATH_SUDO_NOEXEC
char * const *ev; char *preload, **nenvp = NULL;
char *preload, **nenvp; int env_len, env_size;
int env_len = 0, env_size = 128; int preload_idx = -1;
# ifdef RTLD_PRELOAD_ENABLE_VAR
bool enabled = false;
# endif
#endif /* _PATH_SUDO_NOEXEC */ #endif /* _PATH_SUDO_NOEXEC */
debug_decl(disable_execute, SUDO_DEBUG_UTIL) debug_decl(disable_execute, SUDO_DEBUG_UTIL)
@@ -67,55 +70,59 @@ disable_execute(char *const envp[])
#endif /* HAVE_PRIV_SET */ #endif /* HAVE_PRIV_SET */
#ifdef _PATH_SUDO_NOEXEC #ifdef _PATH_SUDO_NOEXEC
nenvp = emalloc2(env_size, sizeof(char *));
/* /*
* Preload a noexec file. For a list of LD_PRELOAD-alikes, see * Preload a noexec file. For a list of LD_PRELOAD-alikes, see
* http://www.fortran-2000.com/ArnaudRecipes/sharedlib.html * http://www.fortran-2000.com/ArnaudRecipes/sharedlib.html
* XXX - need to support 32-bit and 64-bit variants * XXX - need to support 32-bit and 64-bit variants
*/ */
# if defined(__darwin__) || defined(__APPLE__)
nenvp[env_len++] = "DYLD_FORCE_FLAT_NAMESPACE=";
preload = fmt_string("DYLD_INSERT_LIBRARIES", sudo_conf_noexec_path());
# elif defined(__osf__) || defined(__sgi)
easprintf(&preload, "_RLD_LIST=%s:DEFAULT", sudo_conf_noexec_path());
# elif defined(_AIX)
preload = fmt_string("LDR_PRELOAD", sudo_conf_noexec_path());
# else
preload = fmt_string("LD_PRELOAD", sudo_conf_noexec_path());
# endif
if (preload == NULL)
errorx(1, _("unable to allocate memory"));
nenvp[env_len++] = preload;
for (ev = envp; *ev != NULL; ev++) { /* Count entries in envp, looking for LD_PRELOAD as we go. */
/* for (env_len = 0; envp[env_len] != NULL; env_len++) {
* Prune out existing preloaded libraries. if (strncmp(envp[env_len], RTLD_PRELOAD_VAR "=", sizeof(RTLD_PRELOAD_VAR)) == 0) {
* XXX - should append to new value instead. preload_idx = env_len;
*/
# if defined(__darwin__) || defined(__APPLE__)
if (strncmp(*ev, "DYLD_INSERT_LIBRARIES=", sizeof("DYLD_INSERT_LIBRARIES=") - 1) == 0)
continue; 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
/* Need at least 2 slots for current element and a NULL. */
if (env_len + 2 > env_size) {
env_size += 128;
nenvp = erealloc3(nenvp, env_size, sizeof(char *));
} }
nenvp[env_len++] = *ev; #ifdef RTLD_PRELOAD_ENABLE_VAR
if (strncmp(envp[env_len], RTLD_PRELOAD_ENABLE_VAR "=", sizeof(RTLD_PRELOAD_ENABLE_VAR)) == 0) {
enabled = true;
continue;
}
#endif
} }
/* Make a new copy of envp as needed. */
env_size = env_len + 1 + (preload_idx == -1);
#ifdef RTLD_PRELOAD_ENABLE_VAR
if (!enabled)
env_size++;
#endif
nenvp = emalloc2(env_size, sizeof(*envp));
memcpy(nenvp, envp, env_len * sizeof(*envp));
nenvp[env_len] = NULL; nenvp[env_len] = NULL;
/* Prepend our LD_PRELOAD to existing value or add new entry at the end. */
if (preload_idx == -1) {
# ifdef RTLD_PRELOAD_DEFAULT
easprintf(&preload, "%s=%s%s%s", RTLD_PRELOAD_VAR, sudo_conf_noexec_path(), RTLD_PRELOAD_DELIM, RTLD_PRELOAD_DEFAULT);
# else
preload = fmt_string(RTLD_PRELOAD_VAR, sudo_conf_noexec_path());
# endif
if (preload == NULL)
errorx(1, _("unable to allocate memory"));
nenvp[env_len++] = preload;
nenvp[env_len] = NULL;
} else {
easprintf(&preload, "%s=%s%s%s", RTLD_PRELOAD_VAR, sudo_conf_noexec_path(), RTLD_PRELOAD_DELIM, nenvp[preload_idx]);
nenvp[preload_idx] = preload;
}
# ifdef RTLD_PRELOAD_ENABLE_VAR
if (!enabled) {
nenvp[env_len++] = RTLD_PRELOAD_ENABLE_VAR "=";
nenvp[env_len] = NULL;
}
# endif
/* Install new env pointer. */
envp = nenvp; envp = nenvp;
#endif /* _PATH_SUDO_NOEXEC */ #endif /* _PATH_SUDO_NOEXEC */