diff options
-rw-r--r-- | ChangeLog | 10 | ||||
-rw-r--r-- | elf/dl-open.c | 2 | ||||
-rw-r--r-- | elf/dl-reloc.c | 19 | ||||
-rw-r--r-- | elf/rtld.c | 12 | ||||
-rw-r--r-- | sysdeps/generic/ldsodefs.h | 5 |
5 files changed, 42 insertions, 6 deletions
diff --git a/ChangeLog b/ChangeLog index 1cb1255ab9..df296911a2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2018-06-05 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. + 2019-04-11 Florian Weimer <fweimer@redhat.com> * resolv/nss_dns/dns-network.c (getanswer_r): Do not replace root 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. diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h index b1fc5c31f9..9da0809a09 100644 --- a/sysdeps/generic/ldsodefs.h +++ b/sysdeps/generic/ldsodefs.h @@ -928,6 +928,11 @@ 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) attribute_hidden; + /* Protect PT_GNU_RELRO area. */ extern void _dl_protect_relro (struct link_map *map) attribute_hidden; |