Add basic support for 32-bit and 64-bit LD_PRELOAD equivalents.

The noexec and intercept DSO settings may now include both a 32-bit
DSO and a 64-bit DSO specified by a colon.  For example:
/usr/libexec/sudo/sudo_intercept.so:/usr/libexec/sudo/sudo_intercept_64.so.
This commit is contained in:
Todd C. Miller
2023-07-31 13:46:57 -06:00
parent 7cb1f7f3a9
commit 980e0216ac
7 changed files with 439 additions and 195 deletions

View File

@@ -434,24 +434,30 @@ Defaults are listed in brackets after the description.
This is also used to support the "log_subcmds" sudoers
setting. For example, this means that for a shell run
through sudo, the individual commands run by the shell are
also subject to rules in the sudoers file. See the
"Preventing Shell Escapes" section in the sudoers man page
for details. If specified, PATH should be a fully qualified
path name, e.g. /usr/local/libexec/sudo/sudo_intercept.so.
If PATH is "no", intercept support will not be compiled in.
The default is to compile intercept support if libtool
supports building shared objects on your system.
also subject to rules in the sudoers file. See the "Preventing
Shell Escapes" section in the sudoers man page for details.
If specified, PATH should either be a fully-qualified path
name such as /usr/local/libexec/sudo/sudo_intercept.so, or,
for AIX and Solaris systems, it may optionally be set to a
32-bit shared library followed by a 64-bit shared library,
separated by a colon. If PATH is "no", intercept support
will not be compiled in. The default is to compile intercept
support if libtool supports building shared objects on your
system.
--with-noexec[=PATH]
Enable support for the "noexec" functionality which prevents
a dynamically-linked program being run by sudo from executing
another program (think shell escapes). See the "Preventing
Shell Escapes" section in the sudoers man page for details.
If specified, PATH should be a fully qualified path name,
e.g. /usr/local/libexec/sudo/sudo_noexec.so. If PATH is
"no", noexec support will not be compiled in. The default
is to compile noexec support if libtool supports building
shared objects on your system.
If specified, PATH should either be a fully-qualified path
name such as /usr/local/libexec/sudo/sudo_noexec.so, or,
for AIX and Solaris systems, it may optionally be set to a
32-bit shared library followed by a 64-bit shared library,
separated by a colon. If PATH is "no", noexec support
will not be compiled in. The default is to compile noexec
support if libtool supports building shared objects on your
system.
--with-selinux
Enable support for role based access control (RBAC) on systems
@@ -836,7 +842,7 @@ Defaults are listed in brackets after the description.
Sudoers option: exempt_group
--with-fqdn
Define this if you want to put fully qualified host names in the sudoers
Define this if you want to put fully-qualified host names in the sudoers
file. Ie: instead of myhost you would use myhost.mydomain.edu. You may
still use the short form if you wish (and even mix the two). Beware
that turning FQDN on requires sudo to make DNS lookups which may make

View File

@@ -1257,6 +1257,14 @@
/* The environment variable that controls preloading of dynamic objects. */
#undef RTLD_PRELOAD_VAR
/* The environment variable that controls preloading of 32-bit dynamic
objects. */
#undef RTLD_PRELOAD_VAR_32
/* The environment variable that controls preloading of 64-bit dynamic
objects. */
#undef RTLD_PRELOAD_VAR_64
/* The user sudo should run commands as by default. */
#undef RUNAS_DEFAULT
@@ -1286,6 +1294,9 @@
/* The size of 'id_t', as computed by sizeof. */
#undef SIZEOF_ID_T
/* The size of 'long', as computed by sizeof. */
#undef SIZEOF_LONG
/* The size of 'long long', as computed by sizeof. */
#undef SIZEOF_LONG_LONG

273
configure vendored
View File

