[PATCH v5 15/19] kasan: x86: Apply multishot to the inline report handler

Maciej Wieczor-Retman posted 19 patches 1 month, 1 week ago
[PATCH v5 15/19] kasan: x86: Apply multishot to the inline report handler
Posted by Maciej Wieczor-Retman 1 month, 1 week ago
KASAN by default reports only one tag mismatch and based on other
command line parameters either keeps going or panics. The multishot
mechanism - enabled either through a command line parameter or by inline
enable/disable function calls - lifts that restriction and allows an
infinite number of tag mismatch reports to be shown.

Inline KASAN uses the INT3 instruction to pass metadata to the report
handling function. Currently the "recover" field in that metadata is
broken in the compiler layer and causes every inline tag mismatch to
panic the kernel.

Check the multishot state in the KASAN hook called inside the INT3
handling function.

Signed-off-by: Maciej Wieczor-Retman <maciej.wieczor-retman@intel.com>
---
Changelog v4:
- Add this patch to the series.

 arch/x86/mm/kasan_inline.c | 3 +++
 include/linux/kasan.h      | 3 +++
 mm/kasan/report.c          | 8 +++++++-
 3 files changed, 13 insertions(+), 1 deletion(-)

diff --git a/arch/x86/mm/kasan_inline.c b/arch/x86/mm/kasan_inline.c
index 9f85dfd1c38b..f837caf32e6c 100644
--- a/arch/x86/mm/kasan_inline.c
+++ b/arch/x86/mm/kasan_inline.c
@@ -17,6 +17,9 @@ bool kasan_inline_handler(struct pt_regs *regs)
 	if (!kasan_report((void *)addr, size, write, pc))
 		return false;
 
+	if (kasan_multi_shot_enabled())
+		return true;
+
 	kasan_inline_recover(recover, "Oops - KASAN", regs, metadata, die);
 
 	return true;
diff --git a/include/linux/kasan.h b/include/linux/kasan.h
index 8691ad870f3b..7a2527794549 100644
--- a/include/linux/kasan.h
+++ b/include/linux/kasan.h
@@ -663,7 +663,10 @@ void kasan_non_canonical_hook(unsigned long addr);
 static inline void kasan_non_canonical_hook(unsigned long addr) { }
 #endif /* CONFIG_KASAN_GENERIC || CONFIG_KASAN_SW_TAGS */
 
+bool kasan_multi_shot_enabled(void);
+
 #ifdef CONFIG_KASAN_SW_TAGS
+
 /*
  * The instrumentation allows to control whether we can proceed after
  * a crash was detected. This is done by passing the -recover flag to
diff --git a/mm/kasan/report.c b/mm/kasan/report.c
index 50d487a0687a..9e830639e1b2 100644
--- a/mm/kasan/report.c
+++ b/mm/kasan/report.c
@@ -121,6 +121,12 @@ static void report_suppress_stop(void)
 #endif
 }
 
+bool kasan_multi_shot_enabled(void)
+{
+	return test_bit(KASAN_BIT_MULTI_SHOT, &kasan_flags);
+}
+EXPORT_SYMBOL(kasan_multi_shot_enabled);
+
 /*
  * Used to avoid reporting more than one KASAN bug unless kasan_multi_shot
  * is enabled. Note that KASAN tests effectively enable kasan_multi_shot
@@ -128,7 +134,7 @@ static void report_suppress_stop(void)
  */
 static bool report_enabled(void)
 {
-	if (test_bit(KASAN_BIT_MULTI_SHOT, &kasan_flags))
+	if (kasan_multi_shot_enabled())
 		return true;
 	return !test_and_set_bit(KASAN_BIT_REPORTED, &kasan_flags);
 }
