diff --git a/INSTALL b/INSTALL index 88ccb8dc8..eb66c30e6 100644 --- a/INSTALL +++ b/INSTALL @@ -171,6 +171,14 @@ Compilation options: binary itself. This will also disable the noexec option as it too relies on dynamic shared object support. + --enable-static-sudoers + By default, the sudoers plugin is built and installed as a + dynamic shared object. When the --enable-static-sudoers + option is specified, the sudoers plugin is compiled directly + into the sudo binary. Unlike --disable-shared, this does + not prevent other plugins from being used and the noexec + option will continue to function. + --enable-zlib[=location] Enable the use of the zlib compress library when storing I/O log files. If specified, location is the base directory diff --git a/MANIFEST b/MANIFEST index 5e77e7c49..72de7a00d 100644 --- a/MANIFEST +++ b/MANIFEST @@ -52,14 +52,13 @@ common/secure_path.c common/setgroups.c common/sudo_conf.c common/sudo_debug.c +common/sudo_dso.c common/sudo_printf.c common/term.c common/ttysize.c compat/Makefile.in compat/charclass.h compat/closefrom.c -compat/dlfcn.h -compat/dlopen.c compat/endian.h compat/fnmatch.c compat/fnmatch.h @@ -150,6 +149,7 @@ include/queue.h include/secure_path.h include/sudo_conf.h include/sudo_debug.h +include/sudo_dso.h include/sudo_event.h include/sudo_plugin.h indent.pro diff --git a/NEWS b/NEWS index 9e50e8484..73df470b1 100644 --- a/NEWS +++ b/NEWS @@ -3,6 +3,10 @@ What's new in Sudo 1.8.9? * Reworked sudo's main event loop to use a simple event subsystem using poll(2) or select(2) as the back end. + * It is now possible to statically compile the sudoers plugin into + the sudo binary without disabling shared library support. The + sudo.conf file may still be used to configure other plugins. + What's new in Sudo 1.8.8? * Removed a warning on PAM systems with stacked auth modules diff --git a/common/Makefile.in b/common/Makefile.in index acca51271..578c90bd5 100644 --- a/common/Makefile.in +++ b/common/Makefile.in @@ -67,8 +67,8 @@ DEFS = @OSDEFS@ -D_PATH_SUDO_CONF=\"$(sysconfdir)/sudo.conf\" SHELL = @SHELL@ LTOBJS = alloc.lo atobool.lo atoid.lo event.lo fatal.lo fileops.lo \ - fmt_string.lo gidlist.lo lbuf.lo secure_path.lo \ - setgroups.lo sudo_conf.lo sudo_debug.lo sudo_printf.lo term.lo \ + fmt_string.lo gidlist.lo lbuf.lo secure_path.lo setgroups.lo \ + sudo_conf.lo sudo_debug.lo sudo_dso.lo sudo_printf.lo term.lo \ ttysize.lo @COMMON_OBJS@ PARSELN_TEST_OBJS = parseln_test.lo locale_stub.lo @@ -247,6 +247,9 @@ sudo_debug.lo: $(srcdir)/sudo_debug.c $(incdir)/alloc.h $(incdir)/fatal.h \ $(incdir)/sudo_plugin.h $(top_builddir)/config.h \ $(top_srcdir)/compat/stdbool.h $(LIBTOOL) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/sudo_debug.c +sudo_dso.lo: $(srcdir)/sudo_dso.c $(incdir)/missing.h $(incdir)/sudo_dso.h \ + $(top_builddir)/config.h + $(LIBTOOL) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/sudo_dso.c sudo_printf.lo: $(srcdir)/sudo_printf.c $(incdir)/missing.h \ $(incdir)/sudo_debug.h $(incdir)/sudo_plugin.h \ $(top_builddir)/config.h diff --git a/common/sudo_dso.c b/common/sudo_dso.c new file mode 100644 index 000000000..6e71c597f --- /dev/null +++ b/common/sudo_dso.c @@ -0,0 +1,320 @@ +/* + * Copyright (c) 2010, 2012-2013 Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include + +#include +#ifdef STDC_HEADERS +# include +# include +#else +# ifdef HAVE_STDLIB_H +# include +# endif +#endif /* STDC_HEADERS */ +#ifdef HAVE_STRING_H +# include +#endif /* HAVE_STRING_H */ +#ifdef HAVE_STRINGS_H +# include +#endif /* HAVE_STRINGS_H */ +#if defined(HAVE_SHL_LOAD) +# include +#elif defined(HAVE_DLOPEN) +# include +#endif +#include + +#include "sudo_dso.h" +#include "missing.h" + +/* + * Pointer for statically compiled symbols. + */ +static struct sudo_preload_table *preload_table; + +void +sudo_dso_preload_table(struct sudo_preload_table *table) +{ + preload_table = table; +} + +#if defined(HAVE_SHL_LOAD) + +# ifndef DYNAMIC_PATH +# define DYNAMIC_PATH 0 +# endif + +void * +sudo_dso_load(const char *path, int mode) +{ + struct sudo_preload_table *pt; + int flags = DYNAMIC_PATH | BIND_VERBOSE; + + if (mode == 0) + mode = SUDO_DSO_LAZY; /* default behavior */ + + /* Check prelinked symbols first. */ + if (preload_table != NULL) { + for (pt = preload_table; pt->handle != NULL; pt++) { + if (pt->path != NULL && strcmp(path, pt->path) == 0) + return pt->handle; + } + } + + /* We don't support SUDO_DSO_GLOBAL or SUDO_DSO_LOCAL yet. */ + if (ISSET(mode, SUDO_DSO_LAZY)) + flags |= BIND_DEFERRED; + if (ISSET(mode, SUDO_DSO_NOW)) + flags |= BIND_IMMEDIATE; + + return (void *)shl_load(path, flags, 0L); +} + +int +sudo_dso_unload(void *handle) +{ + struct sudo_preload_table *pt; + + /* Check prelinked symbols first. */ + if (preload_table != NULL) { + for (pt = preload_table; pt->handle != NULL; pt++) { + if (pt->handle == handle) + return 0; + } + } + + return shl_unload((shl_t)handle); +} + +void * +sudo_dso_findsym(void *vhandle, const char *symbol) +{ + struct sudo_preload_table *pt; + shl_t handle = vhandle; + void *value = NULL; + + /* Check prelinked symbols first. */ + if (preload_table != NULL) { + for (pt = preload_table; pt->handle != NULL; pt++) { + if (pt->handle == handle) { + struct sudo_preload_symbol *sym; + for (sym = pt->symbols; sym->name != NULL; sym++) { + if (strcmp(sym->name, symbol) == 0) + return sym->addr; + } + errno = ENOENT; + return NULL; + } + } + } + + /* + * Note that the behavior of of SUDO_DSO_NEXT and SUDO_DSO_SELF + * differs from most implementations when called from + * a shared library. + */ + if (vhandle == SUDO_DSO_NEXT) { + /* Iterate over all shared libs looking for symbol. */ + struct shl_descriptor *desc; + int idx = 0; + while (shl_get(idx++, &desc) == 0) { + if (shl_findsym(&desc->handle, symbol, TYPE_UNDEFINED, &value) == 0) + break; + } + } else { + if (vhandle == SUDO_DSO_DEFAULT) + handle = NULL; + else if (vhandle == SUDO_DSO_SELF) + handle = PROG_HANDLE; + (void)shl_findsym(&handle, symbol, TYPE_UNDEFINED, &value); + } + + return value; +} + +char * +sudo_dso_strerror(void) +{ + return strerror(errno); +} + +#elif defined(HAVE_DLOPEN) + +# ifndef RTLD_GLOBAL +# define RTLD_GLOBAL 0 +# endif + +void * +sudo_dso_load(const char *path, int mode) +{ + struct sudo_preload_table *pt; + int flags = 0; + + /* Check prelinked symbols first. */ + if (preload_table != NULL) { + for (pt = preload_table; pt->handle != NULL; pt++) { + if (pt->path != NULL && strcmp(path, pt->path) == 0) + return pt->handle; + } + } + + /* Map SUDO_DSO_* -> RTLD_* */ + if (ISSET(mode, SUDO_DSO_LAZY)) + flags |= RTLD_LAZY; + if (ISSET(mode, SUDO_DSO_NOW)) + flags |= RTLD_NOW; + if (ISSET(mode, SUDO_DSO_GLOBAL)) + flags |= RTLD_GLOBAL; + if (ISSET(mode, SUDO_DSO_LOCAL)) + flags |= RTLD_LOCAL; + + return dlopen(path, flags); +} + +int +sudo_dso_unload(void *handle) +{ + struct sudo_preload_table *pt; + + /* Check prelinked symbols first. */ + if (preload_table != NULL) { + for (pt = preload_table; pt->handle != NULL; pt++) { + if (pt->handle == handle) + return 0; + } + } + + return dlclose(handle); +} + +void * +sudo_dso_findsym(void *handle, const char *symbol) +{ + struct sudo_preload_table *pt; + + /* Check prelinked symbols first. */ + if (preload_table != NULL) { + for (pt = preload_table; pt->handle != NULL; pt++) { + if (pt->handle == handle) { + struct sudo_preload_symbol *sym; + for (sym = pt->symbols; sym->name != NULL; sym++) { + if (strcmp(sym->name, symbol) == 0) + return sym->addr; + } + errno = ENOENT; + return NULL; + } + } + } + + /* + * Not all implementations support the special handles. + */ + if (handle == SUDO_DSO_NEXT) { +# ifdef RTLD_NEXT + handle = RTLD_NEXT; +# else + errno = ENOENT; + return NULL; +# endif + } else if (handle == SUDO_DSO_DEFAULT) { +# ifdef RTLD_DEFAULT + handle = RTLD_DEFAULT; +# else + errno = ENOENT; + return NULL; +# endif + } else if (handle == SUDO_DSO_SELF) { +# ifdef RTLD_SELF + handle = RTLD_SELF; +# else + errno = ENOENT; + return NULL; +# endif + } + + return dlsym(handle, symbol); +} + +char * +sudo_dso_strerror(void) +{ + return dlerror(); +} + +#else /* !HAVE_SHL_LOAD && !HAVE_DLOPEN */ + +/* + * Emulate dlopen() using a static list of symbols compiled into sudo. + */ +void * +sudo_dso_load(const char *path, int mode) +{ + struct sudo_preload_table *pt; + + /* Check prelinked symbols first. */ + if (preload_table != NULL) { + for (pt = preload_table; pt->handle != NULL; pt++) { + if (pt->path != NULL && strcmp(path, pt->path) == 0) + return pt->handle; + } + } + return NULL; +} + +int +sudo_dso_unload(void *handle) +{ + struct sudo_preload_table *pt; + + if (preload_table != NULL) { + for (pt = preload_table; pt->handle != NULL; pt++) { + if (pt->handle == handle) + return 0; + } + } + return -1; +} + +void * +sudo_dso_findsym(void *handle, const char *symbol) +{ + struct sudo_preload_table *pt; + + if (preload_table != NULL) { + for (pt = preload_table; pt->handle != NULL; pt++) { + if (pt->handle == handle) { + struct sudo_preload_symbol *sym; + for (sym = pt->symbols; sym->name != NULL; sym++) { + if (strcmp(sym->name, symbol) == 0) + return sym->addr; + } + } + } + } + errno = ENOENT; + return NULL; +} + +char * +sudo_dso_strerror(void) +{ + return strerror(errno); +} +#endif /* !HAVE_SHL_LOAD && !HAVE_DLOPEN */ diff --git a/compat/Makefile.in b/compat/Makefile.in index da433ac9d..30716ff6f 100644 --- a/compat/Makefile.in +++ b/compat/Makefile.in @@ -166,9 +166,6 @@ cleandir: realclean # Autogenerated dependencies, do not modify closefrom.lo: $(srcdir)/closefrom.c $(incdir)/missing.h $(top_builddir)/config.h $(LIBTOOL) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/closefrom.c -dlopen.lo: $(srcdir)/dlopen.c $(incdir)/missing.h $(top_builddir)/config.h \ - $(top_srcdir)/compat/dlfcn.h - $(LIBTOOL) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/dlopen.c fnm_test.o: $(srcdir)/regress/fnmatch/fnm_test.c $(incdir)/missing.h \ $(top_builddir)/config.h $(top_srcdir)/compat/fnmatch.h $(CC) -c $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/regress/fnmatch/fnm_test.c diff --git a/compat/dlfcn.h b/compat/dlfcn.h deleted file mode 100644 index 922c755e3..000000000 --- a/compat/dlfcn.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c) 2010 Todd C. Miller - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#ifndef _DLFCN_H_ -#define _DLFCN_H_ - -/* Emulated functions. */ -void *sudo_dlopen(const char *path, int mode); -int sudo_dlclose(void *handle); -void *sudo_dlsym(void *handle, const char *symbol); -char *sudo_dlerror(void); - -/* Map emulated functions to standard names. */ -#define dlopen(p, m) sudo_dlopen(p, m) -#define dlclose(h) sudo_dlclose(h) -#define dlsym(h, s) sudo_dlsym(h, s) -#define dlerror() sudo_dlerror() - -/* Values for dlopen() mode. */ -#define RTLD_LAZY 0x1 -#define RTLD_NOW 0x2 -#define RTLD_GLOBAL 0x4 -#define RTLD_LOCAL 0x8 - -/* Special handle arguments for dlsym(). */ -#define RTLD_NEXT ((void *) -1) /* Search subsequent objects. */ -#define RTLD_DEFAULT ((void *) -2) /* Use default search algorithm. */ -#define RTLD_SELF ((void *) -3) /* Search the caller itself. */ - -#endif /* !_DLFCN_H_ */ diff --git a/compat/dlopen.c b/compat/dlopen.c deleted file mode 100644 index dc33d80bd..000000000 --- a/compat/dlopen.c +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Copyright (c) 2010, 2012-2013 Todd C. Miller - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include - -#ifndef HAVE_DLOPEN - -#include - -#include -#ifdef STDC_HEADERS -# include -# include -#else -# ifdef HAVE_STDLIB_H -# include -# endif -#endif /* STDC_HEADERS */ -#ifdef HAVE_STRING_H -# include -#endif /* HAVE_STRING_H */ -#ifdef HAVE_STRINGS_H -# include -#endif /* HAVE_STRINGS_H */ -#include - -#include "compat/dlfcn.h" -#include "missing.h" - -#ifdef HAVE_SHL_LOAD -/* - * Emulate dlopen() using shl_load(). - */ -#include - -#ifndef DYNAMIC_PATH -# define DYNAMIC_PATH 0 -#endif - -void * -sudo_dlopen(const char *path, int mode) -{ - int flags = DYNAMIC_PATH | BIND_VERBOSE; - - if (mode == 0) - mode = RTLD_LAZY; /* default behavior */ - - /* We don't support RTLD_GLOBAL or RTLD_LOCAL yet. */ - if (ISSET(mode, RTLD_LAZY)) - flags |= BIND_DEFERRED; - if (ISSET(mode, RTLD_NOW)) - flags |= BIND_IMMEDIATE; - - return (void *)shl_load(path, flags, 0L); -} - -int -sudo_dlclose(void *handle) -{ - return shl_unload((shl_t)handle); -} - -void * -sudo_dlsym(void *vhandle, const char *symbol) -{ - shl_t handle = vhandle; - void *value = NULL; - - /* - * Note that the behavior of of RTLD_NEXT and RTLD_SELF - * differs from most implementations when called from - * a shared library. - */ - if (vhandle == RTLD_NEXT) { - /* Iterate over all shared libs looking for symbol. */ - struct shl_descriptor *desc; - int idx = 0; - while (shl_get(idx++, &desc) == 0) { - if (shl_findsym(&desc->handle, symbol, TYPE_UNDEFINED, &value) == 0) - break; - } - } else { - if (vhandle == RTLD_DEFAULT) - handle = NULL; - else if (vhandle == RTLD_SELF) - handle = PROG_HANDLE; - (void)shl_findsym(&handle, symbol, TYPE_UNDEFINED, &value); - } - - return value; -} - -char * -sudo_dlerror(void) -{ - return strerror(errno); -} - -#else /* !HAVE_SHL_LOAD */ - -/* - * Emulate dlopen() using a static list of symbols compiled into sudo. - */ - -struct sudo_preload_table { - const char *name; - void *address; -}; -extern struct sudo_preload_table sudo_preload_table[]; - -void * -sudo_dlopen(const char *path, int mode) -{ - return (void *)path; -} - -int -sudo_dlclose(void *handle) -{ - return 0; -} - -void * -sudo_dlsym(void *handle, const char *symbol) -{ - struct sudo_preload_table *sym; - - if (symbol != RTLD_NEXT && symbol != RTLD_DEFAULT && symbol != RTLD_SELF) { - for (sym = sudo_preload_table; sym->name != NULL; sym++) { - if (strcmp(symbol, sym->name) == 0) - return sym->address; - } - } - return NULL; -} - -char * -sudo_dlerror(void) -{ - return strerror(errno); -} -#endif /* HAVE_SHL_LOAD */ -#endif /* HAVE_DLOPEN */ diff --git a/config.h.in b/config.h.in index 4dd539882..908852e2f 100644 --- a/config.h.in +++ b/config.h.in @@ -987,15 +987,16 @@ /* The size of `long int', as computed by sizeof. */ #undef SIZEOF_LONG_INT +/* Define to 1 to compile the sudoers plugin statically into the sudo binary. + */ +#undef STATIC_SUDOERS_PLUGIN + /* Define to 1 if you have the ANSI C header files. */ #undef STDC_HEADERS /* Define to 1 if the code in interfaces.c does not compile for you. */ #undef STUB_LOAD_INTERFACES -/* The name of the sudoers plugin, including extension. */ -#undef SUDOERS_PLUGIN - /* An instance string to append to the username (separated by a slash) for Kerberos V authentication. */ #undef SUDO_KRB5_INSTANCE diff --git a/configure b/configure index 70365285d..c70b06168 100755 --- a/configure +++ b/configure @@ -928,6 +928,7 @@ enable_poll enable_admin_flag enable_nls enable_rpath +enable_static_sudoers with_selinux enable_gss_krb5_ccache_name enable_shared @@ -1594,6 +1595,8 @@ Optional Features: --enable-admin-flag Whether to create a Ubuntu-style admin flag file --disable-nls Disable natural language support using gettext --disable-rpath Disable passing of -Rpath to the linker + --enable-static-sudoers Build the sudoers policy module as part of the sudo + binary instead as a plugin --enable-gss-krb5-ccache-name Use GSS-API to set the Kerberos V cred cache name --enable-shared[=PKGS] build shared libraries [default=yes] @@ -5725,6 +5728,14 @@ else fi +# Check whether --enable-static-sudoers was given. +if test "${enable_static_sudoers+set}" = set; then : + enableval=$enable_static_sudoers; +else + enable_static_sudoers=no +fi + + # Check whether --with-selinux was given. if test "${with_selinux+set}" = set; then : @@ -20991,20 +21002,32 @@ case "$lt_cv_dlopen" in dlopen) $as_echo "#define HAVE_DLOPEN 1" >>confdefs.h - SUDO_OBJS="$SUDO_OBJS locale_stub.o" - LT_STATIC="--tag=disable-static" + if test "$enable_static_sudoers" = "yes"; then + $as_echo "#define STATIC_SUDOERS_PLUGIN 1" >>confdefs.h + + SUDO_OBJS="${SUDO_OBJS} preload.o" + SUDO_LIBS="${SUDO_LIBS} \$(top_builddir)/plugins/sudoers/sudoers.la" + SUDOERS_LDFLAGS="${SUDOERS_LDFLAGS} --tag=disable-shared -static" + LT_STATIC="" + else + SUDO_OBJS="$SUDO_OBJS locale_stub.o" + LT_STATIC="--tag=disable-static" + fi ;; shl_load) $as_echo "#define HAVE_SHL_LOAD 1" >>confdefs.h - SUDO_OBJS="$SUDO_OBJS locale_stub.o" - LT_STATIC="--tag=disable-static" - case " $LIBOBJS " in - *" dlopen.$ac_objext "* ) ;; - *) LIBOBJS="$LIBOBJS dlopen.$ac_objext" - ;; -esac + if test "$enable_static_sudoers" = "yes"; then + $as_echo "#define STATIC_SUDOERS_PLUGIN 1" >>confdefs.h + SUDO_OBJS="${SUDO_OBJS} preload.o" + SUDO_LIBS="${SUDO_LIBS} \$(top_builddir)/plugins/sudoers/sudoers.la" + SUDOERS_LDFLAGS="${SUDOERS_LDFLAGS} --tag=disable-shared -static" + LT_STATIC="" + else + SUDO_OBJS="$SUDO_OBJS locale_stub.o" + LT_STATIC="--tag=disable-static" + fi ;; *) if test X"${ac_cv_func_dlopen}" = X"yes"; then @@ -21014,12 +21037,6 @@ esac SUDO_OBJS="${SUDO_OBJS} preload.o" SUDO_LIBS="${SUDO_LIBS} \$(top_builddir)/plugins/sudoers/sudoers.la" LT_STATIC="" - case " $LIBOBJS " in - *" dlopen.$ac_objext "* ) ;; - *) LIBOBJS="$LIBOBJS dlopen.$ac_objext" - ;; -esac - ;; esac @@ -22026,10 +22043,6 @@ EOF done cat >>confdefs.h <>confdefs.h < + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _SUDO_DSO_H +#define _SUDO_DSO_H + +/* Values for sudo_dso_load() mode. */ +#define SUDO_DSO_LAZY 0x1 +#define SUDO_DSO_NOW 0x2 +#define SUDO_DSO_GLOBAL 0x4 +#define SUDO_DSO_LOCAL 0x8 + +/* Special handle arguments for sudo_dso_findsym(). */ +#define SUDO_DSO_NEXT ((void *)-1) /* Search subsequent objects. */ +#define SUDO_DSO_DEFAULT ((void *)-2) /* Use default search algorithm. */ +#define SUDO_DSO_SELF ((void *)-3) /* Search the caller itself. */ + +/* Internal structs for static linking of plugins. */ +struct sudo_preload_symbol { + const char *name; + void *addr; +}; +struct sudo_preload_table { + const char *path; + void *handle; + struct sudo_preload_symbol *symbols; +}; + +/* Public functions. */ +char *sudo_dso_strerror(void); +int sudo_dso_unload(void *handle); +void *sudo_dso_findsym(void *handle, const char *symbol); +void *sudo_dso_load(const char *path, int mode); +void sudo_dso_preload_table(struct sudo_preload_table *table); + +#endif /* _SUDO_DSO_H */ diff --git a/mkdep.pl b/mkdep.pl index 4cbd0b430..91a2d9bb9 100755 --- a/mkdep.pl +++ b/mkdep.pl @@ -70,7 +70,7 @@ sub mkdep { $makefile =~ s:\@SUDOERS_OBJS\@:bsm_audit.lo linux_audit.lo ldap.lo sssd.lo:; # XXX - fill in AUTH_OBJS from contents of the auth dir instead $makefile =~ s:\@AUTH_OBJS\@:afs.lo aix_auth.lo bsdauth.lo dce.lo fwtk.lo getspwuid.lo kerb5.lo pam.lo passwd.lo rfc1938.lo secureware.lo securid5.lo sia.lo:; - $makefile =~ s:\@LTLIBOBJS\@:closefrom.lo dlopen.lo fnmatch.lo getaddrinfo.lo getcwd.lo getgrouplist.lo getline.lo getprogname.lo getopt_long.lo glob.lo isblank.lo memrchr.lo memset_s.lo mksiglist.lo mksigname.lo mktemp.lo pw_dup.lo sig2str.lo siglist.lo signame.lo snprintf.lo strlcat.lo strlcpy.lo strsignal.lo utimes.lo globtest.o fnm_test.o:; + $makefile =~ s:\@LTLIBOBJS\@:closefrom.lo fnmatch.lo getaddrinfo.lo getcwd.lo getgrouplist.lo getline.lo getprogname.lo getopt_long.lo glob.lo isblank.lo memrchr.lo memset_s.lo mksiglist.lo mksigname.lo mktemp.lo pw_dup.lo sig2str.lo siglist.lo signame.lo snprintf.lo strlcat.lo strlcpy.lo strsignal.lo utimes.lo globtest.o fnm_test.o:; # Parse OBJS lines my %objs; diff --git a/plugins/sudoers/Makefile.in b/plugins/sudoers/Makefile.in index 368a8c97a..9a2e2df37 100644 --- a/plugins/sudoers/Makefile.in +++ b/plugins/sudoers/Makefile.in @@ -328,7 +328,7 @@ check: $(TEST_PROGS) visudo testsudoers diff regress/parser/check_digest.out $(srcdir)/regress/parser/check_digest.out.ok || rval=`expr $$rval + $$?`; \ ./check_fill || rval=`expr $$rval + $$?`; \ ./check_iolog_path $(srcdir)/regress/iolog_path/data || rval=`expr $$rval + $$?`; \ - if [ X"$(soext)" != X"" ]; then \ + if [ X"$(soext)" != X"" -a -e .libs/sudoers$(soext) ]; then \ ./check_symbols .libs/sudoers$(soext) $(shlib_exp) || rval=`expr $$rval + $$?`; \ fi; \ mkdir -p regress/logging; \ @@ -513,8 +513,8 @@ check_iolog_path.o: $(srcdir)/regress/iolog_path/check_iolog_path.c \ $(top_srcdir)/compat/stdbool.h $(CC) -c $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/regress/iolog_path/check_iolog_path.c check_symbols.o: $(srcdir)/regress/check_symbols/check_symbols.c \ - $(incdir)/fatal.h $(incdir)/missing.h \ - $(top_builddir)/config.h $(top_srcdir)/compat/dlfcn.h + $(incdir)/fatal.h $(incdir)/missing.h $(incdir)/sudo_dso.h \ + $(top_builddir)/config.h $(CC) -c $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/regress/check_symbols/check_symbols.c check_wrap.o: $(srcdir)/regress/logging/check_wrap.c $(incdir)/fatal.h \ $(incdir)/missing.h $(incdir)/sudo_plugin.h \ @@ -587,10 +587,10 @@ gram.lo: $(devdir)/gram.c $(devdir)/def_data.h $(incdir)/alloc.h \ group_plugin.lo: $(srcdir)/group_plugin.c $(devdir)/def_data.h \ $(incdir)/alloc.h $(incdir)/fatal.h $(incdir)/fileops.h \ $(incdir)/gettext.h $(incdir)/missing.h $(incdir)/queue.h \ - $(incdir)/sudo_debug.h $(incdir)/sudo_plugin.h \ - $(srcdir)/defaults.h $(srcdir)/logging.h $(srcdir)/sudo_nss.h \ - $(srcdir)/sudoers.h $(top_builddir)/config.h \ - $(top_builddir)/pathnames.h $(top_srcdir)/compat/dlfcn.h \ + $(incdir)/sudo_debug.h $(incdir)/sudo_dso.h \ + $(incdir)/sudo_plugin.h $(srcdir)/defaults.h \ + $(srcdir)/logging.h $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \ + $(top_builddir)/config.h $(top_builddir)/pathnames.h \ $(top_srcdir)/compat/stdbool.h $(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/group_plugin.c group_plugin.o: group_plugin.lo @@ -634,11 +634,10 @@ kerb5.lo: $(authdir)/kerb5.c $(devdir)/def_data.h $(incdir)/alloc.h \ ldap.lo: $(srcdir)/ldap.c $(devdir)/def_data.h $(incdir)/alloc.h \ $(incdir)/fatal.h $(incdir)/fileops.h $(incdir)/gettext.h \ $(incdir)/lbuf.h $(incdir)/missing.h $(incdir)/queue.h \ - $(incdir)/sudo_debug.h $(incdir)/sudo_plugin.h $(srcdir)/defaults.h \ - $(srcdir)/logging.h $(srcdir)/parse.h $(srcdir)/sudo_nss.h \ - $(srcdir)/sudoers.h $(top_builddir)/config.h \ - $(top_builddir)/pathnames.h $(top_srcdir)/compat/dlfcn.h \ - $(top_srcdir)/compat/stdbool.h + $(incdir)/sudo_debug.h $(incdir)/sudo_dso.h $(incdir)/sudo_plugin.h \ + $(srcdir)/defaults.h $(srcdir)/logging.h $(srcdir)/parse.h \ + $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h $(top_builddir)/config.h \ + $(top_builddir)/pathnames.h $(top_srcdir)/compat/stdbool.h $(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/ldap.c linux_audit.lo: $(srcdir)/linux_audit.c $(incdir)/alloc.h $(incdir)/fatal.h \ $(incdir)/gettext.h $(incdir)/missing.h $(incdir)/sudo_debug.h \ @@ -790,11 +789,10 @@ sia.lo: $(authdir)/sia.c $(devdir)/def_data.h $(incdir)/alloc.h \ sssd.lo: $(srcdir)/sssd.c $(devdir)/def_data.h $(incdir)/alloc.h \ $(incdir)/fatal.h $(incdir)/fileops.h $(incdir)/gettext.h \ $(incdir)/lbuf.h $(incdir)/missing.h $(incdir)/queue.h \ - $(incdir)/sudo_debug.h $(incdir)/sudo_plugin.h $(srcdir)/defaults.h \ - $(srcdir)/logging.h $(srcdir)/parse.h $(srcdir)/sudo_nss.h \ - $(srcdir)/sudoers.h $(top_builddir)/config.h \ - $(top_builddir)/pathnames.h $(top_srcdir)/compat/dlfcn.h \ - $(top_srcdir)/compat/stdbool.h + $(incdir)/sudo_debug.h $(incdir)/sudo_dso.h $(incdir)/sudo_plugin.h \ + $(srcdir)/defaults.h $(srcdir)/logging.h $(srcdir)/parse.h \ + $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h $(top_builddir)/config.h \ + $(top_builddir)/pathnames.h $(top_srcdir)/compat/stdbool.h $(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/sssd.c sudo_auth.lo: $(authdir)/sudo_auth.c $(devdir)/def_data.h $(incdir)/alloc.h \ $(incdir)/fatal.h $(incdir)/fileops.h $(incdir)/gettext.h \ diff --git a/plugins/sudoers/group_plugin.c b/plugins/sudoers/group_plugin.c index 7aef1acfa..86790bc4b 100644 --- a/plugins/sudoers/group_plugin.c +++ b/plugins/sudoers/group_plugin.c @@ -40,20 +40,12 @@ #ifdef TIME_WITH_SYS_TIME # include #endif -#ifdef HAVE_DLOPEN -# include -#else -# include "compat/dlfcn.h" -#endif #include #include #include #include "sudoers.h" - -#ifndef RTLD_GLOBAL -# define RTLD_GLOBAL 0 -#endif +#include "sudo_dso.h" #if defined(HAVE_DLOPEN) || defined(HAVE_SHL_LOAD) @@ -108,12 +100,12 @@ group_plugin_load(char *plugin_info) } /* Open plugin and map in symbol. */ - group_handle = dlopen(path, RTLD_LAZY|RTLD_GLOBAL); + group_handle = sudo_dso_load(path, SUDO_DSO_LAZY|SUDO_DSO_GLOBAL); if (!group_handle) { - warningx(U_("unable to dlopen %s: %s"), path, dlerror()); + warningx(U_("unable to load %s: %s"), path, sudo_dso_strerror()); goto done; } - group_plugin = dlsym(group_handle, "group_plugin"); + group_plugin = sudo_dso_findsym(group_handle, "group_plugin"); if (group_plugin == NULL) { warningx(U_("unable to find symbol \"group_plugin\" in %s"), path); goto done; @@ -157,7 +149,7 @@ done: if (rc != true) { if (group_handle != NULL) { - dlclose(group_handle); + sudo_dso_unload(group_handle); group_handle = NULL; group_plugin = NULL; } @@ -176,7 +168,7 @@ group_plugin_unload(void) group_plugin = NULL; } if (group_handle != NULL) { - dlclose(group_handle); + sudo_dso_unload(group_handle); group_handle = NULL; } debug_return; diff --git a/plugins/sudoers/ldap.c b/plugins/sudoers/ldap.c index 232a9b38e..4e5e69f70 100644 --- a/plugins/sudoers/ldap.c +++ b/plugins/sudoers/ldap.c @@ -64,16 +64,12 @@ # else # include # endif -# ifdef HAVE_DLOPEN -# include -# else -# include "compat/dlfcn.h" -# endif #endif /* HAVE_LDAP_SASL_INTERACTIVE_BIND_S */ #include "sudoers.h" #include "parse.h" #include "lbuf.h" +#include "sudo_dso.h" /* Older Netscape LDAP SDKs don't prototype ldapssl_set_strength() */ #if defined(HAVE_LDAPSSL_SET_STRENGTH) && !defined(HAVE_LDAP_SSL_H) && !defined(HAVE_MPS_LDAP_SSL_H) @@ -2046,7 +2042,8 @@ sudo_set_krb5_ccache_name(const char *name, const char **old_name) debug_decl(sudo_set_krb5_ccache_name, SUDO_DEBUG_LDAP) if (!initialized) { - sudo_gss_krb5_ccache_name = dlsym(RTLD_DEFAULT, "gss_krb5_ccache_name"); + sudo_gss_krb5_ccache_name = + sudo_dso_findsym(SUDO_DSO_DEFAULT, "gss_krb5_ccache_name"); initialized = true; } diff --git a/plugins/sudoers/regress/check_symbols/check_symbols.c b/plugins/sudoers/regress/check_symbols/check_symbols.c index 30c8ec332..034b04813 100644 --- a/plugins/sudoers/regress/check_symbols/check_symbols.c +++ b/plugins/sudoers/regress/check_symbols/check_symbols.c @@ -35,21 +35,13 @@ #ifdef HAVE_STRINGS_H # include #endif /* HAVE_STRINGS_H */ -#ifdef HAVE_DLOPEN -# include -#else -# include "compat/dlfcn.h" -#endif #include #include #include "missing.h" +#include "sudo_dso.h" #include "fatal.h" -#ifndef RTLD_GLOBAL -# define RTLD_GLOBAL 0 -#endif - #ifndef LINE_MAX # define LINE_MAX 2048 #endif @@ -82,9 +74,9 @@ main(int argc, char *argv[]) plugin_path = argv[1]; symbols_file = argv[2]; - handle = dlopen(plugin_path, RTLD_LAZY|RTLD_GLOBAL); + handle = sudo_dso_load(plugin_path, SUDO_DSO_LAZY|SUDO_DSO_GLOBAL); if (handle == NULL) - fatalx_nodebug("unable to dlopen %s: %s", plugin_path, dlerror()); + fatalx_nodebug("unable to load %s: %s", plugin_path, sudo_dso_strerror()); fp = fopen(symbols_file, "r"); if (fp == NULL) @@ -94,10 +86,10 @@ main(int argc, char *argv[]) ntests++; if ((cp = strchr(line, '\n')) != NULL) *cp = '\0'; - sym = dlsym(handle, line); + sym = sudo_dso_findsym(handle, line); if (sym == NULL) { printf("%s: test %d: unable to resolve symbol %s: %s\n", - getprogname(), ntests, line, dlerror()); + getprogname(), ntests, line, sudo_dso_strerror()); errors++; } } @@ -106,14 +98,14 @@ main(int argc, char *argv[]) * Make sure unexported symbols are not available. */ ntests++; - sym = dlsym(handle, "user_in_group"); + sym = sudo_dso_findsym(handle, "user_in_group"); if (sym != NULL) { printf("%s: test %d: able to resolve local symbol user_in_group\n", getprogname(), ntests); errors++; } - dlclose(handle); + sudo_dso_unload(handle); printf("%s: %d tests run, %d errors, %d%% success rate\n", getprogname(), ntests, errors, (ntests - errors) * 100 / ntests); diff --git a/plugins/sudoers/sssd.c b/plugins/sudoers/sssd.c index 6c9be92ab..b7ed9dc8b 100644 --- a/plugins/sudoers/sssd.c +++ b/plugins/sudoers/sssd.c @@ -43,11 +43,6 @@ #ifdef TIME_WITH_SYS_TIME # include #endif -#ifdef HAVE_DLOPEN -# include -#else -# include "compat/dlfcn.h" -#endif #include #include #include @@ -58,6 +53,7 @@ #include "sudoers.h" #include "parse.h" #include "lbuf.h" +#include "sudo_dso.h" #include "sudo_debug.h" /* SSSD <--> SUDO interface - do not change */ @@ -250,14 +246,15 @@ static int sudo_sss_open(struct sudo_nss *nss) handle = emalloc(sizeof(struct sudo_sss_handle)); /* Load symbols */ - handle->ssslib = dlopen(path, RTLD_LAZY); + handle->ssslib = sudo_dso_load(path, SUDO_DSO_LAZY); if (handle->ssslib == NULL) { - warningx(U_("unable to dlopen %s: %s"), path, dlerror()); + warningx(U_("unable to load %s: %s"), path, sudo_dso_strerror()); warningx(U_("unable to initialize SSS source. Is SSSD installed on your machine?")); debug_return_int(EFAULT); } - handle->fn_send_recv = dlsym(handle->ssslib, "sss_sudo_send_recv"); + handle->fn_send_recv = + sudo_dso_findsym(handle->ssslib, "sss_sudo_send_recv"); if (handle->fn_send_recv == NULL) { warningx(U_("unable to find symbol \"%s\" in %s"), path, "sss_sudo_send_recv"); @@ -265,28 +262,31 @@ static int sudo_sss_open(struct sudo_nss *nss) } handle->fn_send_recv_defaults = - dlsym(handle->ssslib, "sss_sudo_send_recv_defaults"); + sudo_dso_findsym(handle->ssslib, "sss_sudo_send_recv_defaults"); if (handle->fn_send_recv_defaults == NULL) { warningx(U_("unable to find symbol \"%s\" in %s"), path, "sss_sudo_send_recv_defaults"); debug_return_int(EFAULT); } - handle->fn_free_result = dlsym(handle->ssslib, "sss_sudo_free_result"); + handle->fn_free_result = + sudo_dso_findsym(handle->ssslib, "sss_sudo_free_result"); if (handle->fn_free_result == NULL) { warningx(U_("unable to find symbol \"%s\" in %s"), path, "sss_sudo_free_result"); debug_return_int(EFAULT); } - handle->fn_get_values = dlsym(handle->ssslib, "sss_sudo_get_values"); + handle->fn_get_values = + sudo_dso_findsym(handle->ssslib, "sss_sudo_get_values"); if (handle->fn_get_values == NULL) { warningx(U_("unable to find symbol \"%s\" in %s"), path, "sss_sudo_get_values"); debug_return_int(EFAULT); } - handle->fn_free_values = dlsym(handle->ssslib, "sss_sudo_free_values"); + handle->fn_free_values = + sudo_dso_findsym(handle->ssslib, "sss_sudo_free_values"); if (handle->fn_free_values == NULL) { warningx(U_("unable to find symbol \"%s\" in %s"), path, "sss_sudo_free_values"); @@ -310,7 +310,7 @@ static int sudo_sss_close(struct sudo_nss *nss) if (nss && nss->handle) { handle = nss->handle; - dlclose(handle->ssslib); + sudo_dso_unload(handle->ssslib); } efree(nss->handle); diff --git a/plugins/system_group/Makefile.in b/plugins/system_group/Makefile.in index 75ac7c9fc..c3eadf35c 100644 --- a/plugins/system_group/Makefile.in +++ b/plugins/system_group/Makefile.in @@ -145,6 +145,6 @@ cleandir: realclean # Autogenerated dependencies, do not modify system_group.lo: $(srcdir)/system_group.c $(incdir)/missing.h \ - $(incdir)/sudo_plugin.h $(top_builddir)/config.h \ - $(top_srcdir)/compat/dlfcn.h $(top_srcdir)/compat/stdbool.h + $(incdir)/sudo_dso.h $(incdir)/sudo_plugin.h \ + $(top_builddir)/config.h $(top_srcdir)/compat/stdbool.h $(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/system_group.c diff --git a/plugins/system_group/system_group.c b/plugins/system_group/system_group.c index df2783dd2..f53374ccc 100644 --- a/plugins/system_group/system_group.c +++ b/plugins/system_group/system_group.c @@ -45,11 +45,6 @@ #ifdef HAVE_UNISTD_H # include #endif /* HAVE_UNISTD_H */ -#ifdef HAVE_DLOPEN -# include -#else -# include "compat/dlfcn.h" -#endif #include #include #include @@ -59,10 +54,7 @@ #include "sudo_plugin.h" #include "missing.h" - -#ifndef RTLD_DEFAULT -# define RTLD_DEFAULT NULL -#endif +#include "sudo_dso.h" /* * Sudoers group plugin that does group name-based lookups using the system @@ -97,7 +89,7 @@ sysgroup_init(int version, sudo_printf_t sudo_printf, char *const argv[]) } /* Share group cache with sudo if possible. */ - handle = dlsym(RTLD_DEFAULT, "sudo_getgrnam"); + handle = sudo_dso_findsym(SUDO_DSO_DEFAULT, "sudo_getgrnam"); if (handle != NULL) { sysgroup_getgrnam = (sysgroup_getgrnam_t)handle; } else { @@ -105,7 +97,7 @@ sysgroup_init(int version, sudo_printf_t sudo_printf, char *const argv[]) need_setent = true; } - handle = dlsym(RTLD_DEFAULT, "sudo_getgrgid"); + handle = sudo_dso_findsym(SUDO_DSO_DEFAULT, "sudo_getgrgid"); if (handle != NULL) { sysgroup_getgrgid = (sysgroup_getgrgid_t)handle; } else { @@ -113,7 +105,7 @@ sysgroup_init(int version, sudo_printf_t sudo_printf, char *const argv[]) need_setent = true; } - handle = dlsym(RTLD_DEFAULT, "sudo_gr_delref"); + handle = sudo_dso_findsym(SUDO_DSO_DEFAULT, "sudo_gr_delref"); if (handle != NULL) sysgroup_gr_delref = (sysgroup_gr_delref_t)handle; diff --git a/src/Makefile.in b/src/Makefile.in index 6b55f90e3..e2717943b 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -191,8 +191,8 @@ conversation.o: $(srcdir)/conversation.c $(incdir)/alloc.h $(incdir)/fatal.h \ env_hooks.o: $(srcdir)/env_hooks.c $(incdir)/alloc.h $(incdir)/fatal.h \ $(incdir)/fileops.h $(incdir)/gettext.h $(incdir)/missing.h \ $(incdir)/queue.h $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \ - $(incdir)/sudo_plugin.h $(srcdir)/sudo.h $(top_builddir)/config.h \ - $(top_builddir)/pathnames.h $(top_srcdir)/compat/dlfcn.h \ + $(incdir)/sudo_dso.h $(incdir)/sudo_plugin.h $(srcdir)/sudo.h \ + $(top_builddir)/config.h $(top_builddir)/pathnames.h \ $(top_srcdir)/compat/stdbool.h $(CC) -c $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/env_hooks.c exec.o: $(srcdir)/exec.c $(incdir)/alloc.h $(incdir)/fatal.h \ @@ -233,10 +233,9 @@ hooks.o: $(srcdir)/hooks.c $(incdir)/alloc.h $(incdir)/fatal.h \ load_plugins.o: $(srcdir)/load_plugins.c $(incdir)/alloc.h $(incdir)/fatal.h \ $(incdir)/fileops.h $(incdir)/gettext.h $(incdir)/missing.h \ $(incdir)/queue.h $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \ - $(incdir)/sudo_plugin.h $(srcdir)/sudo.h \ + $(incdir)/sudo_dso.h $(incdir)/sudo_plugin.h $(srcdir)/sudo.h \ $(srcdir)/sudo_plugin_int.h $(top_builddir)/config.h \ - $(top_builddir)/pathnames.h $(top_srcdir)/compat/dlfcn.h \ - $(top_srcdir)/compat/stdbool.h + $(top_builddir)/pathnames.h $(top_srcdir)/compat/stdbool.h $(CC) -c $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/load_plugins.c locale_stub.o: $(srcdir)/locale_stub.c $(incdir)/fatal.h $(incdir)/gettext.h \ $(incdir)/missing.h $(top_builddir)/config.h @@ -258,7 +257,8 @@ parse_args.o: $(srcdir)/parse_args.c $(incdir)/alloc.h $(incdir)/fatal.h \ $(top_builddir)/pathnames.h $(top_srcdir)/compat/getopt.h \ $(top_srcdir)/compat/stdbool.h ./sudo_usage.h $(CC) -c $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/parse_args.c -preload.o: $(srcdir)/preload.c $(incdir)/sudo_plugin.h $(top_builddir)/config.h +preload.o: $(srcdir)/preload.c $(incdir)/sudo_dso.h $(incdir)/sudo_plugin.h \ + $(top_builddir)/config.h $(CC) -c $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/preload.c selinux.o: $(srcdir)/selinux.c $(incdir)/alloc.h $(incdir)/fatal.h \ $(incdir)/fileops.h $(incdir)/gettext.h $(incdir)/missing.h \ diff --git a/src/env_hooks.c b/src/env_hooks.c index 1e1db8cc0..487cc5a9a 100644 --- a/src/env_hooks.c +++ b/src/env_hooks.c @@ -37,14 +37,10 @@ # include #endif /* HAVE_MALLOC_H && !STDC_HEADERS */ #include -#ifdef HAVE_DLOPEN -# include -#else -# include "compat/dlfcn.h" -#endif #include "sudo.h" #include "sudo_plugin.h" +#include "sudo_dso.h" extern char **environ; /* global environment pointer */ static char **priv_environ; /* private environment pointer */ @@ -72,13 +68,11 @@ typedef char * (*sudo_fn_getenv_t)(const char *); char * getenv_unhooked(const char *name) { -#if defined(HAVE_DLOPEN) && defined(RTLD_NEXT) sudo_fn_getenv_t fn; - fn = (sudo_fn_getenv_t)dlsym(RTLD_NEXT, "getenv"); + fn = (sudo_fn_getenv_t)sudo_dso_findsym(SUDO_DSO_NEXT, "getenv"); if (fn != NULL) return fn(name); -#endif /* HAVE_DLOPEN && RTLD_NEXT */ return rpl_getenv(name); } @@ -144,13 +138,11 @@ typedef int (*sudo_fn_putenv_t)(PUTENV_CONST char *); static int putenv_unhooked(PUTENV_CONST char *string) { -#if defined(HAVE_DLOPEN) && defined(RTLD_NEXT) sudo_fn_putenv_t fn; - fn = (sudo_fn_putenv_t)dlsym(RTLD_NEXT, "putenv"); + fn = (sudo_fn_putenv_t)sudo_dso_findsym(SUDO_DSO_NEXT, "putenv"); if (fn != NULL) return fn(string); -#endif /* HAVE_DLOPEN && RTLD_NEXT */ return rpl_putenv(string); } @@ -214,13 +206,11 @@ typedef int (*sudo_fn_setenv_t)(const char *, const char *, int); static int setenv_unhooked(const char *var, const char *val, int overwrite) { -#if defined(HAVE_SETENV) && defined(HAVE_DLOPEN) && defined(RTLD_NEXT) sudo_fn_setenv_t fn; - fn = (sudo_fn_setenv_t)dlsym(RTLD_NEXT, "setenv"); + fn = (sudo_fn_setenv_t)sudo_dso_findsym(SUDO_DSO_NEXT, "setenv"); if (fn != NULL) return fn(var, val, overwrite); -#endif /* HAVE_SETENV && HAVE_DLOPEN && RTLD_NEXT */ return rpl_setenv(var, val, overwrite); } @@ -273,19 +263,16 @@ static int unsetenv_unhooked(const char *var) { int rval = 0; -#if defined(HAVE_UNSETENV) && defined(HAVE_DLOPEN) && defined(RTLD_NEXT) sudo_fn_unsetenv_t fn; - fn = (sudo_fn_unsetenv_t)dlsym(RTLD_NEXT, "unsetenv"); + fn = (sudo_fn_unsetenv_t)sudo_dso_findsym(SUDO_DSO_NEXT, "unsetenv"); if (fn != NULL) { # ifdef UNSETENV_VOID fn(var); # else rval = fn(var); # endif - } else -#endif /* HAVE_UNSETENV && HAVE_DLOPEN && RTLD_NEXT */ - { + } else { rval = rpl_unsetenv(var); } return rval; diff --git a/src/load_plugins.c b/src/load_plugins.c index 503322bef..4bc207a62 100644 --- a/src/load_plugins.c +++ b/src/load_plugins.c @@ -36,26 +36,17 @@ #ifdef HAVE_UNISTD_H # include #endif /* HAVE_UNISTD_H */ -#ifdef HAVE_DLOPEN -# include -#else -# include "compat/dlfcn.h" -#endif #include #include "sudo.h" #include "sudo_plugin.h" #include "sudo_plugin_int.h" #include "sudo_conf.h" +#include "sudo_dso.h" #include "sudo_debug.h" -#ifndef RTLD_GLOBAL -# define RTLD_GLOBAL 0 -#endif - -#ifndef SUDOERS_PLUGIN -# define SUDOERS_PLUGIN "sudoers.la" -#endif +/* We always use the same name for the sudoers plugin, regardless of the OS */ +#define SUDOERS_PLUGIN "sudoers.so" #ifdef _PATH_SUDO_PLUGIN_DIR static int @@ -74,7 +65,27 @@ sudo_stat_plugin(struct plugin_info *info, char *fullpath, } status = stat(fullpath, sb); } else { - int len = snprintf(fullpath, pathsize, "%s%s", _PATH_SUDO_PLUGIN_DIR, + int len; + +#ifdef STATIC_SUDOERS_PLUGIN + /* Check static symbols. */ + if (strcmp(info->path, SUDOERS_PLUGIN) == 0) { + if (strlcpy(fullpath, info->path, pathsize) >= pathsize) { + warningx(U_("error in %s, line %d while loading plugin `%s'"), + _PATH_SUDO_CONF, info->lineno, info->symbol_name); + warningx(U_("%s: %s"), info->path, strerror(ENAMETOOLONG)); + goto done; + } + /* Plugin is static, fake up struct stat. */ + memset(sb, 0, sizeof(*sb)); + sb->st_uid = ROOT_UID; + sb->st_mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH; + status = 0; + goto done; + } +#endif /* STATIC_SUDOERS_PLUGIN */ + + len = snprintf(fullpath, pathsize, "%s%s", _PATH_SUDO_PLUGIN_DIR, info->path); if (len <= 0 || (size_t)len >= pathsize) { warningx(U_("error in %s, line %d while loading plugin `%s'"), @@ -181,14 +192,14 @@ sudo_load_plugin(struct plugin_container *policy_plugin, goto done; /* Open plugin and map in symbol */ - handle = dlopen(path, RTLD_LAZY|RTLD_GLOBAL); + handle = sudo_dso_load(path, SUDO_DSO_LAZY|SUDO_DSO_GLOBAL); if (!handle) { warningx(U_("error in %s, line %d while loading plugin `%s'"), _PATH_SUDO_CONF, info->lineno, info->symbol_name); - warningx(U_("unable to dlopen %s: %s"), path, dlerror()); + warningx(U_("unable to load %s: %s"), path, sudo_dso_strerror()); goto done; } - plugin = dlsym(handle, info->symbol_name); + plugin = sudo_dso_findsym(handle, info->symbol_name); if (!plugin) { warningx(U_("error in %s, line %d while loading plugin `%s'"), _PATH_SUDO_CONF, info->lineno, info->symbol_name); @@ -221,7 +232,7 @@ sudo_load_plugin(struct plugin_container *policy_plugin, } warningx(U_("ignoring duplicate policy plugin `%s' in %s, line %d"), info->symbol_name, _PATH_SUDO_CONF, info->lineno); - dlclose(handle); + sudo_dso_unload(handle); handle = NULL; } if (handle != NULL) { @@ -236,7 +247,7 @@ sudo_load_plugin(struct plugin_container *policy_plugin, if (strcmp(container->name, info->symbol_name) == 0) { warningx(U_("ignoring duplicate I/O plugin `%s' in %s, line %d"), info->symbol_name, _PATH_SUDO_CONF, info->lineno); - dlclose(handle); + sudo_dso_unload(handle); handle = NULL; break; } diff --git a/src/preload.c b/src/preload.c index 03fd73657..7d434d9d5 100644 --- a/src/preload.c +++ b/src/preload.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2011 Todd C. Miller + * Copyright (c) 2010, 2011, 2013 Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -28,18 +28,40 @@ #endif #include "sudo_plugin.h" +#include "sudo_dso.h" + +#ifdef STATIC_SUDOERS_PLUGIN extern struct policy_plugin sudoers_policy; extern struct io_plugin sudoers_io; -struct sudo_preload_table { - const char *name; - void *address; -} sudo_preload_table[] = { - { "sudoers_policy", (void *) &sudoers_policy}, - { "sudoers_io", (void *) &sudoers_io}, -#ifdef HAVE_GSS_KRB5_CCACHE_NAME - { "gss_krb5_ccache_name", (void *) &gss_krb5_ccache_name}, -#endif +static struct sudo_preload_symbol sudo_rtld_default_symbols[] = { +# ifdef HAVE_GSS_KRB5_CCACHE_NAME + { "gss_krb5_ccache_name", (void *)&gss_krb5_ccache_name}, +# endif { (const char *)0, (void *)0 } }; + +/* XXX - can we autogenerate these? */ +static struct sudo_preload_symbol sudo_sudoers_plugin_symbols[] = { + { "sudoers_policy", (void *)&sudoers_policy}, + { "sudoers_io", (void *)&sudoers_io}, + { (const char *)0, (void *)0 } +}; + +/* + * Statically compiled symbols indexed by handle. + */ +static struct sudo_preload_table sudo_preload_table[] = { + { (char *)0, SUDO_DSO_DEFAULT, sudo_rtld_default_symbols }, + { "sudoers.so", &sudo_sudoers_plugin_symbols, sudo_sudoers_plugin_symbols }, + { (char *)0, (void *)0, (struct sudo_preload_symbol *)0 } +}; + +void +preload_static_symbols(void) +{ + sudo_dso_preload_table(sudo_preload_table); +} + +#endif /* STATIC_SUDOERS_PLUGIN */ diff --git a/src/sudo.c b/src/sudo.c index 1057abf90..ffa1baff8 100644 --- a/src/sudo.c +++ b/src/sudo.c @@ -302,6 +302,9 @@ os_init_common(int argc, char *argv[], char *envp[]) #if !defined(HAVE_GETPROGNAME) && !defined(HAVE___PROGNAME) if (argc > 0) setprogname(argv[0]); +#endif +#ifdef STATIC_SUDOERS_PLUGIN + preload_static_symbols(); #endif return 0; } diff --git a/src/sudo.h b/src/sudo.h index 9758c40c9..a8af1e4e3 100644 --- a/src/sudo.h +++ b/src/sudo.h @@ -266,4 +266,7 @@ void save_signals(void); /* gidlist.c */ int parse_gid_list(const char *gidstr, const gid_t *basegid, GETGROUPS_T **gidsp); +/* preload.c */ +void preload_static_symbols(void); + #endif /* _SUDO_SUDO_H */