@@ -3749,11 +3749,6 @@ shadow_funcs=
shadow_libs=
OS_INIT=os_init_common
RTLD_PRELOAD_VAR="LD_PRELOAD"
RTLD_PRELOAD_ENABLE_VAR=
RTLD_PRELOAD_DELIM=":"
RTLD_PRELOAD_DEFAULT=
@@ -17314,7 +17309,7 @@ esac
fi
INTERCEPTFILE="sudo_intercept.so"
INTERCEPTDIR="`echo $intercept_file|sed -e 's:^${\([^}]*\)}:$(\1):' -e 's:^\(.*\)/[^/]*:\1:'`"
INTERCEPTDIR="`echo $intercept_file|sed -e 's:^${\([^}]*\)}:$(\1):' -e 's:^\([^:]*\)/[^/].*$:\1:'`"
# Check whether --with-noexec was given.
@@ -17332,7 +17327,7 @@ esac
fi
NOEXECFILE="sudo_noexec.so"
NOEXECDIR="`echo $noexec_file|sed -e 's:^${\([^}]*\)}:$(\1):' -e 's:^\(.*\)/[^/]*:\1:'`"
NOEXECDIR="`echo $noexec_file|sed -e 's:^${\([^}]*\)}:$(\1):' -e 's:^\([^:]*\)/[^/].*$:\1:'`"
# Extract the first word of "sha1sum", so it can be a program name with args.
set dummy sha1sum; ac_word=$2
@@ -17590,9 +17585,6 @@ case "$host" in
printf "%s\n" "#define PAM_SUN_CODEBASE 1" >>confdefs.h
# LD_PRELOAD is space-delimited
RTLD_PRELOAD_DELIM=" "
# illumos has a broken fmemopen(3)
if test X"`uname -o 2>/dev/null`" = X"illumos"; then
: ${ac_cv_func_fmemopen='no'}
@@ -17663,13 +17655,6 @@ then :
fi
# LDR_PRELOAD is only supported in AIX 5.3 and later
case "$OSREV" in
[1-4].*) with_noexec=no;;
5.[1-2]*) with_noexec=no;;
*) RTLD_PRELOAD_VAR="LDR_PRELOAD";;
esac
# cfmakeraw is broken on AIX (and is not documented)
: ${ac_cv_func_cfmakeraw='no'}
@@ -17917,9 +17902,6 @@ fi
shadow_funcs="getprpwnam dispcrypt"
shadow_libs="-lsecurity"
# ":DEFAULT" must be appended to _RLD_LIST
RTLD_PRELOAD_VAR="_RLD_LIST"
RTLD_PRELOAD_DEFAULT="DEFAULT"
: ${mansectsu='8'}
: ${mansectform='4'}
: ${mansectmisc='5'}
@@ -18176,9 +18158,7 @@ printf "%s\n" "yes, fixing locally" >&6; }
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
# ":DEFAULT" must be appended to _RLD_LIST
RTLD_PRELOAD_VAR="_RLD_LIST"
RTLD_PRELOAD_DEFAULT="DEFAULT"
: ${mansectsu='8'}
: ${mansectform='4'}
: ${mansectmisc='5'}
@@ -18256,9 +18236,7 @@ fi
fi
# ":DEFAULT" must be appended to _RLD_LIST
RTLD_PRELOAD_VAR="_RLD_LIST"
RTLD_PRELOAD_DEFAULT="DEFAULT"
: ${mansectsu='1m'}
: ${mansectform='4'}
: ${mansectmisc='5'}
@@ -18566,21 +18544,6 @@ fi
: ${with_logincap='yes'}
# Darwin has a broken poll(), Apple radar 3710161
: ${enable_poll='no'}
# Darwin 8 and above can interpose library symbols cleanly
if test $OSMAJOR -ge 8
then :
printf "%s\n" "#define HAVE___INTERPOSE 1" >>confdefs.h
dlyld_interpose=yes
else case e in #(
e)
RTLD_PRELOAD_ENABLE_VAR="DYLD_FORCE_FLAT_NAMESPACE"
;;
esac
fi
RTLD_PRELOAD_VAR="DYLD_INSERT_LIBRARIES"
# Build sudo_noexec.so as a shared library, not a module.
# On Darwin, modules and shared libraries are incompatible.
@@ -18742,8 +18705,6 @@ fi
*-*-nextstep*)
# lockf() is broken on the NeXT
ac_cv_func_lockf=no
RTLD_PRELOAD_VAR="DYLD_INSERT_LIBRARIES"
RTLD_PRELOAD_ENABLE_VAR="DYLD_FORCE_FLAT_NAMESPACE"
;;
*-*-*sysv4*)
: ${mansectsu='1m'}
@@ -18779,50 +18740,6 @@ fi
;;
esac
if test X"$enable_intercept" = X"no"
then :
intercept_file=disabled
fi
if test X"$with_noexec" = X"no"
then :
noexec_file=disabled
fi
if test X"${intercept_file} ${noexec_file}" != X"disabled disabled"
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_EXCL=${AUTH_EXCL# }
if test -n "$AUTH_EXCL" -a -n "$AUTH_REG"
@@ -21013,35 +20930,35 @@ fi
# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
# declarations like 'int a3[[(sizeof (unsigned char)) >= 0]];'.
# This bug is HP SR number 8606223364.
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking size of id_t" >&5
printf %s "checking size of id_t... " >&6; }
if test ${ac_cv_sizeof_id_t+y}
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking size of long" >&5
printf %s "checking size of long... " >&6; }
if test ${ac_cv_sizeof_long+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (id_t))" "ac_cv_sizeof_id_t" "$ac_includes_default"
e) if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (long))" "ac_cv_sizeof_long" "$ac_includes_default"
then :
else case e in #(
e) if test "$ac_cv_type_id_t" = yes; then
e) if test "$ac_cv_type_long" = yes; then
{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5
printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;}
as_fn_error 77 "cannot compute sizeof (id_t)
as_fn_error 77 "cannot compute sizeof (long)
See 'config.log' for more details" "$LINENO" 5; }
else
ac_cv_sizeof_id_t=0
ac_cv_sizeof_long=0
fi ;;
esac
fi
;;
esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_id_t" >&5
printf "%s\n" "$ac_cv_sizeof_id_t" >&6; }
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_long" >&5
printf "%s\n" "$ac_cv_sizeof_long" >&6; }
printf "%s\n" "#define SIZEOF_ID_T $ac_cv_sizeof_id_t" >>confdefs.h
printf "%s\n" "#define SIZEOF_LONG $ac_cv_sizeof_long" >>confdefs.h
# The cast to long int works around a bug in the HP C Compiler
@@ -21079,6 +20996,41 @@ printf "%s\n" "$ac_cv_sizeof_long_long" >&6; }
printf "%s\n" "#define SIZEOF_LONG_LONG $ac_cv_sizeof_long_long" >>confdefs.h
# The cast to long int works around a bug in the HP C Compiler
# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
# declarations like 'int a3[[(sizeof (unsigned char)) >= 0]];'.
# This bug is HP SR number 8606223364.
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking size of id_t" >&5
printf %s "checking size of id_t... " >&6; }
if test ${ac_cv_sizeof_id_t+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (id_t))" "ac_cv_sizeof_id_t" "$ac_includes_default"
then :
else case e in #(
e) if test "$ac_cv_type_id_t" = yes; then
{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5
printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;}
as_fn_error 77 "cannot compute sizeof (id_t)
See 'config.log' for more details" "$LINENO" 5; }
else
ac_cv_sizeof_id_t=0
fi ;;
esac
fi
;;
esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_id_t" >&5
printf "%s\n" "$ac_cv_sizeof_id_t" >&6; }
printf "%s\n" "#define SIZEOF_ID_T $ac_cv_sizeof_id_t" >>confdefs.h
# The cast to long int works around a bug in the HP C Compiler
# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
# declarations like 'int a3[[(sizeof (unsigned char)) >= 0]];'.
@@ -21461,6 +21413,131 @@ fi
esac
fi
RTLD_PRELOAD_VAR="LD_PRELOAD"
if test $ac_cv_sizeof_long -eq 4; then
RTLD_PRELOAD_VAR_32="LD_PRELOAD"
else
RTLD_PRELOAD_VAR_64="LD_PRELOAD"
fi
RTLD_PRELOAD_ENABLE_VAR=
RTLD_PRELOAD_DELIM=":"
RTLD_PRELOAD_DEFAULT=
case "$host" in
*-*-solaris2*)
# LD_PRELOAD is space-delimited
RTLD_PRELOAD_DELIM=" "
RTLD_PRELOAD_VAR_32="LD_PRELOAD_32"
RTLD_PRELOAD_VAR_64="LD_PRELOAD_64"
;;
*-*-aix*)
# LDR_PRELOAD and LDR_PRELOAD64 are only supported on
# AIX 5.3 and above.
case "$OSREV" in
[1-4].*|5.[1-2]*)
with_noexec=no
;;
*)
# AIX uses LDR_PRELOAD for 32-bit executables
# and LDR_PRELOAD64 for 64-bit executable.
RTLD_PRELOAD_VAR_32="LDR_PRELOAD"
RTLD_PRELOAD_VAR_64="LDR_PRELOAD64"
if test $ac_cv_sizeof_long -eq 4; then
RTLD_PRELOAD_VAR="LDR_PRELOAD"
else
RTLD_PRELOAD_VAR="LDR_PRELOAD64"
fi
;;
esac
;;
*-dec-osf*|*-*-hiuxmpp*|*-*-irix*)
# ":DEFAULT" must be appended to _RLD_LIST
RTLD_PRELOAD_VAR="_RLD_LIST"
RTLD_PRELOAD_DEFAULT="DEFAULT"
;;
*-*-darwin*)
# Darwin 8 and above can interpose library symbols cleanly
if test $OSMAJOR -ge 8
then :
printf "%s\n" "#define HAVE___INTERPOSE 1" >>confdefs.h
dlyld_interpose=yes
else case e in #(
e)
RTLD_PRELOAD_ENABLE_VAR="DYLD_FORCE_FLAT_NAMESPACE"
;;
esac
fi
RTLD_PRELOAD_VAR="DYLD_INSERT_LIBRARIES"
# Build sudo_noexec.so as a shared library, not a module.
# On Darwin, modules and shared libraries are incompatible.
PRELOAD_MODULE=
;;
*-*-nextstep*)
RTLD_PRELOAD_VAR="DYLD_INSERT_LIBRARIES"
RTLD_PRELOAD_ENABLE_VAR="DYLD_FORCE_FLAT_NAMESPACE"
;;
esac
if test X"$enable_intercept" = X"no"
then :
intercept_file=disabled
fi
if test X"$with_noexec" = X"no"
then :
noexec_file=disabled
fi
if test X"${intercept_file} ${noexec_file}" != X"disabled disabled"
then :
cat >>confdefs.h <<EOF
#define RTLD_PRELOAD_VAR "$RTLD_PRELOAD_VAR"
EOF
if test -n "$RTLD_PRELOAD_VAR_32"; then
cat >>confdefs.h <<EOF
#define RTLD_PRELOAD_VAR_32 "$RTLD_PRELOAD_VAR_32"
EOF
fi
if test -n "$RTLD_PRELOAD_VAR_64"; then
cat >>confdefs.h <<EOF
#define RTLD_PRELOAD_VAR_64 "$RTLD_PRELOAD_VAR_64"
EOF
fi
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
if test ${enable_python-'no'} = "yes"
then :
@@ -38527,6 +38604,8 @@ fi

