Skip to content

Commit

Permalink
ld.so: Adjust the auxv if ld.so is directly invoked.
Browse files Browse the repository at this point in the history
If a binary gets invoked by passing it as argument to ld.so the stack
still holds the auxiliary vector of ld.so when entering the _start
routine of the executable.  So the invocation via ld.so is not fully
transparent to the executable.  This causes problems if the executable
wants to scan the auxv itself.
  • Loading branch information
Andreas Krebbel authored and Ulrich Drepper committed Jan 15, 2010
1 parent 5306d36 commit 3a56ea2
Show file tree
Hide file tree
Showing 5 changed files with 53 additions and 22 deletions.
10 changes: 10 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
2010-01-13 Andreas Krebbel <Andreas.Krebbel@de.ibm.com>

* elf/dl-sysdep.c (_dl_sysdep_start): Added the auxv parameter to
dl_main.
* elf/dl-open.c (_dl_sysdep_start): Likewise..
* sysdeps/generic/ldsodefs.h (_dl_sysdep_start): Likewise.
* elf/rtld.c (dl_main): Added new parameter auxv. Adjust the
AT_PHDR, AT_PHNUM and AT_ENTRY fields if the ld.so is directly
started.

2010-01-14 Ulrich Drepper <drepper@redhat.com>

[BZ #11027]
Expand Down
9 changes: 5 additions & 4 deletions elf/dl-open.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* Load a shared object at runtime, relocate it, and run its initializer.
Copyright (C) 1996-2007, 2009 Free Software Foundation, Inc.
Copyright (C) 1996-2007, 2009, 2010 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
Expand Down Expand Up @@ -40,7 +40,8 @@
extern ElfW(Addr) _dl_sysdep_start (void **start_argptr,
void (*dl_main) (const ElfW(Phdr) *phdr,
ElfW(Word) phnum,
ElfW(Addr) *user_entry));
ElfW(Addr) *user_entry,
ElfW(auxv_t) *auxv));
weak_extern (BP_SYM (_dl_sysdep_start))

