summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2015-09-09 09:16:59 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2015-09-09 09:16:59 +0000
commit2a1748ca4933cc50a719a089c87d84534980dab9 (patch)
treec4072cce733dc6108f104cb6645f12d2331198b5
parent860d1bf002d266a56987b59800a1ed7c272e7737 (diff)
For truly static binaries, force .ctors, .dtors and .got to be read-only.
This will make the segment containing those sections read-only for binaries that use the OpenBSD W^X layout, preventing W^X violations on architectures that need an executable GOT (basically BSS-PLT powerpc). ok miod@
-rw-r--r--gnu/usr.bin/binutils-2.17/ld/emultempl/elf32.em37
1 files changed, 37 insertions, 0 deletions
diff --git a/gnu/usr.bin/binutils-2.17/ld/emultempl/elf32.em b/gnu/usr.bin/binutils-2.17/ld/emultempl/elf32.em
index 1f8222a1db9..f25d2bd8df2 100644
--- a/gnu/usr.bin/binutils-2.17/ld/emultempl/elf32.em
+++ b/gnu/usr.bin/binutils-2.17/ld/emultempl/elf32.em
@@ -1109,6 +1109,22 @@ EOF
if test x"$LDEMUL_AFTER_OPEN" != xgld"$EMULATION_NAME"_after_open; then
cat >>e${EMULATION_NAME}.c <<EOF
+static void
+gld${EMULATION_NAME}_force_readonly(lang_input_statement_type *s)
+{
+ asection *sec;
+
+ if (s->the_bfd == NULL)
+ return;
+
+ sec = bfd_get_section_by_name (s->the_bfd, ".ctors");
+ if (sec)
+ sec->flags |= SEC_READONLY;
+ sec = bfd_get_section_by_name (s->the_bfd, ".dtors");
+ if (sec)
+ sec->flags |= SEC_READONLY;
+}
+
/* This is called after all the input files have been opened. */
static void
@@ -1120,6 +1136,27 @@ gld${EMULATION_NAME}_after_open (void)
if (link_info.relocatable || !link_info.executable)
return;
+ /* If we don't have a .dynamic section, we have no relocations, and
+ we can make .got, .ctors and .dtors read-only. This will make
+ the segment containing those sections to be read-only in static
+ executables. */
+ if (link_info.hash->type == bfd_link_elf_hash_table
+ && !elf_hash_table (&link_info)->dynamic_sections_created)
+ {
+ bfd *dynobj = elf_hash_table (&link_info)->dynobj;
+
+ if (dynobj != NULL)
+ {
+ asection *sec;
+
+ sec = bfd_get_section_by_name (dynobj, ".got");
+ if (sec)
+ sec->flags |= SEC_READONLY;
+ }
+
+ lang_for_each_input_file (gld${EMULATION_NAME}_force_readonly);
+ }
+
/* Get the list of files which appear in DT_NEEDED entries in
dynamic objects included in the link (often there will be none).
For each such file, we want to track down the corresponding