x86/entry: Remove unwanted instrumentation in common_interrupt()
Subsystems (4)
A message that is not in the archive (sent off-list or not yet received): [email protected]
Dmitry Vyukov
reviewerPATCH 1/4 x86/entry: Remove unwanted instrumentation in common_interrupt()
common_interrupt() and friends call kvm_set_cpu_l1tf_flush_l1d(), which is not marked as noinstr nor __always_inline.
So compiler outlines it and adds instrumentation to it. Since the call is inside of instrumentation_begin/end(), objtool does not warn about it.
The manifestation is that KCOV produces spurious coverage in kvm_set_cpu_l1tf_flush_l1d() in random places because the call happens when preempt count is not yet updated to say that we are in an interrupt.
Mark kvm_set_cpu_l1tf_flush_l1d() as __always_inline and move out of instrumentation_begin/end() section.
It only calls __this_cpu_write() which is already safe to call in noinstr contexts.
--- arch/x86/include/asm/hardirq.h | 8 ++++++-- arch/x86/include/asm/idtentry.h | 6 +++--- 2 files changed, 9 insertions(+), 5 deletions(-)
arch/x86/include/asm/hardirq.h +6 -2
@@ -69,7 +69,11 @@ extern u64 arch_irq_stat(void);#define local_softirq_pending_ref pcpu_hot.softirq_pending#if IS_ENABLED (CONFIG_KVM_INTEL ) -static inline void kvm_set_cpu_l1tf_flush_l1d (void ) +/* +* This function is called from noinstr interrupt contexts +* and must be inlined to not get instrumentation. +*/ +static __always_inline void kvm_set_cpu_l1tf_flush_l1d(void) {__this_cpu_write (irq_stat.kvm_cpu_l1tf_flush_l1d,1 ); }
@@ -84,7 +88,7 @@ static __always_inline bool kvm_get_cpu_l1tf_flush_l1d(void)return __this_cpu_read (irq_stat.kvm_cpu_l1tf_flush_l1d); }#else /* !IS_ENABLED(CONFIG_KVM_INTEL) */ -static inline void kvm_set_cpu_l1tf_flush_l1d (void ) { } +static __always_inline void kvm_set_cpu_l1tf_flush_l1d(void) { }#endif /* IS_ENABLED(CONFIG_KVM_INTEL) */ #endif /* _ASM_X86_HARDIRQ_H */
arch/x86/include/asm/idtentry.h +3 -3
@@ -212,8 +212,8 @@ __visible noinstr void func(struct pt_regs *regs, \irqentry_state_t state =irqentry_enter (regs); \u32 vector = (u32 )(u8 )error_code; \ \ +kvm_set_cpu_l1tf_flush_l1d (); \instrumentation_begin (); \ -kvm_set_cpu_l1tf_flush_l1d (); \ run_irq_on_irqstack_cond(__##func, regs, vector); \ instrumentation_end(); \ irqentry_exit(regs, state); \
@@ -250,7 +250,6 @@ static void __##func(struct pt_regs *regs); \ \ static __always_inline void instr_##func(struct pt_regs *regs) \ { \ - kvm_set_cpu_l1tf_flush_l1d(); \ run_sysvec_on_irqstack_cond(__##func, regs); \ } \ \
@@ -258,6 +257,7 @@ __visible noinstr void func(struct pt_regs *regs) \ { \irqentry_state_t state =irqentry_enter (regs); \ \ +kvm_set_cpu_l1tf_flush_l1d (); \instrumentation_begin (); \ instr_##func (regs); \instrumentation_end (); \
@@ -288,7 +288,6 @@ static __always_inline void __##func(struct pt_regs *regs); \ static __always_inline void instr_##func(struct pt_regs *regs) \ { \ __irq_enter_raw(); \ - kvm_set_cpu_l1tf_flush_l1d(); \ __##func (regs); \ __irq_exit_raw(); \ } \
@@ -297,6 +296,7 @@ __visible noinstr void func(struct pt_regs *regs) \ { \irqentry_state_t state =irqentry_enter (regs); \ \ +kvm_set_cpu_l1tf_flush_l1d (); \instrumentation_begin (); \ instr_##func (regs); \instrumentation_end (); \
Signature · 1 line
2.45.1.467.gbab1589fc0-goog
Quoted 12 lines · Dmitry Vyukov
common_interrupt()and friends callkvm_set_cpu_l1tf_flush_l1d(), which is not marked as noinstr nor__always_inline.
So compiler outlines it and adds instrumentation to it. Since the call is inside of instrumentation_begin/end(), objtool does not warn about it.The manifestation is that KCOV produces spurious coverage in
kvm_set_cpu_l1tf_flush_l1d()in random places because the call happens when preempt count is not yet updated to say that we are in an interrupt.
Quoted 6 lines
Mark
kvm_set_cpu_l1tf_flush_l1d()as__always_inlineand move out of instrumentation_begin/end() section.
It only calls__this_cpu_write()which is already safe to call in noinstr contexts.Signed-off-by Dmitry Vyukov <[email protected]>
Quoted 9 lines · Dmitry Vyukov
The manifestation is that KCOV produces spurious coverage in
kvm_set_cpu_l1tf_flush_l1d()in random places because the call happens when preempt count is not yet updated to say that we are in an interrupt.Mark
kvm_set_cpu_l1tf_flush_l1d()as__always_inlineand move out of instrumentation_begin/end() section.
It only calls__this_cpu_write()which is already safe to call in noinstr contexts.
I've internalized the main rules around noinstr to basically be: Only call noinstr functions before begin_instrumentation(). Second, try to minimize the amount of noinstr code.
This patch seems to be adding another rule which is that all code before preempt_count manipulation needs to be noinstr.
_Is_ that a new rule, or was it something I was missing?
Dmitry Vyukov
reviewerQuoted 12 lines · Dave Hansen
Quoted 9 lines · Dmitry Vyukov
The manifestation is that KCOV produces spurious coverage in
kvm_set_cpu_l1tf_flush_l1d()in random places because the call happens when preempt count is not yet updated to say that we are in an interrupt.Mark
kvm_set_cpu_l1tf_flush_l1d()as__always_inlineand move out of instrumentation_begin/end() section.
It only calls__this_cpu_write()which is already safe to call in noinstr contexts.
Quoted 8 lines
I've internalized the main rules around noinstr to basically be: Only call noinstr functions before
begin_instrumentation(). Second, try to minimize the amount of noinstr code.This patch seems to be adding another rule which is that all code before
preempt_countmanipulation needs to be noinstr._Is_ that a new rule, or was it something I was missing?
Hi Dave,
This is an old rule. KCOV was always intended to not trace interrupts:
+void __sanitizer_cov_trace_pc(void)
+{
+ /*
+ * We are interested in code coverage as a function of a
syscall inputs,
+ * so we ignore code executed in interrupts. + */ + if (!t || in_interrupt())
+ return;
At the time the entry code was in asm and wasn't instrumented by the compiler, so the in_interrupt() check was enough to avoid all problems.
Quoted 11 lines · Dave Hansen
Quoted 9 lines · Dmitry Vyukov
The manifestation is that KCOV produces spurious coverage in
kvm_set_cpu_l1tf_flush_l1d()in random places because the call happens when preempt count is not yet updated to say that we are in an interrupt.Mark
kvm_set_cpu_l1tf_flush_l1d()as__always_inlineand move out of instrumentation_begin/end() section.
It only calls__this_cpu_write()which is already safe to call in noinstr contexts.
Quoted 8 lines
I've internalized the main rules around noinstr to basically be: Only call noinstr functions before
begin_instrumentation(). Second, try to minimize the amount of noinstr code.This patch seems to be adding another rule which is that all code before
preempt_countmanipulation needs to be noinstr._Is_ that a new rule, or was it something I was missing?
Specifically, the problem here appears to be that the instrumentation cannot correctly identify the context because the HARDIRQ_MASK bits aren't yet set in preempt_count.
So the preempt_count manipulations as such are not the problem, but the fact that we call into instrumentation code that seems to rely on using the preempt_count to determine context is.
Does that clarify?
Dmitry Vyukov
reviewerPATCH 2/4 kcov: add interrupt handling self test
In reply to a message not in the archiveAdd 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.
---
In my local testing w/o the previous fix,
it immidiatly produced the following splat:
kcov: running selftest
BUG: TASK stack guard page was hit at ffffc90000147ff8 Oops: stack guard page: 0000 [#1] PREEMPT SMP KASAN PTI ... kvm_set_cpu_l1tf_flush_l1d+0x5/0x20 sysvec_call_function+0x15/0xb0 asm_sysvec_call_function+0x1a/0x20 kcov_init+0xe4/0x130 do_one_initcall+0xbc/0x470 kernel_init_freeable+0x4fc/0x930 kernel_init+0x1c/0x2b0 --- kernel/kcov.c | 28 ++++++++++++++++++++++++++++ lib/Kconfig.debug | 9 +++++++++ 2 files changed, 37 insertions(+)
kernel/kcov.c +28 -0
@@ -1057,6 +1057,30 @@ u64 kcov_common_handle(void) }EXPORT_SYMBOL (kcov_common_handle); +#ifdef CONFIG_KCOV_TEST +static void __init selftest (void ) +{ +volatile int i; + +pr_err ("running self test\n" ); +/* +* Test that interrupts don't produce spurious coverage. +* 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. +* It's hard to call the actual interrupt handler directly, +* so we just loop here for ~400 ms waiting for a timer interrupt. +* We set kcov_mode to enable tracing, but don't setup the area, +* so any attempt to trace will crash. +*/ + current->kcov_mode =KCOV_MODE_TRACE_PC ; +for (i =0 ; i < (1 <<28 ); i++) + ; + current->kcov_mode =0 ; +pr_err ("done running self test\n" ); +} +#endif +static int __init kcov_init (void ) {int cpu;
@@ -1076,6 +1100,10 @@ static int __init kcov_init(void)*/ debugfs_create_file_unsafe ("kcov" ,0600 ,NULL ,NULL , &kcov_fops); +#ifdef CONFIG_KCOV_TEST +selftest (); +#endif +return 0 ; }
lib/Kconfig.debug +9 -0
@@ -2171,6 +2171,15 @@ config KCOV_IRQ_AREA_SIZE soft interrupts. This specifies the size of those areas in the number of unsigned long words. +config KCOV_TEST + bool "Test CONFIG_KCOV feature" + depends on KCOV + help + Sanity check for KCOV coverage collection. + Runs built-in self test on boot to detect some common issues. + + If unsure, say N. + menuconfig RUNTIME_TESTING_MENU bool "Runtime Testing" default y
Signature · 1 line
2.45.1.467.gbab1589fc0-goog
Re: [PATCH 2/4] kcov: add interrupt handling self test
Quoted 9 lines · Dmitry Vyukov
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.
Quoted 4 lines
Signed-off-by Dmitry Vyukov <[email protected]>
Re: [PATCH 2/4] kcov: add interrupt handling self test
In reply to Dmitry VyukovQuoted 46 lines · Dmitry Vyukov
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]>---
In my local testing w/o the previous fix,
it immidiatly produced the following splat:kcov: running selftest
BUG: TASK stack guard page was hit at ffffc90000147ff8 Oops: stack guard page: 0000 [#1] PREEMPT SMP KASAN PTI ... kvm_set_cpu_l1tf_flush_l1d+0x5/0x20 sysvec_call_function+0x15/0xb0 asm_sysvec_call_function+0x1a/0x20 kcov_init+0xe4/0x130 do_one_initcall+0xbc/0x470 kernel_init_freeable+0x4fc/0x930 kernel_init+0x1c/0x2b0 --- kernel/kcov.c | 28 ++++++++++++++++++++++++++++ lib/Kconfig.debug | 9 +++++++++ 2 files changed, 37 insertions(+)kernel/kcov.c +3
-0@@ -1057,6 +1057,30 @@ u64 kcov_common_handle(void) }EXPORT_SYMBOL (kcov_common_handle); +#ifdef CONFIG_KCOV_TEST +static void __init selftest (void ) +{
kernel/kcov.c u64 kcov_common_handle(void) · line 1072
Quoted 10 lines
kernel/kcov.c +10
-0+volatile int i; + +pr_err ("running self test\n" ); +/* +* Test that interrupts don't produce spurious coverage. +* 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. +* It's hard to call the actual interrupt handler directly, +* so we just loop here for ~400 ms waiting for a timer interrupt.
Where do the 400 ms come from? I only see that it loops a long time, but that the timing is entirely dependent on how fast the CPU executes the loop.
kernel/kcov.c u64 kcov_common_handle(void) · line 1078
Quoted 6 lines
kernel/kcov.c +6
-0+* We set kcov_mode to enable tracing, but don't setup the area, +* so any attempt to trace will crash. +*/ + current->kcov_mode =KCOV_MODE_TRACE_PC ; +for (i =0 ; i < (1 <<28 ); i++) + ;
Can't you check jiffies, and e.g. check that actual ~100-500ms have elapsed?
timeout = jiffies + msecs_to_jiffies(300);
while (!time_after(jiffies, timeout)) {
cpu_relax();
}
Quoted 24 lines
kernel/kcov.c +9
-0+ current->kcov_mode =0 ; + pr_err("done running self test\n"); +} +#endif +static int __init kcov_init (void ) {int cpu;@@ -1076,6 +1100,10 @@ static int __init kcov_init(void)*/ debugfs_create_file_unsafe ("kcov" ,0600 ,NULL ,NULL , &kcov_fops); +#ifdef CONFIG_KCOV_TEST +selftest (); +#endif +return 0 ; }lib/Kconfig.debug +0
-0
lib/Kconfig.debug config KCOV_IRQ_AREA_SIZE · line 2174
Quoted 4 lines
lib/Kconfig.debug +1
-0@@ -2171,6 +2171,15 @@ config KCOV_IRQ_AREA_SIZE soft interrupts. This specifies the size of those areas in the number of unsigned long words. +config KCOV_TEST
s/TEST/SELFTEST/
It may be confused with a longer standalone test.
lib/Kconfig.debug config KCOV_IRQ_AREA_SIZE · line 2175
Quoted 1 line
lib/Kconfig.debug +1
-0+ bool "Test CONFIG_KCOV feature"
Maybe "Perform short selftests on boot" (similar to CONFIG_KCSAN_SELFTEST).
Quoted 13 lines
lib/Kconfig.debug +7
-1+ depends on KCOV + help + Sanity check for KCOV coverage collection. + Runs built-in self test on boot to detect some common issues. + + If unsure, say N. + menuconfig RUNTIME_TESTING_MENU bool "Runtime Testing" default y --2.45.1.467.gbab1589fc0-goog
Dmitry Vyukov
reviewerRe: [PATCH 2/4] kcov: add interrupt handling self test
Quoted 68 lines · Marco Elver
Quoted 46 lines
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]>---
In my local testing w/o the previous fix,
it immidiatly produced the following splat:kcov: running selftest
BUG: TASK stack guard page was hit at ffffc90000147ff8 Oops: stack guard page: 0000 [#1] PREEMPT SMP KASAN PTI ... kvm_set_cpu_l1tf_flush_l1d+0x5/0x20 sysvec_call_function+0x15/0xb0 asm_sysvec_call_function+0x1a/0x20 kcov_init+0xe4/0x130 do_one_initcall+0xbc/0x470 kernel_init_freeable+0x4fc/0x930 kernel_init+0x1c/0x2b0 --- kernel/kcov.c | 28 ++++++++++++++++++++++++++++ lib/Kconfig.debug | 9 +++++++++ 2 files changed, 37 insertions(+)kernel/kcov.c +3
-0@@ -1057,6 +1057,30 @@ u64 kcov_common_handle(void) }EXPORT_SYMBOL (kcov_common_handle); +#ifdef CONFIG_KCOV_TEST +static void __init selftest (void ) +{kernel/kcov.c u64 kcov_common_handle(void) · line 1072
Quoted 10 lines
kernel/kcov.c +10
-0+volatile int i; + +pr_err ("running self test\n" ); +/* +* Test that interrupts don't produce spurious coverage. +* 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. +* It's hard to call the actual interrupt handler directly, +* so we just loop here for ~400 ms waiting for a timer interrupt. Where do the 400 ms come from? I only see that it loops a long time, but that the timing is entirely dependent on how fast the CPU executes the loop.
kernel/kcov.c u64 kcov_common_handle(void) · line 1078
Quoted 6 lines
kernel/kcov.c +6
-0+* We set kcov_mode to enable tracing, but don't setup the area, +* so any attempt to trace will crash. +*/ + current->kcov_mode =KCOV_MODE_TRACE_PC ; +for (i =0 ; i < (1 <<28 ); i++) + ;
Quoted 6 lines
Can't you check jiffies, and e.g. check that actual ~100-500ms have elapsed?
timeout = jiffies +
msecs_to_jiffies(300);
while (!time_after(jiffies, timeout)) {
cpu_relax();
}
We can't call any functions. If anything is instrumented, the kernel crashes.
But just reading jiffies should be fine, so we can do:
unsigned long start = jiffies;
while ((jiffies - start) * MSEC_PER_SEC / HZ < 500) ;
Quoted 50 lines
Quoted 24 lines
kernel/kcov.c +9
-0+ current->kcov_mode =0 ; + pr_err("done running self test\n"); +} +#endif +static int __init kcov_init (void ) {int cpu;@@ -1076,6 +1100,10 @@ static int __init kcov_init(void)*/ debugfs_create_file_unsafe ("kcov" ,0600 ,NULL ,NULL , &kcov_fops); +#ifdef CONFIG_KCOV_TEST +selftest (); +#endif +return 0 ; }lib/Kconfig.debug +0
-0lib/Kconfig.debug config KCOV_IRQ_AREA_SIZE · line 2174
Quoted 4 lines
lib/Kconfig.debug +1
-0@@ -2171,6 +2171,15 @@ config KCOV_IRQ_AREA_SIZE soft interrupts. This specifies the size of those areas in the number of unsigned long words. +config KCOV_TESTs/TEST/SELFTEST/
It may be confused with a longer standalone test.
lib/Kconfig.debug config KCOV_IRQ_AREA_SIZE · line 2175
Quoted 1 line
lib/Kconfig.debug +1
-0+ bool "Test CONFIG_KCOV feature"Maybe "Perform short selftests on boot" (similar to
CONFIG_KCSAN_SELFTEST).Quoted 13 lines
lib/Kconfig.debug +7
-1+ depends on KCOV + help + Sanity check for KCOV coverage collection. + Runs built-in self test on boot to detect some common issues. + + If unsure, say N. + menuconfig RUNTIME_TESTING_MENU bool "Runtime Testing" default y --2.45.1.467.gbab1589fc0-goog
Re: [PATCH 2/4] kcov: add interrupt handling self test
Quoted 77 lines · Dmitry Vyukov
Quoted 68 lines · Marco Elver
Quoted 46 lines
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]>---
In my local testing w/o the previous fix,
it immidiatly produced the following splat:kcov: running selftest
BUG: TASK stack guard page was hit at ffffc90000147ff8 Oops: stack guard page: 0000 [#1] PREEMPT SMP KASAN PTI ... kvm_set_cpu_l1tf_flush_l1d+0x5/0x20 sysvec_call_function+0x15/0xb0 asm_sysvec_call_function+0x1a/0x20 kcov_init+0xe4/0x130 do_one_initcall+0xbc/0x470 kernel_init_freeable+0x4fc/0x930 kernel_init+0x1c/0x2b0 --- kernel/kcov.c | 28 ++++++++++++++++++++++++++++ lib/Kconfig.debug | 9 +++++++++ 2 files changed, 37 insertions(+)kernel/kcov.c +3
-0@@ -1057,6 +1057,30 @@ u64 kcov_common_handle(void) }EXPORT_SYMBOL (kcov_common_handle); +#ifdef CONFIG_KCOV_TEST +static void __init selftest (void ) +{kernel/kcov.c u64 kcov_common_handle(void) · line 1072
Quoted 10 lines
kernel/kcov.c +10
-0+volatile int i; + +pr_err ("running self test\n" ); +/* +* Test that interrupts don't produce spurious coverage. +* 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. +* It's hard to call the actual interrupt handler directly, +* so we just loop here for ~400 ms waiting for a timer interrupt. Where do the 400 ms come from? I only see that it loops a long time, but that the timing is entirely dependent on how fast the CPU executes the loop.
kernel/kcov.c u64 kcov_common_handle(void) · line 1078
Quoted 6 lines
kernel/kcov.c +6
-0+* We set kcov_mode to enable tracing, but don't setup the area, +* so any attempt to trace will crash. +*/ + current->kcov_mode =KCOV_MODE_TRACE_PC ; +for (i =0 ; i < (1 <<28 ); i++) + ;Quoted 6 lines
Can't you check jiffies, and e.g. check that actual ~100-500ms have elapsed?
timeout = jiffies +
msecs_to_jiffies(300);
while (!time_after(jiffies, timeout)) {
cpu_relax();
}
Quoted 7 lines
We can't call any functions. If anything is instrumented, the kernel crashes.
But just reading jiffies should be fine, so we can do:
unsigned long start = jiffies;
while ((jiffies - start) *MSEC_PER_SEC/ HZ < 500) ;
I'm quite sure that those helpers are macros, but who knows if that will ever change.
The above open-coded version looks reasonable.
Dmitry Vyukov
reviewerRe: [PATCH 2/4] kcov: add interrupt handling self test
Quoted 83 lines · Marco Elver
Quoted 81 lines · Dmitry Vyukov
Quoted 68 lines · Marco Elver
Quoted 46 lines
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]>---
In my local testing w/o the previous fix,
it immidiatly produced the following splat:kcov: running selftest
BUG: TASK stack guard page was hit at ffffc90000147ff8 Oops: stack guard page: 0000 [#1] PREEMPT SMP KASAN PTI ... kvm_set_cpu_l1tf_flush_l1d+0x5/0x20 sysvec_call_function+0x15/0xb0 asm_sysvec_call_function+0x1a/0x20 kcov_init+0xe4/0x130 do_one_initcall+0xbc/0x470 kernel_init_freeable+0x4fc/0x930 kernel_init+0x1c/0x2b0 --- kernel/kcov.c | 28 ++++++++++++++++++++++++++++ lib/Kconfig.debug | 9 +++++++++ 2 files changed, 37 insertions(+)kernel/kcov.c +3
-0@@ -1057,6 +1057,30 @@ u64 kcov_common_handle(void) }EXPORT_SYMBOL (kcov_common_handle); +#ifdef CONFIG_KCOV_TEST +static void __init selftest (void ) +{kernel/kcov.c u64 kcov_common_handle(void) · line 1072
Quoted 10 lines
kernel/kcov.c +10
-0+volatile int i; + +pr_err ("running self test\n" ); +/* +* Test that interrupts don't produce spurious coverage. +* 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. +* It's hard to call the actual interrupt handler directly, +* so we just loop here for ~400 ms waiting for a timer interrupt. Where do the 400 ms come from? I only see that it loops a long time, but that the timing is entirely dependent on how fast the CPU executes the loop.
kernel/kcov.c u64 kcov_common_handle(void) · line 1078
Quoted 6 lines
kernel/kcov.c +6
-0+* We set kcov_mode to enable tracing, but don't setup the area, +* so any attempt to trace will crash. +*/ + current->kcov_mode =KCOV_MODE_TRACE_PC ; +for (i =0 ; i < (1 <<28 ); i++) + ;Quoted 6 lines
Can't you check jiffies, and e.g. check that actual ~100-500ms have elapsed?
timeout = jiffies +
msecs_to_jiffies(300);
while (!time_after(jiffies, timeout)) {
cpu_relax();
}We can't call any functions. If anything is instrumented, the kernel crashes.
But just reading jiffies should be fine, so we can do:
Quoted 8 lines
Quoted 3 lines
unsigned long start = jiffies;
while ((jiffies - start) *MSEC_PER_SEC/ HZ < 500) ;I'm quite sure that those helpers are macros, but who knows if that will ever change.
The above open-coded version looks reasonable.
Sent v2 with fixes, PTAL.
https://lore.kernel.org/all/[email protected]/T/#t
Dmitry Vyukov
reviewerPATCH 3/4 module: Fix KCOV-ignored file name
In reply to a message not in the archiveModule.c was renamed to main.c, but the Makefile directive was copy-pasted verbatim with the old file name. Fix up the file name.
--- kernel/module/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
kernel/module/Makefile +1 -1
@@ -5,7 +5,7 @@ # These are called from save_stack_trace() on slub debug path, # and produce insane amounts of uninteresting coverage. -KCOV_INSTRUMENT_module.o := n +KCOV_INSTRUMENT_main.o := n obj-y += main.o obj-y += strict_rwx.o
Signature · 1 line
2.45.1.467.gbab1589fc0-goog
Re: [PATCH 3/4] module: Fix KCOV-ignored file name
Quoted 11 lines · Dmitry Vyukov
Module.cwas renamed tomain.c, but theMakefiledirective was copy-pasted verbatim with the old file name. Fix up the file name.Signed-off-by Dmitry Vyukov <[email protected]>Fixes cfc1d277891e ("module: Move all into module/")Cc Aaron Tomlin <[email protected]>
Dmitry Vyukov
reviewerPATCH 4/4 x86: Ignore stack unwinding in KCOV
In reply to a message not in the archiveStack unwinding produces large amounts of uninteresting coverage. It's called from KASAN kmalloc/kfree hooks, fault injection, etc. It's not particularly useful and is not a function of system call args. Ignore that code.
--- arch/x86/kernel/Makefile | 8 ++++++++ 1 file changed, 8 insertions(+)
arch/x86/kernel/Makefile +8 -0
@@ -39,6 +39,14 @@ KMSAN_SANITIZE_sev.o := n # first second. KCOV_INSTRUMENT_head$(BITS).o := n KCOV_INSTRUMENT_sev.o := n +# These are called from save_stack_trace() on debug paths, +# and produce large amounts of uninteresting coverage. +KCOV_INSTRUMENT_stacktrace.o := n +KCOV_INSTRUMENT_dumpstack.o := n +KCOV_INSTRUMENT_dumpstack_$(BITS).o := n +KCOV_INSTRUMENT_unwind_orc.o := n +KCOV_INSTRUMENT_unwind_frame.o := n +KCOV_INSTRUMENT_unwind_guess.o := n CFLAGS_irq.o := -I $(src)/../include/asm/trace
Signature · 1 line
2.45.1.467.gbab1589fc0-goog
Re: [PATCH 4/4] x86: Ignore stack unwinding in KCOV
Quoted 10 lines · Dmitry Vyukov' via syzkaller
Stack unwinding produces large amounts of uninteresting coverage. It's called from KASAN kmalloc/kfree hooks, fault injection, etc. It's not particularly useful and is not a function of system call args. Ignore that code.
Signed-off-by Dmitry Vyukov <[email protected]>
Re: [PATCH 4/4] x86: Ignore stack unwinding in KCOV
In reply to Dmitry VyukovQuoted 7 lines · Dmitry Vyukov
Stack unwinding produces large amounts of uninteresting coverage. It's called from KASAN kmalloc/kfree hooks, fault injection, etc. It's not particularly useful and is not a function of system call args. Ignore that code.
Signed-off-by Dmitry Vyukov <[email protected]>
Quoted 29 lines
--- arch/x86/kernel/Makefile | 8 ++++++++ 1 file changed, 8 insertions(+)arch/x86/kernel/Makefile +8
-1@@ -39,6 +39,14 @@ KMSAN_SANITIZE_sev.o := n # first second. KCOV_INSTRUMENT_head$(BITS).o := n KCOV_INSTRUMENT_sev.o := n +# These are called from save_stack_trace() on debug paths, +# and produce large amounts of uninteresting coverage. +KCOV_INSTRUMENT_stacktrace.o := n +KCOV_INSTRUMENT_dumpstack.o := n +KCOV_INSTRUMENT_dumpstack_$(BITS).o := n +KCOV_INSTRUMENT_unwind_orc.o := n +KCOV_INSTRUMENT_unwind_frame.o := n +KCOV_INSTRUMENT_unwind_guess.o := n CFLAGS_irq.o := -I $(src)/../include/asm/trace --2.45.1.467.gbab1589fc0-goog