View File

@@ -257,14 +257,6 @@ shadow_funcs=
shadow_libs=
OS_INIT=os_init_common
dnl
dnl LD_PRELOAD equivalents
dnl
RTLD_PRELOAD_VAR="LD_PRELOAD"
RTLD_PRELOAD_ENABLE_VAR=
RTLD_PRELOAD_DELIM=":"
RTLD_PRELOAD_DEFAULT=
dnl
dnl libc replacement functions live in libsudo_util.a
dnl
@@ -1696,7 +1688,7 @@ AC_ARG_ENABLE(intercept,
esac
], [enable_intercept="$intercept_file"])
INTERCEPTFILE="sudo_intercept.so"
INTERCEPTDIR="`echo $intercept_file|sed -e 's:^${\([[^}]]*\)}:$(\1):' -e 's:^\(.*\)/[[^/]]*:\1:'`"
INTERCEPTDIR="`echo $intercept_file|sed -e 's:^${\([[^}]]*\)}:$(\1):' -e 's:^\([[^:]]*\)/[[^/]].*$:\1:'`"
AC_ARG_WITH(noexec, [AS_HELP_STRING([--with-noexec[[=PATH]]], [fully qualified pathname of sudo_noexec.so])],
[case $with_noexec in
@@ -1706,7 +1698,7 @@ AC_ARG_WITH(noexec, [AS_HELP_STRING([--with-noexec[[=PATH]]], [fully qualified p
;;
esac], [with_noexec="$noexec_file"])
NOEXECFILE="sudo_noexec.so"
NOEXECDIR="`echo $noexec_file|sed -e 's:^${\([[^}]]*\)}:$(\1):' -e 's:^\(.*\)/[[^/]]*:\1:'`"
NOEXECDIR="`echo $noexec_file|sed -e 's:^${\([[^}]]*\)}:$(\1):' -e 's:^\([[^:]]*\)/[[^/]].*$:\1:'`"
dnl
dnl Find programs we use
@@ -1775,9 +1767,6 @@ case "$host" in
*-*-solaris2*)
AC_DEFINE([PAM_SUN_CODEBASE])
# LD_PRELOAD is space-delimited
RTLD_PRELOAD_DELIM=" "
# illumos has a broken fmemopen(3)
if test X"`uname -o 2>/dev/null`" = X"illumos"; then
: ${ac_cv_func_fmemopen='no'}
@@ -1822,13 +1811,6 @@ case "$host" in
with_netsvc="/etc/netsvc.conf"
])
# LDR_PRELOAD is only supported in AIX 5.3 and later
case "$OSREV" in
[[1-4]].*) with_noexec=no;;
5.[[1-2]]*) with_noexec=no;;
*) RTLD_PRELOAD_VAR="LDR_PRELOAD";;
esac
# cfmakeraw is broken on AIX (and is not documented)
: ${ac_cv_func_cfmakeraw='no'}
@@ -1890,9 +1872,6 @@ case "$host" in
shadow_funcs="getprpwnam dispcrypt"
shadow_libs="-lsecurity"
# ":DEFAULT" must be appended to _RLD_LIST
RTLD_PRELOAD_VAR="_RLD_LIST"
RTLD_PRELOAD_DEFAULT="DEFAULT"
: ${mansectsu='8'}
: ${mansectform='4'}
: ${mansectmisc='5'}
@@ -2017,9 +1996,7 @@ case "$host" in
]], [[return(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
])
# ":DEFAULT" must be appended to _RLD_LIST
RTLD_PRELOAD_VAR="_RLD_LIST"
RTLD_PRELOAD_DEFAULT="DEFAULT"
: ${mansectsu='8'}
: ${mansectform='4'}
: ${mansectmisc='5'}
@@ -2037,9 +2014,7 @@ case "$host" in
AS_IF([test "$OSMAJOR" -le 4], [
AC_CHECK_LIB([sun], [getpwnam], [LIBS="${LIBS} -lsun"])
])
# ":DEFAULT" must be appended to _RLD_LIST
RTLD_PRELOAD_VAR="_RLD_LIST"
RTLD_PRELOAD_DEFAULT="DEFAULT"
: ${mansectsu='1m'}
: ${mansectform='4'}
: ${mansectmisc='5'}
@@ -2222,14 +2197,6 @@ case "$host" in
: ${with_logincap='yes'}
# Darwin has a broken poll(), Apple radar 3710161
: ${enable_poll='no'}
# Darwin 8 and above can interpose library symbols cleanly
AS_IF([test $OSMAJOR -ge 8], [
AC_DEFINE(HAVE___INTERPOSE)
dlyld_interpose=yes
], [
RTLD_PRELOAD_ENABLE_VAR="DYLD_FORCE_FLAT_NAMESPACE"
])
RTLD_PRELOAD_VAR="DYLD_INSERT_LIBRARIES"
# Build sudo_noexec.so as a shared library, not a module.
# On Darwin, modules and shared libraries are incompatible.
@@ -2259,8 +2226,6 @@ case "$host" in
*-*-nextstep*)
# lockf() is broken on the NeXT
ac_cv_func_lockf=no
RTLD_PRELOAD_VAR="DYLD_INSERT_LIBRARIES"
RTLD_PRELOAD_ENABLE_VAR="DYLD_FORCE_FLAT_NAMESPACE"
;;
*-*-*sysv4*)
: ${mansectsu='1m'}
@@ -2296,26 +2261,6 @@ case "$host" in
;;
esac
dnl
dnl Library preloading to support NOEXEC
dnl
AS_IF([test X"$enable_intercept" = X"no"], [
intercept_file=disabled
])
AS_IF([test X"$with_noexec" = X"no"], [
noexec_file=disabled
])
AS_IF([test X"${intercept_file} ${noexec_file}" != X"disabled disabled"], [
SUDO_DEFINE_UNQUOTED(RTLD_PRELOAD_VAR, "$RTLD_PRELOAD_VAR")
SUDO_DEFINE_UNQUOTED(RTLD_PRELOAD_DELIM, '$RTLD_PRELOAD_DELIM')
AS_IF([test -n "$RTLD_PRELOAD_DEFAULT"], [
SUDO_DEFINE_UNQUOTED(RTLD_PRELOAD_DEFAULT, "$RTLD_PRELOAD_DEFAULT")
])
AS_IF([test -n "$RTLD_PRELOAD_ENABLE_VAR"], [
SUDO_DEFINE_UNQUOTED(RTLD_PRELOAD_ENABLE_VAR, "$RTLD_PRELOAD_ENABLE_VAR")
])
])
dnl
dnl Check for mixing mutually exclusive and regular auth methods
dnl
@@ -2545,8 +2490,9 @@ AC_INCLUDES_DEFAULT
SUDO_UID_T_LEN
SUDO_SOCK_SA_LEN
SUDO_SOCK_SIN_LEN
AC_CHECK_SIZEOF([id_t])
AC_CHECK_SIZEOF([long])
AC_CHECK_SIZEOF([long long])
AC_CHECK_SIZEOF([id_t])
AC_CHECK_SIZEOF([time_t])
AS_IF([test X"$ac_cv_header_utmps_h" = X"yes"], [
SUDO_CHECK_UTMP_MEMBERS([utmps])
@@ -2556,6 +2502,101 @@ AS_IF([test X"$ac_cv_header_utmps_h" = X"yes"], [
SUDO_CHECK_UTMP_MEMBERS([utmp])
])
dnl
dnl Default values for LD_PRELOAD and related settings.
dnl
RTLD_PRELOAD_VAR="LD_PRELOAD"
if test $ac_cv_sizeof_long -eq 4; then
RTLD_PRELOAD_VAR_32="LD_PRELOAD"
else
RTLD_PRELOAD_VAR_64="LD_PRELOAD"
fi
RTLD_PRELOAD_ENABLE_VAR=
RTLD_PRELOAD_DELIM=":"
RTLD_PRELOAD_DEFAULT=
dnl
dnl System-specific LD_PRELOAD equivalents.
dnl The below tests rely on ac_cv_sizeof_long being defined.
dnl
case "$host" in
*-*-solaris2*)
# LD_PRELOAD is space-delimited
RTLD_PRELOAD_DELIM=" "
RTLD_PRELOAD_VAR_32="LD_PRELOAD_32"
RTLD_PRELOAD_VAR_64="LD_PRELOAD_64"
;;
*-*-aix*)
# LDR_PRELOAD and LDR_PRELOAD64 are only supported on
# AIX 5.3 and above.
case "$OSREV" in
[[1-4]].*|5.[[1-2]]*)
with_noexec=no
;;
*)
# AIX uses LDR_PRELOAD for 32-bit executables
# and LDR_PRELOAD64 for 64-bit executable.
RTLD_PRELOAD_VAR_32="LDR_PRELOAD"
RTLD_PRELOAD_VAR_64="LDR_PRELOAD64"
if test $ac_cv_sizeof_long -eq 4; then
RTLD_PRELOAD_VAR="LDR_PRELOAD"
else
RTLD_PRELOAD_VAR="LDR_PRELOAD64"
fi
;;
esac
;;
*-dec-osf*|*-*-hiuxmpp*|*-*-irix*)
# ":DEFAULT" must be appended to _RLD_LIST
RTLD_PRELOAD_VAR="_RLD_LIST"
RTLD_PRELOAD_DEFAULT="DEFAULT"
;;
*-*-darwin*)
# Darwin 8 and above can interpose library symbols cleanly
AS_IF([test $OSMAJOR -ge 8], [
AC_DEFINE(HAVE___INTERPOSE)
dlyld_interpose=yes
], [
RTLD_PRELOAD_ENABLE_VAR="DYLD_FORCE_FLAT_NAMESPACE"
])
RTLD_PRELOAD_VAR="DYLD_INSERT_LIBRARIES"
# Build sudo_noexec.so as a shared library, not a module.
# On Darwin, modules and shared libraries are incompatible.
PRELOAD_MODULE=
;;
*-*-nextstep*)
RTLD_PRELOAD_VAR="DYLD_INSERT_LIBRARIES"
RTLD_PRELOAD_ENABLE_VAR="DYLD_FORCE_FLAT_NAMESPACE"
;;
esac
dnl
dnl Library preloading to support NOEXEC
dnl
AS_IF([test X"$enable_intercept" = X"no"], [
intercept_file=disabled
])
AS_IF([test X"$with_noexec" = X"no"], [
noexec_file=disabled
])
AS_IF([test X"${intercept_file} ${noexec_file}" != X"disabled disabled"], [
SUDO_DEFINE_UNQUOTED(RTLD_PRELOAD_VAR, "$RTLD_PRELOAD_VAR")
if test -n "$RTLD_PRELOAD_VAR_32"; then
SUDO_DEFINE_UNQUOTED(RTLD_PRELOAD_VAR_32, "$RTLD_PRELOAD_VAR_32")
fi
if test -n "$RTLD_PRELOAD_VAR_64"; then
SUDO_DEFINE_UNQUOTED(RTLD_PRELOAD_VAR_64, "$RTLD_PRELOAD_VAR_64")
fi
SUDO_DEFINE_UNQUOTED(RTLD_PRELOAD_DELIM, '$RTLD_PRELOAD_DELIM')
AS_IF([test -n "$RTLD_PRELOAD_DEFAULT"], [
SUDO_DEFINE_UNQUOTED(RTLD_PRELOAD_DEFAULT, "$RTLD_PRELOAD_DEFAULT")
])
AS_IF([test -n "$RTLD_PRELOAD_ENABLE_VAR"], [
SUDO_DEFINE_UNQUOTED(RTLD_PRELOAD_ENABLE_VAR, "$RTLD_PRELOAD_ENABLE_VAR")
])
])
dnl
dnl Python plugin support
dnl
@@ -4694,6 +4735,8 @@ AH_TEMPLATE(HAVE___FUNC__, [Define to 1 if the compiler supports the C99 __func_
AH_TEMPLATE(HAVE___INTERPOSE, [Define to 1 if you have dyld with __interpose attribute support.])
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_VAR_32, [The environment variable that controls preloading of 32-bit dynamic objects.])
AH_TEMPLATE(RTLD_PRELOAD_VAR_64, [The environment variable that controls preloading of 64-bit 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).])

