elf: Check for empty tokens before dynamic string token expansion [BZ #22625]

The fillin_rpath function in elf/dl-load.c loops over each RPATH or
RUNPATH tokens and interprets empty tokens as the current directory
("./"). In practice the check for empty token is done *after* the
dynamic string token expansion. The expansion process can return an
empty string for the $ORIGIN token if __libc_enable_secure is set
or if the path of the binary can not be determined (/proc not mounted).

Fix that by moving the check for empty tokens before the dynamic string
token expansion. In addition, check for NULL pointer or empty strings
return by expand_dynamic_string_token.

The above changes highlighted a bug in decompose_rpath, an empty array
is represented by the first element being NULL at the fillin_rpath
level, but by using a -1 pointer in decompose_rpath and other functions.

Changelog:
	[BZ #22625]
	* elf/dl-load.c (fillin_rpath): Check for empty tokens before dynamic
	string token expansion. Check for NULL pointer or empty string possibly
	returned by expand_dynamic_string_token.
	(decompose_rpath): Check for empty path after dynamic string
	token expansion.
This commit is contained in:
Aurelien Jarno 2017-12-30 10:54:23 +01:00
parent c48831d0ee
commit 3e3c904dae
3 changed files with 49 additions and 18 deletions

View File

@ -1,3 +1,13 @@
2017-12-30 Aurelien Jarno <aurelien@aurel32.net>
Dmitry V. Levin <ldv@altlinux.org>
[BZ #22625]
* elf/dl-load.c (fillin_rpath): Check for empty tokens before dynamic
string token expansion. Check for NULL pointer or empty string possibly
returned by expand_dynamic_string_token.
(decompose_rpath): Check for empty path after dynamic string
token expansion.
2017-12-29 Dmitry V. Levin <ldv@altlinux.org>
[BZ #22433]

4
NEWS
View File

@ -164,6 +164,10 @@ Security related changes:
CVE-2017-1000366 has been applied, but it is mentioned here only because
of the CVE assignment.) Reported by Qualys.
CVE-2017-16997: Incorrect handling of RPATH or RUNPATH containing $ORIGIN
for AT_SECURE or SUID binaries could be used to load libraries from the
current directory.
The following bugs are resolved with this release:
[The release manager will add the list generated by

View File

@ -389,32 +389,41 @@ fillin_rpath (char *rpath, struct r_search_path_elem **result, const char *sep,
{
char *cp;
size_t nelems = 0;
char *to_free;
while ((cp = __strsep (&rpath, sep)) != NULL)
{
struct r_search_path_elem *dirp;
char *to_free = NULL;
size_t len = 0;
to_free = cp = expand_dynamic_string_token (l, cp);
size_t len = strlen (cp);
/* `strsep' can pass an empty string. This has to be
interpreted as `use the current directory'. */
if (len == 0)
/* `strsep' can pass an empty string. */
if (*cp != '\0')
{
static const char curwd[] = "./";
cp = (char *) curwd;
to_free = cp = expand_dynamic_string_token (l, cp);
/* expand_dynamic_string_token can return NULL in case of empty
path or memory allocation failure. */
if (cp == NULL)
continue;
/* Compute the length after dynamic string token expansion and
ignore empty paths. */
len = strlen (cp);
if (len == 0)
{
free (to_free);
continue;
}
/* Remove trailing slashes (except for "/"). */
while (len > 1 && cp[len - 1] == '/')
--len;
/* Now add one if there is none so far. */
if (len > 0 && cp[len - 1] != '/')
cp[len++] = '/';
}
/* Remove trailing slashes (except for "/"). */
while (len > 1 && cp[len - 1] == '/')
--len;
/* Now add one if there is none so far. */
if (len > 0 && cp[len - 1] != '/')
cp[len++] = '/';
/* See if this directory is already known. */
for (dirp = GL(dl_all_dirs); dirp != NULL; dirp = dirp->next)
if (dirp->dirnamelen == len && memcmp (cp, dirp->dirname, len) == 0)
@ -569,6 +578,14 @@ decompose_rpath (struct r_search_path_struct *sps,
necessary. */
free (copy);
/* There is no path after expansion. */
if (result[0] == NULL)
{
free (result);
sps->dirs = (struct r_search_path_elem **) -1;
return false;
}
sps->dirs = result;
/* The caller will change this value if we haven't used a real malloc. */
sps->malloced = 1;