mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 07:17:35 +00:00
Kernel: Add option to build with coverage instrumentation and KCOV
GCC and Clang allow us to inject a call to a function named __sanitizer_cov_trace_pc on every edge. This function has to be defined by us. By noting down the caller in that function we can trace the code we have encountered during execution. Such information is used by coverage guided fuzzers like AFL and LibFuzzer to determine if a new input resulted in a new code path. This makes fuzzing much more effective. Additionally this adds a basic KCOV implementation. KCOV is an API that allows user space to request the kernel to start collecting coverage information for a given user space thread. Furthermore KCOV then exposes the collected program counters to user space via a BlockDevice which can be mmaped from user space. This work is required to add effective support for fuzzing SerenityOS to the Syzkaller syscall fuzzer. :^) :^)
This commit is contained in:
parent
67b3255fe8
commit
83f88df757
15 changed files with 478 additions and 0 deletions
56
Kernel/Devices/KCOVInstance.h
Normal file
56
Kernel/Devices/KCOVInstance.h
Normal file
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* Copyright (c) 2021, Patrick Meyer <git@the-space.agency>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Kernel/SpinLock.h>
|
||||
#include <Kernel/VM/AnonymousVMObject.h>
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
// Note: These need to be kept in sync with Userland/Libraries/LibC/sys/kcov.h
|
||||
typedef volatile u64 kcov_pc_t;
|
||||
#define KCOV_ENTRY_SIZE sizeof(kcov_pc_t)
|
||||
|
||||
/*
|
||||
* One KCOVInstance is allocated per process, when the process opens /dev/kcov
|
||||
* for the first time. At this point it is in state OPENED. When a thread in
|
||||
* the same process then uses the KCOV_ENABLE ioctl on the block device, the
|
||||
* instance enters state TRACING.
|
||||
*
|
||||
* A KCOVInstance in state TRACING can return to state OPENED by either the
|
||||
* KCOV_DISABLE ioctl or by killing the thread. A KCOVInstance in state OPENED
|
||||
* can return to state UNUSED only when the process dies. At this point
|
||||
* KCOVDevice::free_process will delete the KCOVInstance.
|
||||
*/
|
||||
class KCOVInstance final {
|
||||
public:
|
||||
explicit KCOVInstance(ProcessID pid);
|
||||
|
||||
int buffer_allocate(size_t buffer_size_in_entries);
|
||||
bool has_buffer() const { return m_buffer != nullptr; }
|
||||
void buffer_add_pc(u64 pc);
|
||||
|
||||
SpinLock<u8> lock;
|
||||
enum {
|
||||
UNUSED = 0,
|
||||
OPENED = 1,
|
||||
TRACING = 2,
|
||||
} state;
|
||||
|
||||
RefPtr<AnonymousVMObject> vmobject;
|
||||
|
||||
private:
|
||||
ProcessID m_pid = { 0 };
|
||||
u64 m_buffer_size_in_entries = { 0 };
|
||||
size_t m_buffer_size_in_bytes = { 0 };
|
||||
kcov_pc_t* m_buffer = { nullptr };
|
||||
|
||||
// Here to ensure it's not garbage collected at the end of open()
|
||||
OwnPtr<Region> m_kernel_region;
|
||||
};
|
||||
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue