2
0
mirror of https://github.com/sudo-project/sudo.git synced 2025-08-22 09:57:41 +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 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 else $as_nop

View File

@ -80,7 +80,6 @@ AC_SUBST([INSTALL_BACKUP])
AC_SUBST([INSTALL_INTERCEPT]) AC_SUBST([INSTALL_INTERCEPT])
AC_SUBST([INSTALL_NOEXEC]) AC_SUBST([INSTALL_NOEXEC])
AC_SUBST([CHECK_INTERCEPT]) AC_SUBST([CHECK_INTERCEPT])
AC_SUBST([CHECK_NOEXEC])
AC_SUBST([PRELOAD_MODULE]) AC_SUBST([PRELOAD_MODULE])
AC_SUBST([DONT_LEAK_PATH_INFO]) AC_SUBST([DONT_LEAK_PATH_INFO])
AC_SUBST([BSDAUTH_USAGE]) AC_SUBST([BSDAUTH_USAGE])
@ -235,7 +234,6 @@ INSTALL_BACKUP=
INSTALL_INTERCEPT= INSTALL_INTERCEPT=
INSTALL_NOEXEC= INSTALL_NOEXEC=
CHECK_INTERCEPT= CHECK_INTERCEPT=
CHECK_NOEXEC=
PRELOAD_MODULE=-module PRELOAD_MODULE=-module
exampledir='$(docdir)/examples' exampledir='$(docdir)/examples'
devdir='$(srcdir)' devdir='$(srcdir)'
@ -4511,6 +4509,18 @@ if test "$enable_sanitizer" != "no"; then
AX_APPEND_FLAG([-fno-omit-frame-pointer], [CFLAGS]) AX_APPEND_FLAG([-fno-omit-frame-pointer], [CFLAGS])
]) ])
AC_DEFINE(NO_LEAKS) 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]) 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" PROGS="${PROGS} sudo_noexec.la"
INSTALL_NOEXEC="install-noexec" 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]) SUDO_DEFINE_UNQUOTED(_PATH_SUDO_NOEXEC, "$noexec_file", [The fully qualified pathname of sudo_noexec.so])
else else
SUDO_DEFINE_UNQUOTED(_PATH_SUDO_NOEXEC, NULL) SUDO_DEFINE_UNQUOTED(_PATH_SUDO_NOEXEC, NULL)

View File

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

View File

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

View File

@ -41,7 +41,7 @@ sudo_preload_dso(char *envp[], const char *dso_file, int intercept_fd)
{ {
char *preload = NULL; char *preload = NULL;
char **nenvp = NULL; char **nenvp = NULL;
int env_len; int env_len, len;
int preload_idx = -1; int preload_idx = -1;
int intercept_idx = -1; int intercept_idx = -1;
bool fd_present = false; bool fd_present = false;
@ -50,9 +50,23 @@ sudo_preload_dso(char *envp[], const char *dso_file, int intercept_fd)
bool dso_enabled = false; bool dso_enabled = false;
# else # else
const bool dso_enabled = true; const bool dso_enabled = true;
# endif
# ifdef _PATH_ASAN_LIB
char *dso_buf = NULL;
# endif # endif
debug_decl(sudo_preload_dso, SUDO_DEBUG_UTIL); 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 * Preload a DSO 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
@ -138,18 +152,21 @@ sudo_preload_dso(char *envp[], const char *dso_file, int intercept_fd)
if (!dso_present) { if (!dso_present) {
if (preload_idx == -1) { if (preload_idx == -1) {
# ifdef RTLD_PRELOAD_DEFAULT # 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); RTLD_PRELOAD_DELIM, RTLD_PRELOAD_DEFAULT);
if (len == -1) {
goto oom;
}
# else # else
preload = sudo_new_key_val(RTLD_PRELOAD_VAR, dso_file); preload = sudo_new_key_val(RTLD_PRELOAD_VAR, dso_file);
# endif
if (preload == NULL) { if (preload == NULL) {
goto oom; goto oom;
} }
# endif
envp[env_len++] = preload; envp[env_len++] = preload;
envp[env_len] = NULL; envp[env_len] = NULL;
} else { } 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]); dso_file, RTLD_PRELOAD_DELIM, envp[preload_idx]);
if (len == -1) { if (len == -1) {
goto oom; goto oom;
@ -165,7 +182,6 @@ sudo_preload_dso(char *envp[], const char *dso_file, int intercept_fd)
# endif # endif
if (!fd_present && intercept_fd != -1) { if (!fd_present && intercept_fd != -1) {
char *fdstr; char *fdstr;
int len;
len = asprintf(&fdstr, "SUDO_INTERCEPT_FD=%d", intercept_fd); len = asprintf(&fdstr, "SUDO_INTERCEPT_FD=%d", intercept_fd);
if (len == -1) { if (len == -1) {
@ -178,10 +194,16 @@ sudo_preload_dso(char *envp[], const char *dso_file, int intercept_fd)
envp[env_len] = NULL; envp[env_len] = NULL;
} }
} }
# ifdef _PATH_ASAN_LIB
free(dso_buf);
# endif
debug_return_ptr(envp); debug_return_ptr(envp);
oom: oom:
sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory")); sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
# ifdef _PATH_ASAN_LIB
free(dso_buf);
# endif
free(preload); free(preload);
free(nenvp); free(nenvp);
debug_return_ptr(NULL); debug_return_ptr(NULL);