Index: glibc-2.25/elf/rtld.c =================================================================== --- glibc-2.25.orig/elf/rtld.c +++ glibc-2.25/elf/rtld.c @@ -716,6 +716,57 @@ static const char *preloadlist attribute /* Nonzero if information about versions has to be printed. */ static int version_info attribute_relro; +/* Check that AT_SECURE=0, or that the passed name does not contain + directories and is not overly long. */ +static bool +dso_name_valid_for_suid (const char *p) +{ + if (__builtin_expect (__libc_enable_secure, 0)) + { + /* Ignore pathnames with directories for AT_SECURE=1 + programs, and also skip overlong names. */ + size_t len = strlen (p); + if (len >= NAME_MAX || memchr (p, '/', len) != NULL) + return false; + } + return true; +} + +/* The LD_PRELOAD environment variable gives list of libraries + separated by white space or colons that are loaded before the + executable's dependencies and prepended to the global scope list. + (If the binary is running setuid all elements containing a '/' are + ignored since it is insecure.) Return the number of preloads + performed. */ +static unsigned int +handle_ld_preload (const char *preloadlist, struct link_map *main_map) +{ + unsigned int npreloads = 0; + const char *p = preloadlist; + char fname[PATH_MAX]; + + while (*p != '\0') + { + /* Split preload list at space/colon. */ + size_t len = strcspn (p, " :"); + if (len > 0 && len < PATH_MAX) + { + memcpy (fname, p, len); + fname[len] = '\0'; + if (dso_name_valid_for_suid (fname)) + npreloads += do_preload (fname, main_map, "LD_PRELOAD"); + } + + /* Skip over the substring and the following delimiter. */ + p += len; + if (*p != '\0') + ++p; + } + return npreloads; +} + + + static void dl_main (const ElfW(Phdr) *phdr, ElfW(Word) phnum, @@ -1462,23 +1513,8 @@ ERROR: ld.so: object '%s' cannot be load if (__glibc_unlikely (preloadlist != NULL)) { - /* The LD_PRELOAD environment variable gives list of libraries - separated by white space or colons that are loaded before the - executable's dependencies and prepended to the global scope - list. If the binary is running setuid all elements - containing a '/' are ignored since it is insecure. */ - char *list = strdupa (preloadlist); - char *p; - HP_TIMING_NOW (start); - - /* Prevent optimizing strsep. Speed is not important here. */ - while ((p = (strsep) (&list, " :")) != NULL) - if (p[0] != '\0' - && (__builtin_expect (! __libc_enable_secure, 1) - || strchr (p, '/') == NULL)) - npreloads += do_preload (p, main_map, "LD_PRELOAD"); - + npreloads += handle_ld_preload (preloadlist, main_map); HP_TIMING_NOW (stop); HP_TIMING_DIFF (diff, start, stop); HP_TIMING_ACCUM_NT (load_time, diff); @@ -2340,9 +2376,7 @@ process_dl_audit (char *str) char *p; while ((p = (strsep) (&str, ":")) != NULL) - if (p[0] != '\0' - && (__builtin_expect (! __libc_enable_secure, 1) - || strchr (p, '/') == NULL)) + if (p[0] != '\0' && dso_name_valid_for_suid (p)) { /* This is using the local malloc, not the system malloc. The memory can never be freed. */ @@ -2372,6 +2406,7 @@ process_envvars (enum mode *modep) char *envline; enum mode mode = normal; char *debug_output = NULL; + char *ld_audit = NULL; /* This is the default place for profiling data file. */ GLRO(dl_profile_output) @@ -2406,7 +2441,7 @@ process_envvars (enum mode *modep) break; } if (memcmp (envline, "AUDIT", 5) == 0) - process_dl_audit (&envline[6]); + ld_audit = &envline[6]; break; case 7: @@ -2465,7 +2500,8 @@ process_envvars (enum mode *modep) case 12: /* The library search path. */ - if (memcmp (envline, "LIBRARY_PATH", 12) == 0) + if (!__libc_enable_secure + && memcmp (envline, "LIBRARY_PATH", 12) == 0) { library_path = &envline[13]; break; @@ -2532,6 +2568,12 @@ process_envvars (enum mode *modep) } } + /* Even if LD_AUDIT occurs multiple times in the environment + process_dl_audit should only be called once to avoid polluting the + heap with unused copies of the value. */ + if (ld_audit != NULL) + process_dl_audit (ld_audit); + /* The caller wants this information. */ *modep = mode; Index: glibc-2.25/sysdeps/i386/i686/multiarch/strcspn-c.c =================================================================== --- glibc-2.25.orig/sysdeps/i386/i686/multiarch/strcspn-c.c +++ glibc-2.25/sysdeps/i386/i686/multiarch/strcspn-c.c @@ -1,2 +1,4 @@ -#define __strcspn_sse2 __strcspn_ia32 -#include +#if IS_IN (libc) +# define __strcspn_sse2 __strcspn_ia32 +# include +#endif Index: glibc-2.25/sysdeps/i386/i686/multiarch/varshift.c =================================================================== --- glibc-2.25.orig/sysdeps/i386/i686/multiarch/varshift.c +++ glibc-2.25/sysdeps/i386/i686/multiarch/varshift.c @@ -1 +1,3 @@ -#include +#if IS_IN (libc) +# include +#endif