From: Greg Kroah-Hartman Date: Mon, 23 Jun 2025 09:14:07 +0000 (+0200) Subject: 5.4-stable patches X-Git-Tag: v5.4.295~41 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=4c7d3afad4b12d0046ab9ac98c4cb3b7629dadbe;p=thirdparty%2Fkernel%2Fstable-queue.git 5.4-stable patches added patches: jbd2-fix-data-race-and-null-ptr-deref-in-jbd2_journal_dirty_metadata.patch mm-huge_memory-fix-dereferencing-invalid-pmd-migration-entry.patch rtc-improve-performance-of-rtc_time64_to_tm-.-add-tests.patch rtc-make-rtc_time64_to_tm-support-dates-before-1970.patch --- diff --git a/queue-5.4/jbd2-fix-data-race-and-null-ptr-deref-in-jbd2_journal_dirty_metadata.patch b/queue-5.4/jbd2-fix-data-race-and-null-ptr-deref-in-jbd2_journal_dirty_metadata.patch new file mode 100644 index 0000000000..270870c806 --- /dev/null +++ b/queue-5.4/jbd2-fix-data-race-and-null-ptr-deref-in-jbd2_journal_dirty_metadata.patch @@ -0,0 +1,73 @@ +From af98b0157adf6504fade79b3e6cb260c4ff68e37 Mon Sep 17 00:00:00 2001 +From: Jeongjun Park +Date: Wed, 14 May 2025 22:08:55 +0900 +Subject: jbd2: fix data-race and null-ptr-deref in jbd2_journal_dirty_metadata() + +From: Jeongjun Park + +commit af98b0157adf6504fade79b3e6cb260c4ff68e37 upstream. + +Since handle->h_transaction may be a NULL pointer, so we should change it +to call is_handle_aborted(handle) first before dereferencing it. + +And the following data-race was reported in my fuzzer: + +================================================================== +BUG: KCSAN: data-race in jbd2_journal_dirty_metadata / jbd2_journal_dirty_metadata + +write to 0xffff888011024104 of 4 bytes by task 10881 on cpu 1: + jbd2_journal_dirty_metadata+0x2a5/0x770 fs/jbd2/transaction.c:1556 + __ext4_handle_dirty_metadata+0xe7/0x4b0 fs/ext4/ext4_jbd2.c:358 + ext4_do_update_inode fs/ext4/inode.c:5220 [inline] + ext4_mark_iloc_dirty+0x32c/0xd50 fs/ext4/inode.c:5869 + __ext4_mark_inode_dirty+0xe1/0x450 fs/ext4/inode.c:6074 + ext4_dirty_inode+0x98/0xc0 fs/ext4/inode.c:6103 +.... + +read to 0xffff888011024104 of 4 bytes by task 10880 on cpu 0: + jbd2_journal_dirty_metadata+0xf2/0x770 fs/jbd2/transaction.c:1512 + __ext4_handle_dirty_metadata+0xe7/0x4b0 fs/ext4/ext4_jbd2.c:358 + ext4_do_update_inode fs/ext4/inode.c:5220 [inline] + ext4_mark_iloc_dirty+0x32c/0xd50 fs/ext4/inode.c:5869 + __ext4_mark_inode_dirty+0xe1/0x450 fs/ext4/inode.c:6074 + ext4_dirty_inode+0x98/0xc0 fs/ext4/inode.c:6103 +.... + +value changed: 0x00000000 -> 0x00000001 +================================================================== + +This issue is caused by missing data-race annotation for jh->b_modified. +Therefore, the missing annotation needs to be added. + +Reported-by: syzbot+de24c3fe3c4091051710@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=de24c3fe3c4091051710 +Fixes: 6e06ae88edae ("jbd2: speedup jbd2_journal_dirty_metadata()") +Signed-off-by: Jeongjun Park +Reviewed-by: Jan Kara +Link: https://patch.msgid.link/20250514130855.99010-1-aha310510@gmail.com +Signed-off-by: Theodore Ts'o +Cc: stable@kernel.org +Signed-off-by: Greg Kroah-Hartman +--- + fs/jbd2/transaction.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/fs/jbd2/transaction.c ++++ b/fs/jbd2/transaction.c +@@ -1419,7 +1419,6 @@ int jbd2_journal_dirty_metadata(handle_t + goto out; + } + +- journal = transaction->t_journal; + jbd_lock_bh_state(bh); + + if (is_handle_aborted(handle)) { +@@ -1434,6 +1433,8 @@ int jbd2_journal_dirty_metadata(handle_t + goto out_unlock_bh; + } + ++ journal = transaction->t_journal; ++ + if (jh->b_modified == 0) { + /* + * This buffer's got modified and becoming part diff --git a/queue-5.4/mm-huge_memory-fix-dereferencing-invalid-pmd-migration-entry.patch b/queue-5.4/mm-huge_memory-fix-dereferencing-invalid-pmd-migration-entry.patch new file mode 100644 index 0000000000..c70c13deff --- /dev/null +++ b/queue-5.4/mm-huge_memory-fix-dereferencing-invalid-pmd-migration-entry.patch @@ -0,0 +1,76 @@ +From be6e843fc51a584672dfd9c4a6a24c8cb81d5fb7 Mon Sep 17 00:00:00 2001 +From: Gavin Guo +Date: Mon, 21 Apr 2025 19:35:36 +0800 +Subject: mm/huge_memory: fix dereferencing invalid pmd migration entry + +From: Gavin Guo + +commit be6e843fc51a584672dfd9c4a6a24c8cb81d5fb7 upstream. + +When migrating a THP, concurrent access to the PMD migration entry during +a deferred split scan can lead to an invalid address access, as +illustrated below. To prevent this invalid access, it is necessary to +check the PMD migration entry and return early. In this context, there is +no need to use pmd_to_swp_entry and pfn_swap_entry_to_page to verify the +equality of the target folio. Since the PMD migration entry is locked, it +cannot be served as the target. + +Mailing list discussion and explanation from Hugh Dickins: "An anon_vma +lookup points to a location which may contain the folio of interest, but +might instead contain another folio: and weeding out those other folios is +precisely what the "folio != pmd_folio((*pmd)" check (and the "risk of +replacing the wrong folio" comment a few lines above it) is for." + +BUG: unable to handle page fault for address: ffffea60001db008 +CPU: 0 UID: 0 PID: 2199114 Comm: tee Not tainted 6.14.0+ #4 NONE +Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-debian-1.16.3-2 04/01/2014 +RIP: 0010:split_huge_pmd_locked+0x3b5/0x2b60 +Call Trace: + +try_to_migrate_one+0x28c/0x3730 +rmap_walk_anon+0x4f6/0x770 +unmap_folio+0x196/0x1f0 +split_huge_page_to_list_to_order+0x9f6/0x1560 +deferred_split_scan+0xac5/0x12a0 +shrinker_debugfs_scan_write+0x376/0x470 +full_proxy_write+0x15c/0x220 +vfs_write+0x2fc/0xcb0 +ksys_write+0x146/0x250 +do_syscall_64+0x6a/0x120 +entry_SYSCALL_64_after_hwframe+0x76/0x7e + +The bug is found by syzkaller on an internal kernel, then confirmed on +upstream. + +Link: https://lkml.kernel.org/r/20250421113536.3682201-1-gavinguo@igalia.com +Link: https://lore.kernel.org/all/20250414072737.1698513-1-gavinguo@igalia.com/ +Link: https://lore.kernel.org/all/20250418085802.2973519-1-gavinguo@igalia.com/ +Fixes: 84c3fc4e9c56 ("mm: thp: check pmd migration entry in common path") +Signed-off-by: Gavin Guo +Acked-by: David Hildenbrand +Acked-by: Hugh Dickins +Acked-by: Zi Yan +Reviewed-by: Gavin Shan +Cc: Florent Revest +Cc: Matthew Wilcox (Oracle) +Cc: Miaohe Lin +Cc: +Signed-off-by: Andrew Morton +[gavin: backport the migration checking logic to __split_huge_pmd] +Signed-off-by: Gavin Guo +Signed-off-by: Greg Kroah-Hartman +--- + mm/huge_memory.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/mm/huge_memory.c ++++ b/mm/huge_memory.c +@@ -2334,7 +2334,7 @@ void __split_huge_pmd(struct vm_area_str + VM_BUG_ON(freeze && !page); + if (page) { + VM_WARN_ON_ONCE(!PageLocked(page)); +- if (page != pmd_page(*pmd)) ++ if (is_pmd_migration_entry(*pmd) || page != pmd_page(*pmd)) + goto out; + } + diff --git a/queue-5.4/rtc-improve-performance-of-rtc_time64_to_tm-.-add-tests.patch b/queue-5.4/rtc-improve-performance-of-rtc_time64_to_tm-.-add-tests.patch new file mode 100644 index 0000000000..aafe8d7f42 --- /dev/null +++ b/queue-5.4/rtc-improve-performance-of-rtc_time64_to_tm-.-add-tests.patch @@ -0,0 +1,288 @@ +From 1d1bb12a8b1805ddeef9793ebeb920179fb0fa38 Mon Sep 17 00:00:00 2001 +From: Cassio Neri +Date: Thu, 24 Jun 2021 21:13:43 +0100 +Subject: rtc: Improve performance of rtc_time64_to_tm(). Add tests. + +From: Cassio Neri + +commit 1d1bb12a8b1805ddeef9793ebeb920179fb0fa38 upstream. + +The current implementation of rtc_time64_to_tm() contains unnecessary +loops, branches and look-up tables. The new one uses an arithmetic-based +algorithm appeared in [1] and is approximately 4.3 times faster (YMMV). + +The drawback is that the new code isn't intuitive and contains many 'magic +numbers' (not unusual for this type of algorithm). However, [1] justifies +all those numbers and, given this function's history, the code is unlikely +to need much maintenance, if any at all. + +Add a KUnit test case that checks every day in a 160,000 years interval +starting on 1970-01-01 against the expected result. Add a new config +RTC_LIB_KUNIT_TEST symbol to give the option to run this test suite. + +[1] Neri, Schneider, "Euclidean Affine Functions and Applications to +Calendar Algorithms". https://arxiv.org/abs/2102.06959 + +Signed-off-by: Cassio Neri +Reported-by: kernel test robot +Signed-off-by: Alexandre Belloni +Link: https://lore.kernel.org/r/20210624201343.85441-1-cassio.neri@gmail.com +Signed-off-by: Uwe Kleine-König +Signed-off-by: Greg Kroah-Hartman +--- + drivers/rtc/Kconfig | 10 ++++ + drivers/rtc/Makefile | 1 + drivers/rtc/lib.c | 107 ++++++++++++++++++++++++++++++++++++------------- + drivers/rtc/lib_test.c | 79 ++++++++++++++++++++++++++++++++++++ + 4 files changed, 170 insertions(+), 27 deletions(-) + create mode 100644 drivers/rtc/lib_test.c + +--- a/drivers/rtc/Kconfig ++++ b/drivers/rtc/Kconfig +@@ -10,6 +10,16 @@ config RTC_MC146818_LIB + bool + select RTC_LIB + ++config RTC_LIB_KUNIT_TEST ++ tristate "KUnit test for RTC lib functions" if !KUNIT_ALL_TESTS ++ depends on KUNIT ++ default KUNIT_ALL_TESTS ++ select RTC_LIB ++ help ++ Enable this option to test RTC library functions. ++ ++ If unsure, say N. ++ + menuconfig RTC_CLASS + bool "Real Time Clock" + default n +--- a/drivers/rtc/Makefile ++++ b/drivers/rtc/Makefile +@@ -186,3 +186,4 @@ obj-$(CONFIG_RTC_DRV_WM8350) += rtc-wm83 + obj-$(CONFIG_RTC_DRV_X1205) += rtc-x1205.o + obj-$(CONFIG_RTC_DRV_XGENE) += rtc-xgene.o + obj-$(CONFIG_RTC_DRV_ZYNQMP) += rtc-zynqmp.o ++obj-$(CONFIG_RTC_LIB_KUNIT_TEST) += lib_test.o +--- a/drivers/rtc/lib.c ++++ b/drivers/rtc/lib.c +@@ -6,6 +6,8 @@ + * Author: Alessandro Zummo + * + * based on arch/arm/common/rtctime.c and other bits ++ * ++ * Author: Cassio Neri (rtc_time64_to_tm) + */ + + #include +@@ -22,8 +24,6 @@ static const unsigned short rtc_ydays[2] + { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 } + }; + +-#define LEAPS_THRU_END_OF(y) ((y) / 4 - (y) / 100 + (y) / 400) +- + /* + * The number of days in the month. + */ +@@ -42,42 +42,95 @@ int rtc_year_days(unsigned int day, unsi + } + EXPORT_SYMBOL(rtc_year_days); + +-/* +- * rtc_time64_to_tm - Converts time64_t to rtc_time. +- * Convert seconds since 01-01-1970 00:00:00 to Gregorian date. ++/** ++ * rtc_time64_to_tm - converts time64_t to rtc_time. ++ * ++ * @time: The number of seconds since 01-01-1970 00:00:00. ++ * (Must be positive.) ++ * @tm: Pointer to the struct rtc_time. + */ + void rtc_time64_to_tm(time64_t time, struct rtc_time *tm) + { +- unsigned int month, year, secs; ++ unsigned int secs; + int days; + ++ u64 u64tmp; ++ u32 u32tmp, udays, century, day_of_century, year_of_century, year, ++ day_of_year, month, day; ++ bool is_Jan_or_Feb, is_leap_year; ++ + /* time must be positive */ + days = div_s64_rem(time, 86400, &secs); + + /* day of the week, 1970-01-01 was a Thursday */ + tm->tm_wday = (days + 4) % 7; + +- year = 1970 + days / 365; +- days -= (year - 1970) * 365 +- + LEAPS_THRU_END_OF(year - 1) +- - LEAPS_THRU_END_OF(1970 - 1); +- while (days < 0) { +- year -= 1; +- days += 365 + is_leap_year(year); +- } +- tm->tm_year = year - 1900; +- tm->tm_yday = days + 1; +- +- for (month = 0; month < 11; month++) { +- int newdays; +- +- newdays = days - rtc_month_days(month, year); +- if (newdays < 0) +- break; +- days = newdays; +- } +- tm->tm_mon = month; +- tm->tm_mday = days + 1; ++ /* ++ * The following algorithm is, basically, Proposition 6.3 of Neri ++ * and Schneider [1]. In a few words: it works on the computational ++ * (fictitious) calendar where the year starts in March, month = 2 ++ * (*), and finishes in February, month = 13. This calendar is ++ * mathematically convenient because the day of the year does not ++ * depend on whether the year is leap or not. For instance: ++ * ++ * March 1st 0-th day of the year; ++ * ... ++ * April 1st 31-st day of the year; ++ * ... ++ * January 1st 306-th day of the year; (Important!) ++ * ... ++ * February 28th 364-th day of the year; ++ * February 29th 365-th day of the year (if it exists). ++ * ++ * After having worked out the date in the computational calendar ++ * (using just arithmetics) it's easy to convert it to the ++ * corresponding date in the Gregorian calendar. ++ * ++ * [1] "Euclidean Affine Functions and Applications to Calendar ++ * Algorithms". https://arxiv.org/abs/2102.06959 ++ * ++ * (*) The numbering of months follows rtc_time more closely and ++ * thus, is slightly different from [1]. ++ */ ++ ++ udays = ((u32) days) + 719468; ++ ++ u32tmp = 4 * udays + 3; ++ century = u32tmp / 146097; ++ day_of_century = u32tmp % 146097 / 4; ++ ++ u32tmp = 4 * day_of_century + 3; ++ u64tmp = 2939745ULL * u32tmp; ++ year_of_century = upper_32_bits(u64tmp); ++ day_of_year = lower_32_bits(u64tmp) / 2939745 / 4; ++ ++ year = 100 * century + year_of_century; ++ is_leap_year = year_of_century != 0 ? ++ year_of_century % 4 == 0 : century % 4 == 0; ++ ++ u32tmp = 2141 * day_of_year + 132377; ++ month = u32tmp >> 16; ++ day = ((u16) u32tmp) / 2141; ++ ++ /* ++ * Recall that January 01 is the 306-th day of the year in the ++ * computational (not Gregorian) calendar. ++ */ ++ is_Jan_or_Feb = day_of_year >= 306; ++ ++ /* Converts to the Gregorian calendar. */ ++ year = year + is_Jan_or_Feb; ++ month = is_Jan_or_Feb ? month - 12 : month; ++ day = day + 1; ++ ++ day_of_year = is_Jan_or_Feb ? ++ day_of_year - 306 : day_of_year + 31 + 28 + is_leap_year; ++ ++ /* Converts to rtc_time's format. */ ++ tm->tm_year = (int) (year - 1900); ++ tm->tm_mon = (int) month; ++ tm->tm_mday = (int) day; ++ tm->tm_yday = (int) day_of_year + 1; + + tm->tm_hour = secs / 3600; + secs -= tm->tm_hour * 3600; +--- /dev/null ++++ b/drivers/rtc/lib_test.c +@@ -0,0 +1,79 @@ ++// SPDX-License-Identifier: LGPL-2.1+ ++ ++#include ++#include ++ ++/* ++ * Advance a date by one day. ++ */ ++static void advance_date(int *year, int *month, int *mday, int *yday) ++{ ++ if (*mday != rtc_month_days(*month - 1, *year)) { ++ ++*mday; ++ ++*yday; ++ return; ++ } ++ ++ *mday = 1; ++ if (*month != 12) { ++ ++*month; ++ ++*yday; ++ return; ++ } ++ ++ *month = 1; ++ *yday = 1; ++ ++*year; ++} ++ ++/* ++ * Checks every day in a 160000 years interval starting on 1970-01-01 ++ * against the expected result. ++ */ ++static void rtc_time64_to_tm_test_date_range(struct kunit *test) ++{ ++ /* ++ * 160000 years = (160000 / 400) * 400 years ++ * = (160000 / 400) * 146097 days ++ * = (160000 / 400) * 146097 * 86400 seconds ++ */ ++ time64_t total_secs = ((time64_t) 160000) / 400 * 146097 * 86400; ++ ++ int year = 1970; ++ int month = 1; ++ int mday = 1; ++ int yday = 1; ++ ++ struct rtc_time result; ++ time64_t secs; ++ s64 days; ++ ++ for (secs = 0; secs <= total_secs; secs += 86400) { ++ ++ rtc_time64_to_tm(secs, &result); ++ ++ days = div_s64(secs, 86400); ++ ++ #define FAIL_MSG "%d/%02d/%02d (%2d) : %ld", \ ++ year, month, mday, yday, days ++ ++ KUNIT_ASSERT_EQ_MSG(test, year - 1900, result.tm_year, FAIL_MSG); ++ KUNIT_ASSERT_EQ_MSG(test, month - 1, result.tm_mon, FAIL_MSG); ++ KUNIT_ASSERT_EQ_MSG(test, mday, result.tm_mday, FAIL_MSG); ++ KUNIT_ASSERT_EQ_MSG(test, yday, result.tm_yday, FAIL_MSG); ++ ++ advance_date(&year, &month, &mday, &yday); ++ } ++} ++ ++static struct kunit_case rtc_lib_test_cases[] = { ++ KUNIT_CASE(rtc_time64_to_tm_test_date_range), ++ {} ++}; ++ ++static struct kunit_suite rtc_lib_test_suite = { ++ .name = "rtc_lib_test_cases", ++ .test_cases = rtc_lib_test_cases, ++}; ++ ++kunit_test_suite(rtc_lib_test_suite); diff --git a/queue-5.4/rtc-make-rtc_time64_to_tm-support-dates-before-1970.patch b/queue-5.4/rtc-make-rtc_time64_to_tm-support-dates-before-1970.patch new file mode 100644 index 0000000000..b4a42d19a9 --- /dev/null +++ b/queue-5.4/rtc-make-rtc_time64_to_tm-support-dates-before-1970.patch @@ -0,0 +1,85 @@ +From 7df4cfef8b351fec3156160bedfc7d6d29de4cce Mon Sep 17 00:00:00 2001 +From: Alexandre Mergnat +Date: Mon, 28 Apr 2025 12:06:47 +0200 +Subject: rtc: Make rtc_time64_to_tm() support dates before 1970 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Alexandre Mergnat + +commit 7df4cfef8b351fec3156160bedfc7d6d29de4cce upstream. + +Conversion of dates before 1970 is still relevant today because these +dates are reused on some hardwares to store dates bigger than the +maximal date that is representable in the device's native format. +This prominently and very soon affects the hardware covered by the +rtc-mt6397 driver that can only natively store dates in the interval +1900-01-01 up to 2027-12-31. So to store the date 2028-01-01 00:00:00 +to such a device, rtc_time64_to_tm() must do the right thing for +time=-2208988800. + +Signed-off-by: Alexandre Mergnat +Reviewed-by: Uwe Kleine-König +Link: https://lore.kernel.org/r/20250428-enable-rtc-v4-1-2b2f7e3f9349@baylibre.com +Signed-off-by: Alexandre Belloni +Signed-off-by: Uwe Kleine-König +Signed-off-by: Greg Kroah-Hartman +--- + drivers/rtc/lib.c | 24 +++++++++++++++++++----- + 1 file changed, 19 insertions(+), 5 deletions(-) + +--- a/drivers/rtc/lib.c ++++ b/drivers/rtc/lib.c +@@ -46,24 +46,38 @@ EXPORT_SYMBOL(rtc_year_days); + * rtc_time64_to_tm - converts time64_t to rtc_time. + * + * @time: The number of seconds since 01-01-1970 00:00:00. +- * (Must be positive.) ++ * Works for values since at least 1900 + * @tm: Pointer to the struct rtc_time. + */ + void rtc_time64_to_tm(time64_t time, struct rtc_time *tm) + { +- unsigned int secs; +- int days; ++ int days, secs; + + u64 u64tmp; + u32 u32tmp, udays, century, day_of_century, year_of_century, year, + day_of_year, month, day; + bool is_Jan_or_Feb, is_leap_year; + +- /* time must be positive */ ++ /* ++ * Get days and seconds while preserving the sign to ++ * handle negative time values (dates before 1970-01-01) ++ */ + days = div_s64_rem(time, 86400, &secs); + ++ /* ++ * We need 0 <= secs < 86400 which isn't given for negative ++ * values of time. Fixup accordingly. ++ */ ++ if (secs < 0) { ++ days -= 1; ++ secs += 86400; ++ } ++ + /* day of the week, 1970-01-01 was a Thursday */ + tm->tm_wday = (days + 4) % 7; ++ /* Ensure tm_wday is always positive */ ++ if (tm->tm_wday < 0) ++ tm->tm_wday += 7; + + /* + * The following algorithm is, basically, Proposition 6.3 of Neri +@@ -93,7 +107,7 @@ void rtc_time64_to_tm(time64_t time, str + * thus, is slightly different from [1]. + */ + +- udays = ((u32) days) + 719468; ++ udays = days + 719468; + + u32tmp = 4 * udays + 3; + century = u32tmp / 146097; diff --git a/queue-5.4/series b/queue-5.4/series index a818571711..2f00bc360e 100644 --- a/queue-5.4/series +++ b/queue-5.4/series @@ -215,3 +215,7 @@ arm-dts-am335x-bone-common-increase-mdio-reset-deassert-delay-to-50ms.patch posix-cpu-timers-fix-race-between-handle_posix_cpu_timers-and-posix_cpu_timer_del.patch xprtrdma-fix-pointer-derefs-in-error-cases-of-rpcrdma_ep_create.patch net-fix-checksum-update-for-ila-adj-transport.patch +rtc-improve-performance-of-rtc_time64_to_tm-.-add-tests.patch +rtc-make-rtc_time64_to_tm-support-dates-before-1970.patch +mm-huge_memory-fix-dereferencing-invalid-pmd-migration-entry.patch +jbd2-fix-data-race-and-null-ptr-deref-in-jbd2_journal_dirty_metadata.patch