Skip to content

Commit

Permalink
Fix several problems with our ELF filters implementation.
Browse files Browse the repository at this point in the history
Do not relocate twice an object which happens to be needed by loaded
binary (or dso) and some filtee opened due to symbol resolution when
relocating need objects.  Record the state of the relocation
processing in Obj_Entry and short-circuit relocate_objects() if
current object already processed.

Do not call constructors for filtees loaded during the early
relocation processing before image is initialized enough to run
user-provided code.  Filtees are loaded using dlopen_object(), which
normally performs relocation and initialization.  If filtee is
lazy-loaded during the relocation of dso needed by the main object,
dlopen_object() runs too earlier, when most runtime services are not
yet ready.

Postpone the constructors call to the time when main binary and
depended libraries constructors are run, passing the new flag
RTLD_LO_EARLY to dlopen_object().  Symbol lookups callers inform
symlook_* functions about early stage of initialization with
SYMLOOK_EARLY.  Pass flags through all functions participating in
object relocation.

Use the opportunity and fix flags argument to find_symdef() in
arch-specific reloc.c to use proper name SYMLOOK_IN_PLT instead of
true, which happen to have the same numeric value.

Reported and tested by:	theraven
Reviewed by:	kan
MFC after:	2 weeks
  • Loading branch information
kostikbel committed Mar 20, 2012
1 parent 04296b6 commit 082f959
Show file tree
Hide file tree
Showing 10 changed files with 179 additions and 118 deletions.
34 changes: 18 additions & 16 deletions libexec/rtld-elf/amd64/reloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ do_copy_relocations(Obj_Entry *dstobj)
size = dstsym->st_size;
symlook_init(&req, name);
req.ventry = fetch_ventry(dstobj, ELF_R_SYM(rela->r_info));
req.flags = SYMLOOK_EARLY;

for (srcobj = dstobj->next; srcobj != NULL; srcobj = srcobj->next) {
res = symlook_obj(&req, srcobj);
Expand Down Expand Up @@ -118,7 +119,8 @@ init_pltgot(Obj_Entry *obj)

/* Process the non-PLT relocations. */
int
reloc_non_plt(Obj_Entry *obj, Obj_Entry *obj_rtld, RtldLockState *lockstate)
reloc_non_plt(Obj_Entry *obj, Obj_Entry *obj_rtld, int flags,
RtldLockState *lockstate)
{
const Elf_Rela *relalim;
const Elf_Rela *rela;
Expand Down Expand Up @@ -151,7 +153,7 @@ reloc_non_plt(Obj_Entry *obj, Obj_Entry *obj_rtld, RtldLockState *lockstate)
const Obj_Entry *defobj;

def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj,
false, cache, lockstate);
flags, cache, lockstate);
if (def == NULL)
goto done;

Expand All @@ -170,7 +172,7 @@ reloc_non_plt(Obj_Entry *obj, Obj_Entry *obj_rtld, RtldLockState *lockstate)
const Obj_Entry *defobj;

def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj,
false, cache, lockstate);
flags, cache, lockstate);
if (def == NULL)
goto done;

Expand Down Expand Up @@ -200,7 +202,7 @@ reloc_non_plt(Obj_Entry *obj, Obj_Entry *obj_rtld, RtldLockState *lockstate)
const Obj_Entry *defobj;

def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj,
false, cache, lockstate);
flags, cache, lockstate);
if (def == NULL)
goto done;

Expand All @@ -214,7 +216,7 @@ reloc_non_plt(Obj_Entry *obj, Obj_Entry *obj_rtld, RtldLockState *lockstate)
const Obj_Entry *defobj;

def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj,
false, cache, lockstate);
flags, cache, lockstate);
if (def == NULL)
goto done;

Expand Down Expand Up @@ -245,7 +247,7 @@ reloc_non_plt(Obj_Entry *obj, Obj_Entry *obj_rtld, RtldLockState *lockstate)
const Obj_Entry *defobj;

def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj,
false, cache, lockstate);
flags, cache, lockstate);
if (def == NULL)
goto done;

Expand Down Expand Up @@ -277,7 +279,7 @@ reloc_non_plt(Obj_Entry *obj, Obj_Entry *obj_rtld, RtldLockState *lockstate)
const Obj_Entry *defobj;

def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj,
false, cache, lockstate);
flags, cache, lockstate);
if (def == NULL)
goto done;

