]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
Fixes for 6.1
authorSasha Levin <sashal@kernel.org>
Wed, 11 Dec 2024 18:37:02 +0000 (13:37 -0500)
committerSasha Levin <sashal@kernel.org>
Wed, 11 Dec 2024 18:37:02 +0000 (13:37 -0500)
Signed-off-by: Sasha Levin <sashal@kernel.org>
queue-6.1/kasan-make-report_lock-a-raw-spinlock.patch [new file with mode: 0644]
queue-6.1/kasan-suppress-recursive-reports-for-hw_tags.patch [new file with mode: 0644]
queue-6.1/series

diff --git a/queue-6.1/kasan-make-report_lock-a-raw-spinlock.patch b/queue-6.1/kasan-make-report_lock-a-raw-spinlock.patch
new file mode 100644 (file)
index 0000000..3d0546f
--- /dev/null
@@ -0,0 +1,71 @@
+From 464468fa29f9244613add91dd38810189c07b54b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 19 Nov 2024 13:02:34 -0800
+Subject: kasan: make report_lock a raw spinlock
+
+From: Jared Kangas <jkangas@redhat.com>
+
+[ Upstream commit e30a0361b8515d424c73c67de1a43e45a13b8ba2 ]
+
+If PREEMPT_RT is enabled, report_lock is a sleeping spinlock and must not
+be locked when IRQs are disabled.  However, KASAN reports may be triggered
+in such contexts.  For example:
+
+        char *s = kzalloc(1, GFP_KERNEL);
+        kfree(s);
+        local_irq_disable();
+        char c = *s;  /* KASAN report here leads to spin_lock() */
+        local_irq_enable();
+
+Make report_spinlock a raw spinlock to prevent rescheduling when
+PREEMPT_RT is enabled.
+
+Link: https://lkml.kernel.org/r/20241119210234.1602529-1-jkangas@redhat.com
+Fixes: 342a93247e08 ("locking/spinlock: Provide RT variant header: <linux/spinlock_rt.h>")
+Signed-off-by: Jared Kangas <jkangas@redhat.com>
+Cc: Alexander Potapenko <glider@google.com>
+Cc: Andrey Konovalov <andreyknvl@gmail.com>
+Cc: Andrey Ryabinin <ryabinin.a.a@gmail.com>
+Cc: Dmitry Vyukov <dvyukov@google.com>
+Cc: Vincenzo Frascino <vincenzo.frascino@arm.com>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ mm/kasan/report.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/mm/kasan/report.c b/mm/kasan/report.c
+index 821cd12e8c8a7..6ad986c267b5e 100644
+--- a/mm/kasan/report.c
++++ b/mm/kasan/report.c
+@@ -173,7 +173,7 @@ static void update_kunit_status(bool sync)
+ static void update_kunit_status(bool sync) { }
+ #endif
+-static DEFINE_SPINLOCK(report_lock);
++static DEFINE_RAW_SPINLOCK(report_lock);
+ static void start_report(unsigned long *flags, bool sync)
+ {
+@@ -185,7 +185,7 @@ static void start_report(unsigned long *flags, bool sync)
+       lockdep_off();
+       /* Make sure we don't end up in loop. */
+       report_suppress_start();
+-      spin_lock_irqsave(&report_lock, *flags);
++      raw_spin_lock_irqsave(&report_lock, *flags);
+       pr_err("==================================================================\n");
+ }
+@@ -195,7 +195,7 @@ static void end_report(unsigned long *flags, void *addr)
+               trace_error_report_end(ERROR_DETECTOR_KASAN,
+                                      (unsigned long)addr);
+       pr_err("==================================================================\n");
+-      spin_unlock_irqrestore(&report_lock, *flags);
++      raw_spin_unlock_irqrestore(&report_lock, *flags);
+       if (!test_bit(KASAN_BIT_MULTI_SHOT, &kasan_flags))
+               check_panic_on_warn("KASAN");
+       if (kasan_arg_fault == KASAN_ARG_FAULT_PANIC)
+-- 
+2.43.0
+
diff --git a/queue-6.1/kasan-suppress-recursive-reports-for-hw_tags.patch b/queue-6.1/kasan-suppress-recursive-reports-for-hw_tags.patch
new file mode 100644 (file)
index 0000000..5f086d8
--- /dev/null
@@ -0,0 +1,182 @@
+From f5de8091ce62f9f4dc0ac8ec176cf827bf39c1b0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 11 Mar 2023 00:43:33 +0100
+Subject: kasan: suppress recursive reports for HW_TAGS
+
+From: Andrey Konovalov <andreyknvl@google.com>
+
+[ Upstream commit c6a690e0c978bda8106e7a489c13323f90b087d0 ]
+
+KASAN suppresses reports for bad accesses done by the KASAN reporting
+code.  The reporting code might access poisoned memory for reporting
+purposes.
+
+Software KASAN modes do this by suppressing reports during reporting via
+current->kasan_depth, the same way they suppress reports during accesses
+to poisoned slab metadata.
+
+Hardware Tag-Based KASAN does not use current->kasan_depth, and instead
+resets pointer tags for accesses to poisoned memory done by the reporting
+code.
+
+Despite that, a recursive report can still happen:
+
+1. On hardware with faulty MTE support. This was observed by Weizhao
+   Ouyang on a faulty hardware that caused memory tags to randomly change
+   from time to time.
+
+2. Theoretically, due to a previous MTE-undetected memory corruption.
+
+A recursive report can happen via:
+
+1. Accessing a pointer with a non-reset tag in the reporting code, e.g.
+   slab->slab_cache, which is what Weizhao Ouyang observed.
+
+2. Theoretically, via external non-annotated routines, e.g. stackdepot.
+
+To resolve this issue, resetting tags for all of the pointers in the
+reporting code and all the used external routines would be impractical.
+
+Instead, disable tag checking done by the CPU for the duration of KASAN
+reporting for Hardware Tag-Based KASAN.
+
+Without this fix, Hardware Tag-Based KASAN reporting code might deadlock.
+
+[andreyknvl@google.com: disable preemption instead of migration, fix comment typo]
+  Link: https://lkml.kernel.org/r/d14417c8bc5eea7589e99381203432f15c0f9138.1680114854.git.andreyknvl@google.com
+Link: https://lkml.kernel.org/r/59f433e00f7fa985e8bf9f7caf78574db16b67ab.1678491668.git.andreyknvl@google.com
+Fixes: 2e903b914797 ("kasan, arm64: implement HW_TAGS runtime")
+Signed-off-by: Andrey Konovalov <andreyknvl@google.com>
+Reported-by: Weizhao Ouyang <ouyangweizhao@zeku.com>
+Reviewed-by: Marco Elver <elver@google.com>
+Cc: Alexander Potapenko <glider@google.com>
+Cc: Andrey Ryabinin <ryabinin.a.a@gmail.com>
+Cc: Catalin Marinas <catalin.marinas@arm.com>
+Cc: Dmitry Vyukov <dvyukov@google.com>
+Cc: Evgenii Stepanov <eugenis@google.com>
+Cc: Peter Collingbourne <pcc@google.com>
+Cc: Vincenzo Frascino <vincenzo.frascino@arm.com>
+Cc: Will Deacon <will@kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Stable-dep-of: e30a0361b851 ("kasan: make report_lock a raw spinlock")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ mm/kasan/report.c | 59 ++++++++++++++++++++++++++++++++++++++---------
+ 1 file changed, 48 insertions(+), 11 deletions(-)
+
+diff --git a/mm/kasan/report.c b/mm/kasan/report.c
+index 5d9ae80df4954..821cd12e8c8a7 100644
+--- a/mm/kasan/report.c
++++ b/mm/kasan/report.c
+@@ -73,10 +73,18 @@ static int __init kasan_set_multi_shot(char *str)
+ __setup("kasan_multi_shot", kasan_set_multi_shot);
+ /*
+- * Used to suppress reports within kasan_disable/enable_current() critical
+- * sections, which are used for marking accesses to slab metadata.
++ * This function is used to check whether KASAN reports are suppressed for
++ * software KASAN modes via kasan_disable/enable_current() critical sections.
++ *
++ * This is done to avoid:
++ * 1. False-positive reports when accessing slab metadata,
++ * 2. Deadlocking when poisoned memory is accessed by the reporting code.
++ *
++ * Hardware Tag-Based KASAN instead relies on:
++ * For #1: Resetting tags via kasan_reset_tag().
++ * For #2: Suppression of tag checks via CPU, see report_suppress_start/end().
+  */
+-static bool report_suppressed(void)
++static bool report_suppressed_sw(void)
+ {
+ #if defined(CONFIG_KASAN_GENERIC) || defined(CONFIG_KASAN_SW_TAGS)
+       if (current->kasan_depth)
+@@ -85,6 +93,30 @@ static bool report_suppressed(void)
+       return false;
+ }
++static void report_suppress_start(void)
++{
++#ifdef CONFIG_KASAN_HW_TAGS
++      /*
++       * Disable preemption for the duration of printing a KASAN report, as
++       * hw_suppress_tag_checks_start() disables checks on the current CPU.
++       */
++      preempt_disable();
++      hw_suppress_tag_checks_start();
++#else
++      kasan_disable_current();
++#endif
++}
++
++static void report_suppress_stop(void)
++{
++#ifdef CONFIG_KASAN_HW_TAGS
++      hw_suppress_tag_checks_stop();
++      preempt_enable();
++#else
++      kasan_enable_current();
++#endif
++}
++
+ /*
+  * Used to avoid reporting more than one KASAN bug unless kasan_multi_shot
+  * is enabled. Note that KASAN tests effectively enable kasan_multi_shot
+@@ -152,7 +184,7 @@ static void start_report(unsigned long *flags, bool sync)
+       /* Do not allow LOCKDEP mangling KASAN reports. */
+       lockdep_off();
+       /* Make sure we don't end up in loop. */
+-      kasan_disable_current();
++      report_suppress_start();
+       spin_lock_irqsave(&report_lock, *flags);
+       pr_err("==================================================================\n");
+ }
+@@ -170,7 +202,7 @@ static void end_report(unsigned long *flags, void *addr)
+               panic("kasan.fault=panic set ...\n");
+       add_taint(TAINT_BAD_PAGE, LOCKDEP_NOW_UNRELIABLE);
+       lockdep_on();
+-      kasan_enable_current();
++      report_suppress_stop();
+ }
+ static void print_error_description(struct kasan_report_info *info)
+@@ -439,9 +471,13 @@ void kasan_report_invalid_free(void *ptr, unsigned long ip, enum kasan_report_ty
+       struct kasan_report_info info;
+       /*
+-       * Do not check report_suppressed(), as an invalid-free cannot be
+-       * caused by accessing slab metadata and thus should not be
+-       * suppressed by kasan_disable/enable_current() critical sections.
++       * Do not check report_suppressed_sw(), as an invalid-free cannot be
++       * caused by accessing poisoned memory and thus should not be suppressed
++       * by kasan_disable/enable_current() critical sections.
++       *
++       * Note that for Hardware Tag-Based KASAN, kasan_report_invalid_free()
++       * is triggered by explicit tag checks and not by the ones performed by
++       * the CPU. Thus, reporting invalid-free is not suppressed as well.
+        */
+       if (unlikely(!report_enabled()))
+               return;
+@@ -476,7 +512,7 @@ bool kasan_report(unsigned long addr, size_t size, bool is_write,
+       unsigned long irq_flags;
+       struct kasan_report_info info;
+-      if (unlikely(report_suppressed()) || unlikely(!report_enabled())) {
++      if (unlikely(report_suppressed_sw()) || unlikely(!report_enabled())) {
+               ret = false;
+               goto out;
+       }
+@@ -508,8 +544,9 @@ void kasan_report_async(void)
+       unsigned long flags;
+       /*
+-       * Do not check report_suppressed(), as kasan_disable/enable_current()
+-       * critical sections do not affect Hardware Tag-Based KASAN.
++       * Do not check report_suppressed_sw(), as
++       * kasan_disable/enable_current() critical sections do not affect
++       * Hardware Tag-Based KASAN.
+        */
+       if (unlikely(!report_enabled()))
+               return;
+-- 
+2.43.0
+
index 14050aef07c99871d7ec0bbcefb12c98bc52d081..3414c1d217e39a8105226849fb9cd8932961147c 100644 (file)
@@ -731,3 +731,5 @@ misc-eeprom-eeprom_93cx6-add-quirk-for-extra-read-cl.patch
 rtc-cmos-avoid-taking-rtc_lock-for-extended-period-o.patch
 serial-8250_dw-add-sophgo-sg2044-quirk.patch
 io_uring-tctx-work-around-xa_store-allocation-error-.patch
+kasan-suppress-recursive-reports-for-hw_tags.patch
+kasan-make-report_lock-a-raw-spinlock.patch