about summary refs log tree commit diff
path: root/elf
diff options
context:
space:
mode:
Diffstat (limited to 'elf')
-rw-r--r--elf/dl-open.c2
-rw-r--r--elf/dl-reloc.c19
-rw-r--r--elf/rtld.c12
3 files changed, 27 insertions, 6 deletions
diff --git a/elf/dl-open.c b/elf/dl-open.c
index 12a4f8b853..90c1180a8c 100644
--- a/elf/dl-open.c
+++ b/elf/dl-open.c
@@ -494,6 +494,8 @@ TLS generation counter wrapped!  Please report this."));
 	}
     }
 
+  _dl_relocate_apply_relro (new);
+
   /* Notify the debugger all new objects have been relocated.  */
   if (relocation_in_progress)
     LIBC_PROBE (reloc_complete, 3, args->nsid, r, new);
diff --git a/elf/dl-reloc.c b/elf/dl-reloc.c
index e7fb8da276..f1f8e4ad65 100644
--- a/elf/dl-reloc.c
+++ b/elf/dl-reloc.c
@@ -295,14 +295,8 @@ _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[],
 
       textrels = textrels->next;
     }
-
-  /* In case we can protect the data now that the relocations are
-     done, do it.  */
-  if (l->l_relro_size != 0)
-    _dl_protect_relro (l);
 }
 
-
 void
 _dl_protect_relro (struct link_map *l)
 {
@@ -323,6 +317,19 @@ cannot apply additional memory protection after relocation");
 }
 
 void
+_dl_relocate_apply_relro (struct link_map *new)
+{
+  struct link_map **lp = new->l_searchlist.r_list;
+  struct link_map **end = lp + new->l_searchlist.r_nlist;
+  for (; lp < end; ++lp)
+    {
+      struct link_map *l = *lp;
+      if (l->l_relro_size)
+	_dl_protect_relro (l);
+    }
+}
+
+void
 __attribute_noinline__
 _dl_reloc_bad_type (struct link_map *map, unsigned int type, int plt)
 {
diff --git a/elf/rtld.c b/elf/rtld.c
index c9490ff694..0b07656947 100644
--- a/elf/rtld.c
+++ b/elf/rtld.c
@@ -591,6 +591,7 @@ struct version_check_args
   int dotrace;
 };
 
+/* Callback function used during tracing.  */
 static void
 relocate_doit (void *a)
 {
@@ -2314,6 +2315,17 @@ ERROR: '%s': cannot process note segment.\n", _dl_argv[0]);
       rtld_timer_accum (&relocate_time, start);
     }
 
+  /* Activate RELRO protection.  In the prelink case, this was already
+     done earlier.  */
+  if (! prelinked)
+    {
+      /* Make sure that this covers the dynamic linker as well.
+	 TODO: rtld_multiple_ref is always true because libc.so needs
+	 the dynamic linker internally.  */
+      assert (rtld_multiple_ref);
+      _dl_relocate_apply_relro (main_map);
+    }
+
   /* Do any necessary cleanups for the startup OS interface code.
      We do these now so that no calls are made after rtld re-relocation
      which might be resolved to different functions than we expect.