Expand All @@ -291,7 +293,7 @@ reloc_non_plt(Obj_Entry *obj, Obj_Entry *obj_rtld, RtldLockState *lockstate)
const Obj_Entry *defobj;

def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj,
false, cache, lockstate);
flags, cache, lockstate);
if (def == NULL)
goto done;

Expand All @@ -305,7 +307,7 @@ reloc_non_plt(Obj_Entry *obj, Obj_Entry *obj_rtld, RtldLockState *lockstate)
const Obj_Entry *defobj;

def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj,
false, cache, lockstate);
flags, cache, lockstate);
if (def == NULL)
goto done;

Expand All @@ -330,7 +332,7 @@ reloc_non_plt(Obj_Entry *obj, Obj_Entry *obj_rtld, RtldLockState *lockstate)
done:
if (cache != NULL)
free(cache);
return(r);
return (r);
}

/* Process the PLT relocations. */
Expand Down Expand Up @@ -366,7 +368,7 @@ reloc_plt(Obj_Entry *obj)

/* Relocate the jump slots in an object. */
int
reloc_jmpslots(Obj_Entry *obj, RtldLockState *lockstate)
reloc_jmpslots(Obj_Entry *obj, int flags, RtldLockState *lockstate)
{
const Elf_Rela *relalim;
const Elf_Rela *rela;
Expand All @@ -382,8 +384,8 @@ reloc_jmpslots(Obj_Entry *obj, RtldLockState *lockstate)
switch (ELF_R_TYPE(rela->r_info)) {
case R_X86_64_JMP_SLOT:
where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, true, NULL,
lockstate);
def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj,
SYMLOOK_IN_PLT | flags, NULL, lockstate);
if (def == NULL)
return (-1);
if (ELF_ST_TYPE(def->st_info) == STT_GNU_IFUNC) {
Expand Down Expand Up @@ -438,7 +440,7 @@ reloc_iresolve(Obj_Entry *obj, RtldLockState *lockstate)
}

int
reloc_gnu_ifunc(Obj_Entry *obj, RtldLockState *lockstate)
reloc_gnu_ifunc(Obj_Entry *obj, int flags, RtldLockState *lockstate)
{
const Elf_Rela *relalim;
const Elf_Rela *rela;
Expand All @@ -454,8 +456,8 @@ reloc_gnu_ifunc(Obj_Entry *obj, RtldLockState *lockstate)
switch (ELF_R_TYPE(rela->r_info)) {
case R_X86_64_JMP_SLOT:
where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, true, NULL,
lockstate);
def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj,
SYMLOOK_IN_PLT | flags, NULL, lockstate);
if (def == NULL)
return (-1);
if (ELF_ST_TYPE(def->st_info) != STT_GNU_IFUNC)
Expand Down
26 changes: 15 additions & 11 deletions libexec/rtld-elf/arm/reloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ do_copy_relocations(Obj_Entry *dstobj)
symlook_init(&req, name);
req.ventry = fetch_ventry(dstobj,
ELF_R_SYM(rel->r_info));
req.flags = SYMLOOK_EARLY;

