modern hardware-supported memory protection mechanism
via table: OS decides what memory program sees
granularity of pages — typically 4KB
not in table — segfault (OS gets control)
deliberate holes
accessing — segfualt
call to OS to allocate (not very fast)
likely to ‘waste’ memory
can implement malloc/new by placing guard pages around allocations
problem: minimum actual allocation 4KB
problem: substantially slower
example: ‘‘Electric Fence’’ allocator for Linux (early 1990s)
struct foosuppose heap allocations are:
total allocation of approx 12 000 KB
assuming 4KB pages, estimate space overhead of using guard pages:
W^X (write XOR execute)W xor X is ‘‘almost free’’, keeps attacker from writing code?
problem: useful machine code is in program already
saw special case: arc injection
system function to replace strlenturns out: almost always useful code
char *foo = "Hello";
char bar[] = "Hello";
turns into:
.data
bar:
.string "Hello"
...
foo:
.quad .LC0
.section .rodata.str1.1,"aMS",@progbits
# aMS = allocatable,mergeable,strings, @progbits = data
.LC0:
.string "Hello"
LOAD off 0x0018000 vaddr 0x0018000 paddr 0x0018000 align 2**12
filesz 0x0007458 memsz 0x0007458 flags r--
LOAD off 0x001ffd0 vaddr 0x0020fd0 paddr 0x0020fd0 align 2**12
filesz 0x00012a8 memsz 0x0002570 flags rw-
compiler needs to separate constants/code/data into different segments
linker uses this info to make LOAD directives
need to add padding to make sure segments start at beginning of page
usually compiler writes linker script specifying order of sections + padding + how many LOAD directives
global offset table and vtable entries produced at runtime
addresses of functions, etc. not chosen until program loaded
… or later with ‘‘lazy’’ linking
addresses filled in by dynamic linker big target
would like them to be read-only
… but they can’t be read-only when initially loaded
RELocation Read-Only
Linux option: make dynamic linker structures read-only after startup
partial RELRO: everything but GOT pointers to library functions
full RELRO: everything including GOT pointers
appears as ELF program header entry
-z relro/-z norerlo: enable/disable relocation read-only-z now: disable lazy binding (fill in whole GOT immediately)objdump (RELRO header; bit 3 of Dynamic Section FLAGS):Program Headers:
...
RELRO off 0x0000020f30 vaddr 0x0000021f30 paddr 0x0000021f30 align 2**0
filesz 0x00000010d0 memsz 0x00000010d0 flags r--
...
Dynamic Section:
...
FLAGS 0x0000000000000008
...