mirror of
git://sourceware.org/git/glibc.git
synced 2025-02-17 13:00:43 +08:00
(dl_main): First check existence of ld.so.preload with access.
This commit is contained in:
parent
6698501fda
commit
761490a1d7
185
elf/rtld.c
185
elf/rtld.c
@ -1138,103 +1138,114 @@ of this helper program; chances are you did not intend to run this program.\n\
|
|||||||
HP_TIMING_ACCUM_NT (load_time, diff);
|
HP_TIMING_ACCUM_NT (load_time, diff);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Read the contents of the file. */
|
/* There usually is no ld.so.preload file, it should only be used
|
||||||
const char preload_file[] = "/etc/ld.so.preload";
|
for emergencies and testing. So the open call etc should usually
|
||||||
file = _dl_sysdep_read_whole_file (preload_file, &file_size,
|
fail. Using access() on a non-existing file is faster than using
|
||||||
PROT_READ | PROT_WRITE);
|
open(). So we do this first. If it succeeds we do almost twice
|
||||||
if (__builtin_expect (file != MAP_FAILED, 0))
|
the work but this does not matter, since it is not for production
|
||||||
|
use. */
|
||||||
|
static const char preload_file[] = "/etc/ld.so.preload";
|
||||||
|
if (__builtin_expect (__access (preload_file, R_OK) == 0, 0))
|
||||||
{
|
{
|
||||||
/* Parse the file. It contains names of libraries to be loaded,
|
/* Read the contents of the file. */
|
||||||
separated by white spaces or `:'. It may also contain
|
file = _dl_sysdep_read_whole_file (preload_file, &file_size,
|
||||||
comments introduced by `#'. */
|
PROT_READ | PROT_WRITE);
|
||||||
char *problem;
|
if (__builtin_expect (file != MAP_FAILED, 0))
|
||||||
char *runp;
|
|
||||||
size_t rest;
|
|
||||||
|
|
||||||
/* Eliminate comments. */
|
|
||||||
runp = file;
|
|
||||||
rest = file_size;
|
|
||||||
while (rest > 0)
|
|
||||||
{
|
{
|
||||||
char *comment = memchr (runp, '#', rest);
|
/* Parse the file. It contains names of libraries to be loaded,
|
||||||
if (comment == NULL)
|
separated by white spaces or `:'. It may also contain
|
||||||
break;
|
comments introduced by `#'. */
|
||||||
|
char *problem;
|
||||||
|
char *runp;
|
||||||
|
size_t rest;
|
||||||
|
|
||||||
rest -= comment - runp;
|
/* Eliminate comments. */
|
||||||
do
|
|
||||||
*comment = ' ';
|
|
||||||
while (--rest > 0 && *++comment != '\n');
|
|
||||||
}
|
|
||||||
|
|
||||||
/* We have one problematic case: if we have a name at the end of
|
|
||||||
the file without a trailing terminating characters, we cannot
|
|
||||||
place the \0. Handle the case separately. */
|
|
||||||
if (file[file_size - 1] != ' ' && file[file_size - 1] != '\t'
|
|
||||||
&& file[file_size - 1] != '\n' && file[file_size - 1] != ':')
|
|
||||||
{
|
|
||||||
problem = &file[file_size];
|
|
||||||
while (problem > file && problem[-1] != ' ' && problem[-1] != '\t'
|
|
||||||
&& problem[-1] != '\n' && problem[-1] != ':')
|
|
||||||
--problem;
|
|
||||||
|
|
||||||
if (problem > file)
|
|
||||||
problem[-1] = '\0';
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
problem = NULL;
|
|
||||||
file[file_size - 1] = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
HP_TIMING_NOW (start);
|
|
||||||
|
|
||||||
if (file != problem)
|
|
||||||
{
|
|
||||||
char *p;
|
|
||||||
runp = file;
|
runp = file;
|
||||||
while ((p = strsep (&runp, ": \t\n")) != NULL)
|
rest = file_size;
|
||||||
if (p[0] != '\0')
|
while (rest > 0)
|
||||||
{
|
{
|
||||||
const char *objname;
|
char *comment = memchr (runp, '#', rest);
|
||||||
const char *err_str = NULL;
|
if (comment == NULL)
|
||||||
struct map_args args;
|
break;
|
||||||
|
|
||||||
args.str = p;
|
rest -= comment - runp;
|
||||||
args.loader = GL(dl_loaded);
|
do
|
||||||
args.is_preloaded = 1;
|
*comment = ' ';
|
||||||
args.mode = 0;
|
while (--rest > 0 && *++comment != '\n');
|
||||||
|
}
|
||||||
|
|
||||||
(void) _dl_catch_error (&objname, &err_str, map_doit, &args);
|
/* We have one problematic case: if we have a name at the end of
|
||||||
if (__builtin_expect (err_str != NULL, 0))
|
the file without a trailing terminating characters, we cannot
|
||||||
|
place the \0. Handle the case separately. */
|
||||||
|
if (file[file_size - 1] != ' ' && file[file_size - 1] != '\t'
|
||||||
|
&& file[file_size - 1] != '\n' && file[file_size - 1] != ':')
|
||||||
|
{
|
||||||
|
problem = &file[file_size];
|
||||||
|
while (problem > file && problem[-1] != ' '
|
||||||
|
&& problem[-1] != '\t'
|
||||||
|
&& problem[-1] != '\n' && problem[-1] != ':')
|
||||||
|
--problem;
|
||||||
|
|
||||||
|
if (problem > file)
|
||||||
|
problem[-1] = '\0';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
problem = NULL;
|
||||||
|
file[file_size - 1] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
HP_TIMING_NOW (start);
|
||||||
|
|
||||||
|
if (file != problem)
|
||||||
|
{
|
||||||
|
char *p;
|
||||||
|
runp = file;
|
||||||
|
while ((p = strsep (&runp, ": \t\n")) != NULL)
|
||||||
|
if (p[0] != '\0')
|
||||||
{
|
{
|
||||||
_dl_error_printf ("\
|
const char *objname;
|
||||||
|
const char *err_str = NULL;
|
||||||
|
struct map_args args;
|
||||||
|
|
||||||
|
args.str = p;
|
||||||
|
args.loader = GL(dl_loaded);
|
||||||
|
args.is_preloaded = 1;
|
||||||
|
args.mode = 0;
|
||||||
|
|
||||||
|
(void) _dl_catch_error (&objname, &err_str, map_doit,
|
||||||
|
&args);
|
||||||
|
if (__builtin_expect (err_str != NULL, 0))
|
||||||
|
{
|
||||||
|
_dl_error_printf ("\
|
||||||
ERROR: ld.so: object '%s' from %s cannot be preloaded: ignored.\n",
|
ERROR: ld.so: object '%s' from %s cannot be preloaded: ignored.\n",
|
||||||
p, preload_file);
|
p, preload_file);
|
||||||
/* No need to call free, this is still before the libc's
|
/* No need to call free, this is still before
|
||||||
malloc is used. */
|
the libc's malloc is used. */
|
||||||
|
}
|
||||||
|
else if (++args.map->l_opencount == 1)
|
||||||
|
/* It is no duplicate. */
|
||||||
|
++npreloads;
|
||||||
}
|
}
|
||||||
else if (++args.map->l_opencount == 1)
|
}
|
||||||
/* It is no duplicate. */
|
|
||||||
++npreloads;
|
if (problem != NULL)
|
||||||
}
|
{
|
||||||
|
char *p = strndupa (problem, file_size - (problem - file));
|
||||||
|
struct link_map *new_map = _dl_map_object (GL(dl_loaded), p, 1,
|
||||||
|
lt_library, 0, 0);
|
||||||
|
if (++new_map->l_opencount == 1)
|
||||||
|
/* It is no duplicate. */
|
||||||
|
++npreloads;
|
||||||
|
}
|
||||||
|
|
||||||
|
HP_TIMING_NOW (stop);
|
||||||
|
HP_TIMING_DIFF (diff, start, stop);
|
||||||
|
HP_TIMING_ACCUM_NT (load_time, diff);
|
||||||
|
|
||||||
|
/* We don't need the file anymore. */
|
||||||
|
__munmap (file, file_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (problem != NULL)
|
|
||||||
{
|
|
||||||
char *p = strndupa (problem, file_size - (problem - file));
|
|
||||||
struct link_map *new_map = _dl_map_object (GL(dl_loaded), p, 1,
|
|
||||||
lt_library, 0, 0);
|
|
||||||
if (++new_map->l_opencount == 1)
|
|
||||||
/* It is no duplicate. */
|
|
||||||
++npreloads;
|
|
||||||
}
|
|
||||||
|
|
||||||
HP_TIMING_NOW (stop);
|
|
||||||
HP_TIMING_DIFF (diff, start, stop);
|
|
||||||
HP_TIMING_ACCUM_NT (load_time, diff);
|
|
||||||
|
|
||||||
/* We don't need the file anymore. */
|
|
||||||
__munmap (file, file_size);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (__builtin_expect (npreloads, 0) != 0)
|
if (__builtin_expect (npreloads, 0) != 0)
|
||||||
|
Loading…
Reference in New Issue
Block a user