-- 
2.50.1
Re: [PATCH v5 15/19] kasan: x86: Apply multishot to the inline report handler
Posted by Andrey Konovalov 3 weeks, 6 days ago
On Mon, Aug 25, 2025 at 10:30 PM Maciej Wieczor-Retman
<maciej.wieczor-retman@intel.com> wrote:
>
> KASAN by default reports only one tag mismatch and based on other
> command line parameters either keeps going or panics. The multishot
> mechanism - enabled either through a command line parameter or by inline
> enable/disable function calls - lifts that restriction and allows an
> infinite number of tag mismatch reports to be shown.
>
> Inline KASAN uses the INT3 instruction to pass metadata to the report
> handling function. Currently the "recover" field in that metadata is
> broken in the compiler layer and causes every inline tag mismatch to
> panic the kernel.
>
> Check the multishot state in the KASAN hook called inside the INT3
> handling function.
>
> Signed-off-by: Maciej Wieczor-Retman <maciej.wieczor-retman@intel.com>
> ---
> Changelog v4:
> - Add this patch to the series.
>
>  arch/x86/mm/kasan_inline.c | 3 +++
>  include/linux/kasan.h      | 3 +++
>  mm/kasan/report.c          | 8 +++++++-
>  3 files changed, 13 insertions(+), 1 deletion(-)
>
> diff --git a/arch/x86/mm/kasan_inline.c b/arch/x86/mm/kasan_inline.c
> index 9f85dfd1c38b..f837caf32e6c 100644
> --- a/arch/x86/mm/kasan_inline.c
> +++ b/arch/x86/mm/kasan_inline.c
> @@ -17,6 +17,9 @@ bool kasan_inline_handler(struct pt_regs *regs)
>         if (!kasan_report((void *)addr, size, write, pc))
>                 return false;
>
> +       if (kasan_multi_shot_enabled())
> +               return true;

It's odd this this is required on x86 but not on arm64, see my comment
on the patch that adds kasan_inline_handler().



> +
>         kasan_inline_recover(recover, "Oops - KASAN", regs, metadata, die);
>
>         return true;
> diff --git a/include/linux/kasan.h b/include/linux/kasan.h
> index 8691ad870f3b..7a2527794549 100644
> --- a/include/linux/kasan.h
> +++ b/include/linux/kasan.h
> @@ -663,7 +663,10 @@ void kasan_non_canonical_hook(unsigned long addr);
>  static inline void kasan_non_canonical_hook(unsigned long addr) { }
>  #endif /* CONFIG_KASAN_GENERIC || CONFIG_KASAN_SW_TAGS */
>
> +bool kasan_multi_shot_enabled(void);
> +
>  #ifdef CONFIG_KASAN_SW_TAGS
> +
>  /*
>   * The instrumentation allows to control whether we can proceed after
>   * a crash was detected. This is done by passing the -recover flag to
> diff --git a/mm/kasan/report.c b/mm/kasan/report.c
> index 50d487a0687a..9e830639e1b2 100644
> --- a/mm/kasan/report.c
> +++ b/mm/kasan/report.c
> @@ -121,6 +121,12 @@ static void report_suppress_stop(void)
>  #endif
>  }
>
> +bool kasan_multi_shot_enabled(void)
> +{
> +       return test_bit(KASAN_BIT_MULTI_SHOT, &kasan_flags);
> +}
> +EXPORT_SYMBOL(kasan_multi_shot_enabled);
> +
>  /*
>   * Used to avoid reporting more than one KASAN bug unless kasan_multi_shot
>   * is enabled. Note that KASAN tests effectively enable kasan_multi_shot
> @@ -128,7 +134,7 @@ static void report_suppress_stop(void)
>   */
>  static bool report_enabled(void)
>  {
> -       if (test_bit(KASAN_BIT_MULTI_SHOT, &kasan_flags))
> +       if (kasan_multi_shot_enabled())
>                 return true;
>         return !test_and_set_bit(KASAN_BIT_REPORTED, &kasan_flags);
>  }
> --
> 2.50.1
>
Re: [PATCH v5 15/19] kasan: x86: Apply multishot to the inline report handler
Posted by Maciej Wieczor-Retman 3 weeks, 4 days ago
On 2025-09-06 at 19:19:06 +0200, Andrey Konovalov wrote:
>On Mon, Aug 25, 2025 at 10:30 PM Maciej Wieczor-Retman
><maciej.wieczor-retman@intel.com> wrote:
>>
>> KASAN by default reports only one tag mismatch and based on other
>> command line parameters either keeps going or panics. The multishot
>> mechanism - enabled either through a command line parameter or by inline
>> enable/disable function calls - lifts that restriction and allows an
>> infinite number of tag mismatch reports to be shown.
>>
>> Inline KASAN uses the INT3 instruction to pass metadata to the report
>> handling function. Currently the "recover" field in that metadata is
>> broken in the compiler layer and causes every inline tag mismatch to
>> panic the kernel.
>>
>> Check the multishot state in the KASAN hook called inside the INT3
>> handling function.
>>
>> Signed-off-by: Maciej Wieczor-Retman <maciej.wieczor-retman@intel.com>
>> ---
>> Changelog v4:
>> - Add this patch to the series.
>>
>>  arch/x86/mm/kasan_inline.c | 3 +++
>>  include/linux/kasan.h      | 3 +++
>>  mm/kasan/report.c          | 8 +++++++-
>>  3 files changed, 13 insertions(+), 1 deletion(-)
>>
>> diff --git a/arch/x86/mm/kasan_inline.c b/arch/x86/mm/kasan_inline.c
>> index 9f85dfd1c38b..f837caf32e6c 100644
>> --- a/arch/x86/mm/kasan_inline.c
>> +++ b/arch/x86/mm/kasan_inline.c
>> @@ -17,6 +17,9 @@ bool kasan_inline_handler(struct pt_regs *regs)
>>         if (!kasan_report((void *)addr, size, write, pc))
>>                 return false;
>>
>> +       if (kasan_multi_shot_enabled())
>> +               return true;
>
>It's odd this this is required on x86 but not on arm64, see my comment
>on the patch that adds kasan_inline_handler().
>

