diff --git a/.gitattributes b/.gitattributes index 4f0fb956bf10048628e373bce056aaddcb54ff26..7721b1baac0cb92710725283633a1a23d7d81cfa 100644 --- a/.gitattributes +++ b/.gitattributes @@ -8,7 +8,9 @@ non_overlapping_heap/Makefile -text non_overlapping_heap/noh.c -text non_overlapping_heap/tests/Makefile -text -non_overlapping_heap/tests/tester.c -text +non_overlapping_heap/tests/inputfile -text +non_overlapping_heap/tests/test1.c -text +non_overlapping_heap/tests/test2.c -text /postgres_setup.sh -text /set_command_envs -text /set_env_vars -text diff --git a/non_overlapping_heap/noh.c b/non_overlapping_heap/noh.c index c5cf80f7b5119d7dd886bba2962b60f89526cca8..9db3b9b43456887946a4207fb08dcf47d1d342da 100644 --- a/non_overlapping_heap/noh.c +++ b/non_overlapping_heap/noh.c @@ -107,40 +107,8 @@ size_t rounduptopagemultiple(size_t length) { return rounduptomultiple(length, pagesize); } -void* mmap(void* address, size_t length, int protect, int flags, int filedes, off_t offset) { - bool is_diversified = false; - //size_t originallength = length; - size_t alignedlength = length; - void* new_mapping = MAP_FAILED; -#ifdef DEBUG - printf("entering mmap call\n"); -#endif - if( - (address && (flags & MAP_FIXED)) // must use normal mmap, since the program is now guaranteed the destination address or failure - || (flags & MAP_SHARED) // we're sharing between multiple programs, which is complex enough as it is - alignment is important, and we'd have to do funky stuff to ensure non-overlappingness with this regardless - || ((!flags) & MAP_ANONYMOUS) // we're mapping a file, so the kernel needs to know the actual location - ) { - //return orig_mmap(address, length, protect, flags, filedes, offset); - // don't modify the arguments - we unfortunately can't touch this much, since it's going to be mapped in a way that we can't nicely diversify (yet) - } else { - is_diversified = true; - if(randfd != 0) { - // we're in probabalistic mode - uint32_t target = 0; - read(randfd, &target, 4); - nthisvar = (int)(target % PROB_NUM_VARIANTS); - } -#if defined(MAP_ALIGN) - // gotta round up to the next barrier, but this only matters on solaris (in theory) - // support it as soon as it actually comes up - length = rounduptomultiple(length, address); -#endif - // we want to allocate a bit more space - this is so that each variant gets its own part of the allocated segment, in a non-overlapping fashion - // let's keep page alignment the same - alignedlength = rounduptopagemultiple(length); - length = alignedlength * nnumvar; - } - +// the non-diversified part of the mapping - this basically acts as a call to mmap that works in a couple of odd additional contexts +void* actually_mmap(void* address, size_t length, int protect, int flags, int filedes, off_t offset) { // ok, now we need to actually do the call if(orig_mmap == NULL) { /* @@ -171,27 +139,80 @@ void* mmap(void* address, size_t length, int protect, int flags, int filedes, of return MAP_FAILED; } #ifdef SYS_mmap2 - new_mapping = (void*)syscall(SYS_mmap2, address, length, protect, flags, filedes, offset/UNIT); + return (void*)syscall(SYS_mmap2, address, length, protect, flags, filedes, offset/UNIT); #else - new_mapping = (void*)syscall(SYS_mmap, address, length, protect, flags, filedes, offset); + return (void*)syscall(SYS_mmap, address, length, protect, flags, filedes, offset); #endif } else { // it's actually been initialized, so use the original glibc/other mmap implementation - let's hope it plays nice with the hacky stuff above - new_mapping = orig_mmap(address, length, protect, flags, filedes, offset); + return orig_mmap(address, length, protect, flags, filedes, offset); } +} - // now that we've done the call, handle the result and return - if(new_mapping == MAP_FAILED || !is_diversified) { - // it failed, and if we were to retry, it would diverge anyway - just return the failure - // alternatively, we had to do just a normal mmap, so just return the pointer - return new_mapping; - } +void* mmap(void* address, size_t length, int protect, int flags, int filedes, off_t offset) { +#ifdef DEBUG + printf("entering mmap call\n"); +#endif + // figure out what index we are in a randomized context - // in the event that we got the memory and such, mprotect the other portions so that they won't be able to be accesssed improperly - mprotect(new_mapping, alignedlength * nthisvar, PROT_NONE); - mprotect(new_mapping + alignedlength * (nthisvar+1), alignedlength * (nnumvar - (nthisvar + 1)), PROT_NONE); + if( + (flags & MAP_FIXED) // must use normal mmap, since the program is now guaranteed the destination address or failure + || (flags & MAP_SHARED) // we're sharing between multiple programs, which is complex enough as it is - alignment is important, and we'd have to do funky stuff to ensure non-overlappingness with this regardless + ) { + // don't modify the arguments - we unfortunately can't touch this much, since it's going to be mapped in a way that we can't nicely diversify (yet) + return actually_mmap(address, length, protect, flags, filedes, offset); + } else { + // we're diversified now - do fancier stuff + size_t alignedlength = length; + void* new_mapping = MAP_FAILED; + // get the nthisvar for this run + if(randfd != 0) { + // we're in probabalistic mode + uint32_t target = 0; + read(randfd, &target, 4); + nthisvar = (int)(target % PROB_NUM_VARIANTS); + printf("using randomization, is at %i/%i\n",nthisvar,nnumvar); + } + // branch on whether this is a file-backed allocation or not + if (flags & MAP_ANONYMOUS) { + // if it's a non-file mapping, just allocate a larger area, and then use part of that +#if defined(MAP_ALIGN) + // gotta round up to the next barrier, but this only matters on solaris (in theory) + // support it as soon as it actually comes up + length = rounduptomultiple(length, address); +#endif + // we want to allocate a bit more space - this is so that each variant gets its own part of the allocated segment, in a non-overlapping fashion + // let's keep page alignment the same + alignedlength = rounduptopagemultiple(length); + length = alignedlength * nnumvar; + new_mapping = actually_mmap(address, length, protect, flags, filedes, offset); + + // now that we've done the call, handle the result and return + if(new_mapping == MAP_FAILED) { + // it failed, and if we were to retry, it would diverge anyway - just return the failure + // alternatively, we had to do just a normal mmap, so just return the pointer + return new_mapping; + } + + // in the event that we got the memory and such, mprotect the other portions so that they won't be able to be accesssed improperly + mprotect(new_mapping, alignedlength * nthisvar, PROT_NONE); + mprotect(new_mapping + alignedlength * (nthisvar+1), alignedlength * (nnumvar - (nthisvar + 1)), PROT_NONE); #ifdef DEBUG - printf("returning new mapping at %p\n", new_mapping + alignedlength * nthisvar); + printf("returning new mapping at %p\n", new_mapping + alignedlength * nthisvar); #endif - return new_mapping + alignedlength * nthisvar; + return new_mapping + alignedlength * nthisvar; + } else { + // for file mappings, handle them by repeated allocation of the required size and selection of the currect index + int i=0; + for(i=0; i < nnumvar; i++) { + if(i == nthisvar) { + new_mapping = actually_mmap(address, length, protect, flags, filedes, offset); + } else { + // ignored + actually_mmap(address, length, PROT_NONE, flags | MAP_ANONYMOUS, -1, 0); + } + } + return new_mapping; + } + } } diff --git a/non_overlapping_heap/tests/Makefile b/non_overlapping_heap/tests/Makefile index 889f3e32e312b899c39a3d9f0f435b37414761ad..a3fbecec1b1244238845a5b4e6ea369648a8c58a 100644 --- a/non_overlapping_heap/tests/Makefile +++ b/non_overlapping_heap/tests/Makefile @@ -1,12 +1,18 @@ -all: Tester -Tester: tester.c - gcc -fno-stack-protector -o Tester tester.c +all: test +define maketest +Test$(1): test$(1).c + gcc -fno-stack-protector -o Test$(1) test$(1).c +testTest$(1): Test$(1) + ./Test$(1) + LD_PRELOAD=../noh.so setarch $$$$(uname -m) --addr-no-randomize ./Test$(1) + LD_PRELOAD=../noh.so setarch $$$$(uname -m) --addr-no-randomize ./Test$(1) + NUMVARIANTS=4 VARIANTINDEX=0 LD_PRELOAD=../noh.so setarch $$$$(uname -m) --addr-no-randomize ./Test$(1) + NUMVARIANTS=4 VARIANTINDEX=1 LD_PRELOAD=../noh.so setarch $$$$(uname -m) --addr-no-randomize ./Test$(1) + NUMVARIANTS=4 VARIANTINDEX=2 LD_PRELOAD=../noh.so setarch $$$$(uname -m) --addr-no-randomize ./Test$(1) + NUMVARIANTS=4 VARIANTINDEX=3 LD_PRELOAD=../noh.so setarch $$$$(uname -m) --addr-no-randomize ./Test$(1) +endef +tests=1 2 +$(foreach i,$(tests),$(eval $(call maketest,$(i)))) clean: - rm Tester -test: Tester - LD_PRELOAD=../noh.so setarch $$(uname -m) --addr-no-randomize ./Tester - LD_PRELOAD=../noh.so setarch $$(uname -m) --addr-no-randomize ./Tester - NUMVARIANTS=4 VARIANTINDEX=0 LD_PRELOAD=../noh.so setarch $$(uname -m) --addr-no-randomize ./Tester - NUMVARIANTS=4 VARIANTINDEX=1 LD_PRELOAD=../noh.so setarch $$(uname -m) --addr-no-randomize ./Tester - NUMVARIANTS=4 VARIANTINDEX=2 LD_PRELOAD=../noh.so setarch $$(uname -m) --addr-no-randomize ./Tester - NUMVARIANTS=4 VARIANTINDEX=3 LD_PRELOAD=../noh.so setarch $$(uname -m) --addr-no-randomize ./Tester + rm Test* +test: $(foreach i,$(tests),testTest$(i)) diff --git a/non_overlapping_heap/tests/inputfile b/non_overlapping_heap/tests/inputfile new file mode 100644 index 0000000000000000000000000000000000000000..17d9f97de22aa38e2ca9f939f2dc98069e300807 --- /dev/null +++ b/non_overlapping_heap/tests/inputfile @@ -0,0 +1 @@ +test passed! diff --git a/non_overlapping_heap/tests/tester.c b/non_overlapping_heap/tests/test1.c similarity index 100% rename from non_overlapping_heap/tests/tester.c rename to non_overlapping_heap/tests/test1.c diff --git a/non_overlapping_heap/tests/test2.c b/non_overlapping_heap/tests/test2.c new file mode 100644 index 0000000000000000000000000000000000000000..facfe1cc79644480e0336ef528e13341c2133caa --- /dev/null +++ b/non_overlapping_heap/tests/test2.c @@ -0,0 +1,11 @@ +#include <sys/mman.h> +#include <stdio.h> +#include <fcntl.h> + +int main() { + int fd = open("./inputfile", O_RDONLY); + void* foobar = mmap(NULL, 1024, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); + printf("%p\n",foobar); + printf("%s\n",(char*)foobar); + return 0; +}