Add support for RELR relocations in the executable and share objects.
authorguenther <guenther@openbsd.org>
Fri, 12 Nov 2021 22:28:13 +0000 (22:28 +0000)
committerguenther <guenther@openbsd.org>
Fri, 12 Nov 2021 22:28:13 +0000 (22:28 +0000)
This doesn't affect ld.so's self-reloc, which still requires DT_REL/DT_RELA

ok kettenis@

libexec/ld.so/loader.c
libexec/ld.so/resolve.c
libexec/ld.so/resolve.h

index db66346..2063098 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: loader.c,v 1.192 2021/05/25 17:01:36 kn Exp $ */
+/*     $OpenBSD: loader.c,v 1.193 2021/11/12 22:28:13 guenther Exp $ */
 
 /*
  * Copyright (c) 1998 Per Fogelstrom, Opsycon AB
@@ -61,6 +61,7 @@ void _dl_call_init_recurse(elf_object_t *object, int initfirst);
 void _dl_clean_boot(void);
 static inline void unprotect_if_textrel(elf_object_t *_object);
 static inline void reprotect_if_textrel(elf_object_t *_object);
+static void _dl_rreloc(elf_object_t *_object);
 
 int _dl_pagesz __relro = 4096;
 int _dl_bindnow __relro = 0;
@@ -721,6 +722,7 @@ _dl_rtld(elf_object_t *object)
         * Do relocation information first, then GOT.
         */
        unprotect_if_textrel(object);
+       _dl_rreloc(object);
        fails =_dl_md_reloc(object, DT_REL, DT_RELSZ);
        fails += _dl_md_reloc(object, DT_RELA, DT_RELASZ);
        reprotect_if_textrel(object);
@@ -947,3 +949,35 @@ reprotect_if_textrel(elf_object_t *object)
                }
        }
 }
+
+static void
+_dl_rreloc(elf_object_t *object)
+{
+       const Elf_Relr  *reloc, *rend;
+       Elf_Addr        loff = object->obj_base;
+
+       reloc = object->dyn.relr;
+       rend  = (const Elf_Relr *)((char *)reloc + object->dyn.relrsz);
+
+       while (reloc < rend) {
+               Elf_Addr *where;
+
+               where = (Elf_Addr *)(*reloc + loff);
+               *where++ += loff;
+
+               for (reloc++; reloc < rend && (*reloc & 1); reloc++) {
+                       Elf_Addr bits = *reloc >> 1;
+
+                       Elf_Addr *here = where;
+                       while (bits != 0) {
+                               if (bits & 1) {
+                                       *here += loff;
+                               }
+                               bits >>= 1;
+                               here++;
+                       }
+                       where += (8 * sizeof *reloc) - 1;
+               }
+       }
+}
+
index 4d0928b..2879c33 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: resolve.c,v 1.95 2021/06/02 07:29:03 semarie Exp $ */
+/*     $OpenBSD: resolve.c,v 1.96 2021/11/12 22:28:13 guenther Exp $ */
 
 /*
  * Copyright (c) 1998 Per Fogelstrom, Opsycon AB
@@ -368,6 +368,8 @@ _dl_finalize_object(const char *objname, Elf_Dyn *dynp, Elf_Phdr *phdrp,
                object->Dyn.info[DT_FINI_ARRAY] += obase;
        if (object->Dyn.info[DT_PREINIT_ARRAY])
                object->Dyn.info[DT_PREINIT_ARRAY] += obase;
+       if (object->Dyn.info[DT_RELR])
+               object->Dyn.info[DT_RELR] += obase;
 
        if (gnu_hash) {
                Elf_Word *hashtab = (Elf_Word *)(gnu_hash + obase);
index 7c14005..6b0d36b 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: resolve.h,v 1.98 2021/06/02 07:29:03 semarie Exp $ */
+/*     $OpenBSD: resolve.h,v 1.99 2021/11/12 22:28:13 guenther Exp $ */
 
 /*
  * Copyright (c) 1998 Per Fogelstrom, Opsycon AB
@@ -47,7 +47,7 @@
 #endif
 
 /* Number of low tags that are used saved internally (0 .. DT_NUM-1) */
-#define DT_NUM (DT_PREINIT_ARRAYSZ + 1)
+#define DT_NUM (DT_RELR + 1)
 
 struct load_list {
        struct load_list *next;
@@ -132,6 +132,9 @@ struct elf_object {
                        Elf_Addr        encoding;
                        initarrayfunc   **preinit_array;
                        Elf_Addr        preinit_arraysz;
+                       Elf_Addr        unassigned;
+                       Elf_Addr        relrsz;
+                       Elf_Relr        *relr;
                } u;
        } Dyn;
 #define dyn Dyn.u