2
0
mirror of https://github.com/sudo-project/sudo.git synced 2025-08-22 18:08:23 +00:00

If building with address sanitizer make sure its DSO is first.

Address sanitizer requires that it be preloaded before any other
DSO in LD_PRELOAD.  This should not be required for clang, which
links in asan statically by default.
This commit is contained in:
Todd C. Miller 2021-08-09 15:50:26 -06:00
parent 8f8a9c37b3
commit dfe26f8c34
5 changed files with 56 additions and 14 deletions

11
configure vendored
View File

@ -28505,6 +28505,17 @@ fi
printf "%s\n" "#define NO_LEAKS 1" >>confdefs.h
case `$CC --version 2>&1` in
*gcc*)
libasan=`$CC -print-file-name=libasan.so 2>/dev/null`
if test -n "$libasan" -a X"$libasan" != X"libasan.so"; then
cat >>confdefs.h <<EOF
#define _PATH_ASAN_LIB "$libasan"
EOF
fi
;;
esac
else $as_nop

View File

@ -80,7 +80,6 @@ AC_SUBST([INSTALL_BACKUP])
AC_SUBST([INSTALL_INTERCEPT])
AC_SUBST([INSTALL_NOEXEC])
AC_SUBST([CHECK_INTERCEPT])
AC_SUBST([CHECK_NOEXEC])
AC_SUBST([PRELOAD_MODULE])
AC_SUBST([DONT_LEAK_PATH_INFO])
AC_SUBST([BSDAUTH_USAGE])
@ -235,7 +234,6 @@ INSTALL_BACKUP=
INSTALL_INTERCEPT=
INSTALL_NOEXEC=
CHECK_INTERCEPT=
CHECK_NOEXEC=
PRELOAD_MODULE=-module
exampledir='$(docdir)/examples'
devdir='$(srcdir)'
@ -4511,6 +4509,18 @@ if test "$enable_sanitizer" != "no"; then
AX_APPEND_FLAG([-fno-omit-frame-pointer], [CFLAGS])
])
AC_DEFINE(NO_LEAKS)
dnl
dnl check for libasan.so so we can preload it before sudo_intercept.so
dnl gcc links asan dynamically, clang links it statically.
dnl
case `$CC --version 2>&1` in
*gcc*)
libasan=`$CC -print-file-name=libasan.so 2>/dev/null`
if test -n "$libasan" -a X"$libasan" != X"libasan.so"; then
SUDO_DEFINE_UNQUOTED(_PATH_ASAN_LIB, "$libasan", [Path to the libasan.so shared library])
fi
;;
esac
], [
AC_MSG_ERROR([$CC does not support the $enable_sanitizer flag])
])
@ -4807,11 +4817,6 @@ if test X"$with_noexec" != X"no"; then
PROGS="${PROGS} sudo_noexec.la"
INSTALL_NOEXEC="install-noexec"
# Can't use sanitizers with LD_PRELOAD
if test "$enable_sanitizer" != "yes"; then
CHECK_NOEXEC=check_noexec
fi
SUDO_DEFINE_UNQUOTED(_PATH_SUDO_NOEXEC, "$noexec_file", [The fully qualified pathname of sudo_noexec.so])
else
SUDO_DEFINE_UNQUOTED(_PATH_SUDO_NOEXEC, NULL)

View File

@ -182,6 +182,10 @@
# undef _PATH_SUDO_DEVSEARCH
#endif /* _PATH_SUDO_DEVSEARCH */
#ifndef _PATH_ASAN_LIB
# undef _PATH_ASAN_LIB
#endif /* _PATH_ASAN_LIB */
#ifndef _PATH_VI
# undef _PATH_VI
#endif /* _PATH_VI */

View File

