Full ASLR for Static Binaries! Using the x86_64 gs segment register. - No indirection! - Requires no changes in the kernel! - Combine the .data and .bss sections into one writable section. - Expose a read-only symbol using the linker that points to the beginning of the combined section. - Using mmap() remap the combined data section into a new random region. - munmap() the old region. - Set the gs segment register to point to the beginning of the random section using a kernel system call. - All data access uses the new value in the gs segment register going forward. - Works with thread local storage too! Each thread uses it's own gs segment register to access global shared data. Assuming threads are using the fs segment register to access thread local variables. - Assuming the .text segment is PIC the .text and .rodata section can be randomized together. - Kernel randomizes the whole initial binary (assuming .text section is PIC) and the rest is done in userspace. Section Base Table (SBT): - Similar to the Global Offset Table (GOT). - Contains all sections used by the program. - Kernel later populates this table for each section. - Extra level of indirection similar to the GOT. - Linker computes an offset into each section when referencing data and computes the final address using the SBT entry for that section. mov rax, [rip + var@PCRELSBT] ; Relative load of section base. mov rax, [rax + var_offset] ; Load var using offset. Userspace: - Linker must produce calls to the offsets described above. - Linker marks all sections relocatable with a base of 0. Kernelspace: - Go through each relocation with a base of 0 and create a new random base address. - Populate the SBT with the new base addresses. - Map the SBT where the binary wants it (should be just below the .text section and aligned to a page boundary). - Map the SBT read only as it is unchanged for static binaries (linker controls this but should have it read only). Assuming the .text section is position independent code, all processes that exec() this binary can share the .text and .rodata sections but have them located at different base offsets. Pros: - Eloquent, minimal changes to kernel. Cons: - Wasted space (~1 page in the virtual address space) as the SBT contains only a few entries. But overall this is negligible. GOT makes better use of the space but requires larger and more complex changes to the kernel to implement the same behaviour. - Requires changes to existing tooling.