diff options
Diffstat (limited to 'executor')
| -rw-r--r-- | executor/executor.cc | 8 | ||||
| -rw-r--r-- | executor/executor_bsd.h | 22 | ||||
| -rw-r--r-- | executor/executor_darwin.h | 3 | ||||
| -rw-r--r-- | executor/executor_linux.h | 38 | ||||
| -rw-r--r-- | executor/executor_test.h | 18 |
5 files changed, 52 insertions, 37 deletions
diff --git a/executor/executor.cc b/executor/executor.cc index fb73efc5c..704a284a9 100644 --- a/executor/executor.cc +++ b/executor/executor.cc @@ -348,8 +348,16 @@ struct call_t { struct cover_t { int fd; uint32 size; + // mmap_alloc_ptr is the internal pointer to KCOV mapping, possibly with guard pages. + // It is only used to allocate/deallocate the buffer of mmap_alloc_size. + char* mmap_alloc_ptr; uint32 mmap_alloc_size; + // data is the pointer to the kcov buffer containing the recorded PCs. + // data may differ from mmap_alloc_ptr. char* data; + // data_size is set by cover_open(). This is the requested kcov buffer size. + uint32 data_size; + // data_end is simply data + data_size. char* data_end; // Currently collecting comparisons. bool collect_comps; diff --git a/executor/executor_bsd.h b/executor/executor_bsd.h index b7cbdd4f5..88e1f46cb 100644 --- a/executor/executor_bsd.h +++ b/executor/executor_bsd.h @@ -71,7 +71,7 @@ static void cover_open(cover_t* cov, bool extra) #if GOOS_freebsd if (ioctl(cov->fd, KIOSETBUFSIZE, kCoverSize)) fail("ioctl init trace write failed"); - cov->mmap_alloc_size = kCoverSize * KCOV_ENTRY_SIZE; + cov->data_size = kCoverSize * KCOV_ENTRY_SIZE; #elif GOOS_openbsd unsigned long cover_size = kCoverSize; if (ioctl(cov->fd, KIOSETBUFSIZE, &cover_size)) @@ -83,7 +83,7 @@ static void cover_open(cover_t* cov, bool extra) if (ioctl(cov->fd, KIOREMOTEATTACH, &args)) fail("ioctl remote attach failed"); } - cov->mmap_alloc_size = kCoverSize * (is_kernel_64_bit ? 8 : 4); + cov->data_size = kCoverSize * (is_kernel_64_bit ? 8 : 4); #elif GOOS_netbsd uint64_t cover_size; if (extra) { @@ -100,18 +100,20 @@ static void cover_open(cover_t* cov, bool extra) if (ioctl(cov->fd, KCOV_IOC_SETBUFSIZE, &cover_size)) fail("ioctl init trace write failed"); } - cov->mmap_alloc_size = cover_size * KCOV_ENTRY_SIZE; + cov->data_size = cover_size * KCOV_ENTRY_SIZE; #endif } static void cover_mmap(cover_t* cov) { - if (cov->data != NULL) + if (cov->mmap_alloc_ptr != NULL) fail("cover_mmap invoked on an already mmapped cover_t object"); + cov->mmap_alloc_size = cov->data_size; void* mmap_ptr = mmap(NULL, cov->mmap_alloc_size, PROT_READ | PROT_WRITE, MAP_SHARED, cov->fd, 0); if (mmap_ptr == MAP_FAILED) fail("cover mmap failed"); + cov->mmap_alloc_ptr = (char*)mmap_ptr; cov->data = (char*)mmap_ptr; cov->data_end = cov->data + cov->mmap_alloc_size; cov->data_offset = is_kernel_64_bit ? sizeof(uint64_t) : sizeof(uint32_t); @@ -120,13 +122,13 @@ static void cover_mmap(cover_t* cov) static void cover_protect(cover_t* cov) { - if (cov->data == NULL) + if (cov->mmap_alloc_ptr == NULL) fail("cover_protect invoked on an unmapped cover_t object"); #if GOOS_freebsd size_t mmap_alloc_size = kCoverSize * KCOV_ENTRY_SIZE; long page_size = sysconf(_SC_PAGESIZE); if (page_size > 0) - mprotect(cov->data + page_size, mmap_alloc_size - page_size, + mprotect(cov->mmap_alloc_ptr + page_size, mmap_alloc_size - page_size, PROT_READ); #elif GOOS_openbsd int mib[2], page_size; @@ -135,20 +137,20 @@ static void cover_protect(cover_t* cov) mib[1] = HW_PAGESIZE; size_t len = sizeof(page_size); if (sysctl(mib, ARRAY_SIZE(mib), &page_size, &len, NULL, 0) != -1) - mprotect(cov->data + page_size, mmap_alloc_size - page_size, PROT_READ); + mprotect(cov->mmap_alloc_ptr + page_size, mmap_alloc_size - page_size, PROT_READ); #endif } static void cover_unprotect(cover_t* cov) { - if (cov->data == NULL) + if (cov->mmap_alloc_ptr == NULL) fail("cover_unprotect invoked on an unmapped cover_t object"); #if GOOS_freebsd size_t mmap_alloc_size = kCoverSize * KCOV_ENTRY_SIZE; - mprotect(cov->data, mmap_alloc_size, PROT_READ | PROT_WRITE); + mprotect(cov->mmap_alloc_ptr, mmap_alloc_size, PROT_READ | PROT_WRITE); #elif GOOS_openbsd size_t mmap_alloc_size = kCoverSize * sizeof(uintptr_t); - mprotect(cov->data, mmap_alloc_size, PROT_READ | PROT_WRITE); + mprotect(cov->mmap_alloc_ptr, mmap_alloc_size, PROT_READ | PROT_WRITE); #endif } diff --git a/executor/executor_darwin.h b/executor/executor_darwin.h index bb7956c20..d555eeb02 100644 --- a/executor/executor_darwin.h +++ b/executor/executor_darwin.h @@ -73,7 +73,7 @@ static void cover_open(cover_t* cov, bool extra) static void cover_mmap(cover_t* cov) { - if (cov->data != NULL) + if (cov->mmap_alloc_ptr != NULL) fail("cover_mmap invoked on an already mmapped cover_t object"); uintptr_t mmap_ptr = 0; if (ksancov_map(cov->fd, &mmap_ptr, &cov->mmap_alloc_size)) @@ -84,6 +84,7 @@ static void cover_mmap(cover_t* cov) if (cov->mmap_alloc_size > kCoverSize) fail("mmap allocation size larger than anticipated"); + cov->mmap_alloc_ptr = (char*)mmap_ptr; cov->data = (char*)mmap_ptr; cov->data_end = cov->data + cov->mmap_alloc_size; } diff --git a/executor/executor_linux.h b/executor/executor_linux.h index f882b9c40..a5a073ba0 100644 --- a/executor/executor_linux.h +++ b/executor/executor_linux.h @@ -114,7 +114,7 @@ static void cover_open(cover_t* cov, bool extra) : kCoverSize; if (ioctl(cov->fd, kcov_init_trace, cover_size)) fail("cover init trace write failed"); - cov->mmap_alloc_size = cover_size * (is_kernel_64_bit ? 8 : 4); + cov->data_size = cover_size * (is_kernel_64_bit ? 8 : 4); if (pkeys_enabled) debug("pkey protection enabled\n"); } @@ -133,35 +133,37 @@ static void cover_unprotect(cover_t* cov) static void cover_mmap(cover_t* cov) { - if (cov->data != NULL) + if (cov->mmap_alloc_ptr != NULL) fail("cover_mmap invoked on an already mmapped cover_t object"); - if (cov->mmap_alloc_size == 0) + if (cov->data_size == 0) fail("cover_t structure is corrupted"); // Allocate kcov buffer plus two guard pages surrounding it. - char* mapped = (char*)mmap(NULL, cov->mmap_alloc_size + 2 * SYZ_PAGE_SIZE, - PROT_NONE, MAP_PRIVATE | MAP_ANON, -1, 0); - if (mapped == MAP_FAILED) + cov->mmap_alloc_size = cov->data_size + 2 * SYZ_PAGE_SIZE; + cov->mmap_alloc_ptr = (char*)mmap(NULL, cov->mmap_alloc_size, + PROT_NONE, MAP_PRIVATE | MAP_ANON, -1, 0); + if (cov->mmap_alloc_ptr == MAP_FAILED) exitf("failed to preallocate kcov buffer"); // Now map the kcov buffer to the file, overwriting the existing mapping above. int prot = flag_read_only_coverage ? PROT_READ : (PROT_READ | PROT_WRITE); - cov->data = (char*)mmap(mapped + SYZ_PAGE_SIZE, cov->mmap_alloc_size, - prot, MAP_SHARED | MAP_FIXED, cov->fd, 0); - if (cov->data == MAP_FAILED) + void* data_buf = (char*)mmap(cov->mmap_alloc_ptr + SYZ_PAGE_SIZE, cov->data_size, + prot, MAP_SHARED | MAP_FIXED, cov->fd, 0); + if (data_buf == MAP_FAILED) exitf("cover mmap failed"); - if (pkeys_enabled && pkey_mprotect(cov->data, cov->mmap_alloc_size, prot, RESERVED_PKEY)) + if (pkeys_enabled && pkey_mprotect(data_buf, cov->data_size, prot, RESERVED_PKEY)) exitf("failed to pkey_mprotect kcov buffer"); - cov->data_end = cov->data + cov->mmap_alloc_size; + cov->data = (char*)data_buf; + cov->data_end = cov->data + cov->data_size; cov->data_offset = is_kernel_64_bit ? sizeof(uint64_t) : sizeof(uint32_t); cov->pc_offset = 0; } static void cover_munmap(cover_t* cov) { - if (cov->data == NULL) + if (cov->mmap_alloc_ptr == NULL) fail("cover_munmap invoked on a non-mmapped cover_t object"); - if (munmap(cov->data - SYZ_PAGE_SIZE, cov->mmap_alloc_size + 2 * SYZ_PAGE_SIZE)) + if (munmap(cov->mmap_alloc_ptr, cov->mmap_alloc_size)) fail("cover_munmap failed"); - cov->data = NULL; + cov->mmap_alloc_ptr = NULL; } static void cover_enable(cover_t* cov, bool collect_comps, bool extra) @@ -303,8 +305,8 @@ static const char* setup_delay_kcov() cov.fd = kCoverFd; cover_open(&cov, false); cover_mmap(&cov); - char* first = cov.data; - cov.data = nullptr; + char* first = cov.mmap_alloc_ptr; + cov.mmap_alloc_ptr = nullptr; cover_mmap(&cov); // If delayed kcov mmap is not supported by the kernel, // accesses to the second mapping will crash. @@ -316,9 +318,9 @@ static const char* setup_delay_kcov() fail("clock_gettime failed"); error = "kernel commit b3d7fe86fbd0 is not present"; } else { - munmap(cov.data - SYZ_PAGE_SIZE, cov.mmap_alloc_size + 2 * SYZ_PAGE_SIZE); + munmap(cov.mmap_alloc_ptr, cov.mmap_alloc_size); } - munmap(first - SYZ_PAGE_SIZE, cov.mmap_alloc_size + 2 * SYZ_PAGE_SIZE); + munmap(first, cov.mmap_alloc_size); close(cov.fd); return error; } diff --git a/executor/executor_test.h b/executor/executor_test.h index e2a2002bb..d8471e6b5 100644 --- a/executor/executor_test.h +++ b/executor/executor_test.h @@ -75,7 +75,7 @@ static intptr_t execute_syscall(const call_t* c, intptr_t a[kMaxArgs]) static void cover_open(cover_t* cov, bool extra) { - cov->mmap_alloc_size = kCoverSize * sizeof(unsigned long); + cov->data_size = kCoverSize * sizeof(unsigned long); } static void cover_enable(cover_t* cov, bool collect_comps, bool extra) @@ -102,14 +102,16 @@ static void cover_protect(cover_t* cov) static void cover_mmap(cover_t* cov) { - if (cov->data != NULL) + if (cov->mmap_alloc_ptr != NULL) fail("cover_mmap invoked on an already mmapped cover_t object"); - if (cov->mmap_alloc_size == 0) + if (cov->data_size == 0) fail("cover_t structure is corrupted"); - cov->data = (char*)mmap(NULL, cov->mmap_alloc_size, - PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0); - if (cov->data == MAP_FAILED) + cov->mmap_alloc_size = cov->data_size; + cov->mmap_alloc_ptr = (char*)mmap(NULL, cov->mmap_alloc_size, + PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0); + if (cov->mmap_alloc_ptr == MAP_FAILED) exitf("cover mmap failed"); + cov->data = cov->mmap_alloc_ptr; cov->data_end = cov->data + cov->mmap_alloc_size; cov->data_offset = is_kernel_64_bit ? sizeof(uint64_t) : sizeof(uint32_t); // We don't care about the specific PC values for now. @@ -125,9 +127,9 @@ static long inject_cover(cover_t* cov, long a, long b) { if (cov->data == nullptr) return ENOENT; - uint32 size = std::min((uint32)b, cov->mmap_alloc_size); + uint32 size = std::min((uint32)b, cov->data_size); memcpy(cov->data, (void*)a, size); - memset(cov->data + size, 0xcd, std::min<uint64>(100, cov->mmap_alloc_size - size)); + memset(cov->data + size, 0xcd, std::min<uint64>(100, cov->data_size - size)); return 0; } |
