From 0ee3535ea8ff21d50e44372bb1cfd147e299ab5b Mon Sep 17 00:00:00 2001 From: Alexander Potapenko Date: Wed, 3 Apr 2024 12:20:00 +0200 Subject: 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 --- executor/executor_linux.h | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) (limited to 'executor/executor_linux.h') 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; -- cgit mrf-deployment