Skip to content
Snippets Groups Projects
Commit 054d428c authored by dem7yw's avatar dem7yw
Browse files

Copy some changes from the nol version of this sort of stuff to the noh...

Copy some changes from the nol version of this sort of stuff to the noh version - now handles file mappings as well. Only remaining unhandled mapping types are shared and fixed mappings, and it's likely possible to use something similar to the file mapping approach used here to do shared mappings.
parent 873de118
No related branches found
No related tags found
No related merge requests found
......@@ -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
......
......@@ -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;
}
}
}
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))
test passed!
#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;
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment