On Mon, May 24, 2021 at 4:59 AM Klemens Nanni <[email protected]> wrote:

> When tinkering with ld.so crashes due to file corruption the other day
> I tested a few changes but did not want to replace /usr/libexec/ld.so
> and since recompiling executable to change their interpreter is not
> always an option, I went for https://github.com/NixOS/patchelf which
> allows me to manipulate executables in place.
>
> The tool works just fine and as a byproduct rearanges program headers;
> that in itself is fine except our run-time link-editor is not happy with
> such valid executables:
>
>
>  ELF mandates nothing but the file header be at a fixed location, hence
>  ld.so(1) must not assume any specific order for headers, segments, etc.
>

(Not quite: it does place ordering requirements in some specific cases,
such as that PT_INTERP and PT_PHDR, if present, must appear before any
PT_LOAD segments in the program header, and that PT_LOAD segments must
appear in p_vaddr order.)


 Looping over the program header table to parse segment headers,
>  _dl_boot() creates the executable object upon DYNAMIC and expects it to
>  be set upon GNU_RELRO, resulting in a NULL dereference iff that order is
>  reversed.
>
>  Store relocation bits in temporary variables and update the executable
>  object once all segment headers are parsed to lift this dependency.
>
>  Under __mips__ _dl_boot() later on uses the same temporary variable, so
>  move nothing but the declaration out of MI code so as to not alter the
>  MD code's logic/behaviour.
>
>
> This fix is needed for the following work on OpenBSD:
>
>         $ patchelf --set-interpreter $PWD/obj/ld.so ./my-ldso-test
>         $ readelf -l ./my-ldso-test | grep interpreter
>               [Requesting program interpreter: /usr/src/libexec/
> ld.so/obj/ld.so]
>         $ ./my-ldso-test
>         it works!
>
> amd64 and arm64 regress is happy and all my patched executables work
> with this.
>
> Feedback? Objections? OK?
>
> diff d7231fb4fb547dd287a884c56ae7c8b10f9145fe
> f023dbe355bef379d55eb93eddbb2702559d5bdb
> blob - 18bd30af759bffbc4e3fbfee9ffc29906f0d1bb0
> blob + b66dbb169aad9afffa1283d480ad9276aff9072a
> --- libexec/ld.so/loader.c
> +++ libexec/ld.so/loader.c
> @@ -464,6 +464,7 @@ _dl_boot(const char **argv, char **envp, const long dy
>         int failed;
>         struct dep_node *n;
>         Elf_Addr minva, maxva, exe_loff, exec_end, cur_exec_end;
> +       Elf_Addr relro_addr = 0, relro_size = 0;
>         Elf_Phdr *ptls = NULL;
>         int align;
>
> @@ -552,8 +553,8 @@ _dl_boot(const char **argv, char **envp, const long dy
>                         ptls = phdp;
>                         break;
>                 case PT_GNU_RELRO:
> -                       exe_obj->relro_addr = phdp->p_vaddr + exe_loff;
> -                       exe_obj->relro_size = phdp->p_memsz;
> +                       relro_addr = phdp->p_vaddr + exe_loff;
> +                       relro_size = phdp->p_memsz;
>                         break;
>                 }
>                 phdp++;
> @@ -561,6 +562,8 @@ _dl_boot(const char **argv, char **envp, const long dy
>         exe_obj->load_list = load_list;
>         exe_obj->obj_flags |= DF_1_GLOBAL;
>         exe_obj->load_size = maxva - minva;
> +       exe_obj->relro_addr = relro_addr;
> +       exe_obj->relro_size = relro_size;
>         _dl_set_sod(exe_obj->load_name, &exe_obj->sod);
>
>  #ifdef __i386__
> @@ -638,7 +641,7 @@ _dl_boot(const char **argv, char **envp, const long dy
>                 debug_map->r_ldbase = dyn_loff;
>                 _dl_debug_map = debug_map;
>  #ifdef __mips__
> -               Elf_Addr relro_addr = exe_obj->relro_addr;
> +               relro_addr = exe_obj->relro_addr;
>                 if (dynp->d_tag == DT_DEBUG &&
>                     ((Elf_Addr)map_link + sizeof(*map_link) <= relro_addr
> ||
>                      (Elf_Addr)map_link >= relro_addr +
> exe_obj->relro_size)) {
>
>
ok guenther@

(This still assumes PT_GNU_RELRO comes after PT_PHDR, for exe_loff, but I
suspect even patchelf wouldn't screw with that.)

Reply via email to