ld.so: command argument "--preload"
Commit Message
On 7/11/18 8:53 pm, Florian Weimer wrote:
> Yes, as long as it's not text/html. Please resend your patch as an
> attachment; it looks like some lines were wrapped.
I like HTML email (I know! and I've been doing UNIX since '80s) but this
client is doing the movement no favour by mangling what I asked to be
pre-formatted text. Here it is as an attachment.
Comments
* David Newall:
> On 7/11/18 8:53 pm, Florian Weimer wrote:
>> Yes, as long as it's not text/html. Please resend your patch as an
>> attachment; it looks like some lines were wrapped.
>
> I like HTML email (I know! and I've been doing UNIX since '80s) but
> this client is doing the movement no favour by mangling what I asked
> to be pre-formatted text. Here it is as an attachment.
Much better, thanks.
> diff --git a/elf/Makefile b/elf/Makefile
> index d72e7b6..901e188 100644
> --- a/elf/Makefile
> +++ b/elf/Makefile
> @@ -353,7 +353,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
> @@ -882,6 +883,13 @@ $(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
Missing dependency on the objects in $(tst-rtld-preload-OBJS), I think.
I expect you need to add the prefix $(objpfx) to the dependency.
> + $(SHELL) $^ '$(test-wrapper)' '$(test-wrapper-env)' '$(run_program_env)' \
> + '$(rpath-link)' '$(tst-rtld-preload-OBJS)' > $@; \
> + $(evaluate-test)
There are two whitespace errors on this line (leading and trailing
space).
> $(objpfx)initfirst: $(libdl)
> $(objpfx)initfirst.out: $(objpfx)firstobj.so
>
> diff --git a/elf/rtld.c b/elf/rtld.c
> index 1b0c747..f046f6e 100644
> --- a/elf/rtld.c
> +++ b/elf/rtld.c
> @@ -826,6 +826,8 @@ 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
> @@ -833,8 +835,9 @@ static int version_info attribute_relro;
> (If the binary is running setuid all elements containing a '/' are
> ignored since it is insecure.) Return the number of preloads
> performed. */
> +/* Ditto for --preload command argument */
I would merge the last line into the existing comment, and there should
be a ". " at the end (period followed by two spaces, as before).
> 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)
Please wrap the at 79 characters.
Rest looks good to me.
Thanks,
Florian
On 8/11/18 12:02 am, Florian Weimer wrote:
>>
>> +tst-rtld-preload-OBJS = $(subst $(empty) ,:,$(strip $(preloadtest-preloads:=.so)))
>> +$(objpfx)tst-rtld-preload.out: tst-rtld-preload.sh $(objpfx)ld.so \
>> + $(objpfx)preloadtest
> Missing dependency on the objects in $(tst-rtld-preload-OBJS), I think.
I think not. This is the same as preloadtest-ENV (without
"LD_PRELOAD="). Is it okay? Should I have included a comment to
explain this?
* David Newall:
> On 8/11/18 12:02 am, Florian Weimer wrote:
>>> +tst-rtld-preload-OBJS = $(subst $(empty) ,:,$(strip
>>> $(preloadtest-preloads:=.so)))
>>> +$(objpfx)tst-rtld-preload.out: tst-rtld-preload.sh $(objpfx)ld.so \
>>> + $(objpfx)preloadtest
>> Missing dependency on the objects in $(tst-rtld-preload-OBJS), I think.
> I think not. This is the same as preloadtest-ENV (without
> "LD_PRELOAD="). Is it okay? Should I have included a comment to
> explain this?
preloadtest.out has this:
$(objpfx)preloadtest.out: $(preloadtest-preloads:%=$(objpfx)%.so)
preloadtest-ENV = \
LD_PRELOAD=$(subst $(empty) ,:,$(strip $(preloadtest-preloads:=.so)))
So I think you should add $(preloadtest-preloads:%=$(objpfx)%.so) as
well.
Thanks,
Florian
On 8/11/18 12:36 am, Florian Weimer wrote:
> preloadtest.out has this:
>
> $(objpfx)preloadtest.out: $(preloadtest-preloads:%=$(objpfx)%.so)
> preloadtest-ENV = \
> LD_PRELOAD=$(subst $(empty) ,:,$(strip $(preloadtest-preloads:=.so)))
>
> So I think you should add $(preloadtest-preloads:%=$(objpfx)%.so) as
> well.
Oh, I see, yes, you are right. Interesting that preloadtest.out does
not depend on preloadtest.
This is a disincentive to use of $^ in the recipe. It should be like this?
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)
(or be explicit instead of $<)
* David Newall:
> On 8/11/18 12:36 am, Florian Weimer wrote:
>> preloadtest.out has this:
>>
>> $(objpfx)preloadtest.out: $(preloadtest-preloads:%=$(objpfx)%.so)
>> preloadtest-ENV = \
>> LD_PRELOAD=$(subst $(empty) ,:,$(strip $(preloadtest-preloads:=.so)))
>>
>> So I think you should add $(preloadtest-preloads:%=$(objpfx)%.so) as
>> well.
>
> Oh, I see, yes, you are right. Interesting that preloadtest.out does
> not depend on preloadtest.
>
> This is a disincentive to use of $^ in the recipe. It should be like this?
>
> 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)
>
> (or be explicit instead of $<)
Yes, you will have to use $<. I do not have a strong preference ($< vs
tst-rtld-preload.sh). The test runs in the source tree, so both are
okay.
Thanks,
Florian
@@ -353,7 +353,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
@@ -882,6 +883,13 @@ $(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
+ $(SHELL) $^ '$(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
@@ -826,6 +826,8 @@ 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
@@ -833,8 +835,9 @@ static int version_info attribute_relro;
(If the binary is running setuid all elements containing a '/' are
ignored since it is insecure.) Return the number of preloads
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;
}
@@ -978,6 +981,13 @@ dl_main (const ElfW(Phdr) *phdr,
_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;
+ }
else
break;
@@ -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);
new file mode 100755
@@ -0,0 +1,37 @@
+#!/bin/sh
+# Test how rtld loads itself.
+# Copyright (C) 2012-2016 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