mirror of
https://sourceware.org/git/glibc.git
synced 2024-11-21 20:40:05 +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>
|
2019-02-04 Matthew Malcomson <matthew.malcomson@arm.com>
|
||||||
|
|
||||||
* Makefile (testrun.sh): Exit in case of incorrect argument.
|
* Makefile (testrun.sh): Exit in case of incorrect argument.
|
||||||
|
3
NEWS
3
NEWS
@ -9,7 +9,8 @@ Version 2.30
|
|||||||
|
|
||||||
Major new features:
|
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:
|
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 (yes,$(build-shared))
|
||||||
ifeq ($(run-built-tests),yes)
|
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
|
endif
|
||||||
tests-special += $(objpfx)check-textrel.out $(objpfx)check-execstack.out \
|
tests-special += $(objpfx)check-textrel.out $(objpfx)check-execstack.out \
|
||||||
$(objpfx)check-localplt.out $(objpfx)check-initfini.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)' > $@; \
|
$(SHELL) $^ '$(test-wrapper)' '$(test-wrapper-env)' > $@; \
|
||||||
$(evaluate-test)
|
$(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: $(libdl)
|
||||||
$(objpfx)initfirst.out: $(objpfx)firstobj.so
|
$(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;
|
static const char *preloadlist attribute_relro;
|
||||||
/* Nonzero if information about versions has to be printed. */
|
/* Nonzero if information about versions has to be printed. */
|
||||||
static int version_info attribute_relro;
|
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
|
/* The LD_PRELOAD environment variable gives list of libraries
|
||||||
separated by white space or colons that are loaded before the
|
separated by white space or colons that are loaded before the
|
||||||
executable's dependencies and prepended to the global scope list.
|
executable's dependencies and prepended to the global scope list.
|
||||||
(If the binary is running setuid all elements containing a '/' are
|
(If the binary is running setuid all elements containing a '/' are
|
||||||
ignored since it is insecure.) Return the number of preloads
|
ignored since it is insecure.) Return the number of preloads
|
||||||
performed. */
|
performed. Ditto for --preload command argument. */
|
||||||
unsigned int
|
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;
|
unsigned int npreloads = 0;
|
||||||
const char *p = preloadlist;
|
const char *p = preloadlist;
|
||||||
@ -858,7 +861,7 @@ handle_ld_preload (const char *preloadlist, struct link_map *main_map)
|
|||||||
++p;
|
++p;
|
||||||
|
|
||||||
if (dso_name_valid_for_suid (fname))
|
if (dso_name_valid_for_suid (fname))
|
||||||
npreloads += do_preload (fname, main_map, "LD_PRELOAD");
|
npreloads += do_preload (fname, main_map, where);
|
||||||
}
|
}
|
||||||
return npreloads;
|
return npreloads;
|
||||||
}
|
}
|
||||||
@ -974,6 +977,13 @@ dl_main (const ElfW(Phdr) *phdr,
|
|||||||
{
|
{
|
||||||
process_dl_audit (_dl_argv[2]);
|
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_skip_args += 2;
|
||||||
_dl_argc -= 2;
|
_dl_argc -= 2;
|
||||||
_dl_argv += 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\
|
variable LD_LIBRARY_PATH\n\
|
||||||
--inhibit-rpath LIST ignore RUNPATH and RPATH information in object names\n\
|
--inhibit-rpath LIST ignore RUNPATH and RPATH information in object names\n\
|
||||||
in LIST\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_skip_args;
|
||||||
--_dl_argc;
|
--_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))
|
if (__glibc_unlikely (preloadlist != NULL))
|
||||||
{
|
{
|
||||||
HP_TIMING_NOW (start);
|
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_NOW (stop);
|
||||||
HP_TIMING_DIFF (diff, start, stop);
|
HP_TIMING_DIFF (diff, start, stop);
|
||||||
HP_TIMING_ACCUM_NT (load_time, diff);
|
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