View File

@@ -17,7 +17,7 @@
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
.nr SL @SEMAN@
.TH "SUDO.CONF" "@mansectform@" "January 16, 2023" "Sudo @PACKAGE_VERSION@" "File Formats Manual"
.TH "SUDO.CONF" "@mansectform@" "July 29, 2023" "Sudo @PACKAGE_VERSION@" "File Formats Manual"
.nh
.if n .ad l
.SH "NAME"
@@ -210,7 +210,7 @@ versions, if
\fBsudoers\fR
is configured as the security policy, it will be used as an audit
plugin as well.
This guarantees that the logging behavior will be consistnet with that of
This guarantees that the logging behavior will be consistent with that of
\fBsudo\fR
versions 1.9.0 and below.
.PP
@@ -287,7 +287,7 @@ BSD,
macOS and Solaris.
.TP 6n
intercept
The fully-qualified path to a shared library containing a wrappers for the
The path to a shared library containing a wrappers for the
execve(2),
execl(3),
execle(3),
@@ -301,15 +301,29 @@ library functions that intercepts attempts to run further commands and
performs a policy check before allowing them to be executed.
This is used to implement the
\fIintercept\fR
and
\fIlog_subcmds\fR
functionality on systems that support
\fRLD_PRELOAD\fR
or its equivalent.
or the equivalent.
.sp
The
\fIintercept\fR
path may be set to either a single fully-qualified path, or, for systems
that support separate
\fRLD_PRELOAD\fR
environment variables for 32-bit and 64-bit executables, it may optionally
be set to two fully-qualified paths separated by a colon
(\(oq:\&\(cq).
The first path should be the 32-bit version and the second the
64-bit version.
This two-path form is currently only supported on AIX and Solaris
systems.
The default value is
\fI@intercept_file@\fR.
.TP 6n
noexec
The fully-qualified path to a shared library containing wrappers
for the
The path to a shared library containing wrappers for the
execve(2),
execl(3),
execle(3),
@@ -332,7 +346,20 @@ This is used to implement the
\fInoexec\fR
functionality on systems that support
\fRLD_PRELOAD\fR
or its equivalent.
or the equivalent.
.sp
The
\fInoexec\fR
path may be set to either a single fully-qualified path, or, for systems
that support separate
\fRLD_PRELOAD\fR
environment variables for 32-bit and 64-bit executables, it may optionally
be set to two fully-qualified paths separated by a colon
(\(oq:\&\(cq).
The first path should be the 32-bit version and the second the
64-bit version.
This two-path form is currently only supported on AIX and Solaris
systems.
The default value is
\fI@noexec_file@\fR.
.TP 6n

View File

@@ -16,7 +16,7 @@
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
.nr SL @SEMAN@
.Dd January 16, 2023
.Dd July 29, 2023
.Dt SUDO.CONF @mansectform@
.Os Sudo @PACKAGE_VERSION@
.Sh NAME
@@ -192,7 +192,7 @@ versions, if
.Nm sudoers
is configured as the security policy, it will be used as an audit
plugin as well.
This guarantees that the logging behavior will be consistnet with that of
This guarantees that the logging behavior will be consistent with that of
.Nm sudo
versions 1.9.0 and below.
.Pp
@@ -264,7 +264,7 @@ functions, for example
.Bx ,
macOS and Solaris.
.It intercept
The fully-qualified path to a shared library containing a wrappers for the
The path to a shared library containing a wrappers for the
.Xr execve 2 ,
.Xr execl 3 ,
.Xr execle 3 ,
@@ -278,14 +278,28 @@ library functions that intercepts attempts to run further commands and
performs a policy check before allowing them to be executed.
This is used to implement the
.Em intercept
and
.Em log_subcmds
functionality on systems that support
.Ev LD_PRELOAD
or its equivalent.
or the equivalent.
.Pp
The
.Em intercept
path may be set to either a single fully-qualified path, or, for systems
that support separate
.Dv LD_PRELOAD
environment variables for 32-bit and 64-bit executables, it may optionally
be set to two fully-qualified paths separated by a colon
.Pq Ql :\& .
The first path should be the 32-bit version and the second the
64-bit version.
This two-path form is currently only supported on AIX and Solaris
systems.
The default value is
.Pa @intercept_file@ .
.It noexec
The fully-qualified path to a shared library containing wrappers
for the
The path to a shared library containing wrappers for the
.Xr execve 2 ,
.Xr execl 3 ,
.Xr execle 3 ,
@@ -308,7 +322,20 @@ This is used to implement the
.Em noexec
functionality on systems that support
.Ev LD_PRELOAD
or its equivalent.
or the equivalent.
.Pp
The
.Em noexec
path may be set to either a single fully-qualified path, or, for systems
that support separate
.Dv LD_PRELOAD
environment variables for 32-bit and 64-bit executables, it may optionally
be set to two fully-qualified paths separated by a colon
.Pq Ql :\& .
The first path should be the 32-bit version and the second the
64-bit version.
This two-path form is currently only supported on AIX and Solaris
systems.
The default value is
.Pa @noexec_file@ .
.It plugin_dir

View File

@@ -173,9 +173,11 @@ oflow:
* Add a DSO file to LD_PRELOAD or the system equivalent.
*/
static char **
sudo_preload_dso_alloc(char *const envp[], const char *dso_file,
int intercept_fd, sudo_alloc_fn_t alloc_fn, sudo_free_fn_t free_fn)
sudo_preload_dso_alloc(char *const envp[], const char *preload_var,
const char *dso_file, int intercept_fd,
sudo_alloc_fn_t alloc_fn, sudo_free_fn_t free_fn)
{
const size_t preload_var_len = strlen(preload_var);
char *preload = NULL;
char **nep, **nenvp = NULL;
char *const *ep;
@@ -232,12 +234,13 @@ sudo_preload_dso_alloc(char *const envp[], const char *dso_file,
goto oom;
/*
* Shallow copy envp, with special handling for RTLD_PRELOAD_VAR,
* Shallow copy envp, with special handling for preload_var,
* RTLD_PRELOAD_ENABLE_VAR and SUDO_INTERCEPT_FD.
*/
for (ep = envp, nep = nenvp; *ep != NULL; ep++) {
if (strncmp(*ep, RTLD_PRELOAD_VAR "=", sizeof(RTLD_PRELOAD_VAR)) == 0) {
const char *cp = *ep + sizeof(RTLD_PRELOAD_VAR);
if (strncmp(*ep, preload_var, preload_var_len) == 0 &&
(*ep)[preload_var_len] == '=') {
const char *cp = *ep + preload_var_len + 1;
const size_t dso_len = strlen(dso_file);
/* Skip duplicates. */
@@ -291,13 +294,13 @@ copy:
if (!dso_present) {
if (preload_ptr == NULL) {
# ifdef RTLD_PRELOAD_DEFAULT
preload = fmtstr(alloc_fn, free_fn, "%s=%s%c%s", RTLD_PRELOAD_VAR,
preload = fmtstr(alloc_fn, free_fn, "%s=%s%c%s", preload_var,
dso_file, RTLD_PRELOAD_DELIM, RTLD_PRELOAD_DEFAULT);
if (preload == NULL) {
goto oom;
}
# else
preload = fmtstr(alloc_fn, free_fn, "%s=%s", RTLD_PRELOAD_VAR,
preload = fmtstr(alloc_fn, free_fn, "%s=%s", preload_var,
dso_file);
if (preload == NULL) {
goto oom;
@@ -305,8 +308,8 @@ copy:
# endif
*nep++ = preload;
} else {
const char *old_val = *preload_ptr + sizeof(RTLD_PRELOAD_VAR);
preload = fmtstr(alloc_fn, free_fn, "%s=%s%c%s", RTLD_PRELOAD_VAR,
const char *old_val = *preload_ptr + preload_var_len + 1;
preload = fmtstr(alloc_fn, free_fn, "%s=%s%c%s", preload_var,
dso_file, RTLD_PRELOAD_DELIM, old_val);
if (preload == NULL) {
goto oom;
@@ -350,11 +353,59 @@ oom:
debug_return_ptr(NULL);
}
static char **
sudo_preload_dso_path(char *const envp[], const char *dso_file,
int intercept_fd, sudo_alloc_fn_t alloc_fn, sudo_free_fn_t free_fn)
{
char **ret = NULL;
const char *ep;
debug_decl(sudo_preload_dso_path, SUDO_DEBUG_UTIL);
ep = strchr(dso_file, ':');
if (ep == NULL) {
/* Use default LD_PRELOAD */
return sudo_preload_dso_alloc(envp, RTLD_PRELOAD_VAR, dso_file,
intercept_fd, alloc_fn, free_fn);
}
/* Add 32-bit LD_PRELOAD if present. */
if (ep != dso_file) {
#ifdef RTLD_PRELOAD_VAR_32
const size_t len = (size_t)(ep - dso_file);
char name[PATH_MAX];
if (len >= sizeof(name)) {
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
"%.*s: path too long", (int)len, dso_file);
} else {
memcpy(name, dso_file, len);
name[len] = '\0';
ret = sudo_preload_dso_alloc(envp, RTLD_PRELOAD_VAR_32, name,
intercept_fd, alloc_fn, free_fn);
envp = ret;
}
#endif /* RTLD_PRELOAD_VAR_32 */
dso_file = ep + 1;
}
#ifdef RTLD_PRELOAD_VAR_64
/* Add 64-bit LD_PRELOAD if present. */
if (*dso_file != '\0') {
char **new_envp = sudo_preload_dso_alloc(envp, RTLD_PRELOAD_VAR_64,
dso_file, intercept_fd, alloc_fn, free_fn);
free_fn(ret);
ret = new_envp;
}
#endif /* RTLD_PRELOAD_VAR_64 */
debug_return_ptr(ret);
}
char **
sudo_preload_dso_mmap(char *const envp[], const char *dso_file,
int intercept_fd)
{
return sudo_preload_dso_alloc(envp, dso_file, intercept_fd,
return sudo_preload_dso_path(envp, dso_file, intercept_fd,
sudo_mmap_allocarray_v1, sudo_mmap_free_v1);
}
@@ -362,7 +413,7 @@ char **
sudo_preload_dso(char *const envp[], const char *dso_file,
int intercept_fd)
{
return sudo_preload_dso_alloc(envp, dso_file, intercept_fd,
return sudo_preload_dso_path(envp, dso_file, intercept_fd,
sudo_allocarray, free);
}
#endif /* RTLD_PRELOAD_VAR */