diff options
| author | Alexander Potapenko <glider@google.com> | 2024-04-03 12:20:00 +0200 |
|---|---|---|
| committer | Alexander Potapenko <glider@google.com> | 2024-04-04 08:55:07 +0000 |
| commit | 0ee3535ea8ff21d50e44372bb1cfd147e299ab5b (patch) | |
| tree | cc3584d9b5ec5ce2f0b5da7b33cbe20ea3d33c57 | |
| parent | 51c4dcff83b0574620c280cc5130ef59cc4a2e32 (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.h | 18 |
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; |
