aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2020-04-18 14:43:29 +0200
committerDmitry Vyukov <dvyukov@google.com>2020-04-18 14:43:29 +0200
commit365fba2440cee3aed74c774867a1f43e3e2f7aac (patch)
treed148c5d3f2e417b31d3dca1ae0e5d9c77da847b9
parent6fe0f49646813924a072d786e080ab7bf4f9ab65 (diff)
executor: surround the data mapping with PROT_NONE pages
Surround the main data mapping with PROT_NONE pages to make virtual address layout more consistent across different configurations (static/non-static build) and C repros. One observed case before: executor had a mapping above the data mapping (output region), while C repros did not have that mapping above, as the result in one case VMA had next link, while in the other it didn't and it caused a bug to not reproduce with the C repro. The bug that reproduces only with the mapping above: https://lkml.org/lkml/2020/4/17/819
-rw-r--r--executor/executor.cc2
-rw-r--r--executor/executor_linux.h11
-rw-r--r--sys/akaros/init.go2
-rw-r--r--sys/freebsd/init.go2
-rw-r--r--sys/linux/init.go2
-rw-r--r--sys/netbsd/init.go2
-rw-r--r--sys/openbsd/init.go2
-rw-r--r--sys/targets/common.go29
8 files changed, 36 insertions, 16 deletions
diff --git a/executor/executor.cc b/executor/executor.cc
index 9553228a2..084bb5736 100644
--- a/executor/executor.cc
+++ b/executor/executor.cc
@@ -356,7 +356,7 @@ int main(int argc, char** argv)
start_time_ms = current_time_ms();
- os_init(argc, argv, (void*)SYZ_DATA_OFFSET, SYZ_NUM_PAGES * SYZ_PAGE_SIZE);
+ os_init(argc, argv, (char*)SYZ_DATA_OFFSET, SYZ_NUM_PAGES * SYZ_PAGE_SIZE);
#if SYZ_EXECUTOR_USES_SHMEM
if (mmap(&input_data[0], kMaxInput, PROT_READ, MAP_PRIVATE | MAP_FIXED, kInFd, 0) != &input_data[0])
diff --git a/executor/executor_linux.h b/executor/executor_linux.h
index 33f4e377a..47804f4f4 100644
--- a/executor/executor_linux.h
+++ b/executor/executor_linux.h
@@ -59,12 +59,21 @@ static inline __u64 kcov_remote_handle(__u64 subsys, __u64 inst)
static bool detect_kernel_bitness();
-static void os_init(int argc, char** argv, void* data, size_t data_size)
+static void os_init(int argc, char** argv, char* data, size_t data_size)
{
prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0);
is_kernel_64_bit = detect_kernel_bitness();
+ // Surround the main data mapping with PROT_NONE pages to make virtual address layout more consistent
+ // across different configurations (static/non-static build) and C repros.
+ // One observed case before: executor had a mapping above the data mapping (output region),
+ // while C repros did not have that mapping above, as the result in one case VMA had next link,
+ // while in the other it didn't and it caused a bug to not reproduce with the C repro.
+ if (mmap(data - SYZ_PAGE_SIZE, SYZ_PAGE_SIZE, PROT_NONE, MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, 0) != data - SYZ_PAGE_SIZE)
+ fail("mmap of left data PROT_NONE page failed");
if (mmap(data, data_size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, 0) != data)
fail("mmap of data segment failed");
+ if (mmap(data + data_size, SYZ_PAGE_SIZE, PROT_NONE, MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, 0) != data + data_size)
+ fail("mmap of right data PROT_NONE page failed");
}
static __thread cover_t* current_cover;
diff --git a/sys/akaros/init.go b/sys/akaros/init.go
index 3016b3dee..c669cedef 100644
--- a/sys/akaros/init.go
+++ b/sys/akaros/init.go
@@ -16,7 +16,7 @@ func InitTarget(target *prog.Target) {
arch := &arch{
MAP_FIXED: target.GetConst("MAP_FIXED"),
}
- target.MakeDataMmap = targets.MakePosixMmap(target, true)
+ target.MakeDataMmap = targets.MakePosixMmap(target, true, false)
target.Neutralize = arch.Neutralize
}
diff --git a/sys/freebsd/init.go b/sys/freebsd/init.go
index eff43b288..33f93825a 100644
--- a/sys/freebsd/init.go
+++ b/sys/freebsd/init.go
@@ -13,7 +13,7 @@ func InitTarget(target *prog.Target) {
unix: targets.MakeUnixNeutralizer(target),
}
- target.MakeDataMmap = targets.MakePosixMmap(target, true)
+ target.MakeDataMmap = targets.MakePosixMmap(target, true, false)
target.Neutralize = arch.unix.Neutralize
}
diff --git a/sys/linux/init.go b/sys/linux/init.go
index 6a10c7d82..c9c15a283 100644
--- a/sys/linux/init.go
+++ b/sys/linux/init.go
@@ -48,7 +48,7 @@ func InitTarget(target *prog.Target) {
ARCH_SET_GS: target.ConstMap["ARCH_SET_GS"],
}
- target.MakeDataMmap = targets.MakePosixMmap(target, true)
+ target.MakeDataMmap = targets.MakePosixMmap(target, true, true)
target.Neutralize = arch.neutralize
target.SpecialTypes = map[string]func(g *prog.Gen, typ prog.Type, old prog.Arg) (
prog.Arg, []*prog.Call){
diff --git a/sys/netbsd/init.go b/sys/netbsd/init.go
index c90c51eb8..1a7988d61 100644
--- a/sys/netbsd/init.go
+++ b/sys/netbsd/init.go
@@ -13,7 +13,7 @@ func InitTarget(target *prog.Target) {
unix: targets.MakeUnixNeutralizer(target),
}
- target.MakeDataMmap = targets.MakePosixMmap(target, false)
+ target.MakeDataMmap = targets.MakePosixMmap(target, false, false)
target.Neutralize = arch.unix.Neutralize
}
diff --git a/sys/openbsd/init.go b/sys/openbsd/init.go
index 40ab996f4..6948139aa 100644
--- a/sys/openbsd/init.go
+++ b/sys/openbsd/init.go
@@ -19,7 +19,7 @@ func InitTarget(target *prog.Target) {
S_IFCHR: target.GetConst("S_IFCHR"),
}
- target.MakeDataMmap = targets.MakePosixMmap(target, false)
+ target.MakeDataMmap = targets.MakePosixMmap(target, false, false)
target.Neutralize = arch.neutralize
target.AnnotateCall = arch.annotateCall
}
diff --git a/sys/targets/common.go b/sys/targets/common.go
index 75a1aba4f..d7ee71983 100644
--- a/sys/targets/common.go
+++ b/sys/targets/common.go
@@ -8,18 +8,21 @@ import (
)
// MakePosixMmap creates a "normal" posix mmap call that maps the target data range.
-func MakePosixMmap(target *prog.Target, exec bool) func() []*prog.Call {
+// If exec is set, the mapping is mapped as PROT_EXEC.
+// If contain is set, the mapping is surrounded by PROT_NONE pages.
+// These flags should be in sync with what executor.
+func MakePosixMmap(target *prog.Target, exec, contain bool) func() []*prog.Call {
meta := target.SyscallMap["mmap"]
- prot := target.GetConst("PROT_READ") | target.GetConst("PROT_WRITE")
+ protRW := target.GetConst("PROT_READ") | target.GetConst("PROT_WRITE")
if exec {
- prot |= target.GetConst("PROT_EXEC")
+ protRW |= target.GetConst("PROT_EXEC")
}
flags := target.GetConst("MAP_ANONYMOUS") | target.GetConst("MAP_PRIVATE") | target.GetConst("MAP_FIXED")
- const invalidFD = ^uint64(0)
size := target.NumPages * target.PageSize
- return func() []*prog.Call {
+ const invalidFD = ^uint64(0)
+ makeMmap := func(addr, size, prot uint64) *prog.Call {
args := []prog.Arg{
- prog.MakeVmaPointerArg(meta.Args[0], 0, size),
+ prog.MakeVmaPointerArg(meta.Args[0], addr, size),
prog.MakeConstArg(meta.Args[1], size),
prog.MakeConstArg(meta.Args[2], prot),
prog.MakeConstArg(meta.Args[3], flags),
@@ -32,13 +35,21 @@ func MakePosixMmap(target *prog.Target, exec bool) func() []*prog.Call {
i++
}
args = append(args, prog.MakeConstArg(meta.Args[i], 0))
-
- mmapCall := &prog.Call{
+ return &prog.Call{
Meta: meta,
Args: args,
Ret: prog.MakeReturnArg(meta.Ret),
}
- return []*prog.Call{mmapCall}
+ }
+ return func() []*prog.Call {
+ if contain {
+ return []*prog.Call{
+ makeMmap(^uint64(target.PageSize)+1, target.PageSize, 0),
+ makeMmap(0, size, protRW),
+ makeMmap(size, target.PageSize, 0),
+ }
+ }
+ return []*prog.Call{makeMmap(0, size, protRW)}
}
}