I think this is needed if we want to keep the kasan_inline_recover below.
Because without this patch, kasan_report() will report a mismatch, an then die()
will be called. So the multishot gets ignored.

I'll check what happens on arm64 when a mismatch happens with inline mode +
multishot.

>
>> +
>>         kasan_inline_recover(recover, "Oops - KASAN", regs, metadata, die);
>>
>>         return true;
>> diff --git a/include/linux/kasan.h b/include/linux/kasan.h
>> index 8691ad870f3b..7a2527794549 100644
>> --- a/include/linux/kasan.h
>> +++ b/include/linux/kasan.h
>> @@ -663,7 +663,10 @@ void kasan_non_canonical_hook(unsigned long addr);
>>  static inline void kasan_non_canonical_hook(unsigned long addr) { }
>>  #endif /* CONFIG_KASAN_GENERIC || CONFIG_KASAN_SW_TAGS */
>>
>> +bool kasan_multi_shot_enabled(void);
>> +
>>  #ifdef CONFIG_KASAN_SW_TAGS
>> +
>>  /*
>>   * The instrumentation allows to control whether we can proceed after
>>   * a crash was detected. This is done by passing the -recover flag to
>> diff --git a/mm/kasan/report.c b/mm/kasan/report.c
>> index 50d487a0687a..9e830639e1b2 100644
>> --- a/mm/kasan/report.c
>> +++ b/mm/kasan/report.c
>> @@ -121,6 +121,12 @@ static void report_suppress_stop(void)
>>  #endif
>>  }
>>
>> +bool kasan_multi_shot_enabled(void)
>> +{
>> +       return test_bit(KASAN_BIT_MULTI_SHOT, &kasan_flags);
>> +}
>> +EXPORT_SYMBOL(kasan_multi_shot_enabled);
>> +
>>  /*
>>   * Used to avoid reporting more than one KASAN bug unless kasan_multi_shot
>>   * is enabled. Note that KASAN tests effectively enable kasan_multi_shot
>> @@ -128,7 +134,7 @@ static void report_suppress_stop(void)
>>   */
>>  static bool report_enabled(void)
>>  {
>> -       if (test_bit(KASAN_BIT_MULTI_SHOT, &kasan_flags))
>> +       if (kasan_multi_shot_enabled())
>>                 return true;
>>         return !test_and_set_bit(KASAN_BIT_REPORTED, &kasan_flags);
>>  }
>> --
>> 2.50.1
>>

-- 
Kind regards
Maciej Wieczór-Retman
Re: [PATCH v5 15/19] kasan: x86: Apply multishot to the inline report handler
Posted by Andrey Konovalov 3 weeks, 4 days ago
On Mon, Sep 8, 2025 at 3:04 PM Maciej Wieczor-Retman
<maciej.wieczor-retman@intel.com> wrote:
>
> >> +       if (kasan_multi_shot_enabled())
> >> +               return true;
> >
> >It's odd this this is required on x86 but not on arm64, see my comment
> >on the patch that adds kasan_inline_handler().
> >
>
> I think this is needed if we want to keep the kasan_inline_recover below.
> Because without this patch, kasan_report() will report a mismatch, an then die()
> will be called. So the multishot gets ignored.

But die() should be called only when recovery is disabled. And
recovery should always be enabled.

