From 0b8a938978b959133947248ea9e0622313d59825 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sun, 12 Jan 2025 13:37:53 +0100 Subject: [PATCH] 5.15-stable patches added patches: drivers-block-zram-zram_drv.c-do-not-keep-dangling-zcomp-pointer-after-zram-reset.patch md-raid5-fix-atomicity-violation-in-raid5_cache_count.patch scripts-sorttable-fix-orc_sort_cmp-to-maintain-symmetry-and-transitivity.patch zram-check-comp-is-non-null-before-calling-comp_destroy.patch zram-fix-uninitialized-zram-not-releasing-backing-device.patch --- ...gling-zcomp-pointer-after-zram-reset.patch | 62 ++++++++++ ...icity-violation-in-raid5_cache_count.patch | 114 ++++++++++++++++++ ...o-maintain-symmetry-and-transitivity.patch | 64 ++++++++++ queue-5.15/series | 5 + ...non-null-before-calling-comp_destroy.patch | 38 ++++++ ...ed-zram-not-releasing-backing-device.patch | 61 ++++++++++ 6 files changed, 344 insertions(+) create mode 100644 queue-5.15/drivers-block-zram-zram_drv.c-do-not-keep-dangling-zcomp-pointer-after-zram-reset.patch create mode 100644 queue-5.15/md-raid5-fix-atomicity-violation-in-raid5_cache_count.patch create mode 100644 queue-5.15/scripts-sorttable-fix-orc_sort_cmp-to-maintain-symmetry-and-transitivity.patch create mode 100644 queue-5.15/zram-check-comp-is-non-null-before-calling-comp_destroy.patch create mode 100644 queue-5.15/zram-fix-uninitialized-zram-not-releasing-backing-device.patch diff --git a/queue-5.15/drivers-block-zram-zram_drv.c-do-not-keep-dangling-zcomp-pointer-after-zram-reset.patch b/queue-5.15/drivers-block-zram-zram_drv.c-do-not-keep-dangling-zcomp-pointer-after-zram-reset.patch new file mode 100644 index 00000000000..e9a07be3a19 --- /dev/null +++ b/queue-5.15/drivers-block-zram-zram_drv.c-do-not-keep-dangling-zcomp-pointer-after-zram-reset.patch @@ -0,0 +1,62 @@ +From 6d2453c3dbc5f70eafc1c866289a90a1fc57ce18 Mon Sep 17 00:00:00 2001 +From: Sergey Senozhatsky +Date: Wed, 24 Aug 2022 12:51:00 +0900 +Subject: drivers/block/zram/zram_drv.c: do not keep dangling zcomp pointer after zram reset + +From: Sergey Senozhatsky + +commit 6d2453c3dbc5f70eafc1c866289a90a1fc57ce18 upstream. + +We do all reset operations under write lock, so we don't need to save +->disksize and ->comp to stack variables. Another thing is that ->comp is +freed during zram reset, but comp pointer is not NULL-ed, so zram keeps +the freed pointer value. + +Link: https://lkml.kernel.org/r/20220824035100.971816-1-senozhatsky@chromium.org +Signed-off-by: Sergey Senozhatsky +Cc: Minchan Kim +Cc: Nitin Gupta +Signed-off-by: Andrew Morton +Stable-dep-of: 74363ec674cb ("zram: fix uninitialized ZRAM not releasing backing device") +Signed-off-by: Sasha Levin +Signed-off-by: Dominique Martinet +Signed-off-by: Greg Kroah-Hartman +--- + drivers/block/zram/zram_drv.c | 13 ++++--------- + 1 file changed, 4 insertions(+), 9 deletions(-) + +--- a/drivers/block/zram/zram_drv.c ++++ b/drivers/block/zram/zram_drv.c +@@ -1695,9 +1695,6 @@ out: + + static void zram_reset_device(struct zram *zram) + { +- struct zcomp *comp; +- u64 disksize; +- + down_write(&zram->init_lock); + + zram->limit_pages = 0; +@@ -1707,18 +1704,16 @@ static void zram_reset_device(struct zra + return; + } + +- comp = zram->comp; +- disksize = zram->disksize; +- zram->disksize = 0; +- + set_capacity_and_notify(zram->disk, 0); + part_stat_set_all(zram->disk->part0, 0); + + up_write(&zram->init_lock); + /* I/O operation under all of CPU are done so let's free */ +- zram_meta_free(zram, disksize); ++ zram_meta_free(zram, zram->disksize); ++ zram->disksize = 0; + memset(&zram->stats, 0, sizeof(zram->stats)); +- zcomp_destroy(comp); ++ zcomp_destroy(zram->comp); ++ zram->comp = NULL; + reset_bdev(zram); + } + diff --git a/queue-5.15/md-raid5-fix-atomicity-violation-in-raid5_cache_count.patch b/queue-5.15/md-raid5-fix-atomicity-violation-in-raid5_cache_count.patch new file mode 100644 index 00000000000..5624c12eb01 --- /dev/null +++ b/queue-5.15/md-raid5-fix-atomicity-violation-in-raid5_cache_count.patch @@ -0,0 +1,114 @@ +From dfd2bf436709b2bccb78c2dda550dde93700efa7 Mon Sep 17 00:00:00 2001 +From: Gui-Dong Han <2045gemini@gmail.com> +Date: Fri, 12 Jan 2024 15:10:17 +0800 +Subject: md/raid5: fix atomicity violation in raid5_cache_count + +From: Gui-Dong Han <2045gemini@gmail.com> + +commit dfd2bf436709b2bccb78c2dda550dde93700efa7 upstream. + +In raid5_cache_count(): + if (conf->max_nr_stripes < conf->min_nr_stripes) + return 0; + return conf->max_nr_stripes - conf->min_nr_stripes; +The current check is ineffective, as the values could change immediately +after being checked. + +In raid5_set_cache_size(): + ... + conf->min_nr_stripes = size; + ... + while (size > conf->max_nr_stripes) + conf->min_nr_stripes = conf->max_nr_stripes; + ... + +Due to intermediate value updates in raid5_set_cache_size(), concurrent +execution of raid5_cache_count() and raid5_set_cache_size() may lead to +inconsistent reads of conf->max_nr_stripes and conf->min_nr_stripes. +The current checks are ineffective as values could change immediately +after being checked, raising the risk of conf->min_nr_stripes exceeding +conf->max_nr_stripes and potentially causing an integer overflow. + +This possible bug is found by an experimental static analysis tool +developed by our team. This tool analyzes the locking APIs to extract +function pairs that can be concurrently executed, and then analyzes the +instructions in the paired functions to identify possible concurrency bugs +including data races and atomicity violations. The above possible bug is +reported when our tool analyzes the source code of Linux 6.2. + +To resolve this issue, it is suggested to introduce local variables +'min_stripes' and 'max_stripes' in raid5_cache_count() to ensure the +values remain stable throughout the check. Adding locks in +raid5_cache_count() fails to resolve atomicity violations, as +raid5_set_cache_size() may hold intermediate values of +conf->min_nr_stripes while unlocked. With this patch applied, our tool no +longer reports the bug, with the kernel configuration allyesconfig for +x86_64. Due to the lack of associated hardware, we cannot test the patch +in runtime testing, and just verify it according to the code logic. + +Fixes: edbe83ab4c27 ("md/raid5: allow the stripe_cache to grow and shrink.") +Cc: stable@vger.kernel.org +Signed-off-by: Gui-Dong Han <2045gemini@gmail.com> +Reviewed-by: Yu Kuai +Signed-off-by: Song Liu +Link: https://lore.kernel.org/r/20240112071017.16313-1-2045gemini@gmail.com +Signed-off-by: Song Liu +Signed-off-by: Greg Kroah-Hartman +--- + drivers/md/raid5.c | 14 ++++++++------ + 1 file changed, 8 insertions(+), 6 deletions(-) + +--- a/drivers/md/raid5.c ++++ b/drivers/md/raid5.c +@@ -2349,7 +2349,7 @@ static int grow_one_stripe(struct r5conf + atomic_inc(&conf->active_stripes); + + raid5_release_stripe(sh); +- conf->max_nr_stripes++; ++ WRITE_ONCE(conf->max_nr_stripes, conf->max_nr_stripes + 1); + return 1; + } + +@@ -2646,7 +2646,7 @@ static int drop_one_stripe(struct r5conf + shrink_buffers(sh); + free_stripe(conf->slab_cache, sh); + atomic_dec(&conf->active_stripes); +- conf->max_nr_stripes--; ++ WRITE_ONCE(conf->max_nr_stripes, conf->max_nr_stripes - 1); + return 1; + } + +@@ -6577,7 +6577,7 @@ raid5_set_cache_size(struct mddev *mddev + if (size <= 16 || size > 32768) + return -EINVAL; + +- conf->min_nr_stripes = size; ++ WRITE_ONCE(conf->min_nr_stripes, size); + mutex_lock(&conf->cache_size_mutex); + while (size < conf->max_nr_stripes && + drop_one_stripe(conf)) +@@ -6589,7 +6589,7 @@ raid5_set_cache_size(struct mddev *mddev + mutex_lock(&conf->cache_size_mutex); + while (size > conf->max_nr_stripes) + if (!grow_one_stripe(conf, GFP_KERNEL)) { +- conf->min_nr_stripes = conf->max_nr_stripes; ++ WRITE_ONCE(conf->min_nr_stripes, conf->max_nr_stripes); + result = -ENOMEM; + break; + } +@@ -7153,11 +7153,13 @@ static unsigned long raid5_cache_count(s + struct shrink_control *sc) + { + struct r5conf *conf = container_of(shrink, struct r5conf, shrinker); ++ int max_stripes = READ_ONCE(conf->max_nr_stripes); ++ int min_stripes = READ_ONCE(conf->min_nr_stripes); + +- if (conf->max_nr_stripes < conf->min_nr_stripes) ++ if (max_stripes < min_stripes) + /* unlikely, but not impossible */ + return 0; +- return conf->max_nr_stripes - conf->min_nr_stripes; ++ return max_stripes - min_stripes; + } + + static struct r5conf *setup_conf(struct mddev *mddev) diff --git a/queue-5.15/scripts-sorttable-fix-orc_sort_cmp-to-maintain-symmetry-and-transitivity.patch b/queue-5.15/scripts-sorttable-fix-orc_sort_cmp-to-maintain-symmetry-and-transitivity.patch new file mode 100644 index 00000000000..53c1a9749a8 --- /dev/null +++ b/queue-5.15/scripts-sorttable-fix-orc_sort_cmp-to-maintain-symmetry-and-transitivity.patch @@ -0,0 +1,64 @@ +From 0210d251162f4033350a94a43f95b1c39ec84a90 Mon Sep 17 00:00:00 2001 +From: Kuan-Wei Chiu +Date: Thu, 26 Dec 2024 22:03:32 +0800 +Subject: scripts/sorttable: fix orc_sort_cmp() to maintain symmetry and transitivity + +From: Kuan-Wei Chiu + +commit 0210d251162f4033350a94a43f95b1c39ec84a90 upstream. + +The orc_sort_cmp() function, used with qsort(), previously violated the +symmetry and transitivity rules required by the C standard. Specifically, +when both entries are ORC_TYPE_UNDEFINED, it could result in both a < b +and b < a, which breaks the required symmetry and transitivity. This can +lead to undefined behavior and incorrect sorting results, potentially +causing memory corruption in glibc implementations [1]. + +Symmetry: If x < y, then y > x. +Transitivity: If x < y and y < z, then x < z. + +Fix the comparison logic to return 0 when both entries are +ORC_TYPE_UNDEFINED, ensuring compliance with qsort() requirements. + +Link: https://www.qualys.com/2024/01/30/qsort.txt [1] +Link: https://lkml.kernel.org/r/20241226140332.2670689-1-visitorckw@gmail.com +Fixes: 57fa18994285 ("scripts/sorttable: Implement build-time ORC unwind table sorting") +Fixes: fb799447ae29 ("x86,objtool: Split UNWIND_HINT_EMPTY in two") +Signed-off-by: Kuan-Wei Chiu +Cc: Ching-Chun (Jim) Huang +Cc: +Cc: Ingo Molnar +Cc: Josh Poimboeuf +Cc: Peter Zijlstra +Cc: Shile Zhang +Cc: Steven Rostedt +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Kuan-Wei Chiu +Signed-off-by: Greg Kroah-Hartman +--- + scripts/sorttable.h | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +--- a/scripts/sorttable.h ++++ b/scripts/sorttable.h +@@ -103,7 +103,7 @@ static inline unsigned long orc_ip(const + + static int orc_sort_cmp(const void *_a, const void *_b) + { +- struct orc_entry *orc_a; ++ struct orc_entry *orc_a, *orc_b; + const int *a = g_orc_ip_table + *(int *)_a; + const int *b = g_orc_ip_table + *(int *)_b; + unsigned long a_val = orc_ip(a); +@@ -121,6 +121,10 @@ static int orc_sort_cmp(const void *_a, + * whitelisted .o files which didn't get objtool generation. + */ + orc_a = g_orc_table + (a - g_orc_ip_table); ++ orc_b = g_orc_table + (b - g_orc_ip_table); ++ if (orc_a->sp_reg == ORC_REG_UNDEFINED && !orc_a->end && ++ orc_b->sp_reg == ORC_REG_UNDEFINED && !orc_b->end) ++ return 0; + return orc_a->sp_reg == ORC_REG_UNDEFINED && !orc_a->end ? -1 : 1; + } + diff --git a/queue-5.15/series b/queue-5.15/series index 4d0eb7839fd..3d4bda098e4 100644 --- a/queue-5.15/series +++ b/queue-5.15/series @@ -35,3 +35,8 @@ riscv-fix-sleeping-in-invalid-context-in-die.patch acpi-resource-add-tongfang-gm5hg0a-to-irq1_edge_low_force_override.patch acpi-resource-add-asus-vivobook-x1504vap-to-irq1_level_low_skip_override.patch drm-amd-display-increase-max_surfaces-to-the-value-supported-by-hw.patch +drivers-block-zram-zram_drv.c-do-not-keep-dangling-zcomp-pointer-after-zram-reset.patch +zram-check-comp-is-non-null-before-calling-comp_destroy.patch +zram-fix-uninitialized-zram-not-releasing-backing-device.patch +scripts-sorttable-fix-orc_sort_cmp-to-maintain-symmetry-and-transitivity.patch +md-raid5-fix-atomicity-violation-in-raid5_cache_count.patch diff --git a/queue-5.15/zram-check-comp-is-non-null-before-calling-comp_destroy.patch b/queue-5.15/zram-check-comp-is-non-null-before-calling-comp_destroy.patch new file mode 100644 index 00000000000..332395becc9 --- /dev/null +++ b/queue-5.15/zram-check-comp-is-non-null-before-calling-comp_destroy.patch @@ -0,0 +1,38 @@ +From 677294e4da96547b9ea2955661a4bbf1d13552a3 Mon Sep 17 00:00:00 2001 +From: Dominique Martinet +Date: Tue, 7 Jan 2025 16:16:04 +0900 +Subject: zram: check comp is non-NULL before calling comp_destroy + +From: Dominique Martinet + +commit 677294e4da96547b9ea2955661a4bbf1d13552a3 upstream. + +This is a pre-requisite for the backport of commit 74363ec674cb ("zram: +fix uninitialized ZRAM not releasing backing device"), which has been +implemented differently in commit 7ac07a26dea7 ("zram: preparation for +multi-zcomp support") upstream. + +We only need to ensure that zcomp_destroy is not called with a NULL +comp, so add this check as the other commit cannot be backported easily. + +Stable-dep-of: 74363ec674cb ("zram: fix uninitialized ZRAM not releasing backing device") +Link: https://lore.kernel.org/Z3ytcILx4S1v_ueJ@codewreck.org +Suggested-by: Kairui Song +Signed-off-by: Dominique Martinet +Signed-off-by: Greg Kroah-Hartman +--- + drivers/block/zram/zram_drv.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/block/zram/zram_drv.c ++++ b/drivers/block/zram/zram_drv.c +@@ -1712,7 +1712,8 @@ static void zram_reset_device(struct zra + zram_meta_free(zram, zram->disksize); + zram->disksize = 0; + memset(&zram->stats, 0, sizeof(zram->stats)); +- zcomp_destroy(zram->comp); ++ if (zram->comp) ++ zcomp_destroy(zram->comp); + zram->comp = NULL; + reset_bdev(zram); + } diff --git a/queue-5.15/zram-fix-uninitialized-zram-not-releasing-backing-device.patch b/queue-5.15/zram-fix-uninitialized-zram-not-releasing-backing-device.patch new file mode 100644 index 00000000000..39357e81db6 --- /dev/null +++ b/queue-5.15/zram-fix-uninitialized-zram-not-releasing-backing-device.patch @@ -0,0 +1,61 @@ +From 74363ec674cb172d8856de25776c8f3103f05e2f Mon Sep 17 00:00:00 2001 +From: Kairui Song +Date: Tue, 10 Dec 2024 00:57:16 +0800 +Subject: zram: fix uninitialized ZRAM not releasing backing device + +From: Kairui Song + +commit 74363ec674cb172d8856de25776c8f3103f05e2f upstream. + +Setting backing device is done before ZRAM initialization. If we set the +backing device, then remove the ZRAM module without initializing the +device, the backing device reference will be leaked and the device will be +hold forever. + +Fix this by always reset the ZRAM fully on rmmod or reset store. + +Link: https://lkml.kernel.org/r/20241209165717.94215-3-ryncsn@gmail.com +Fixes: 013bf95a83ec ("zram: add interface to specif backing device") +Signed-off-by: Kairui Song +Reported-by: Desheng Wu +Suggested-by: Sergey Senozhatsky +Reviewed-by: Sergey Senozhatsky +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Dominique Martinet +Signed-off-by: Greg Kroah-Hartman +--- + drivers/block/zram/zram_drv.c | 9 ++++----- + 1 file changed, 4 insertions(+), 5 deletions(-) + +--- a/drivers/block/zram/zram_drv.c ++++ b/drivers/block/zram/zram_drv.c +@@ -1150,12 +1150,16 @@ static void zram_meta_free(struct zram * + size_t num_pages = disksize >> PAGE_SHIFT; + size_t index; + ++ if (!zram->table) ++ return; ++ + /* Free all pages that are still in this zram device */ + for (index = 0; index < num_pages; index++) + zram_free_page(zram, index); + + zs_destroy_pool(zram->mem_pool); + vfree(zram->table); ++ zram->table = NULL; + } + + static bool zram_meta_alloc(struct zram *zram, u64 disksize) +@@ -1699,11 +1703,6 @@ static void zram_reset_device(struct zra + + zram->limit_pages = 0; + +- if (!init_done(zram)) { +- up_write(&zram->init_lock); +- return; +- } +- + set_capacity_and_notify(zram->disk, 0); + part_stat_set_all(zram->disk->part0, 0); + -- 2.47.3