1- kcov : code coverage for fuzzing
1+ KCOV : code coverage for fuzzing
22===============================
33
4- kcov exposes kernel code coverage information in a form suitable for coverage-
5- guided fuzzing (randomized testing) . Coverage data of a running kernel is
6- exported via the " kcov" debugfs file. Coverage collection is enabled on a task
7- basis, and thus it can capture precise coverage of a single system call.
4+ KCOV collects and exposes kernel code coverage information in a form suitable
5+ for coverage- guided fuzzing. Coverage data of a running kernel is exported via
6+ the `` kcov `` debugfs file. Coverage collection is enabled on a task basis, and
7+ thus KCOV can capture precise coverage of a single system call.
88
9- Note that kcov does not aim to collect as much coverage as possible. It aims
10- to collect more or less stable coverage that is function of syscall inputs.
11- To achieve this goal it does not collect coverage in soft/hard interrupts
12- and instrumentation of some inherently non-deterministic parts of kernel is
13- disabled (e.g. scheduler, locking).
9+ Note that KCOV does not aim to collect as much coverage as possible. It aims
10+ to collect more or less stable coverage that is a function of syscall inputs.
11+ To achieve this goal, it does not collect coverage in soft/hard interrupts
12+ (unless remove coverage collection is enabled, see below) and from some
13+ inherently non-deterministic parts of the kernel (e.g. scheduler, locking).
1414
15- kcov is also able to collect comparison operands from the instrumented code
16- (this feature currently requires that the kernel is compiled with clang).
15+ Besides collecting code coverage, KCOV can also collect comparison operands.
16+ See the "Comparison operands collection" section for details.
17+
18+ Besides collecting coverage data from syscall handlers, KCOV can also collect
19+ coverage for annotated parts of the kernel executing in background kernel
20+ tasks or soft interrupts. See the "Remote coverage collection" section for
21+ details.
1722
1823Prerequisites
1924-------------
2025
21- Configure the kernel with::
26+ KCOV relies on compiler instrumentation and requires GCC 6.1.0 or later
27+ or any Clang version supported by the kernel.
2228
23- CONFIG_KCOV=y
29+ Collecting comparison operands is supported with GCC 8+ or with Clang.
2430
25- CONFIG_KCOV requires gcc 6.1.0 or later.
31+ To enable KCOV, configure the kernel with::
2632
27- If the comparison operands need to be collected, set::
33+ CONFIG_KCOV=y
34+
35+ To enable comparison operands collection, set::
2836
2937 CONFIG_KCOV_ENABLE_COMPARISONS=y
3038
31- Profiling data will only become accessible once debugfs has been mounted::
39+ Coverage data only becomes accessible once debugfs has been mounted::
3240
3341 mount -t debugfs none /sys/kernel/debug
3442
3543Coverage collection
3644-------------------
3745
38- The following program demonstrates coverage collection from within a test
39- program using kcov :
46+ The following program demonstrates how to use KCOV to collect coverage for a
47+ single syscall from within a test program :
4048
4149.. code-block :: c
4250
@@ -84,7 +92,7 @@ program using kcov:
8492 perror("ioctl"), exit(1);
8593 /* Reset coverage from the tail of the ioctl() call. */
8694 __atomic_store_n(&cover[0], 0, __ATOMIC_RELAXED);
87- /* That's the target syscal call. */
95+ /* Call the target syscall call. */
8896 read(-1, NULL, 0);
8997 /* Read number of PCs collected. */
9098 n = __atomic_load_n(&cover[0], __ATOMIC_RELAXED);
@@ -103,7 +111,7 @@ program using kcov:
103111 return 0;
104112 }
105113
106- After piping through addr2line output of the program looks as follows::
114+ After piping through `` addr2line `` the output of the program looks as follows::
107115
108116 SyS_read
109117 fs/read_write.c:562
@@ -121,12 +129,13 @@ After piping through addr2line output of the program looks as follows::
121129 fs/read_write.c:562
122130
123131If a program needs to collect coverage from several threads (independently),
124- it needs to open /sys/kernel/debug/kcov in each thread separately.
132+ it needs to open `` /sys/kernel/debug/kcov `` in each thread separately.
125133
126134The interface is fine-grained to allow efficient forking of test processes.
127- That is, a parent process opens /sys/kernel/debug/kcov, enables trace mode,
128- mmaps coverage buffer and then forks child processes in a loop. Child processes
129- only need to enable coverage (disable happens automatically on thread end).
135+ That is, a parent process opens ``/sys/kernel/debug/kcov ``, enables trace mode,
136+ mmaps coverage buffer, and then forks child processes in a loop. The child
137+ processes only need to enable coverage (it gets disabled automatically when
138+ a thread exits).
130139
131140Comparison operands collection
132141------------------------------
@@ -205,52 +214,78 @@ Comparison operands collection is similar to coverage collection:
205214 return 0;
206215 }
207216
208- Note that the kcov modes (coverage collection or comparison operands) are
209- mutually exclusive.
217+ Note that the KCOV modes (collection of code coverage or comparison operands)
218+ are mutually exclusive.
210219
211220Remote coverage collection
212221--------------------------
213222
214- With KCOV_ENABLE coverage is collected only for syscalls that are issued
215- from the current process. With KCOV_REMOTE_ENABLE it's possible to collect
216- coverage for arbitrary parts of the kernel code, provided that those parts
217- are annotated with kcov_remote_start()/kcov_remote_stop().
218-
219- This allows to collect coverage from two types of kernel background
220- threads: the global ones, that are spawned during kernel boot in a limited
221- number of instances (e.g. one USB hub_event() worker thread is spawned per
222- USB HCD); and the local ones, that are spawned when a user interacts with
223- some kernel interface (e.g. vhost workers); as well as from soft
224- interrupts.
225-
226- To enable collecting coverage from a global background thread or from a
227- softirq, a unique global handle must be assigned and passed to the
228- corresponding kcov_remote_start() call. Then a userspace process can pass
229- a list of such handles to the KCOV_REMOTE_ENABLE ioctl in the handles
230- array field of the kcov_remote_arg struct. This will attach the used kcov
231- device to the code sections, that are referenced by those handles.
232-
233- Since there might be many local background threads spawned from different
234- userspace processes, we can't use a single global handle per annotation.
235- Instead, the userspace process passes a non-zero handle through the
236- common_handle field of the kcov_remote_arg struct. This common handle gets
237- saved to the kcov_handle field in the current task_struct and needs to be
238- passed to the newly spawned threads via custom annotations. Those threads
239- should in turn be annotated with kcov_remote_start()/kcov_remote_stop().
240-
241- Internally kcov stores handles as u64 integers. The top byte of a handle
242- is used to denote the id of a subsystem that this handle belongs to, and
243- the lower 4 bytes are used to denote the id of a thread instance within
244- that subsystem. A reserved value 0 is used as a subsystem id for common
245- handles as they don't belong to a particular subsystem. The bytes 4-7 are
246- currently reserved and must be zero. In the future the number of bytes
247- used for the subsystem or handle ids might be increased.
248-
249- When a particular userspace process collects coverage via a common
250- handle, kcov will collect coverage for each code section that is annotated
251- to use the common handle obtained as kcov_handle from the current
252- task_struct. However non common handles allow to collect coverage
253- selectively from different subsystems.
223+ Besides collecting coverage data from handlers of syscalls issued from a
224+ userspace process, KCOV can also collect coverage for parts of the kernel
225+ executing in other contexts - so-called "remote" coverage.
226+
227+ Using KCOV to collect remote coverage requires:
228+
229+ 1. Modifying kernel code to annotate the code section from where coverage
230+ should be collected with ``kcov_remote_start `` and ``kcov_remote_stop ``.
231+
232+ 2. Using ``KCOV_REMOTE_ENABLE `` instead of ``KCOV_ENABLE `` in the userspace
233+ process that collects coverage.
234+
235+ Both ``kcov_remote_start `` and ``kcov_remote_stop `` annotations and the
236+ ``KCOV_REMOTE_ENABLE `` ioctl accept handles that identify particular coverage
237+ collection sections. The way a handle is used depends on the context where the
238+ matching code section executes.
239+
240+ KCOV supports collecting remote coverage from the following contexts:
241+
242+ 1. Global kernel background tasks. These are the tasks that are spawned during
243+ kernel boot in a limited number of instances (e.g. one USB ``hub_event ``
244+ worker is spawned per one USB HCD).
245+
246+ 2. Local kernel background tasks. These are spawned when a userspace process
247+ interacts with some kernel interface and are usually killed when the process
248+ exits (e.g. vhost workers).
249+
250+ 3. Soft interrupts.
251+
252+ For #1 and #3, a unique global handle must be chosen and passed to the
253+ corresponding ``kcov_remote_start `` call. Then a userspace process must pass
254+ this handle to ``KCOV_REMOTE_ENABLE `` in the ``handles `` array field of the
255+ ``kcov_remote_arg `` struct. This will attach the used KCOV device to the code
256+ section referenced by this handle. Multiple global handles identifying
257+ different code sections can be passed at once.
258+
259+ For #2, the userspace process instead must pass a non-zero handle through the
260+ ``common_handle `` field of the ``kcov_remote_arg `` struct. This common handle
261+ gets saved to the ``kcov_handle `` field in the current ``task_struct `` and
262+ needs to be passed to the newly spawned local tasks via custom kernel code
263+ modifications. Those tasks should in turn use the passed handle in their
264+ ``kcov_remote_start `` and ``kcov_remote_stop `` annotations.
265+
266+ KCOV follows a predefined format for both global and common handles. Each
267+ handle is a ``u64 `` integer. Currently, only the one top and the lower 4 bytes
268+ are used. Bytes 4-7 are reserved and must be zero.
269+
270+ For global handles, the top byte of the handle denotes the id of a subsystem
271+ this handle belongs to. For example, KCOV uses ``1 `` as the USB subsystem id.
272+ The lower 4 bytes of a global handle denote the id of a task instance within
273+ that subsystem. For example, each ``hub_event `` worker uses the USB bus number
274+ as the task instance id.
275+
276+ For common handles, a reserved value ``0 `` is used as a subsystem id, as such
277+ handles don't belong to a particular subsystem. The lower 4 bytes of a common
278+ handle identify a collective instance of all local tasks spawned by the
279+ userspace process that passed a common handle to ``KCOV_REMOTE_ENABLE ``.
280+
281+ In practice, any value can be used for common handle instance id if coverage
282+ is only collected from a single userspace process on the system. However, if
283+ common handles are used by multiple processes, unique instance ids must be
284+ used for each process. One option is to use the process id as the common
285+ handle instance id.
286+
287+ The following program demonstrates using KCOV to collect coverage from both
288+ local tasks spawned by the process and the global task that handles USB bus #1:
254289
255290.. code-block :: c
256291
0 commit comments