mirror of
https://github.com/freebsd/freebsd-src.git
synced 2024-11-30 21:43:34 +00:00
Implement LD_BIND_NOT knob for rtld.
From the manpage: When set to a nonempty string, prevents modifications of the PLT slots when doing bindings. As result, each call of the PLT-resolved function is resolved. In combination with debug output, this provides complete account of all bind actions at runtime. Same feature exists on Linux and Solaris. Sponsored by: The FreeBSD Foundation MFC after: 2 weeks
This commit is contained in:
parent
d10e4cd0c0
commit
e35ddbe448
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=315331
@ -298,10 +298,9 @@ reloc_jmpslot(Elf_Addr *where, Elf_Addr target, const Obj_Entry *defobj,
|
||||
|
||||
assert(ELF_R_TYPE(rel->r_info) == R_AARCH64_JUMP_SLOT);
|
||||
|
||||
if (*where != target)
|
||||
if (*where != target && !ld_bind_not)
|
||||
*where = target;
|
||||
|
||||
return target;
|
||||
return (target);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -47,9 +47,8 @@ struct Struct_Obj_Entry;
|
||||
})
|
||||
|
||||
Elf_Addr reloc_jmpslot(Elf_Addr *where, Elf_Addr target,
|
||||
const struct Struct_Obj_Entry *defobj,
|
||||
const struct Struct_Obj_Entry *obj,
|
||||
const Elf_Rel *rel);
|
||||
const struct Struct_Obj_Entry *defobj, const struct Struct_Obj_Entry *obj,
|
||||
const Elf_Rel *rel);
|
||||
|
||||
#define make_function_pointer(def, defobj) \
|
||||
((defobj)->relocbase + (def)->st_value)
|
||||
|
@ -387,6 +387,20 @@ reloc_jmpslots(Obj_Entry *obj, int flags, RtldLockState *lockstate)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Fixup the jump slot at "where" to transfer control to "target". */
|
||||
Elf_Addr
|
||||
reloc_jmpslot(Elf_Addr *where, Elf_Addr target,
|
||||
const struct Struct_Obj_Entry *obj, const struct Struct_Obj_Entry *refobj,
|
||||
const Elf_Rel *rel)
|
||||
{
|
||||
#ifdef dbg
|
||||
dbg("reloc_jmpslot: *%p = %p", where, (void *)target);
|
||||
#endif
|
||||
if (!ld_bind_not)
|
||||
*where = target;
|
||||
return (target);
|
||||
}
|
||||
|
||||
int
|
||||
reloc_iresolve(Obj_Entry *obj, RtldLockState *lockstate)
|
||||
{
|
||||
|
@ -38,21 +38,11 @@ struct Struct_Obj_Entry;
|
||||
Elf_Dyn *rtld_dynamic_addr(void);
|
||||
#define rtld_dynamic(obj) rtld_dynamic_addr()
|
||||
|
||||
/* Fixup the jump slot at "where" to transfer control to "target". */
|
||||
static inline Elf_Addr
|
||||
reloc_jmpslot(Elf_Addr *where, Elf_Addr target,
|
||||
const struct Struct_Obj_Entry *obj,
|
||||
const struct Struct_Obj_Entry *refobj, const Elf_Rel *rel)
|
||||
{
|
||||
#ifdef dbg
|
||||
dbg("reloc_jmpslot: *%p = %p", (void *)(where),
|
||||
(void *)(target));
|
||||
#endif
|
||||
(*(Elf_Addr *)(where) = (Elf_Addr)(target));
|
||||
return target;
|
||||
}
|
||||
Elf_Addr reloc_jmpslot(Elf_Addr *where, Elf_Addr target,
|
||||
const struct Struct_Obj_Entry *obj, const struct Struct_Obj_Entry *refobj,
|
||||
const Elf_Rel *rel);
|
||||
|
||||
#define make_function_pointer(def, defobj) \
|
||||
#define make_function_pointer(def, defobj) \
|
||||
((defobj)->relocbase + (def)->st_value)
|
||||
|
||||
#define call_initfini_pointer(obj, target) \
|
||||
|
@ -468,15 +468,14 @@ reloc_gnu_ifunc(Obj_Entry *obj, int flags,
|
||||
|
||||
Elf_Addr
|
||||
reloc_jmpslot(Elf_Addr *where, Elf_Addr target, const Obj_Entry *defobj,
|
||||
const Obj_Entry *obj, const Elf_Rel *rel)
|
||||
const Obj_Entry *obj, const Elf_Rel *rel)
|
||||
{
|
||||
|
||||
assert(ELF_R_TYPE(rel->r_info) == R_ARM_JUMP_SLOT);
|
||||
|
||||
if (*where != target)
|
||||
if (*where != target && !ld_bind_not)
|
||||
*where = target;
|
||||
|
||||
return target;
|
||||
return (target);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -38,9 +38,8 @@ struct Struct_Obj_Entry;
|
||||
#define rtld_dynamic(obj) (&_DYNAMIC)
|
||||
|
||||
Elf_Addr reloc_jmpslot(Elf_Addr *where, Elf_Addr target,
|
||||
const struct Struct_Obj_Entry *defobj,
|
||||
const struct Struct_Obj_Entry *obj,
|
||||
const Elf_Rel *rel);
|
||||
const struct Struct_Obj_Entry *defobj, const struct Struct_Obj_Entry *obj,
|
||||
const Elf_Rel *rel);
|
||||
|
||||
#define make_function_pointer(def, defobj) \
|
||||
((defobj)->relocbase + (def)->st_value)
|
||||
|
@ -344,6 +344,20 @@ reloc_jmpslots(Obj_Entry *obj, int flags, RtldLockState *lockstate)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Fixup the jump slot at "where" to transfer control to "target". */
|
||||
Elf_Addr
|
||||
reloc_jmpslot(Elf_Addr *where, Elf_Addr target,
|
||||
const struct Struct_Obj_Entry *obj, const struct Struct_Obj_Entry *refobj,
|
||||
const Elf_Rel *rel)
|
||||
{
|
||||
#ifdef dbg
|
||||
dbg("reloc_jmpslot: *%p = %p", where, (void *)target);
|
||||
#endif
|
||||
if (!ld_bind_not)
|
||||
*where = target;
|
||||
return (target);
|
||||
}
|
||||
|
||||
int
|
||||
reloc_iresolve(Obj_Entry *obj, RtldLockState *lockstate)
|
||||
{
|
||||
|
@ -38,21 +38,11 @@ struct Struct_Obj_Entry;
|
||||
#define rtld_dynamic(obj) \
|
||||
((const Elf_Dyn *)((obj)->relocbase + (Elf_Addr)&_DYNAMIC))
|
||||
|
||||
/* Fixup the jump slot at "where" to transfer control to "target". */
|
||||
static inline Elf_Addr
|
||||
reloc_jmpslot(Elf_Addr *where, Elf_Addr target,
|
||||
const struct Struct_Obj_Entry *obj,
|
||||
const struct Struct_Obj_Entry *refobj, const Elf_Rel *rel)
|
||||
{
|
||||
#ifdef dbg
|
||||
dbg("reloc_jmpslot: *%p = %p", (void *)(where),
|
||||
(void *)(target));
|
||||
#endif
|
||||
(*(Elf_Addr *)(where) = (Elf_Addr)(target));
|
||||
return target;
|
||||
}
|
||||
Elf_Addr reloc_jmpslot(Elf_Addr *where, Elf_Addr target,
|
||||
const struct Struct_Obj_Entry *obj, const struct Struct_Obj_Entry *refobj,
|
||||
const Elf_Rel *rel);
|
||||
|
||||
#define make_function_pointer(def, defobj) \
|
||||
#define make_function_pointer(def, defobj) \
|
||||
((defobj)->relocbase + (def)->st_value)
|
||||
|
||||
#define call_initfini_pointer(obj, target) \
|
||||
|
@ -274,7 +274,8 @@ _mips_rtld_bind(Obj_Entry *obj, Elf_Size reloff)
|
||||
obj->path,
|
||||
(intmax_t)reloff, defobj->strtab + def->st_name,
|
||||
(void *)*where, (void *)target);
|
||||
*where = target;
|
||||
if (!ld_bind_not)
|
||||
*where = target;
|
||||
lock_release(rtld_bind_lock, &lockstate);
|
||||
return (Elf_Addr)target;
|
||||
}
|
||||
|
@ -39,9 +39,8 @@ struct Struct_Obj_Entry;
|
||||
#define rtld_dynamic(obj) (&_DYNAMIC)
|
||||
|
||||
Elf_Addr reloc_jmpslot(Elf_Addr *where, Elf_Addr target,
|
||||
const struct Struct_Obj_Entry *defobj,
|
||||
const struct Struct_Obj_Entry *obj,
|
||||
const Elf_Rel *rel);
|
||||
const struct Struct_Obj_Entry *defobj, const struct Struct_Obj_Entry *obj,
|
||||
const Elf_Rel *rel);
|
||||
|
||||
#define make_function_pointer(def, defobj) \
|
||||
((defobj)->relocbase + (def)->st_value)
|
||||
|
@ -468,7 +468,7 @@ reloc_jmpslots(Obj_Entry *obj, int flags, RtldLockState *lockstate)
|
||||
*/
|
||||
Elf_Addr
|
||||
reloc_jmpslot(Elf_Addr *wherep, Elf_Addr target, const Obj_Entry *defobj,
|
||||
const Obj_Entry *obj, const Elf_Rel *rel)
|
||||
const Obj_Entry *obj, const Elf_Rel *rel)
|
||||
{
|
||||
Elf_Addr offset;
|
||||
const Elf_Rela *rela = (const Elf_Rela *) rel;
|
||||
@ -476,6 +476,9 @@ reloc_jmpslot(Elf_Addr *wherep, Elf_Addr target, const Obj_Entry *defobj,
|
||||
dbg(" reloc_jmpslot: where=%p, target=%p",
|
||||
(void *)wherep, (void *)target);
|
||||
|
||||
if (ld_bind_not)
|
||||
goto out;
|
||||
|
||||
/*
|
||||
* At the PLT entry pointed at by `wherep', construct
|
||||
* a direct transfer to the now fully resolved function
|
||||
@ -519,6 +522,7 @@ reloc_jmpslot(Elf_Addr *wherep, Elf_Addr target, const Obj_Entry *defobj,
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
return (target);
|
||||
}
|
||||
|
||||
|
@ -38,9 +38,8 @@ struct Struct_Obj_Entry;
|
||||
#define rtld_dynamic(obj) (&_DYNAMIC)
|
||||
|
||||
Elf_Addr reloc_jmpslot(Elf_Addr *where, Elf_Addr target,
|
||||
const struct Struct_Obj_Entry *defobj,
|
||||
const struct Struct_Obj_Entry *obj,
|
||||
const Elf_Rel *rel);
|
||||
const struct Struct_Obj_Entry *defobj, const struct Struct_Obj_Entry *obj,
|
||||
const Elf_Rel *rel);
|
||||
|
||||
#define make_function_pointer(def, defobj) \
|
||||
((defobj)->relocbase + (def)->st_value)
|
||||
|
@ -433,7 +433,7 @@ reloc_jmpslots(Obj_Entry *obj, int flags, RtldLockState *lockstate)
|
||||
*/
|
||||
Elf_Addr
|
||||
reloc_jmpslot(Elf_Addr *wherep, Elf_Addr target, const Obj_Entry *defobj,
|
||||
const Obj_Entry *obj, const Elf_Rel *rel)
|
||||
const Obj_Entry *obj, const Elf_Rel *rel)
|
||||
{
|
||||
|
||||
/*
|
||||
@ -447,6 +447,9 @@ reloc_jmpslot(Elf_Addr *wherep, Elf_Addr target, const Obj_Entry *defobj,
|
||||
(void *)wherep, (void *)target, *(Elf_Addr *)target,
|
||||
(Elf_Addr)defobj->relocbase);
|
||||
|
||||
if (ld_bind_not)
|
||||
goto out;
|
||||
|
||||
/*
|
||||
* For the trampoline, the second two elements of the function
|
||||
* descriptor are unused, so we are fine replacing those at any time
|
||||
@ -476,11 +479,13 @@ reloc_jmpslot(Elf_Addr *wherep, Elf_Addr target, const Obj_Entry *defobj,
|
||||
((struct funcdesc *)(wherep))->toc +=
|
||||
(Elf_Addr)defobj->relocbase;
|
||||
}
|
||||
out:
|
||||
#else
|
||||
dbg(" reloc_jmpslot: where=%p, target=%p", (void *)wherep,
|
||||
(void *)target);
|
||||
|
||||
*wherep = target;
|
||||
if (!ld_bind_not)
|
||||
*wherep = target;
|
||||
#endif
|
||||
|
||||
return (target);
|
||||
|
@ -38,9 +38,8 @@ struct Struct_Obj_Entry;
|
||||
#define rtld_dynamic(obj) (&_DYNAMIC)
|
||||
|
||||
Elf_Addr reloc_jmpslot(Elf_Addr *where, Elf_Addr target,
|
||||
const struct Struct_Obj_Entry *defobj,
|
||||
const struct Struct_Obj_Entry *obj,
|
||||
const Elf_Rel *rel);
|
||||
const struct Struct_Obj_Entry *defobj, const struct Struct_Obj_Entry *obj,
|
||||
const Elf_Rel *rel);
|
||||
|
||||
#define make_function_pointer(def, defobj) \
|
||||
((defobj)->relocbase + (def)->st_value)
|
||||
|
@ -226,10 +226,9 @@ reloc_jmpslot(Elf_Addr *where, Elf_Addr target, const Obj_Entry *defobj,
|
||||
|
||||
assert(ELF_R_TYPE(rel->r_info) == R_RISCV_JUMP_SLOT);
|
||||
|
||||
if (*where != target)
|
||||
if (*where != target && !ld_bind_not)
|
||||
*where = target;
|
||||
|
||||
return target;
|
||||
return (target);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -54,9 +54,8 @@ uint64_t set_gp(struct Struct_Obj_Entry *obj);
|
||||
})
|
||||
|
||||
Elf_Addr reloc_jmpslot(Elf_Addr *where, Elf_Addr target,
|
||||
const struct Struct_Obj_Entry *defobj,
|
||||
const struct Struct_Obj_Entry *obj,
|
||||
const Elf_Rel *rel);
|
||||
const struct Struct_Obj_Entry *defobj, const struct Struct_Obj_Entry *obj,
|
||||
const Elf_Rel *rel);
|
||||
|
||||
#define make_function_pointer(def, defobj) \
|
||||
((defobj)->relocbase + (def)->st_value)
|
||||
|
@ -28,7 +28,7 @@
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd June 20, 2014
|
||||
.Dd March 16, 2017
|
||||
.Dt RTLD 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -199,6 +199,12 @@ This is intended for use within
|
||||
sandboxes, when global namespaces such as the filesystem are unavailable.
|
||||
It is consulted just after LD_LIBRARY_PATH.
|
||||
This variable is unset for set-user-ID and set-group-ID programs.
|
||||
.It Ev LD_BIND_NOT
|
||||
When set to a nonempty string, prevents modifications of the PLT slots when
|
||||
doing bindings.
|
||||
As result, each call of the PLT-resolved function is resolved.
|
||||
In combination with debug output, this provides complete account of
|
||||
all bind actions at runtime.
|
||||
.It Ev LD_BIND_NOW
|
||||
When set to a nonempty string, causes
|
||||
.Nm
|
||||
|
@ -178,6 +178,7 @@ static char *libmap_override; /* Maps to use in addition to libmap.conf */
|
||||
static bool trust; /* False for setuid and setgid programs */
|
||||
static bool dangerous_ld_env; /* True if environment variables have been
|
||||
used to affect the libraries loaded */
|
||||
bool ld_bind_not; /* Disable PLT update */
|
||||
static char *ld_bind_now; /* Environment variable for immediate binding */
|
||||
static char *ld_debug; /* Environment variable for debugging */
|
||||
static char *ld_library_path; /* Environment variable for search path */
|
||||
@ -416,6 +417,9 @@ _rtld(Elf_Addr *sp, func_ptr_type *exit_proc, Obj_Entry **objp)
|
||||
md_abi_variant_hook(aux_info);
|
||||
|
||||
ld_bind_now = getenv(_LD("BIND_NOW"));
|
||||
if (ld_bind_now == NULL)
|
||||
ld_bind_not = getenv(_LD("BIND_NOT")) != NULL;
|
||||
|
||||
/*
|
||||
* If the process is tainted, then we un-set the dangerous environment
|
||||
* variables. The process will be marked as tainted until setuid(2)
|
||||
|
@ -358,6 +358,7 @@ void *malloc_aligned(size_t size, size_t align);
|
||||
void free_aligned(void *ptr);
|
||||
extern Elf_Addr _GLOBAL_OFFSET_TABLE_[];
|
||||
extern Elf_Sym sym_zero; /* For resolving undefined weak refs. */
|
||||
extern bool ld_bind_not;
|
||||
|
||||
void dump_relocations(Obj_Entry *);
|
||||
void dump_obj_relocations(Obj_Entry *);
|
||||
|
@ -581,7 +581,9 @@ reloc_jmpslot(Elf_Addr *wherep, Elf_Addr target, const Obj_Entry *obj,
|
||||
Elf_Addr offset;
|
||||
Elf_Word *where;
|
||||
|
||||
if (rela - refobj->pltrela < 32764) {
|
||||
if (ld_bind_not) {
|
||||
/* Skip any PLT modifications */
|
||||
} else if (rela - refobj->pltrela < 32764) {
|
||||
/*
|
||||
* At the PLT entry pointed at by `where', we now construct
|
||||
* a direct transfer to the now fully resolved function
|
||||
|
@ -39,9 +39,8 @@ Elf_Dyn *rtld_dynamic_addr(void);
|
||||
#define rtld_dynamic(obj) rtld_dynamic_addr()
|
||||
|
||||
Elf_Addr reloc_jmpslot(Elf_Addr *, Elf_Addr,
|
||||
const struct Struct_Obj_Entry *,
|
||||
const struct Struct_Obj_Entry *,
|
||||
const Elf_Rel *);
|
||||
const struct Struct_Obj_Entry *, const struct Struct_Obj_Entry *,
|
||||
const Elf_Rel *);
|
||||
|
||||
#define make_function_pointer(def, defobj) \
|
||||
((defobj)->relocbase + (def)->st_value)
|
||||
|
Loading…
Reference in New Issue
Block a user