summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Weimer <fweimer@redhat.com>2017-01-24 13:06:05 +0100
committerFlorian Weimer <fweimer@redhat.com>2017-01-24 13:06:05 +0100
commitfeb6d6b394bd0ebd74d3f4370394dfb94b1f011a (patch)
tree74217da91017677610cf7e0a4d141e15c24be3a5
parentf3bef6a748097d02d196df247f7b292c7b83744c (diff)
downloadglibc-feb6d6b394bd0ebd74d3f4370394dfb94b1f011a.tar.gz
ld.so: Defer applying RELRO protection
This is a prerequisite of a future change which applies additional cross-object relocations after _dl_relocate_object has been called.
-rw-r--r--ChangeLog10
-rw-r--r--elf/dl-open.c2
-rw-r--r--elf/dl-reloc.c20
-rw-r--r--elf/rtld.c12
-rw-r--r--sysdeps/generic/ldsodefs.h6
5 files changed, 44 insertions, 6 deletions
diff --git a/ChangeLog b/ChangeLog
index 1518c7f9ad..dea9779520 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+2017-01-24 Florian Weimer <fweimer@redhat.com>
+
+ * sysdeps/generic/ldsodefs.h (_dl_relocate_apply_relro): Declare.
+ * elf/rtld.c (relocate_doit): Add comment.
+ (dl_main): Call _dl_relocate_apply_relro.
+ * elf/dl-open.c (dl_open_worker): Likewise.
+ * elf/dl-reloc.c (_dl_relocate_object): Do not call
+ _dl_protect_relro.
+ (_dl_relocate_apply_relro): New function.
+
2017-01-20 DJ Delorie <dj@redhat.com>
* elf/dl-tunables.c (tunable_set_val_if_valid_range): Split into ...
diff --git a/elf/dl-open.c b/elf/dl-open.c
index cec54db413..d238fb2cc5 100644
--- a/elf/dl-open.c
+++ b/elf/dl-open.c
@@ -552,6 +552,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 52311f0278..926056269a 100644
--- a/elf/dl-reloc.c
+++ b/elf/dl-reloc.c
@@ -306,14 +306,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 internal_function
_dl_protect_relro (struct link_map *l)
{
@@ -333,6 +327,20 @@ cannot apply additional memory protection after relocation");
}
}
+void internal_function
+_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
internal_function __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 a036ece956..16119e8c31 100644
--- a/elf/rtld.c
+++ b/elf/rtld.c
@@ -465,6 +465,7 @@ struct version_check_args
int dotrace;
};
+/* Callback function used during tracing. */
static void
relocate_doit (void *a)
{
@@ -2113,6 +2114,17 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
HP_TIMING_ACCUM_NT (relocate_time, add);
}
+ /* 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.
diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
index f26a8b2051..469f33e857 100644
--- a/sysdeps/generic/ldsodefs.h
+++ b/sysdeps/generic/ldsodefs.h
@@ -863,6 +863,12 @@ extern void _dl_relocate_object (struct link_map *map,
int reloc_mode, int consider_profiling)
attribute_hidden;
+/* Apply RELRO protection for all objects on the search path of NEW.
+ This is the final step of relocation processing for freshly loaded
+ objects. */
+void _dl_relocate_apply_relro (struct link_map *new)
+ internal_function attribute_hidden;
+
/* Protect PT_GNU_RELRO area. */
extern void _dl_protect_relro (struct link_map *map)
internal_function attribute_hidden;