From 6f6b0dec6c804300ea8ebfe1942b354aa50acc5d Mon Sep 17 00:00:00 2001 From: "Todd C. Miller" Date: Wed, 13 Jun 2012 14:01:16 -0400 Subject: [PATCH] Use gcc's visibility attribute to specify when symbols are visible or hidden, if available. If not available, use an ELF version script if it is supported. If all else fails, fall back to using libtool's -export-symbols. --- MANIFEST | 11 ++- configure | 114 +++++++++++++++++++++++++- configure.in | 56 ++++++++++++- include/missing.h | 23 +++++- plugins/sample/Makefile.in | 6 +- plugins/sample/sample_plugin.map | 8 ++ plugins/sample_group/Makefile.in | 6 +- plugins/sample_group/sample_group.map | 7 ++ plugins/sudoers/Makefile.in | 9 +- plugins/sudoers/iolog.c | 2 +- plugins/sudoers/sudoers.c | 2 +- plugins/sudoers/sudoers.map | 8 ++ plugins/system_group/Makefile.in | 6 +- plugins/system_group/system_group.map | 7 ++ src/sudo_noexec.c | 8 +- src/sudo_noexec.map | 5 ++ 16 files changed, 255 insertions(+), 23 deletions(-) create mode 100644 plugins/sample/sample_plugin.map create mode 100644 plugins/sample_group/sample_group.map create mode 100644 plugins/sudoers/sudoers.map create mode 100644 plugins/system_group/system_group.map create mode 100644 src/sudo_noexec.map diff --git a/MANIFEST b/MANIFEST index 35bc4a2d6..79375dd78 100644 --- a/MANIFEST +++ b/MANIFEST @@ -127,15 +127,14 @@ mkpkg pathnames.h.in plugins/sample/Makefile.in plugins/sample/sample_plugin.c +plugins/sample/sample_plugin.map plugins/sample/sample_plugin.sym plugins/sample_group/Makefile.in plugins/sample_group/getgrent.c plugins/sample_group/plugin_test.c plugins/sample_group/sample_group.c +plugins/sample_group/sample_group.map plugins/sample_group/sample_group.sym -plugins/system_group/Makefile.in -plugins/system_group/system_group.c -plugins/system_group/system_group.sym plugins/sudoers/Makefile.in plugins/sudoers/aixcrypt.exp plugins/sudoers/alias.c @@ -262,6 +261,7 @@ plugins/sudoers/sudo_nss.h plugins/sudoers/sudoers.c plugins/sudoers/sudoers.h plugins/sudoers/sudoers.in +plugins/sudoers/sudoers.map plugins/sudoers/sudoers.sym plugins/sudoers/sudoers2ldif plugins/sudoers/sudoers_version.h @@ -275,6 +275,10 @@ plugins/sudoers/toke_util.c plugins/sudoers/tsgetgrpw.c plugins/sudoers/tsgetgrpw.h plugins/sudoers/visudo.c +plugins/system_group/Makefile.in +plugins/system_group/system_group.c +plugins/system_group/system_group.map +plugins/system_group/system_group.sym pp src/Makefile.in src/conversation.c @@ -332,6 +336,7 @@ src/sudo.h src/sudo_edit.c src/sudo_exec.h src/sudo_noexec.c +src/sudo_noexec.map src/sudo_plugin_int.h src/sudo_usage.h.in src/tgetpass.c diff --git a/configure b/configure index ccc7bec3d..e71ec5f9e 100755 --- a/configure +++ b/configure @@ -695,6 +695,7 @@ iolog_dir COMPAT_TEST_PROGS SUDO_NLS LIBINTL +LTEXP LT_STATIC LIBDL CONFIGURE_ARGS @@ -2880,6 +2881,7 @@ $as_echo "$as_me: Configuring Sudo version $PACKAGE_VERSION" >&6;} + # @@ -2935,6 +2937,7 @@ PROGS="sudo" : ${SUDOERS_GID='0'} DEVEL= LDAP="#" +LTEXP="" BAMAN=0 LCMAN=0 SEMAN=0 @@ -20072,9 +20075,118 @@ EOF $as_echo "$iolog_dir" >&6; } -if test "$enable_hardening" != "no"; then ac_c_werror_flag=yes +as_CACHEVAR=`$as_echo "ax_cv_check_cflags__-fvisibility=hidden" | $as_tr_sh` +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -fvisibility=hidden" >&5 +$as_echo_n "checking whether C compiler accepts -fvisibility=hidden... " >&6; } +if eval \${$as_CACHEVAR+:} false; then : + $as_echo_n "(cached) " >&6 +else + + ax_check_save_flags=$CFLAGS + CFLAGS="$CFLAGS -fvisibility=hidden" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + eval "$as_CACHEVAR=yes" +else + eval "$as_CACHEVAR=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + CFLAGS=$ax_check_save_flags +fi +eval ac_res=\$$as_CACHEVAR + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +if test x"`eval 'as_val=${'$as_CACHEVAR'};$as_echo "$as_val"'`" = xyes; then : + + CFLAGS="${CFLAGS} -fvisibility=hidden" + LTEXP="#" + +else + : +fi + + +if test -z "$LTEXP"; then + if test "$lt_cv_prog_gnu_ld" = "yes"; then + cat > conftest.map <<-EOF + VERS_1.0 { + global: foo; + local: *; + }; + EOF + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ld supports map files" >&5 +$as_echo_n "checking whether ld supports map files... " >&6; } + _LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS -fPIC -shared -Wl,--version-script,./conftest.map" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +int foo; +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + + LTEXP="#"; LTLDFLAGS="$LTLDFLAGS -Wl,--version-script,\$(mapfile)" + +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS="$_LDFLAGS" + else + case "$host" in + *-*-solaris2*) + cat > conftest.map <<-EOF + VERS_1.0 { + global: foo; + local: *; + }; + EOF + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ld supports map files" >&5 +$as_echo_n "checking whether ld supports map files... " >&6; } + _LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS -fPIC -shared -Wl,-M,./conftest.map" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +int foo; +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + + LTEXP="#"; LTLDFLAGS="$LTLDFLAGS -Wl,-M,\$(mapfile)" + +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS="$_LDFLAGS" + ;; + esac + fi +fi + +if test "$enable_hardening" != "no"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -fstack-protector" >&5 $as_echo_n "checking whether C compiler accepts -fstack-protector... " >&6; } if ${ax_cv_check_cflags___fstack_protector+:} false; then : diff --git a/configure.in b/configure.in index 5b3875237..62ad00dc1 100644 --- a/configure.in +++ b/configure.in @@ -66,6 +66,7 @@ AC_SUBST([ac_config_libobj_dir]) AC_SUBST([CONFIGURE_ARGS]) AC_SUBST([LIBDL]) AC_SUBST([LT_STATIC]) +AC_SUBST([LTEXP]) AC_SUBST([LIBINTL]) AC_SUBST([SUDO_NLS]) AC_SUBST([COMPAT_TEST_PROGS]) @@ -164,6 +165,7 @@ PROGS="sudo" : ${SUDOERS_GID='0'} DEVEL= LDAP="#" +LTEXP="" BAMAN=0 LCMAN=0 SEMAN=0 @@ -3165,12 +3167,62 @@ SUDO_TIMEDIR SUDO_IO_LOGDIR dnl -dnl Check for -fstack-protector and -z relro support +dnl Check for gcc 4.0-style symbol visibility support. dnl This must be towards the end as it turns warnings dnl into fatal errors (and there is no way to undo that) dnl +AC_LANG_WERROR +AX_CHECK_COMPILE_FLAG([-fvisibility=hidden], [ + CFLAGS="${CFLAGS} -fvisibility=hidden" + LTEXP="#" +]) + +dnl +dnl If the compiler doesn't have symbol visibility support, it may +dnl support version scripts (only GNU and Solaris ld). +dnl +if test -z "$LTEXP"; then + if test "$lt_cv_prog_gnu_ld" = "yes"; then + cat > conftest.map <<-EOF + VERS_1.0 { + global: foo; + local: *; + }; + EOF + AC_MSG_CHECKING([whether ld supports map files]) + _LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS -fPIC -shared -Wl,--version-script,./conftest.map" + AC_TRY_LINK([int foo;], [], [ + LTEXP="#"; LTLDFLAGS="$LTLDFLAGS -Wl,--version-script,\$(mapfile)" + ]) + LDFLAGS="$_LDFLAGS" + else + case "$host" in + *-*-solaris2*) + cat > conftest.map <<-EOF + VERS_1.0 { + global: foo; + local: *; + }; + EOF + AC_MSG_CHECKING([whether ld supports map files]) + _LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS -fPIC -shared -Wl,-M,./conftest.map" + AC_TRY_LINK([int foo;], [], [ + LTEXP="#"; LTLDFLAGS="$LTLDFLAGS -Wl,-M,\$(mapfile)" + ]) + LDFLAGS="$_LDFLAGS" + ;; + esac + fi +fi + +dnl +dnl Check for -fstack-protector and -z relro support +dnl This after the call to AC_LANG_WERROR so that warnings +dnl are treated as fatal errors. +dnl if test "$enable_hardening" != "no"; then - AC_LANG_WERROR AX_CHECK_COMPILE_FLAG([-fstack-protector], [ AX_CHECK_LINK_FLAG([-fstack-protector], [ CFLAGS="${CFLAGS} -fstack-protector" diff --git a/include/missing.h b/include/missing.h index 6f00a5760..bf35d9a57 100644 --- a/include/missing.h +++ b/include/missing.h @@ -29,20 +29,39 @@ * Macros and functions that may be missing on some operating systems. */ +#ifndef __GNUC_PREREQ__ +# ifdef __GNUC__ +# define __GNUC_PREREQ__(ma, mi) \ + ((__GNUC__ > (ma)) || (__GNUC__ == (ma) && __GNUC_MINOR__ >= (mi))) +# else +# define __GNUC_PREREQ__(ma, mi) 0 +# endif +#endif + /* Define away __attribute__ for non-gcc or old gcc */ -#if !defined(__GNUC__) || __GNUC__ < 2 || __GNUC__ == 2 && __GNUC_MINOR__ < 5 +#if !defined(__attribute__) && !__GNUC_PREREQ__(2, 5) # define __attribute__(x) #endif /* For catching format string mismatches */ #ifndef __printflike -# if defined(__GNUC__) && (__GNUC__ > 2 || __GNUC__ == 2 && __GNUC_MINOR__ >= 7) +# if __GNUC_PREREQ__(2, 7) # define __printflike(f, v) __attribute__((__format__ (__printf__, f, v))) # else # define __printflike(f, v) # endif #endif +#ifndef __dso_public +# if __GNUC_PREREQ__(4, 0) +# define __dso_public __attribute__((__visibility__("default"))) +# define __dso_hidden __attribute__((__visibility__("hidden"))) +# else +# define __dso_public +# define __dso_hidden +# endif +#endif + /* * Some systems lack full limit definitions. */ diff --git a/plugins/sample/Makefile.in b/plugins/sample/Makefile.in index 4f083a6d5..78ed8f066 100644 --- a/plugins/sample/Makefile.in +++ b/plugins/sample/Makefile.in @@ -44,6 +44,7 @@ CFLAGS = @CFLAGS@ # Flags to pass to the link stage LDFLAGS = @LDFLAGS@ LTLDFLAGS = @LTLDFLAGS@ +@LTEXP@LTEXPORTS = -export-symbols $(srcdir)/sample_plugin.sym # Where to install things... prefix = @prefix@ @@ -56,9 +57,10 @@ datarootdir = @datarootdir@ localstatedir = @localstatedir@ plugindir = @PLUGINDIR@ -# File extension and mode to use for shared libraries/objects +# File extension, mode and map file to use for shared libraries/objects soext = @SOEXT@ shlib_mode = @SHLIB_MODE@ +mapfile = $(srcdir)/sample_plugin.map # OS dependent defines DEFS = @OSDEFS@ @@ -84,7 +86,7 @@ Makefile: $(srcdir)/Makefile.in $(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $< sample_plugin.la: $(OBJS) - $(LIBTOOL) --mode=link $(CC) $(LDFLAGS) $(LTLDFLAGS) -o $@ $(OBJS) $(LIBS) -module -export-symbols $(srcdir)/sample_plugin.sym -avoid-version -rpath $(plugindir) + $(LIBTOOL) --mode=link $(CC) $(LDFLAGS) $(LTLDFLAGS) -o $@ $(OBJS) $(LIBS) -module $(LTEXPORTS) -avoid-version -rpath $(plugindir) pre-install: diff --git a/plugins/sample/sample_plugin.map b/plugins/sample/sample_plugin.map new file mode 100644 index 000000000..90ea39eee --- /dev/null +++ b/plugins/sample/sample_plugin.map @@ -0,0 +1,8 @@ +sample_plugin.so { + global: + # Policy and I/O plugin structs + sample_policy; + sample_io; + local: + *; +}; diff --git a/plugins/sample_group/Makefile.in b/plugins/sample_group/Makefile.in index a2d9087e8..805e2ba71 100644 --- a/plugins/sample_group/Makefile.in +++ b/plugins/sample_group/Makefile.in @@ -45,6 +45,7 @@ CFLAGS = @CFLAGS@ # Flags to pass to the link stage LDFLAGS = @LDFLAGS@ LTLDFLAGS = @LTLDFLAGS@ +@LTEXP@LTEXPORTS = -export-symbols $(srcdir)/sample_group.sym # Where to install things... prefix = @prefix@ @@ -57,9 +58,10 @@ datarootdir = @datarootdir@ localstatedir = @localstatedir@ plugindir = @PLUGINDIR@ -# File extension and mode to use for shared libraries/objects +# File extension, mode and map file to use for shared libraries/objects soext = @SOEXT@ shlib_mode = @SHLIB_MODE@ +mapfile = $(srcdir)/sample_group.map # OS dependent defines DEFS = @OSDEFS@ @@ -85,7 +87,7 @@ Makefile: $(srcdir)/Makefile.in $(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $< sample_group.la: $(OBJS) $(LT_LIBS) - $(LIBTOOL) --mode=link $(CC) $(LDFLAGS) $(LTLDFLAGS) -o $@ $(OBJS) $(LIBS) -module -export-symbols $(srcdir)/sample_group.sym -avoid-version -rpath $(plugindir) + $(LIBTOOL) --mode=link $(CC) $(LDFLAGS) $(LTLDFLAGS) -o $@ $(OBJS) $(LIBS) -module $(LTEXPORTS) -avoid-version -rpath $(plugindir) pre-install: diff --git a/plugins/sample_group/sample_group.map b/plugins/sample_group/sample_group.map new file mode 100644 index 000000000..62e4b7a92 --- /dev/null +++ b/plugins/sample_group/sample_group.map @@ -0,0 +1,7 @@ +sample_group.so { + global: + # Group plugin structure + group_plugin; + local: + *; +}; diff --git a/plugins/sudoers/Makefile.in b/plugins/sudoers/Makefile.in index 3ec7e4e11..6bca91bbf 100644 --- a/plugins/sudoers/Makefile.in +++ b/plugins/sudoers/Makefile.in @@ -60,6 +60,7 @@ CFLAGS = @CFLAGS@ LDFLAGS = @LDFLAGS@ SUDOERS_LDFLAGS = $(LDFLAGS) @SUDOERS_LDFLAGS@ LTLDFLAGS = @LTLDFLAGS@ +@LTEXP@LTEXPORTS = -export-symbols $(srcdir)/sudoers.sym # Where to install things... prefix = @prefix@ @@ -72,9 +73,10 @@ datarootdir = @datarootdir@ localedir = @localedir@ localstatedir = @localstatedir@ -# File extension and mode to use for shared libraries/objects +# File extension, mode and map file to use for shared libraries/objects soext = @SOEXT@ shlib_mode = @SHLIB_MODE@ +mapfile = $(srcdir)/sudoers.map # Directory in which to install the sudoers plugin plugindir = @PLUGINDIR@ @@ -167,7 +169,7 @@ libparsesudoers.la: $(LIBPARSESUDOERS_OBJS) $(LIBTOOL) --mode=link $(CC) -o $@ $(LIBPARSESUDOERS_OBJS) -no-install sudoers.la: $(SUDOERS_OBJS) $(LT_LIBS) libparsesudoers.la - $(LIBTOOL) @LT_STATIC@ --mode=link $(CC) $(SUDOERS_LDFLAGS) $(LTLDFLAGS) -o $@ $(SUDOERS_OBJS) libparsesudoers.la $(SUDOERS_LIBS) -module -export-symbols $(srcdir)/sudoers.sym -avoid-version -rpath $(plugindir) + $(LIBTOOL) @LT_STATIC@ --mode=link $(CC) $(SUDOERS_LDFLAGS) $(LTLDFLAGS) -o $@ $(SUDOERS_OBJS) libparsesudoers.la $(SUDOERS_LIBS) -module $(LTEXPORTS) -avoid-version -rpath $(plugindir) visudo: libparsesudoers.la $(VISUDO_OBJS) $(LT_LIBS) $(LIBTOOL) --mode=link $(CC) -o $@ $(VISUDO_OBJS) $(LDFLAGS) libparsesudoers.la $(LIBS) $(NET_LIBS) @@ -737,7 +739,8 @@ testsudoers.o: $(srcdir)/testsudoers.c $(top_builddir)/config.h \ $(devdir)/def_data.h $(srcdir)/logging.h $(srcdir)/sudo_nss.h \ $(incdir)/sudo_plugin.h $(incdir)/sudo_debug.h \ $(incdir)/gettext.h $(srcdir)/interfaces.h $(srcdir)/parse.h \ - $(incdir)/sudo_conf.h $(incdir)/list.h $(devdir)/gram.h + $(incdir)/sudo_conf.h $(incdir)/list.h $(incdir)/secure_path.h \ + $(devdir)/gram.h $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/testsudoers.c timestr.lo: $(srcdir)/timestr.c $(top_builddir)/config.h $(incdir)/missing.h $(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/timestr.c diff --git a/plugins/sudoers/iolog.c b/plugins/sudoers/iolog.c index 2757b1fc7..22096efcf 100644 --- a/plugins/sudoers/iolog.c +++ b/plugins/sudoers/iolog.c @@ -683,7 +683,7 @@ sudoers_io_log_stderr(const char *buf, unsigned int len) return sudoers_io_log(buf, len, IOFD_STDERR); } -struct io_plugin sudoers_io = { +__dso_public struct io_plugin sudoers_io = { SUDO_IO_PLUGIN, SUDO_API_VERSION, sudoers_io_open, diff --git a/plugins/sudoers/sudoers.c b/plugins/sudoers/sudoers.c index 9002712bc..5b700f438 100644 --- a/plugins/sudoers/sudoers.c +++ b/plugins/sudoers/sudoers.c @@ -1596,7 +1596,7 @@ sudoers_policy_register_hooks(int version, int (*register_hook)(struct sudo_hook register_hook(&hook); } -struct policy_plugin sudoers_policy = { +__dso_public struct policy_plugin sudoers_policy = { SUDO_POLICY_PLUGIN, SUDO_API_VERSION, sudoers_policy_open, diff --git a/plugins/sudoers/sudoers.map b/plugins/sudoers/sudoers.map new file mode 100644 index 000000000..ae0ca503c --- /dev/null +++ b/plugins/sudoers/sudoers.map @@ -0,0 +1,8 @@ +sudoers.so { + global: + # Policy and I/O plugin structs + sudoers_policy; + sudoers_io; + local: + *; +}; diff --git a/plugins/system_group/Makefile.in b/plugins/system_group/Makefile.in index 4834c65c2..6665085b4 100644 --- a/plugins/system_group/Makefile.in +++ b/plugins/system_group/Makefile.in @@ -45,6 +45,7 @@ CFLAGS = @CFLAGS@ # Flags to pass to the link stage LDFLAGS = @LDFLAGS@ LTLDFLAGS = @LTLDFLAGS@ +@LTEXP@LTEXPORTS = -export-symbols $(srcdir)/system_group.sym # Where to install things... prefix = @prefix@ @@ -57,9 +58,10 @@ datarootdir = @datarootdir@ localstatedir = @localstatedir@ plugindir = @PLUGINDIR@ -# File extension and mode to use for shared libraries/objects +# File extension, mode and map file to use for shared libraries/objects soext = @SOEXT@ shlib_mode = @SHLIB_MODE@ +mapfile = $(srcdir)/system_group.map # OS dependent defines DEFS = @OSDEFS@ @@ -85,7 +87,7 @@ Makefile: $(srcdir)/Makefile.in $(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $< system_group.la: $(OBJS) $(LT_LIBS) - $(LIBTOOL) --mode=link $(CC) $(LDFLAGS) $(LTLDFLAGS) -o $@ $(OBJS) $(LIBS) -module -export-symbols $(srcdir)/system_group.sym -avoid-version -rpath $(plugindir) + $(LIBTOOL) --mode=link $(CC) $(LDFLAGS) $(LTLDFLAGS) -o $@ $(OBJS) $(LIBS) -module $(LTEXPORTS) -avoid-version -rpath $(plugindir) pre-install: diff --git a/plugins/system_group/system_group.map b/plugins/system_group/system_group.map new file mode 100644 index 000000000..1bfc4acff --- /dev/null +++ b/plugins/system_group/system_group.map @@ -0,0 +1,7 @@ +system_group.so { + global: + # Group plugin structure + group_plugin; + local: + *; +}; diff --git a/src/sudo_noexec.c b/src/sudo_noexec.c index af1915f03..287250125 100644 --- a/src/sudo_noexec.c +++ b/src/sudo_noexec.c @@ -41,22 +41,22 @@ } #define DUMMY2(fn, t1, t2) \ -int \ +__dso_public int \ fn(t1 a1, t2 a2) \ DUMMY_BODY #define DUMMY3(fn, t1, t2, t3) \ -int \ +__dso_public int \ fn(t1 a1, t2 a2, t3 a3) \ DUMMY_BODY #define DUMMY6(fn, t1, t2, t3, t4, t5, t6) \ -int \ +__dso_public int \ fn(t1 a1, t2 a2, t3 a3, t4 a4, t5 a5, t6 a6) \ DUMMY_BODY #define DUMMY_VA(fn, t1, t2) \ -int \ +__dso_public int \ fn(t1 a1, t2 a2, ...) \ DUMMY_BODY diff --git a/src/sudo_noexec.map b/src/sudo_noexec.map new file mode 100644 index 000000000..c493655c3 --- /dev/null +++ b/src/sudo_noexec.map @@ -0,0 +1,5 @@ +sudo_noexec.so { + global: + # All symbols are exported + *; +}; -- 2.40.0