Skip to content

Commit

Permalink
This is a project to modify executables so that they do not have any
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
drahn committed Jan 17, 2003
1 parent 347b2b4 commit 58cb065
Show file tree
Hide file tree
Showing 11 changed files with 36 additions and 2 deletions.
2 changes: 1 addition & 1 deletion gnu/usr.bin/binutils/bfd/elf.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
2 changes: 2 additions & 0 deletions gnu/usr.bin/binutils/ld/emulparams/elf32_sparc.sh
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,6 @@ ARCH=sparc
MACHINE=
TEMPLATE_NAME=elf32
DATA_PLT=
PAD_PLT=
PAD_GOT=
GENERATE_SHLIB_SCRIPT=yes
2 changes: 2 additions & 0 deletions gnu/usr.bin/binutils/ld/emulparams/elf32ppc.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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='
Expand Down
2 changes: 2 additions & 0 deletions gnu/usr.bin/binutils/ld/emulparams/elf64_sparc.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ MAXPAGESIZE=0x100000
ARCH="sparc:v9"
MACHINE=
DATA_PLT=
PAD_GOT=
PAD_PLT=
GENERATE_SHLIB_SCRIPT=yes
NOP=0x01000000

Expand Down
2 changes: 2 additions & 0 deletions gnu/usr.bin/binutils/ld/emulparams/elf64alpha.sh
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ ARCH=alpha
MACHINE=
GENERATE_SHLIB_SCRIPT=yes
DATA_PLT=
PAD_GOT=
PAD_PLT=
NOP=0x47ff041f

OTHER_READONLY_SECTIONS='.reginfo : { *(.reginfo) }'
Expand Down
1 change: 1 addition & 0 deletions gnu/usr.bin/binutils/ld/emulparams/elf_i386.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,6 @@ NONPAGED_TEXT_START_ADDR=0x08048000
ARCH=i386
MACHINE=
NOP=0x9090
PAD_GOT=
TEMPLATE_NAME=elf32
GENERATE_SHLIB_SCRIPT=yes
6 changes: 6 additions & 0 deletions gnu/usr.bin/binutils/ld/genscripts.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 4 additions & 0 deletions gnu/usr.bin/binutils/ld/ld.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
1 change: 1 addition & 0 deletions gnu/usr.bin/binutils/ld/ldmain.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion gnu/usr.bin/binutils/ld/lexsup.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
14 changes: 14 additions & 0 deletions gnu/usr.bin/binutils/ld/scripttempl/elf.sc
Original file line number Diff line number Diff line change
Expand Up @@ -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}}
Expand Down Expand Up @@ -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}}
Expand Down Expand Up @@ -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)
Expand Down

0 comments on commit 58cb065

Please sign in to comment.