From 207e77fd3f0a94acdf0557608dd4f10ce0e0f22f Mon Sep 17 00:00:00 2001 From: Andreas Schwab Date: Mon, 9 May 2011 10:55:58 +0200 Subject: [PATCH] Never leave $ORIGIN unexpanded * elf/dl-load.c (is_dst): Remove parameter secure, all callers changed. Move check for valid use of $ORIGIN ... (_dl_dst_substitute): ... here. Reset check_for_trusted when a path element is skipped. --- ChangeLog | 7 +++++++ elf/dl-load.c | 34 ++++++++++++++++------------------ 2 files changed, 23 insertions(+), 18 deletions(-) diff --git a/elf/dl-load.c b/elf/dl-load.c index 18a83d2..6e16a9a 100644 --- a/elf/dl-load.c +++ b/elf/dl-load.c @@ -249,8 +249,7 @@ is_trusted_path_normalize (const char *path, size_t len) 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; @@ -279,12 +278,6 @@ is_dst (const char *start, const char *name, const char *str, && (!is_path || name[len] != ':')) return 0; - if (__glibc_unlikely (secure) - && ((name[len] != '\0' && name[len] != '/' - && (!is_path || name[len] != ':')) - || (name != start + 1 && (!is_path || name[-2] != ':')))) - return 0; - return len; } @@ -299,13 +292,10 @@ _dl_dst_count (const char *name, int is_path) { 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, - __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, '$'); @@ -338,10 +328,18 @@ _dl_dst_substitute (struct link_map *l, const char *name, char *result, size_t len; ++name; - if ((len = is_dst (start, name, "ORIGIN", is_path, - __libc_enable_secure)) != 0) + if ((len = is_dst (start, name, "ORIGIN", is_path)) != 0) { - repl = l->l_origin; + /* For SUID/GUID programs $ORIGIN must always appear + first in a path element. */ + if (__glibc_unlikely (__libc_enable_secure) + && ((name[len] != '\0' && name[len] != '/' + && (!is_path || name[len] != ':')) + || (name != start + 1 && (!is_path || name[-2] != ':')))) + repl = (const char *) -1; + else + repl = l->l_origin; + check_for_trusted = (__libc_enable_secure && l->l_type == lt_executable); } @@ -351,9 +348,9 @@ _dl_dst_substitute (struct link_map *l, const char *name, char *result, check_for_trusted = (__libc_enable_secure && l->l_type == lt_executable); } - 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) @@ -373,6 +370,7 @@ _dl_dst_substitute (struct link_map *l, const char *name, char *result, element, but keep an empty element at the end. */ if (wp == result && is_path && *name == ':' && name[1] != '\0') ++name; + check_for_trusted = false; } else /* No DST we recognize. */