for (srcobj = dstobj->next; srcobj != NULL;
srcobj = srcobj->next) {
res = symlook_obj(&req, srcobj);
Expand Down Expand Up @@ -135,7 +137,7 @@ store_ptr(void *where, Elf_Addr val)

static int
reloc_nonplt_object(Obj_Entry *obj, const Elf_Rel *rel, SymCache *cache,
RtldLockState *lockstate)
int flags, RtldLockState *lockstate)
{
Elf_Addr *where;
const Elf_Sym *def;
Expand All @@ -161,7 +163,7 @@ reloc_nonplt_object(Obj_Entry *obj, const Elf_Rel *rel, SymCache *cache,
if (addend & 0x00800000)
addend |= 0xff000000;

def = find_symdef(symnum, obj, &defobj, false, cache,
def = find_symdef(symnum, obj, &defobj, flags, cache,
lockstate);
if (def == NULL)
return -1;
Expand All @@ -188,7 +190,7 @@ reloc_nonplt_object(Obj_Entry *obj, const Elf_Rel *rel, SymCache *cache,

case R_ARM_ABS32: /* word32 B + S + A */
case R_ARM_GLOB_DAT: /* word32 B + S */
def = find_symdef(symnum, obj, &defobj, false, cache,
def = find_symdef(symnum, obj, &defobj, flags, cache,
lockstate);
if (def == NULL)
return -1;
Expand Down Expand Up @@ -237,7 +239,7 @@ reloc_nonplt_object(Obj_Entry *obj, const Elf_Rel *rel, SymCache *cache,
break;

case R_ARM_TLS_DTPOFF32:
def = find_symdef(symnum, obj, &defobj, false, cache,
def = find_symdef(symnum, obj, &defobj, flags, cache,
lockstate);
if (def == NULL)
return -1;
Expand All @@ -254,7 +256,7 @@ reloc_nonplt_object(Obj_Entry *obj, const Elf_Rel *rel, SymCache *cache,

break;
case R_ARM_TLS_DTPMOD32:
def = find_symdef(symnum, obj, &defobj, false, cache,
def = find_symdef(symnum, obj, &defobj, flags, cache,
lockstate);
if (def == NULL)
return -1;
Expand All @@ -272,7 +274,7 @@ reloc_nonplt_object(Obj_Entry *obj, const Elf_Rel *rel, SymCache *cache,
break;

case R_ARM_TLS_TPOFF32:
def = find_symdef(symnum, obj, &defobj, false, cache,
def = find_symdef(symnum, obj, &defobj, flags, cache,
lockstate);
if (def == NULL)
return -1;
Expand Down Expand Up @@ -311,7 +313,8 @@ reloc_nonplt_object(Obj_Entry *obj, const Elf_Rel *rel, SymCache *cache,
* * Process non-PLT relocations
* */
int
reloc_non_plt(Obj_Entry *obj, Obj_Entry *obj_rtld, RtldLockState *lockstate)
reloc_non_plt(Obj_Entry *obj, Obj_Entry *obj_rtld, int flags,
RtldLockState *lockstate)
{
const Elf_Rel *rellim;
const Elf_Rel *rel;
Expand All @@ -330,7 +333,7 @@ reloc_non_plt(Obj_Entry *obj, Obj_Entry *obj_rtld, RtldLockState *lockstate)

rellim = (const Elf_Rel *)((caddr_t)obj->rel + obj->relsize);
for (rel = obj->rel; rel < rellim; rel++) {
if (reloc_nonplt_object(obj, rel, cache, lockstate) < 0)
if (reloc_nonplt_object(obj, rel, cache, flags, lockstate) < 0)
goto done;
}
r = 0;
Expand Down Expand Up @@ -367,7 +370,7 @@ reloc_plt(Obj_Entry *obj)
* * LD_BIND_NOW was set - force relocation for all jump slots
* */
int
reloc_jmpslots(Obj_Entry *obj, RtldLockState *lockstate)
reloc_jmpslots(Obj_Entry *obj, int flags, RtldLockState *lockstate)
{
const Obj_Entry *defobj;
const Elf_Rel *rellim;
Expand All @@ -381,7 +384,7 @@ reloc_jmpslots(Obj_Entry *obj, RtldLockState *lockstate)
assert(ELF_R_TYPE(rel->r_info) == R_ARM_JUMP_SLOT);
where = (Elf_Addr *)(obj->relocbase + rel->r_offset);
def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj,
true, NULL, lockstate);
SYMLOOK_IN_PLT | flags, NULL, lockstate);
if (def == NULL) {
dbg("reloc_jmpslots: sym not found");
return (-1);
Expand All @@ -406,7 +409,8 @@ reloc_iresolve(Obj_Entry *obj, struct Struct_RtldLockState *lockstate)
}

int
reloc_gnu_ifunc(Obj_Entry *obj, struct Struct_RtldLockState *lockstate)
reloc_gnu_ifunc(Obj_Entry *obj, int flags,
struct Struct_RtldLockState *lockstate)
{

/* XXX not implemented */
Expand Down
30 changes: 16 additions & 14 deletions libexec/rtld-elf/i386/reloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ do_copy_relocations(Obj_Entry *dstobj)
size = dstsym->st_size;
symlook_init(&req, name);
req.ventry = fetch_ventry(dstobj, ELF_R_SYM(rel->r_info));
req.flags = SYMLOOK_EARLY;

for (srcobj = dstobj->next; srcobj != NULL; srcobj = srcobj->next) {
res = symlook_obj(&req, srcobj);
Expand Down Expand Up @@ -119,7 +120,8 @@ init_pltgot(Obj_Entry *obj)

/* Process the non-PLT relocations. */
int
reloc_non_plt(Obj_Entry *obj, Obj_Entry *obj_rtld, RtldLockState *lockstate)
reloc_non_plt(Obj_Entry *obj, Obj_Entry *obj_rtld, int flags,
RtldLockState *lockstate)
{
const Elf_Rel *rellim;
const Elf_Rel *rel;
Expand Down Expand Up @@ -151,7 +153,7 @@ reloc_non_plt(Obj_Entry *obj, Obj_Entry *obj_rtld, RtldLockState *lockstate)
const Obj_Entry *defobj;

def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj,
false, cache, lockstate);
flags, cache, lockstate);
if (def == NULL)
goto done;

Expand All @@ -170,7 +172,7 @@ reloc_non_plt(Obj_Entry *obj, Obj_Entry *obj_rtld, RtldLockState *lockstate)
const Obj_Entry *defobj;

def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj,
false, cache, lockstate);
flags, cache, lockstate);
if (def == NULL)
goto done;

Expand Down Expand Up @@ -200,7 +202,7 @@ reloc_non_plt(Obj_Entry *obj, Obj_Entry *obj_rtld, RtldLockState *lockstate)
const Obj_Entry *defobj;

def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj,
false, cache, lockstate);
flags, cache, lockstate);
if (def == NULL)
goto done;

Expand All @@ -220,7 +222,7 @@ reloc_non_plt(Obj_Entry *obj, Obj_Entry *obj_rtld, RtldLockState *lockstate)
Elf_Addr add;

def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj,
false, cache, lockstate);
flags, cache, lockstate);
if (def == NULL)
goto done;

Expand Down Expand Up @@ -253,7 +255,7 @@ reloc_non_plt(Obj_Entry *obj, Obj_Entry *obj_rtld, RtldLockState *lockstate)
const Obj_Entry *defobj;

def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj,
false, cache, lockstate);
flags, cache, lockstate);
if (def == NULL)
goto done;

Expand All @@ -267,7 +269,7 @@ reloc_non_plt(Obj_Entry *obj, Obj_Entry *obj_rtld, RtldLockState *lockstate)
const Obj_Entry *defobj;

def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj,
false, cache, lockstate);
flags, cache, lockstate);
if (def == NULL)
goto done;

Expand All @@ -286,7 +288,7 @@ reloc_non_plt(Obj_Entry *obj, Obj_Entry *obj_rtld, RtldLockState *lockstate)
done:
if (cache != NULL)
free(cache);
return(r);
return (r);
}

/* Process the PLT relocations. */
Expand Down Expand Up @@ -322,7 +324,7 @@ reloc_plt(Obj_Entry *obj)

/* Relocate the jump slots in an object. */
int
reloc_jmpslots(Obj_Entry *obj, RtldLockState *lockstate)
reloc_jmpslots(Obj_Entry *obj, int flags, RtldLockState *lockstate)
{
const Elf_Rel *rellim;
const Elf_Rel *rel;
Expand All @@ -338,8 +340,8 @@ reloc_jmpslots(Obj_Entry *obj, RtldLockState *lockstate)
switch (ELF_R_TYPE(rel->r_info)) {
case R_386_JMP_SLOT:
where = (Elf_Addr *)(obj->relocbase + rel->r_offset);
def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj, true, NULL,
lockstate);
def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj,
SYMLOOK_IN_PLT | flags, NULL, lockstate);
if (def == NULL)
return (-1);
if (ELF_ST_TYPE(def->st_info) == STT_GNU_IFUNC) {
Expand Down Expand Up @@ -390,7 +392,7 @@ reloc_iresolve(Obj_Entry *obj, RtldLockState *lockstate)
}

int
reloc_gnu_ifunc(Obj_Entry *obj, RtldLockState *lockstate)
reloc_gnu_ifunc(Obj_Entry *obj, int flags, RtldLockState *lockstate)
{
const Elf_Rel *rellim;
const Elf_Rel *rel;
Expand All @@ -406,8 +408,8 @@ reloc_gnu_ifunc(Obj_Entry *obj, RtldLockState *lockstate)
switch (ELF_R_TYPE(rel->r_info)) {
case R_386_JMP_SLOT:
where = (Elf_Addr *)(obj->relocbase + rel->r_offset);
def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj, true, NULL,
lockstate);
def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj,
SYMLOOK_IN_PLT | flags, NULL, lockstate);
if (def == NULL)
return (-1);
if (ELF_ST_TYPE(def->st_info) != STT_GNU_IFUNC)
Expand Down
Loading

0 comments on commit 082f959

Please sign in to comment.