2011-03-14 Andreas Schwab * elf/dl-load.c (is_dst): Remove parameter secure, all callers changed. Don't check for isolated use. (_dl_dst_substitute): Ignore rpath elements containing non-isolated use of $ORIGIN when privileged. * elf/dl-load.c (_dl_dst_substitute): When skipping the first rpath element also skip the following colon. (expand_dynamic_string_token): Add is_path parameter and pass down to DL_DST_REQUIRED and _dl_dst_substitute. (decompose_rpath): Call expand_dynamic_string_token with non-zero is_path. Ignore empty rpaths. (_dl_map_object_from_fd): Call expand_dynamic_string_token with zero is_path. Index: glibc-2.12-2-gc4ccff1/elf/dl-load.c =================================================================== --- glibc-2.12-2-gc4ccff1.orig/elf/dl-load.c +++ glibc-2.12-2-gc4ccff1/elf/dl-load.c @@ -169,8 +169,7 @@ local_strdup (const char *s) static size_t -is_dst (const char *start, const char *name, const char *str, - int is_path, int secure) +is_dst (const char *start, const char *name, const char *str, int is_path) { size_t len; bool is_curly = false; @@ -199,11 +198,6 @@ is_dst (const char *start, const char *n && (!is_path || name[len] != ':')) return 0; - if (__builtin_expect (secure, 0) - && ((name[len] != '\0' && (!is_path || name[len] != ':')) - || (name != start + 1 && (!is_path || name[-2] != ':')))) - return 0; - return len; } @@ -218,13 +212,10 @@ _dl_dst_count (const char *name, int is_ { size_t len; - /* $ORIGIN is not expanded for SUID/GUID programs (except if it - is $ORIGIN alone) and it must always appear first in path. */ ++name; - if ((len = is_dst (start, name, "ORIGIN", is_path, - INTUSE(__libc_enable_secure))) != 0 - || (len = is_dst (start, name, "PLATFORM", is_path, 0)) != 0 - || (len = is_dst (start, name, "LIB", is_path, 0)) != 0) + if ((len = is_dst (start, name, "ORIGIN", is_path)) != 0 + || (len = is_dst (start, name, "PLATFORM", is_path)) != 0 + || (len = is_dst (start, name, "LIB", is_path)) != 0) ++cnt; name = strchr (name + len, '$'); @@ -256,9 +247,16 @@ _dl_dst_substitute (struct link_map *l, size_t len; ++name; - if ((len = is_dst (start, name, "ORIGIN", is_path, - INTUSE(__libc_enable_secure))) != 0) + if ((len = is_dst (start, name, "ORIGIN", is_path)) != 0) { + /* $ORIGIN is not expanded for SUID/GUID programs + (except if it is $ORIGIN alone) and it must always + appear first in path. */ + if (__builtin_expect (INTUSE(__libc_enable_secure), 0) + && ((name[len] != '\0' && (!is_path || name[len] != ':')) + || (name != start + 1 && (!is_path || name[-2] != ':')))) + repl = (const char *) -1; + else #ifndef SHARED if (l == NULL) repl = _dl_get_origin (); @@ -266,9 +264,9 @@ _dl_dst_substitute (struct link_map *l, #endif repl = l->l_origin; } - else if ((len = is_dst (start, name, "PLATFORM", is_path, 0)) != 0) + else if ((len = is_dst (start, name, "PLATFORM", is_path)) != 0) repl = GLRO(dl_platform); - else if ((len = is_dst (start, name, "LIB", is_path, 0)) != 0) + else if ((len = is_dst (start, name, "LIB", is_path)) != 0) repl = DL_DST_LIB; if (repl != NULL && repl != (const char *) -1) @@ -284,6 +282,10 @@ _dl_dst_substitute (struct link_map *l, name += len; while (*name != '\0' && (!is_path || *name != ':')) ++name; + /* Also skip following colon if this is the first rpath + element, but keep an empty element at the end. */ + if (wp == result && is_path && *name == ':' && name[1] != '\0') + ++name; } else /* No DST we recognize. */ @@ -310,7 +312,7 @@ _dl_dst_substitute (struct link_map *l, belonging to the map is loaded. In this case the path element containing $ORIGIN is left out. */ static char * -expand_dynamic_string_token (struct link_map *l, const char *s) +expand_dynamic_string_token (struct link_map *l, const char *s, int is_path) { /* We make two runs over the string. First we determine how large the resulting string is and then we copy it over. Since this is no @@ -321,7 +323,7 @@ expand_dynamic_string_token (struct link char *result; /* Determine the number of DST elements. */ - cnt = DL_DST_COUNT (s, 1); + cnt = DL_DST_COUNT (s, is_path); /* If we do not have to replace anything simply copy the string. */ if (__builtin_expect (cnt, 0) == 0) @@ -335,7 +337,7 @@ expand_dynamic_string_token (struct link if (result == NULL) return NULL; - return _dl_dst_substitute (l, s, result, 1); + return _dl_dst_substitute (l, s, result, is_path); } @@ -551,13 +553,21 @@ decompose_rpath (struct r_search_path_st /* Make a writable copy. At the same time expand possible dynamic string tokens. */ - copy = expand_dynamic_string_token (l, rpath); + copy = expand_dynamic_string_token (l, rpath, 1); if (copy == NULL) { errstring = N_("cannot create RUNPATH/RPATH copy"); goto signal_error; } + /* Ignore empty rpaths. */ + if (*copy == 0) + { + free (copy); + sps->dirs = (char *) -1; + return false; + } + /* Count the number of necessary elements in the result array. */ nelems = 0; for (cp = copy; *cp != '\0'; ++cp) @@ -2176,7 +2186,7 @@ _dl_map_object (struct link_map *loader, { /* The path may contain dynamic string tokens. */ realname = (loader - ? expand_dynamic_string_token (loader, name) + ? expand_dynamic_string_token (loader, name, 0) : local_strdup (name)); if (realname == NULL) fd = -1;