diff options
author | Dale Rahn <drahn@cvs.openbsd.org> | 2003-01-17 20:50:14 +0000 |
---|---|---|
committer | Dale Rahn <drahn@cvs.openbsd.org> | 2003-01-17 20:50:14 +0000 |
commit | c74953a6610ab567e0d578b0efe913e513e987ae (patch) | |
tree | fe6189df78259efcd870a8677b3d4f20437ab56f /gnu/usr.bin/binutils | |
parent | 2dd69e36ac9facfcacc4c30c34e093939131f7db (diff) |
This is a project to modify executables so that they do not have any
executable regions which are writable. If a section of an executable is
writable and executable, it is much easier for errant code to modify the
executable's behavior.
Two current areas in shared library environments which have this
critical problem are the GOT (Global Offset Table) and PLT (Procedure
Linkage Table). The PLT is required to be executable and both GOT and
PLT are writable on most architectures. On most ELF architecture
machines this would cause shared libraries to have data and BSS marked
as executable.
Padding to the linker script for programs and shared libraries/objects
to isolate the GOT and PLT into their own load sections in the
executables. This allows only the text(readonly) region and the PLT
region to be marked executable with the normal data and BSS not marked
as executable. The PLT region is still marked executable on most
architectures because the PLT lives in the "data" or "BSS" regions
and the dynamic loader will need to modify it. Since the GOT and PLT
should only ever be written by the dynamic linker, it will be modified
to mprotect those regions so that they are not writable during normal
execution. If the dynamic linker needs to modify the regions later,
(eg for lazy binding), it will mprotect the region, make the necessary
changes, and mprotect it back. Since it is possible to receive a
signal which would interrupt the program flow and perhaps cause the
dynamic linker to modify the same (or nearby) PLT references, it is now
necessary for signals to be blocked for the duration of the mprotect.
Diffstat (limited to 'gnu/usr.bin/binutils')
-rw-r--r-- | gnu/usr.bin/binutils/bfd/elf.c | 2 | ||||
-rw-r--r-- | gnu/usr.bin/binutils/ld/emulparams/elf32_sparc.sh | 2 | ||||
-rw-r--r-- | gnu/usr.bin/binutils/ld/emulparams/elf32ppc.sh | 2 | ||||
-rw-r--r-- | gnu/usr.bin/binutils/ld/emulparams/elf64_sparc.sh | 2 | ||||
-rw-r--r-- | gnu/usr.bin/binutils/ld/emulparams/elf64alpha.sh | 2 | ||||
-rw-r--r-- | gnu/usr.bin/binutils/ld/emulparams/elf_i386.sh | 1 | ||||
-rw-r--r-- | gnu/usr.bin/binutils/ld/genscripts.sh | 6 | ||||
-rw-r--r-- | gnu/usr.bin/binutils/ld/ld.h | 4 | ||||
-rw-r--r-- | gnu/usr.bin/binutils/ld/ldmain.c | 1 | ||||
-rw-r--r-- | gnu/usr.bin/binutils/ld/lexsup.c | 2 | ||||
-rw-r--r-- | gnu/usr.bin/binutils/ld/scripttempl/elf.sc | 14 |
11 files changed, 36 insertions, 2 deletions
diff --git a/gnu/usr.bin/binutils/bfd/elf.c b/gnu/usr.bin/binutils/bfd/elf.c index 0afda164edf..7b1964a7023 100644 --- a/gnu/usr.bin/binutils/bfd/elf.c +++ b/gnu/usr.bin/binutils/bfd/elf.c @@ -3100,7 +3100,7 @@ get_program_header_size (abfd) /* Assume we will need exactly two PT_LOAD segments: one for text and one for data. */ - segs = 2; + segs = 6; s = bfd_get_section_by_name (abfd, ".interp"); if (s != NULL && (s->flags & SEC_LOAD) != 0) diff --git a/gnu/usr.bin/binutils/ld/emulparams/elf32_sparc.sh b/gnu/usr.bin/binutils/ld/emulparams/elf32_sparc.sh index da5c4a7a079..68c9e4fb39f 100644 --- a/gnu/usr.bin/binutils/ld/emulparams/elf32_sparc.sh +++ b/gnu/usr.bin/binutils/ld/emulparams/elf32_sparc.sh @@ -8,4 +8,6 @@ ARCH=sparc MACHINE= TEMPLATE_NAME=elf32 DATA_PLT= +PAD_PLT= +PAD_GOT= GENERATE_SHLIB_SCRIPT=yes diff --git a/gnu/usr.bin/binutils/ld/emulparams/elf32ppc.sh b/gnu/usr.bin/binutils/ld/emulparams/elf32ppc.sh index 22208105a70..7c8b5c95caa 100644 --- a/gnu/usr.bin/binutils/ld/emulparams/elf32ppc.sh +++ b/gnu/usr.bin/binutils/ld/emulparams/elf32ppc.sh @@ -9,6 +9,8 @@ MAXPAGESIZE=0x10000 ARCH=powerpc MACHINE= BSS_PLT= +PAD_GOT= +PAD_PLT= EXECUTABLE_SYMBOLS='PROVIDE (__stack = 0); PROVIDE (___stack = 0);' OTHER_BSS_END_SYMBOLS='__end = .;' OTHER_READWRITE_SECTIONS=' diff --git a/gnu/usr.bin/binutils/ld/emulparams/elf64_sparc.sh b/gnu/usr.bin/binutils/ld/emulparams/elf64_sparc.sh index b0a58eadcb7..00790d59201 100644 --- a/gnu/usr.bin/binutils/ld/emulparams/elf64_sparc.sh +++ b/gnu/usr.bin/binutils/ld/emulparams/elf64_sparc.sh @@ -6,6 +6,8 @@ MAXPAGESIZE=0x100000 ARCH="sparc:v9" MACHINE= DATA_PLT= +PAD_GOT= +PAD_PLT= GENERATE_SHLIB_SCRIPT=yes NOP=0x01000000 diff --git a/gnu/usr.bin/binutils/ld/emulparams/elf64alpha.sh b/gnu/usr.bin/binutils/ld/emulparams/elf64alpha.sh index 5c69816b2b7..fa9fad04695 100644 --- a/gnu/usr.bin/binutils/ld/emulparams/elf64alpha.sh +++ b/gnu/usr.bin/binutils/ld/emulparams/elf64alpha.sh @@ -10,6 +10,8 @@ ARCH=alpha MACHINE= GENERATE_SHLIB_SCRIPT=yes DATA_PLT= +PAD_GOT= +PAD_PLT= NOP=0x47ff041f OTHER_READONLY_SECTIONS='.reginfo : { *(.reginfo) }' diff --git a/gnu/usr.bin/binutils/ld/emulparams/elf_i386.sh b/gnu/usr.bin/binutils/ld/emulparams/elf_i386.sh index dff567bffbc..0defc2d866f 100644 --- a/gnu/usr.bin/binutils/ld/emulparams/elf_i386.sh +++ b/gnu/usr.bin/binutils/ld/emulparams/elf_i386.sh @@ -6,5 +6,6 @@ NONPAGED_TEXT_START_ADDR=0x08048000 ARCH=i386 MACHINE= NOP=0x9090 +PAD_GOT= TEMPLATE_NAME=elf32 GENERATE_SHLIB_SCRIPT=yes diff --git a/gnu/usr.bin/binutils/ld/genscripts.sh b/gnu/usr.bin/binutils/ld/genscripts.sh index bd9db1d1418..a4c28708edf 100644 --- a/gnu/usr.bin/binutils/ld/genscripts.sh +++ b/gnu/usr.bin/binutils/ld/genscripts.sh @@ -131,6 +131,12 @@ if test -n "$GENERATE_SHLIB_SCRIPT"; then ldscripts/${EMULATION_NAME}.xs fi +LD_FLAG=Z +DATA_ALIGNMENT=${DATA_ALIGNMENT_} +RELOCATING=" " +(. ${srcdir}/scripttempl/${SCRIPT_NAME}.sc) | sed -e '/^ *$/d' > \ + ldscripts/${EMULATION_NAME}.xz + for i in $EMULATION_LIBPATH ; do test "$i" = "$EMULATION_NAME" && COMPILE_IN=true done diff --git a/gnu/usr.bin/binutils/ld/ld.h b/gnu/usr.bin/binutils/ld/ld.h index 620c3ba57bd..49e3db9c7af 100644 --- a/gnu/usr.bin/binutils/ld/ld.h +++ b/gnu/usr.bin/binutils/ld/ld.h @@ -196,6 +196,10 @@ typedef struct { boolean text_read_only; + /* Classic ELF executable which has data and bss next to each + other with no padding for GOT/PLT. */ + boolean data_bss_contig; + char *map_filename; FILE *map_file; diff --git a/gnu/usr.bin/binutils/ld/ldmain.c b/gnu/usr.bin/binutils/ld/ldmain.c index 0b8120ffc9d..3ed628a546e 100644 --- a/gnu/usr.bin/binutils/ld/ldmain.c +++ b/gnu/usr.bin/binutils/ld/ldmain.c @@ -249,6 +249,7 @@ main (argc, argv) force_make_executable = false; config.magic_demand_paged = true; config.text_read_only = true; + config.data_bss_contig = false; emulation = get_emulation (argc, argv); ldemul_choose_mode (emulation); diff --git a/gnu/usr.bin/binutils/ld/lexsup.c b/gnu/usr.bin/binutils/ld/lexsup.c index e0ea6a4f73e..344ca53ad04 100644 --- a/gnu/usr.bin/binutils/ld/lexsup.c +++ b/gnu/usr.bin/binutils/ld/lexsup.c @@ -739,7 +739,7 @@ parse_args (argc, argv) config.dynamic_link = false; break; case 'Z': - /* compatibility flag, unused */ + config.data_bss_contig = true; break; case OPTION_NO_DEMANGLE: demangling = false; diff --git a/gnu/usr.bin/binutils/ld/scripttempl/elf.sc b/gnu/usr.bin/binutils/ld/scripttempl/elf.sc index 3c1bfb40c19..e155639eff9 100644 --- a/gnu/usr.bin/binutils/ld/scripttempl/elf.sc +++ b/gnu/usr.bin/binutils/ld/scripttempl/elf.sc @@ -70,6 +70,11 @@ DYNAMIC=".dynamic ${RELOCATING-0} : { *(.dynamic) }" RODATA=".rodata ${RELOCATING-0} : { *(.rodata) ${RELOCATING+*(.rodata.*)} ${RELOCATING+*(.gnu.linkonce.r.*)} }" SBSS2=".sbss2 ${RELOCATING-0} : { *(.sbss2) ${RELOCATING+*(.sbss2.*)} ${RELOCATING+*(.gnu.linkonce.sb2.*)} }" SDATA2=".sdata2 ${RELOCATING-0} : { *(.sdata2) ${RELOCATING+*(.sdata2.*)} ${RELOCATING+*(.gnu.linkonce.s2.*)} }" +test "$LD_FLAG" = "N" || test "$LD_FLAG" = "Z" || PAD_PLT0="${RELOCATING+. = ALIGN(${MAXPAGESIZE}) + (. & (${MAXPAGESIZE} - 1));} .pltpad0 ${RELOCATING-0} : { ${RELOCATING+__plt_start = .;} }" +test "$LD_FLAG" = "N" || test "$LD_FLAG" = "Z" || PAD_PLT1=".pltpad1 ${RELOCATING-0} : { ${RELOCATING+__plt_end = .;}} ${RELOCATING+. = ALIGN(${MAXPAGESIZE}) + (. & (${MAXPAGESIZE} - 1));}" +test "$LD_FLAG" = "N" || test "$LD_FLAG" = "Z" || PAD_GOT0="${RELOCATING+. = ALIGN(${MAXPAGESIZE}) + (. & (${MAXPAGESIZE} - 1));} .gotpad0 ${RELOCATING-0} : { ${RELOCATING+__got_start = .;} }" +test "$LD_FLAG" = "N" || test "$LD_FLAG" = "Z" || PAD_GOT1=".gotpad1 ${RELOCATING-0} : { ${RELOCATING+__got_end = .;}} ${RELOCATING+. = ALIGN(${MAXPAGESIZE}) + (. & (${MAXPAGESIZE} - 1));}" + CTOR=".ctors ${CONSTRUCTING-0} : { ${CONSTRUCTING+${CTOR_START}} @@ -310,9 +315,16 @@ SECTIONS ${RELOCATING+${OTHER_READWRITE_SECTIONS}} ${RELOCATING+${CTOR}} ${RELOCATING+${DTOR}} + + /* pad GOT (and PLT if DATA_PLT) to page aligned if PAD_GOT */ + ${DATA_PLT+${PAD_PLT+${PAD_PLT0}}} ${DATA_PLT+${PLT}} + ${DATA_PLT+${PAD_PLT+${PAD_PLT1}}} + ${PAD_GOT+${PAD_GOT0}} ${RELOCATING+${OTHER_GOT_SYMBOLS}} .got ${RELOCATING-0} : { *(.got.plt) *(.got) } + ${PAD_GOT+${PAD_GOT1}} + ${CREATE_SHLIB+${SDATA2}} ${CREATE_SHLIB+${SBSS2}} ${TEXT_DYNAMIC-${DYNAMIC}} @@ -343,7 +355,9 @@ SECTIONS ${RELOCATING+PROVIDE (__sbss_end = .);} ${RELOCATING+PROVIDE (___sbss_end = .);} } + ${BSS_PLT+${PAD_PLT+${PAD_PLT0}}} ${BSS_PLT+${PLT}} + ${BSS_PLT+${PAD_PLT+${PAD_PLT1}}} .bss ${RELOCATING-0} : { *(.dynbss) |