Skip to content

Commit 6cd0dd9

Browse files
dvyukovKAGA-KOKO
authored andcommitted
kcov: Add interrupt handling self test
Add a boot self test that can catch sprious coverage from interrupts. The coverage callback filters out interrupt code, but only after the handler updates preempt count. Some code periodically leaks out of that section and leads to spurious coverage. Add a best-effort (but simple) test that is likely to catch such bugs. If the test is enabled on CI systems that use KCOV, they should catch any issues fast. Signed-off-by: Dmitry Vyukov <[email protected]> Signed-off-by: Thomas Gleixner <[email protected]> Reviewed-by: Alexander Potapenko <[email protected]> Reviewed-by: Marco Elver <[email protected]> Reviewed-by: Andrey Konovalov <[email protected]> Link: https://lore.kernel.org/all/7662127c97e29da1a748ad1c1539dd7b65b737b2.1718092070.git.dvyukov@google.com
1 parent 477d81a commit 6cd0dd9

File tree

2 files changed

+39
-0
lines changed

2 files changed

+39
-0
lines changed

kernel/kcov.c

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include <linux/fs.h>
1212
#include <linux/hashtable.h>
1313
#include <linux/init.h>
14+
#include <linux/jiffies.h>
1415
#include <linux/kmsan-checks.h>
1516
#include <linux/mm.h>
1617
#include <linux/preempt.h>
@@ -1058,6 +1059,32 @@ u64 kcov_common_handle(void)
10581059
}
10591060
EXPORT_SYMBOL(kcov_common_handle);
10601061

1062+
#ifdef CONFIG_KCOV_SELFTEST
1063+
static void __init selftest(void)
1064+
{
1065+
unsigned long start;
1066+
1067+
pr_err("running self test\n");
1068+
/*
1069+
* Test that interrupts don't produce spurious coverage.
1070+
* The coverage callback filters out interrupt code, but only
1071+
* after the handler updates preempt count. Some code periodically
1072+
* leaks out of that section and leads to spurious coverage.
1073+
* It's hard to call the actual interrupt handler directly,
1074+
* so we just loop here for a bit waiting for a timer interrupt.
1075+
* We set kcov_mode to enable tracing, but don't setup the area,
1076+
* so any attempt to trace will crash. Note: we must not call any
1077+
* potentially traced functions in this region.
1078+
*/
1079+
start = jiffies;
1080+
current->kcov_mode = KCOV_MODE_TRACE_PC;
1081+
while ((jiffies - start) * MSEC_PER_SEC / HZ < 300)
1082+
;
1083+
current->kcov_mode = 0;
1084+
pr_err("done running self test\n");
1085+
}
1086+
#endif
1087+
10611088
static int __init kcov_init(void)
10621089
{
10631090
int cpu;
@@ -1077,6 +1104,10 @@ static int __init kcov_init(void)
10771104
*/
10781105
debugfs_create_file_unsafe("kcov", 0600, NULL, NULL, &kcov_fops);
10791106

1107+
#ifdef CONFIG_KCOV_SELFTEST
1108+
selftest();
1109+
#endif
1110+
10801111
return 0;
10811112
}
10821113

lib/Kconfig.debug

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2173,6 +2173,14 @@ config KCOV_IRQ_AREA_SIZE
21732173
soft interrupts. This specifies the size of those areas in the
21742174
number of unsigned long words.
21752175

2176+
config KCOV_SELFTEST
2177+
bool "Perform short selftests on boot"
2178+
depends on KCOV
2179+
help
2180+
Run short KCOV coverage collection selftests on boot.
2181+
On test failure, causes the kernel to panic. Recommended to be
2182+
enabled, ensuring critical functionality works as intended.
2183+
21762184
menuconfig RUNTIME_TESTING_MENU
21772185
bool "Runtime Testing"
21782186
default y

0 commit comments

Comments
 (0)