From 2831f74217fb010469f2c93f062dfaf20ea0be8e Mon Sep 17 00:00:00 2001 From: kib Date: Wed, 29 Mar 2017 11:03:08 +0000 Subject: MFC r315331: Implement LD_BIND_NOT knob for rtld. MFC r315337: Disable LD_BIND_NOT for setugid processes. MFC r315429 (by jilles): Document that LD_BIND_NOT is unset for setugid processes. --- libexec/rtld-elf/aarch64/reloc.c | 5 ++--- libexec/rtld-elf/aarch64/rtld_machdep.h | 5 ++--- libexec/rtld-elf/amd64/reloc.c | 14 ++++++++++++++ libexec/rtld-elf/amd64/rtld_machdep.h | 18 ++++-------------- libexec/rtld-elf/arm/reloc.c | 7 +++---- libexec/rtld-elf/arm/rtld_machdep.h | 5 ++--- libexec/rtld-elf/i386/reloc.c | 14 ++++++++++++++ libexec/rtld-elf/i386/rtld_machdep.h | 18 ++++-------------- libexec/rtld-elf/mips/reloc.c | 3 ++- libexec/rtld-elf/mips/rtld_machdep.h | 5 ++--- libexec/rtld-elf/powerpc/reloc.c | 6 +++++- libexec/rtld-elf/powerpc/rtld_machdep.h | 5 ++--- libexec/rtld-elf/powerpc64/reloc.c | 9 +++++++-- libexec/rtld-elf/powerpc64/rtld_machdep.h | 5 ++--- libexec/rtld-elf/riscv/reloc.c | 5 ++--- libexec/rtld-elf/riscv/rtld_machdep.h | 5 ++--- libexec/rtld-elf/rtld.1 | 9 ++++++++- libexec/rtld-elf/rtld.c | 6 +++++- libexec/rtld-elf/rtld.h | 1 + libexec/rtld-elf/sparc64/reloc.c | 4 +++- libexec/rtld-elf/sparc64/rtld_machdep.h | 5 ++--- 21 files changed, 88 insertions(+), 66 deletions(-) (limited to 'libexec/rtld-elf') diff --git a/libexec/rtld-elf/aarch64/reloc.c b/libexec/rtld-elf/aarch64/reloc.c index 3f9de07..41f9396 100644 --- a/libexec/rtld-elf/aarch64/reloc.c +++ b/libexec/rtld-elf/aarch64/reloc.c @@ -293,10 +293,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 diff --git a/libexec/rtld-elf/aarch64/rtld_machdep.h b/libexec/rtld-elf/aarch64/rtld_machdep.h index 84f060f..eb72a61 100644 --- a/libexec/rtld-elf/aarch64/rtld_machdep.h +++ b/libexec/rtld-elf/aarch64/rtld_machdep.h @@ -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) diff --git a/libexec/rtld-elf/amd64/reloc.c b/libexec/rtld-elf/amd64/reloc.c index 10b9332..47d9522 100644 --- a/libexec/rtld-elf/amd64/reloc.c +++ b/libexec/rtld-elf/amd64/reloc.c @@ -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) { diff --git a/libexec/rtld-elf/amd64/rtld_machdep.h b/libexec/rtld-elf/amd64/rtld_machdep.h index 0a6354f..df1aff6 100644 --- a/libexec/rtld-elf/amd64/rtld_machdep.h +++ b/libexec/rtld-elf/amd64/rtld_machdep.h @@ -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) \ diff --git a/libexec/rtld-elf/arm/reloc.c b/libexec/rtld-elf/arm/reloc.c index 1b022c5..c1d50c0 100644 --- a/libexec/rtld-elf/arm/reloc.c +++ b/libexec/rtld-elf/arm/reloc.c @@ -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 diff --git a/libexec/rtld-elf/arm/rtld_machdep.h b/libexec/rtld-elf/arm/rtld_machdep.h index 2c1a2b8..5639def 100644 --- a/libexec/rtld-elf/arm/rtld_machdep.h +++ b/libexec/rtld-elf/arm/rtld_machdep.h @@ -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) diff --git a/libexec/rtld-elf/i386/reloc.c b/libexec/rtld-elf/i386/reloc.c index 42efcf7..e97121b 100644 --- a/libexec/rtld-elf/i386/reloc.c +++ b/libexec/rtld-elf/i386/reloc.c @@ -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) { diff --git a/libexec/rtld-elf/i386/rtld_machdep.h b/libexec/rtld-elf/i386/rtld_machdep.h index 1ffdca4..ea9df63 100644 --- a/libexec/rtld-elf/i386/rtld_machdep.h +++ b/libexec/rtld-elf/i386/rtld_machdep.h @@ -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) \ diff --git a/libexec/rtld-elf/mips/reloc.c b/libexec/rtld-elf/mips/reloc.c index a3ba2f4..5dc5c79 100644 --- a/libexec/rtld-elf/mips/reloc.c +++ b/libexec/rtld-elf/mips/reloc.c @@ -259,7 +259,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; } diff --git a/libexec/rtld-elf/mips/rtld_machdep.h b/libexec/rtld-elf/mips/rtld_machdep.h index 484af1b..8536061 100644 --- a/libexec/rtld-elf/mips/rtld_machdep.h +++ b/libexec/rtld-elf/mips/rtld_machdep.h @@ -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) diff --git a/libexec/rtld-elf/powerpc/reloc.c b/libexec/rtld-elf/powerpc/reloc.c index dea564b..8d4f87c 100644 --- a/libexec/rtld-elf/powerpc/reloc.c +++ b/libexec/rtld-elf/powerpc/reloc.c @@ -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); } diff --git a/libexec/rtld-elf/powerpc/rtld_machdep.h b/libexec/rtld-elf/powerpc/rtld_machdep.h index 92bbf9a..b4e8b15 100644 --- a/libexec/rtld-elf/powerpc/rtld_machdep.h +++ b/libexec/rtld-elf/powerpc/rtld_machdep.h @@ -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) diff --git a/libexec/rtld-elf/powerpc64/reloc.c b/libexec/rtld-elf/powerpc64/reloc.c index e6198f0..eca489d 100644 --- a/libexec/rtld-elf/powerpc64/reloc.c +++ b/libexec/rtld-elf/powerpc64/reloc.c @@ -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); diff --git a/libexec/rtld-elf/powerpc64/rtld_machdep.h b/libexec/rtld-elf/powerpc64/rtld_machdep.h index 90253d7..a0fed7f 100644 --- a/libexec/rtld-elf/powerpc64/rtld_machdep.h +++ b/libexec/rtld-elf/powerpc64/rtld_machdep.h @@ -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) diff --git a/libexec/rtld-elf/riscv/reloc.c b/libexec/rtld-elf/riscv/reloc.c index 71259cd..a0fedf1 100644 --- a/libexec/rtld-elf/riscv/reloc.c +++ b/libexec/rtld-elf/riscv/reloc.c @@ -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); } /* diff --git a/libexec/rtld-elf/riscv/rtld_machdep.h b/libexec/rtld-elf/riscv/rtld_machdep.h index 4fb4947..95669ff 100644 --- a/libexec/rtld-elf/riscv/rtld_machdep.h +++ b/libexec/rtld-elf/riscv/rtld_machdep.h @@ -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) diff --git a/libexec/rtld-elf/rtld.1 b/libexec/rtld-elf/rtld.1 index a8e9d68..79f1478 100644 --- a/libexec/rtld-elf/rtld.1 +++ b/libexec/rtld-elf/rtld.1 @@ -28,7 +28,7 @@ .\" .\" $FreeBSD$ .\" -.Dd June 20, 2014 +.Dd March 16, 2017 .Dt RTLD 1 .Os .Sh NAME @@ -199,6 +199,13 @@ 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. +This variable is unset for set-user-ID and set-group-ID programs. .It Ev LD_BIND_NOW When set to a nonempty string, causes .Nm diff --git a/libexec/rtld-elf/rtld.c b/libexec/rtld-elf/rtld.c index a3def35..25d5970 100644 --- a/libexec/rtld-elf/rtld.c +++ b/libexec/rtld-elf/rtld.c @@ -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,7 @@ _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 the process is tainted, then we un-set the dangerous environment * variables. The process will be marked as tainted until setuid(2) @@ -425,7 +427,7 @@ _rtld(Elf_Addr *sp, func_ptr_type *exit_proc, Obj_Entry **objp) if (!trust) { if (unsetenv(_LD("PRELOAD")) || unsetenv(_LD("LIBMAP")) || unsetenv(_LD("LIBRARY_PATH")) || unsetenv(_LD("LIBRARY_PATH_FDS")) || - unsetenv(_LD("LIBMAP_DISABLE")) || + unsetenv(_LD("LIBMAP_DISABLE")) || unsetenv(_LD("BIND_NOT")) || unsetenv(_LD("DEBUG")) || unsetenv(_LD("ELF_HINTS_PATH")) || unsetenv(_LD("LOADFLTR")) || unsetenv(_LD("LIBRARY_PATH_RPATH"))) { _rtld_error("environment corrupt; aborting"); @@ -433,6 +435,8 @@ _rtld(Elf_Addr *sp, func_ptr_type *exit_proc, Obj_Entry **objp) } } ld_debug = getenv(_LD("DEBUG")); + if (ld_bind_now == NULL) + ld_bind_not = getenv(_LD("BIND_NOT")) != NULL; libmap_disable = getenv(_LD("LIBMAP_DISABLE")) != NULL; libmap_override = getenv(_LD("LIBMAP")); ld_library_path = getenv(_LD("LIBRARY_PATH")); diff --git a/libexec/rtld-elf/rtld.h b/libexec/rtld-elf/rtld.h index 4e48026..19fb8fc 100644 --- a/libexec/rtld-elf/rtld.h +++ b/libexec/rtld-elf/rtld.h @@ -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 *); diff --git a/libexec/rtld-elf/sparc64/reloc.c b/libexec/rtld-elf/sparc64/reloc.c index 197c66c..108af80 100644 --- a/libexec/rtld-elf/sparc64/reloc.c +++ b/libexec/rtld-elf/sparc64/reloc.c @@ -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 diff --git a/libexec/rtld-elf/sparc64/rtld_machdep.h b/libexec/rtld-elf/sparc64/rtld_machdep.h index 6e86e65..5266f8b 100644 --- a/libexec/rtld-elf/sparc64/rtld_machdep.h +++ b/libexec/rtld-elf/sparc64/rtld_machdep.h @@ -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) -- cgit v1.1