mirror of
https://sourceware.org/git/glibc.git
synced 2024-11-21 12:30:06 +00:00
elf: Implement --preload option for the dynamic linker
This commit is contained in:
parent
5e10136b3c
commit
8692ebdb12
13
ChangeLog
13
ChangeLog
@ -1,3 +1,16 @@
|
||||
2019-02-04 David Newall <glibc@davidnewall.com>
|
||||
|
||||
elf: Implement --preload option for the dynamic linker.
|
||||
* elf/rtld.c (preloadarg): New variable.
|
||||
(handle_preload_list): Pass through “where” argument to
|
||||
do_preload.
|
||||
(dl_main): Handle "--preload" and add second call to
|
||||
handle_preload_list.
|
||||
* elf/Makefile (tests-special): Add tst-rtld-preload.out.
|
||||
(tst-rtld-preload-OBJS): Set variable.
|
||||
(tst-rtld-preload.out): New target.
|
||||
* elf/tst-rtld-preload.sh: New file.
|
||||
|
||||
2019-02-04 Matthew Malcomson <matthew.malcomson@arm.com>
|
||||
|
||||
* Makefile (testrun.sh): Exit in case of incorrect argument.
|
||||
|
3
NEWS
3
NEWS
@ -9,7 +9,8 @@ Version 2.30
|
||||
|
||||
Major new features:
|
||||
|
||||
[Add new features here]
|
||||
* The dynamic linker accepts the --preload argument to preload shared
|
||||
objects, in addition to the LD_PRELOAD environment variable.
|
||||
|
||||
Deprecated and removed features, and other changes affecting compatibility:
|
||||
|
||||
|
12
elf/Makefile
12
elf/Makefile
@ -354,7 +354,8 @@ endif
|
||||
|
||||
ifeq (yes,$(build-shared))
|
||||
ifeq ($(run-built-tests),yes)
|
||||
tests-special += $(objpfx)tst-pathopt.out $(objpfx)tst-rtld-load-self.out
|
||||
tests-special += $(objpfx)tst-pathopt.out $(objpfx)tst-rtld-load-self.out \
|
||||
$(objpfx)tst-rtld-preload.out
|
||||
endif
|
||||
tests-special += $(objpfx)check-textrel.out $(objpfx)check-execstack.out \
|
||||
$(objpfx)check-localplt.out $(objpfx)check-initfini.out
|
||||
@ -883,6 +884,15 @@ $(objpfx)tst-rtld-load-self.out: tst-rtld-load-self.sh $(objpfx)ld.so
|
||||
$(SHELL) $^ '$(test-wrapper)' '$(test-wrapper-env)' > $@; \
|
||||
$(evaluate-test)
|
||||
|
||||
tst-rtld-preload-OBJS = $(subst $(empty) ,:,$(strip $(preloadtest-preloads:=.so)))
|
||||
$(objpfx)tst-rtld-preload.out: tst-rtld-preload.sh $(objpfx)ld.so \
|
||||
$(objpfx)preloadtest \
|
||||
$(preloadtest-preloads:%=$(objpfx)%.so)
|
||||
$(SHELL) $< $(objpfx)ld.so $(objpfx)preloadtest \
|
||||
'$(test-wrapper)' '$(test-wrapper-env)' '$(run_program_env)' \
|
||||
'$(rpath-link)' '$(tst-rtld-preload-OBJS)' > $@; \
|
||||
$(evaluate-test)
|
||||
|
||||
$(objpfx)initfirst: $(libdl)
|
||||
$(objpfx)initfirst.out: $(objpfx)firstobj.so
|
||||
|
||||
|
30
elf/rtld.c
30
elf/rtld.c
@ -826,15 +826,18 @@ static const char *library_path attribute_relro;
|
||||
static const char *preloadlist attribute_relro;
|
||||
/* Nonzero if information about versions has to be printed. */
|
||||
static int version_info attribute_relro;
|
||||
/* The preload list passed as a command argument. */
|
||||
static const char *preloadarg attribute_relro;
|
||||
|
||||
/* The LD_PRELOAD environment variable gives list of libraries
|
||||
separated by white space or colons that are loaded before the
|
||||
executable's dependencies and prepended to the global scope list.
|
||||
(If the binary is running setuid all elements containing a '/' are
|
||||
ignored since it is insecure.) Return the number of preloads
|
||||
performed. */
|
||||
performed. Ditto for --preload command argument. */
|
||||
unsigned int
|
||||
handle_ld_preload (const char *preloadlist, struct link_map *main_map)
|
||||
handle_preload_list (const char *preloadlist, struct link_map *main_map,
|
||||
const char *where)
|
||||
{
|
||||
unsigned int npreloads = 0;
|
||||
const char *p = preloadlist;
|
||||
@ -858,7 +861,7 @@ handle_ld_preload (const char *preloadlist, struct link_map *main_map)
|
||||
++p;
|
||||
|
||||
if (dso_name_valid_for_suid (fname))
|
||||
npreloads += do_preload (fname, main_map, "LD_PRELOAD");
|
||||
npreloads += do_preload (fname, main_map, where);
|
||||
}
|
||||
return npreloads;
|
||||
}
|
||||
@ -974,6 +977,13 @@ dl_main (const ElfW(Phdr) *phdr,
|
||||
{
|
||||
process_dl_audit (_dl_argv[2]);
|
||||
|
||||
_dl_skip_args += 2;
|
||||
_dl_argc -= 2;
|
||||
_dl_argv += 2;
|
||||
}
|
||||
else if (! strcmp (_dl_argv[1], "--preload") && _dl_argc > 2)
|
||||
{
|
||||
preloadarg = _dl_argv[2];
|
||||
_dl_skip_args += 2;
|
||||
_dl_argc -= 2;
|
||||
_dl_argv += 2;
|
||||
@ -1006,7 +1016,8 @@ of this helper program; chances are you did not intend to run this program.\n\
|
||||
variable LD_LIBRARY_PATH\n\
|
||||
--inhibit-rpath LIST ignore RUNPATH and RPATH information in object names\n\
|
||||
in LIST\n\
|
||||
--audit LIST use objects named in LIST as auditors\n");
|
||||
--audit LIST use objects named in LIST as auditors\n\
|
||||
--preload LIST preload objects named in LIST\n");
|
||||
|
||||
++_dl_skip_args;
|
||||
--_dl_argc;
|
||||
@ -1620,7 +1631,16 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
|
||||
if (__glibc_unlikely (preloadlist != NULL))
|
||||
{
|
||||
HP_TIMING_NOW (start);
|
||||
npreloads += handle_ld_preload (preloadlist, main_map);
|
||||
npreloads += handle_preload_list (preloadlist, main_map, "LD_PRELOAD");
|
||||
HP_TIMING_NOW (stop);
|
||||
HP_TIMING_DIFF (diff, start, stop);
|
||||
HP_TIMING_ACCUM_NT (load_time, diff);
|
||||
}
|
||||
|
||||
if (__glibc_unlikely (preloadarg != NULL))
|
||||
{
|
||||
HP_TIMING_NOW (start);
|
||||
npreloads += handle_preload_list (preloadarg, main_map, "--preload");
|
||||
HP_TIMING_NOW (stop);
|
||||
HP_TIMING_DIFF (diff, start, stop);
|
||||
HP_TIMING_ACCUM_NT (load_time, diff);
|
||||
|
38
elf/tst-rtld-preload.sh
Executable file
38
elf/tst-rtld-preload.sh
Executable file
@ -0,0 +1,38 @@
|
||||
#!/bin/sh
|
||||
# Test --preload argument ld.so.
|
||||
# Copyright (C) 2019 Free Software Foundation, Inc.
|
||||
# This file is part of the GNU C Library.
|
||||
#
|
||||
# The GNU C Library is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU Lesser General Public
|
||||
# License as published by the Free Software Foundation; either
|
||||
# version 2.1 of the License, or (at your option) any later version.
|
||||
#
|
||||
# The GNU C Library is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public
|
||||
# License along with the GNU C Library; if not, see
|
||||
# <http://www.gnu.org/licenses/>.
|
||||
|
||||
set -e
|
||||
|
||||
rtld=$1
|
||||
test_program=$2
|
||||
test_wrapper=$3
|
||||
test_wrapper_env=$4
|
||||
run_program_env=$5
|
||||
library_path=$6
|
||||
preload=$7
|
||||
|
||||
echo "# [${test_wrapper}] [$rtld] [--library-path] [$library_path]" \
|
||||
"[--preload] [$preload] [$test_program]"
|
||||
${test_wrapper_env} \
|
||||
${run_program_env} \
|
||||
${test_wrapper} $rtld --library-path "$library_path" \
|
||||
--preload "$preload" $test_program 2>&1 && rc=0 || rc=$?
|
||||
echo "# exit status $rc"
|
||||
|
||||
exit $rc
|
Loading…
Reference in New Issue
Block a user