@ -120,7 +120,7 @@ INIT_DIR=@INIT_DIR@
INIT_SCRIPT=@INIT_SCRIPT@
RC_LINK=@RC_LINK@
TEST_PROGS = check_net_ifs @CHECK_NOEXEC@ check_ttyname
TEST_PROGS = check_net_ifs check_noexec check_ttyname
TEST_LIBS = @LIBS@ $(LT_LIBS)
TEST_LDFLAGS = @LDFLAGS@
@ -317,7 +317,7 @@ check: $(TEST_PROGS) check-fuzzer
MALLOC_OPTIONS=S; export MALLOC_OPTIONS; \
MALLOC_CONF="abort:true,junk:true"; export MALLOC_CONF; \
./check_net_ifs; \
if test X"@CHECK_NOEXEC@" != X""; then \
if [ -f .libs/$(noexecfile) ]; then \
./check_noexec .libs/$(noexecfile); \
fi; \
./check_ttyname; \

View File

@ -41,7 +41,7 @@ sudo_preload_dso(char *envp[], const char *dso_file, int intercept_fd)
{
char *preload = NULL;
char **nenvp = NULL;
int env_len;
int env_len, len;
int preload_idx = -1;
int intercept_idx = -1;
bool fd_present = false;
@ -50,9 +50,23 @@ sudo_preload_dso(char *envp[], const char *dso_file, int intercept_fd)
bool dso_enabled = false;
# else
const bool dso_enabled = true;
# endif
# ifdef _PATH_ASAN_LIB
char *dso_buf = NULL;
# endif
debug_decl(sudo_preload_dso, SUDO_DEBUG_UTIL);
# ifdef _PATH_ASAN_LIB
/*
* The address sanitizer DSO needs to be first in the list.
*/
len = asprintf(&dso_buf, "%s%c%s", _PATH_ASAN_LIB, RTLD_PRELOAD_DELIM,
dso_file);
if (len == -1)
goto oom;
dso_file = dso_buf;
# endif
/*
* Preload a DSO file. For a list of LD_PRELOAD-alikes, see
* http://www.fortran-2000.com/ArnaudRecipes/sharedlib.html
@ -138,18 +152,21 @@ sudo_preload_dso(char *envp[], const char *dso_file, int intercept_fd)
if (!dso_present) {
if (preload_idx == -1) {
# ifdef RTLD_PRELOAD_DEFAULT
asprintf(&preload, "%s=%s%c%s", RTLD_PRELOAD_VAR, dso_file,
len = asprintf(&preload, "%s=%s%c%s", RTLD_PRELOAD_VAR, dso_file,
RTLD_PRELOAD_DELIM, RTLD_PRELOAD_DEFAULT);
if (len == -1) {
goto oom;
}
# else
preload = sudo_new_key_val(RTLD_PRELOAD_VAR, dso_file);
# endif
if (preload == NULL) {
goto oom;
}
# endif
envp[env_len++] = preload;
envp[env_len] = NULL;
} else {
int len = asprintf(&preload, "%s=%s%c%s", RTLD_PRELOAD_VAR,
len = asprintf(&preload, "%s=%s%c%s", RTLD_PRELOAD_VAR,
dso_file, RTLD_PRELOAD_DELIM, envp[preload_idx]);
if (len == -1) {
goto oom;
@ -165,7 +182,6 @@ sudo_preload_dso(char *envp[], const char *dso_file, int intercept_fd)
# endif
if (!fd_present && intercept_fd != -1) {
char *fdstr;
int len;
len = asprintf(&fdstr, "SUDO_INTERCEPT_FD=%d", intercept_fd);
if (len == -1) {
@ -178,10 +194,16 @@ sudo_preload_dso(char *envp[], const char *dso_file, int intercept_fd)
envp[env_len] = NULL;
}
}
# ifdef _PATH_ASAN_LIB
free(dso_buf);
# endif
debug_return_ptr(envp);
oom:
sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
# ifdef _PATH_ASAN_LIB
free(dso_buf);
# endif
free(preload);
free(nenvp);
debug_return_ptr(NULL);