From 22836f52e3e4740e450f9b93a2f1e31a90b168a6 Mon Sep 17 00:00:00 2001 From: Ulrich Drepper Date: Wed, 11 May 2011 00:15:38 -0400 Subject: [PATCH] Fix up testing for valid $ORIGIN use --- ChangeLog | 12 ++++++++++++ elf/dl-load.c | 48 ++++++++++++++++++++++++++++++++---------------- 2 files changed, 44 insertions(+), 16 deletions(-) diff --git a/ChangeLog b/ChangeLog index f4363af..60d160c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +2011-05-11 Ulrich Drepper + + [BZ #12393] + * elf/dl-load.c (is_trusted_path): Remove unnecessary test. + (is_trusted_path_normalize): Skip initial colon. Append slash + to empty buffer. Duplicate is_trusted_path code but allow + constructed patch to be prefix. + (is_dst): Allow $ORIGIN followed by /. + (_dl_dst_substitute): Correct clearing of check_for_trusted. + Correct testing of result of is_trusted_path_normalize + (decompose_rpath): Fix warning. + 2011-05-10 Ulrich Drepper [BZ #11257] diff --git a/elf/dl-load.c b/elf/dl-load.c index f2773d5..18a83d2 100644 --- a/elf/dl-load.c +++ b/elf/dl-load.c @@ -171,10 +171,6 @@ local_strdup (const char *s) static bool is_trusted_path (const char *path, size_t len) { - /* All trusted directories must be complete names. */ - if (path[0] != '/') - return false; - const char *trun = system_dirs; for (size_t idx = 0; idx < nsystem_dirs_len; ++idx) @@ -193,9 +189,17 @@ is_trusted_path (const char *path, size_t len) static bool is_trusted_path_normalize (const char *path, size_t len) { + if (len == 0) + return false; + + if (*path == ':') + { + ++path; + --len; + } + char *npath = (char *) alloca (len + 2); char *wnp = npath; - while (*path != '\0') { if (path[0] == '/') @@ -225,11 +229,23 @@ is_trusted_path_normalize (const char *path, size_t len) *wnp++ = *path++; } - if (wnp > npath && wnp[-1] != '/') + + if (wnp == npath || wnp[-1] != '/') *wnp++ = '/'; - *wnp = '\0'; - return is_trusted_path (npath, wnp - npath); + const char *trun = system_dirs; + + for (size_t idx = 0; idx < nsystem_dirs_len; ++idx) + { + if (wnp - npath >= system_dirs_len[idx] + && memcmp (trun, npath, system_dirs_len[idx]) == 0) + /* Found it. */ + return true; + + trun += system_dirs_len[idx] + 1; + } + + return false; } @@ -265,7 +281,8 @@ is_dst (const char *start, const char *name, const char *str, return 0; if (__builtin_expect (secure, 0) - && ((name[len] != '\0' && (!is_path || name[len] != ':')) + && ((name[len] != '\0' && name[len] != '/' + && (!is_path || name[len] != ':')) || (name != start + 1 && (!is_path || name[-2] != ':')))) return 0; @@ -371,13 +388,12 @@ _dl_dst_substitute (struct link_map *l, const char *name, char *result, normalized path must be rooted in one of the trusted directories. */ if (__builtin_expect (check_for_trusted, false) - && is_trusted_path_normalize (last_elem, wp - last_elem)) - { - wp = last_elem; - check_for_trusted = false; - } + && !is_trusted_path_normalize (last_elem, wp - last_elem)) + wp = last_elem; else last_elem = wp; + + check_for_trusted = false; } } } @@ -386,7 +402,7 @@ _dl_dst_substitute (struct link_map *l, const char *name, char *result, /* In SUID/SGID programs, after $ORIGIN expansion the normalized path must be rooted in one of the trusted directories. */ if (__builtin_expect (check_for_trusted, false) - && is_trusted_path_normalize (last_elem, wp - last_elem)) + && !is_trusted_path_normalize (last_elem, wp - last_elem)) wp = last_elem; *wp = '\0'; @@ -628,7 +644,7 @@ decompose_rpath (struct r_search_path_struct *sps, if (*copy == 0) { free (copy); - sps->dirs = (char *) -1; + sps->dirs = (struct r_search_path_elem **) -1; return false; } -- 2.7.4