But maybe this is the problem with when kasan_inline_handler(), see my
comment on the the patch #13.
Re: [PATCH v5 15/19] kasan: x86: Apply multishot to the inline report handler
Posted by Maciej Wieczor-Retman 3 weeks, 3 days ago
On 2025-09-08 at 22:19:11 +0200, Andrey Konovalov wrote:
>On Mon, Sep 8, 2025 at 3:04 PM Maciej Wieczor-Retman
><maciej.wieczor-retman@intel.com> wrote:
>>
>> >> +       if (kasan_multi_shot_enabled())
>> >> +               return true;
>> >
>> >It's odd this this is required on x86 but not on arm64, see my comment
>> >on the patch that adds kasan_inline_handler().
>> >
>>
>> I think this is needed if we want to keep the kasan_inline_recover below.
>> Because without this patch, kasan_report() will report a mismatch, an then die()
>> will be called. So the multishot gets ignored.
>
>But die() should be called only when recovery is disabled. And
>recovery should always be enabled.

Hmm I thought when I was testing inline mode last time, that recovery was always
disabled. I'll recheck later.

But just looking at llvm code, hwasan-recover has init(false). And the kernel
doesn't do anything to this value in Makefile.kasan. Perhaps it just needs to be
corrected in the Makefile.kasan?

>But maybe this is the problem with when kasan_inline_handler(), see my
>comment on the the patch #13.

-- 
Kind regards
Maciej Wieczór-Retman
Re: [PATCH v5 15/19] kasan: x86: Apply multishot to the inline report handler
Posted by Andrey Konovalov 3 weeks, 3 days ago
On Tue, Sep 9, 2025 at 10:42 AM Maciej Wieczor-Retman
<maciej.wieczor-retman@intel.com> wrote:
>
> On 2025-09-08 at 22:19:11 +0200, Andrey Konovalov wrote:
> >On Mon, Sep 8, 2025 at 3:04 PM Maciej Wieczor-Retman
> ><maciej.wieczor-retman@intel.com> wrote:
> >>
> >> >> +       if (kasan_multi_shot_enabled())
> >> >> +               return true;
> >> >
> >> >It's odd this this is required on x86 but not on arm64, see my comment
> >> >on the patch that adds kasan_inline_handler().
> >> >
> >>
> >> I think this is needed if we want to keep the kasan_inline_recover below.
> >> Because without this patch, kasan_report() will report a mismatch, an then die()
> >> will be called. So the multishot gets ignored.
> >
> >But die() should be called only when recovery is disabled. And
> >recovery should always be enabled.
>
> Hmm I thought when I was testing inline mode last time, that recovery was always
> disabled. I'll recheck later.
>
> But just looking at llvm code, hwasan-recover has init(false). And the kernel
> doesn't do anything to this value in Makefile.kasan. Perhaps it just needs to be
> corrected in the Makefile.kasan?

Recovery should be disabled as the default when
-fsanitize=kernel-hwaddress is used (unless something was
broken/changed); see this patch:

https://github.com/llvm/llvm-project/commit/1ba9d9c6ca1ffeef7e833261ebca463a92adf82f
Re: [PATCH v5 15/19] kasan: x86: Apply multishot to the inline report handler
Posted by Andrey Konovalov 3 weeks, 3 days ago
On Tue, Sep 9, 2025 at 4:45 PM Andrey Konovalov <andreyknvl@gmail.com> wrote:
>
> On Tue, Sep 9, 2025 at 10:42 AM Maciej Wieczor-Retman
> <maciej.wieczor-retman@intel.com> wrote:
> >
> > On 2025-09-08 at 22:19:11 +0200, Andrey Konovalov wrote:
> > >On Mon, Sep 8, 2025 at 3:04 PM Maciej Wieczor-Retman
> > ><maciej.wieczor-retman@intel.com> wrote:
> > >>
> > >> >> +       if (kasan_multi_shot_enabled())
> > >> >> +               return true;
> > >> >
> > >> >It's odd this this is required on x86 but not on arm64, see my comment
> > >> >on the patch that adds kasan_inline_handler().
> > >> >
> > >>
> > >> I think this is needed if we want to keep the kasan_inline_recover below.
> > >> Because without this patch, kasan_report() will report a mismatch, an then die()
> > >> will be called. So the multishot gets ignored.
> > >
> > >But die() should be called only when recovery is disabled. And
> > >recovery should always be enabled.
> >
> > Hmm I thought when I was testing inline mode last time, that recovery was always
> > disabled. I'll recheck later.
> >
> > But just looking at llvm code, hwasan-recover has init(false). And the kernel
> > doesn't do anything to this value in Makefile.kasan. Perhaps it just needs to be
> > corrected in the Makefile.kasan?
>
> Recovery should be disabled as the default when

Eh, enabled, not disabled.

> -fsanitize=kernel-hwaddress is used (unless something was
> broken/changed); see this patch:
>
> https://github.com/llvm/llvm-project/commit/1ba9d9c6ca1ffeef7e833261ebca463a92adf82f