aboutsummaryrefslogtreecommitdiff
path: root/elf
diff options
context:
space:
mode:
Diffstat (limited to 'elf')
-rw-r--r--elf/dl-load.c90
1 files changed, 48 insertions, 42 deletions
diff --git a/elf/dl-load.c b/elf/dl-load.c
index ad29386823..21c3274ae9 100644
--- a/elf/dl-load.c
+++ b/elf/dl-load.c
@@ -126,6 +126,8 @@ static const size_t system_dirs_len[] =
{
SYSTEM_DIRS_LEN
};
+#define nsystem_dirs_len \
+ (sizeof (system_dirs_len) / sizeof (system_dirs_len[0]))
/* Local version of `strdup' function. */
@@ -362,32 +364,6 @@ fillin_rpath (char *rpath, struct r_search_path_elem **result, const char *sep,
if (len > 0 && cp[len - 1] != '/')
cp[len++] = '/';
- /* Make sure we don't use untrusted directories if we run SUID. */
- if (check_trusted)
- {
- const char *trun = system_dirs;
- size_t idx;
-
- /* All trusted directories must be complete names. */
- if (cp[0] != '/')
- continue;
-
- for (idx = 0;
- idx < sizeof (system_dirs_len) / sizeof (system_dirs_len[0]);
- ++idx)
- {
- if (len == system_dirs_len[idx] && memcmp (trun, cp, len) == 0)
- /* Found it. */
- break;
-
- trun += system_dirs_len[idx] + 1;
- }
-
- if (idx == sizeof (system_dirs_len) / sizeof (system_dirs_len[0]))
- /* It's no trusted directory, skip it. */
- continue;
- }
-
/* See if this directory is already known. */
for (dirp = all_dirs; dirp != NULL; dirp = dirp->next)
if (dirp->dirnamelen == len && memcmp (cp, dirp->dirname, len) == 0)
@@ -408,7 +384,7 @@ fillin_rpath (char *rpath, struct r_search_path_elem **result, const char *sep,
{
size_t cnt;
enum r_dir_status init_val;
- size_t where_len = strlen (where) + 1;
+ size_t where_len = where ? strlen (where) + 1 : 0;
/* It's a new directory. Create an entry and add it. */
dirp = (struct r_search_path_elem *)
@@ -424,17 +400,51 @@ fillin_rpath (char *rpath, struct r_search_path_elem **result, const char *sep,
if (len > max_dirnamelen)
max_dirnamelen = len;
- /* We have to make sure all the relative directories are never
- ignored. The current directory might change and all our
- saved information would be void. */
- init_val = cp[0] != '/' ? existing : unknown;
+ /* Make sure we don't use untrusted directories if we run SUID. */
+ if (__builtin_expect (check_trusted, 0))
+ {
+ const char *trun = system_dirs;
+ size_t idx;
+
+ /* By default we don't trust anything. */
+ init_val = nonexisting;
+
+ /* All trusted directories must be complete names. */
+ if (cp[0] == '/')
+ {
+ for (idx = 0; idx < nsystem_dirs_len; ++idx)
+ {
+ if (len == system_dirs_len[idx]
+ && memcmp (trun, cp, len) == 0)
+ /* Found it. */
+ break;
+
+ trun += system_dirs_len[idx] + 1;
+ }
+
+ if (idx < nsystem_dirs_len)
+ /* It's a trusted directory so allow checking for it. */
+ init_val = unknown;
+ }
+ }
+ else
+ /* We don't have to check for trusted directories and can
+ accept everything. We have to make sure all the
+ relative directories are never ignored. The current
+ directory might change and all our saved information
+ would be void. */
+ init_val = cp[0] != '/' ? existing : unknown;
+
for (cnt = 0; cnt < ncapstr; ++cnt)
dirp->status[cnt] = init_val;
dirp->what = what;
- dirp->where = memcpy ((char *) dirp + sizeof (*dirp)
- + ncapstr * sizeof (enum r_dir_status),
- where, where_len);
+ if (__builtin_expect (where != NULL, 1))
+ dirp->where = memcpy ((char *) dirp + sizeof (*dirp)
+ + ncapstr * sizeof (enum r_dir_status),
+ where, where_len);
+ else
+ dirp->where = NULL;
dirp->next = all_dirs;
all_dirs = dirp;
@@ -531,8 +541,7 @@ _dl_init_paths (const char *llp)
/* First set up the rest of the default search directory entries. */
aelem = rtld_search_dirs = (struct r_search_path_elem **)
- malloc ((sizeof (system_dirs_len) / sizeof (system_dirs_len[0]) + 1)
- * sizeof (struct r_search_path_elem *));
+ malloc ((nsystem_dirs_len + 1) * sizeof (struct r_search_path_elem *));
if (rtld_search_dirs == NULL)
_dl_signal_error (ENOMEM, NULL, N_("cannot create search path array"));
@@ -570,13 +579,11 @@ _dl_init_paths (const char *llp)
for (cnt = 0; cnt < ncapstr; ++cnt)
pelem->status[cnt] = unknown;
- pelem->next = (++idx == (sizeof (system_dirs_len)
- / sizeof (system_dirs_len[0]))
- ? NULL : (pelem + round_size));
+ pelem->next = (++idx == nsystem_dirs_len ? NULL : (pelem + round_size));
pelem += round_size;
}
- while (idx < sizeof (system_dirs_len) / sizeof (system_dirs_len[0]));
+ while (idx < nsystem_dirs_len);
max_dirnamelen = SYSTEM_DIRS_MAX_LEN;
*aelem = NULL;
@@ -1506,8 +1513,7 @@ _dl_map_object (struct link_map *loader, const char *name, int preloaded,
dirp += system_dirs_len[cnt] + 1;
++cnt;
}
- while (cnt < (sizeof (system_dirs_len)
- / sizeof (system_dirs_len[0])));
+ while (cnt < nsystem_dirs_len);
}
if (cached)