extern int __libc_multiple_libcs; /* Defined in init-first.c. */
Expand Down Expand Up @@ -346,8 +347,8 @@ dl_open_worker (void *a)
{
/* If this here is the shared object which we want to profile
make sure the profile is started. We can find out whether
this is necessary or not by observing the `_dl_profile_map'
variable. If was NULL but is not NULL afterwars we must
this is necessary or not by observing the `_dl_profile_map'
variable. If was NULL but is not NULL afterwars we must
start the profiling. */
struct link_map *old_profile_map = GL(dl_profile_map);

Expand Down
10 changes: 5 additions & 5 deletions elf/dl-sysdep.c
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ void *_dl_random attribute_relro = NULL;
ElfW(Addr)
_dl_sysdep_start (void **start_argptr,
void (*dl_main) (const ElfW(Phdr) *phdr, ElfW(Word) phnum,
ElfW(Addr) *user_entry))
ElfW(Addr) *user_entry, ElfW(auxv_t) *auxv))
{
const ElfW(Phdr) *phdr = NULL;
ElfW(Word) phnum = 0;
Expand Down Expand Up @@ -241,7 +241,7 @@ _dl_sysdep_start (void **start_argptr,
if (__builtin_expect (INTUSE(__libc_enable_secure), 0))
__libc_check_standard_fds ();

(*dl_main) (phdr, phnum, &user_entry);
(*dl_main) (phdr, phnum, &user_entry, _dl_auxv);
return user_entry;
}

Expand Down Expand Up @@ -511,9 +511,9 @@ _dl_important_hwcaps (const char *platform, size_t platform_len, size_t *sz,
/* Fill in the information. This follows the following scheme
(indeces from TEMP for four strings):
entry #0: 0, 1, 2, 3 binary: 1111
#1: 0, 1, 3 1101
#2: 0, 2, 3 1011
#3: 0, 3 1001
#1: 0, 1, 3 1101
#2: 0, 2, 3 1011
#3: 0, 3 1001
This allows the representation of all possible combinations of
capability names in the string. First generate the strings. */
result[1].str = result[0].str = cp = (char *) (result + *sz);
Expand Down
41 changes: 30 additions & 11 deletions elf/rtld.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* Run time dynamic linker.
Copyright (C) 1995-2006, 2007, 2008, 2009 Free Software Foundation, Inc.
Copyright (C) 1995-2006, 2007, 2008, 2009, 2010 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
Expand Down Expand Up @@ -182,7 +182,7 @@ extern struct rtld_global_ro _rtld_local_ro


static void dl_main (const ElfW(Phdr) *phdr, ElfW(Word) phnum,
ElfW(Addr) *user_entry);
ElfW(Addr) *user_entry, ElfW(auxv_t) *auxv);

/* These two variables cannot be moved into .data.rel.ro. */
static struct libname_list _dl_rtld_libname;
Expand Down Expand Up @@ -882,7 +882,8 @@ static int version_info attribute_relro;
static void
dl_main (const ElfW(Phdr) *phdr,
ElfW(Word) phnum,
ElfW(Addr) *user_entry)
ElfW(Addr) *user_entry,
ElfW(auxv_t) *auxv)
{
const ElfW(Phdr) *ph;
enum mode mode;
Expand Down Expand Up @@ -927,6 +928,8 @@ dl_main (const ElfW(Phdr) *phdr,

if (*user_entry == (ElfW(Addr)) ENTRY_POINT)
{
ElfW(auxv_t) *av;

/* Ho ho. We are not the program interpreter! We are the program
itself! This means someone ran ld.so as a command. Well, that
might be convenient to do sometimes. We support it by
Expand Down Expand Up @@ -1013,11 +1016,11 @@ of this helper program; chances are you did not intend to run this program.\n\
\n\
--list list all dependencies and how they are resolved\n\
--verify verify that given object really is a dynamically linked\n\
object we can handle\n\
object we can handle\n\
--library-path PATH use given PATH instead of content of the environment\n\
variable LD_LIBRARY_PATH\n\
variable LD_LIBRARY_PATH\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");

++_dl_skip_args;
Expand Down Expand Up @@ -1082,6 +1085,22 @@ of this helper program; chances are you did not intend to run this program.\n\
makes sense to free the old string first. */
main_map->l_name = (char *) "";
*user_entry = main_map->l_entry;

/* Adjust the on-stack auxiliary vector so that it looks like the
binary was executed directly. */
for (av = auxv; av->a_type != AT_NULL; av++)
switch (av->a_type)
{
case AT_PHDR:
av->a_un.a_val = phdr;
break;
case AT_PHNUM:
av->a_un.a_val = phnum;
break;
case AT_ENTRY:
av->a_un.a_val = *user_entry;
break;
}
}
else
{
Expand Down Expand Up @@ -2013,7 +2032,7 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
_dl_relocate_object (&GL(dl_rtld_map),
main_map->l_scope, 0, 0);
}
}
}
#define VERNEEDTAG (DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGIDX (DT_VERNEED))
if (version_info)
{
Expand Down Expand Up @@ -2682,10 +2701,10 @@ process_envvars (enum mode *modep)
while (*nextp != '\0');

if (__access ("/etc/suid-debug", F_OK) != 0)
{
{
unsetenv ("MALLOC_CHECK_");
GLRO(dl_debug_mask) = 0;
}
}

if (mode != normal)
_exit (5);
Expand Down Expand Up @@ -2752,7 +2771,7 @@ print_statistics (hp_timing_t *rtld_total_timep)
}
*wp = '\0';
_dl_debug_printf ("\
time needed for relocation: %s (%s%%)\n", buf, pbuf);
time needed for relocation: %s (%s%%)\n", buf, pbuf);
}
#endif

Expand Down Expand Up @@ -2815,7 +2834,7 @@ print_statistics (hp_timing_t *rtld_total_timep)
}
*wp = '\0';
_dl_debug_printf ("\
time needed to load objects: %s (%s%%)\n",
time needed to load objects: %s (%s%%)\n",
buf, pbuf);
}
#endif
Expand Down
5 changes: 3 additions & 2 deletions sysdeps/generic/ldsodefs.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* Run-time dynamic linker data structures for loaded ELF shared objects.
Copyright (C) 1995-2006, 2007, 2008, 2009 Free Software Foundation, Inc.
Copyright (C) 1995-2009, 2010 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
Expand Down Expand Up @@ -1015,7 +1015,8 @@ extern void *_dl_sysdep_read_whole_file (const char *file, size_t *sizep,
extern ElfW(Addr) _dl_sysdep_start (void **start_argptr,
void (*dl_main) (const ElfW(Phdr) *phdr,
ElfW(Word) phnum,
ElfW(Addr) *user_entry))
ElfW(Addr) *user_entry,
ElfW(auxv_t) *auxv))
attribute_hidden;

extern void _dl_sysdep_start_cleanup (void)
Expand Down

0 comments on commit 3a56ea2

Please sign in to comment.