aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexander Potapenko <glider@google.com>2024-04-03 12:20:00 +0200
committerAlexander Potapenko <glider@google.com>2024-04-04 08:55:07 +0000
commit0ee3535ea8ff21d50e44372bb1cfd147e299ab5b (patch)
treecc3584d9b5ec5ce2f0b5da7b33cbe20ea3d33c57
parent51c4dcff83b0574620c280cc5130ef59cc4a2e32 (diff)
executor: add guard pages around the kcov mapping
Because the executor may place other mappings next to the buffer used by kcov, occasional out-of-bound writes to them may corrupt the coverage, creating garbage PCs (see https://github.com/google/syzkaller/issues/4531). To prevent those, map two extra pages for the kcov buffer, and protect them, so that OOB writes cause a segfault. Fixes https://github.com/google/syzkaller/issues/4532
-rw-r--r--executor/executor_linux.h18
1 files changed, 16 insertions, 2 deletions
diff --git a/executor/executor_linux.h b/executor/executor_linux.h
index 8e3c35044..578c65673 100644
--- a/executor/executor_linux.h
+++ b/executor/executor_linux.h
@@ -107,8 +107,22 @@ static void cover_mmap(cover_t* cov)
fail("cover_mmap invoked on an already mmapped cover_t object");
if (cov->mmap_alloc_size == 0)
fail("cover_t structure is corrupted");
- cov->data = (char*)mmap(NULL, cov->mmap_alloc_size,
- PROT_READ | PROT_WRITE, MAP_SHARED, cov->fd, 0);
+ // Allocate kcov buffer plus two guard pages surrounding it.
+ char* mapped = (char*)mmap(NULL, cov->mmap_alloc_size + 2 * SYZ_PAGE_SIZE,
+ PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
+ if (mapped == MAP_FAILED)
+ exitf("failed to preallocate kcov buffer");
+ // Protect the guard pages.
+ int res = mprotect(mapped, SYZ_PAGE_SIZE, PROT_NONE);
+ if (res == -1)
+ exitf("failed to protect kcov guard page");
+ res = mprotect(mapped + SYZ_PAGE_SIZE + cov->mmap_alloc_size,
+ SYZ_PAGE_SIZE, PROT_NONE);
+ if (res == -1)
+ exitf("failed to protect kcov guard page");
+ // Now map the kcov buffer to the file, overwriting the existing mapping above.
+ cov->data = (char*)mmap(mapped + SYZ_PAGE_SIZE, cov->mmap_alloc_size,
+ PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FIXED, cov->fd, 0);
if (cov->data == MAP_FAILED)
exitf("cover mmap failed");
cov->data_end = cov->data + cov->mmap_alloc_size;