From 44bcf51e8bdbddf1fa5a395414a76e40bdb1680a Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 6 Mar 2023 12:32:04 +0100 Subject: [PATCH] 5.15-stable patches added patches: arm-dts-exynos-correct-hdmi-phy-compatible-in-exynos4.patch btrfs-hold-block-group-refcount-during-async-discard.patch ksmbd-do-not-allow-the-actual-frame-length-to-be-smaller-than-the-rfc1002-length.patch ksmbd-fix-wrong-data-area-length-for-smb2-lock-request.patch locking-rwsem-prevent-non-first-waiter-from-spinning-in-down_write-slowpath.patch --- ...rrect-hdmi-phy-compatible-in-exynos4.patch | 31 ++++ ...-group-refcount-during-async-discard.patch | 153 ++++++++++++++++++ ...o-be-smaller-than-the-rfc1002-length.patch | 58 +++++++ ...ta-area-length-for-smb2-lock-request.patch | 47 ++++++ ...from-spinning-in-down_write-slowpath.patch | 99 ++++++++++++ queue-5.15/series | 5 + 6 files changed, 393 insertions(+) create mode 100644 queue-5.15/arm-dts-exynos-correct-hdmi-phy-compatible-in-exynos4.patch create mode 100644 queue-5.15/btrfs-hold-block-group-refcount-during-async-discard.patch create mode 100644 queue-5.15/ksmbd-do-not-allow-the-actual-frame-length-to-be-smaller-than-the-rfc1002-length.patch create mode 100644 queue-5.15/ksmbd-fix-wrong-data-area-length-for-smb2-lock-request.patch create mode 100644 queue-5.15/locking-rwsem-prevent-non-first-waiter-from-spinning-in-down_write-slowpath.patch diff --git a/queue-5.15/arm-dts-exynos-correct-hdmi-phy-compatible-in-exynos4.patch b/queue-5.15/arm-dts-exynos-correct-hdmi-phy-compatible-in-exynos4.patch new file mode 100644 index 00000000000..0f4f7b43d43 --- /dev/null +++ b/queue-5.15/arm-dts-exynos-correct-hdmi-phy-compatible-in-exynos4.patch @@ -0,0 +1,31 @@ +From af1c89ddb74f170eccd5a57001d7317560b638ea Mon Sep 17 00:00:00 2001 +From: Krzysztof Kozlowski +Date: Wed, 25 Jan 2023 10:45:05 +0100 +Subject: ARM: dts: exynos: correct HDMI phy compatible in Exynos4 + +From: Krzysztof Kozlowski + +commit af1c89ddb74f170eccd5a57001d7317560b638ea upstream. + +The HDMI phy compatible was missing vendor prefix. + +Fixes: ed80d4cab772 ("ARM: dts: add hdmi related nodes for exynos4 SoCs") +Cc: +Link: https://lore.kernel.org/r/20230125094513.155063-1-krzysztof.kozlowski@linaro.org +Signed-off-by: Krzysztof Kozlowski +Signed-off-by: Greg Kroah-Hartman +--- + arch/arm/boot/dts/exynos4.dtsi | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/arch/arm/boot/dts/exynos4.dtsi ++++ b/arch/arm/boot/dts/exynos4.dtsi +@@ -605,7 +605,7 @@ + status = "disabled"; + + hdmi_i2c_phy: hdmiphy@38 { +- compatible = "exynos4210-hdmiphy"; ++ compatible = "samsung,exynos4210-hdmiphy"; + reg = <0x38>; + }; + }; diff --git a/queue-5.15/btrfs-hold-block-group-refcount-during-async-discard.patch b/queue-5.15/btrfs-hold-block-group-refcount-during-async-discard.patch new file mode 100644 index 00000000000..d07ddddc43b --- /dev/null +++ b/queue-5.15/btrfs-hold-block-group-refcount-during-async-discard.patch @@ -0,0 +1,153 @@ +From 2b5463fcbdfb24e898916bcae2b1359042d26963 Mon Sep 17 00:00:00 2001 +From: Boris Burkov +Date: Thu, 12 Jan 2023 16:05:11 -0800 +Subject: btrfs: hold block group refcount during async discard + +From: Boris Burkov + +commit 2b5463fcbdfb24e898916bcae2b1359042d26963 upstream. + +Async discard does not acquire the block group reference count while it +holds a reference on the discard list. This is generally OK, as the +paths which destroy block groups tend to try to synchronize on +cancelling async discard work. However, relying on cancelling work +requires careful analysis to be sure it is safe from races with +unpinning scheduling more work. + +While I am unable to find a race with unpinning in the current code for +either the unused bgs or relocation paths, I believe we have one in an +older version of auto relocation in a Meta internal build. This suggests +that this is in fact an error prone model, and could be fragile to +future changes to these bg deletion paths. + +To make this ownership more clear, add a refcount for async discard. If +work is queued for a block group, its refcount should be incremented, +and when work is completed or canceled, it should be decremented. + +CC: stable@vger.kernel.org # 5.15+ +Signed-off-by: Boris Burkov +Signed-off-by: David Sterba +Signed-off-by: Greg Kroah-Hartman +--- + fs/btrfs/discard.c | 41 ++++++++++++++++++++++++++++++++++++++--- + 1 file changed, 38 insertions(+), 3 deletions(-) + +--- a/fs/btrfs/discard.c ++++ b/fs/btrfs/discard.c +@@ -77,6 +77,7 @@ static struct list_head *get_discard_lis + static void __add_to_discard_list(struct btrfs_discard_ctl *discard_ctl, + struct btrfs_block_group *block_group) + { ++ lockdep_assert_held(&discard_ctl->lock); + if (!btrfs_run_discard_work(discard_ctl)) + return; + +@@ -88,6 +89,8 @@ static void __add_to_discard_list(struct + BTRFS_DISCARD_DELAY); + block_group->discard_state = BTRFS_DISCARD_RESET_CURSOR; + } ++ if (list_empty(&block_group->discard_list)) ++ btrfs_get_block_group(block_group); + + list_move_tail(&block_group->discard_list, + get_discard_list(discard_ctl, block_group)); +@@ -107,8 +110,12 @@ static void add_to_discard_list(struct b + static void add_to_discard_unused_list(struct btrfs_discard_ctl *discard_ctl, + struct btrfs_block_group *block_group) + { ++ bool queued; ++ + spin_lock(&discard_ctl->lock); + ++ queued = !list_empty(&block_group->discard_list); ++ + if (!btrfs_run_discard_work(discard_ctl)) { + spin_unlock(&discard_ctl->lock); + return; +@@ -120,6 +127,8 @@ static void add_to_discard_unused_list(s + block_group->discard_eligible_time = (ktime_get_ns() + + BTRFS_DISCARD_UNUSED_DELAY); + block_group->discard_state = BTRFS_DISCARD_RESET_CURSOR; ++ if (!queued) ++ btrfs_get_block_group(block_group); + list_add_tail(&block_group->discard_list, + &discard_ctl->discard_list[BTRFS_DISCARD_INDEX_UNUSED]); + +@@ -130,6 +139,7 @@ static bool remove_from_discard_list(str + struct btrfs_block_group *block_group) + { + bool running = false; ++ bool queued = false; + + spin_lock(&discard_ctl->lock); + +@@ -139,7 +149,16 @@ static bool remove_from_discard_list(str + } + + block_group->discard_eligible_time = 0; ++ queued = !list_empty(&block_group->discard_list); + list_del_init(&block_group->discard_list); ++ /* ++ * If the block group is currently running in the discard workfn, we ++ * don't want to deref it, since it's still being used by the workfn. ++ * The workfn will notice this case and deref the block group when it is ++ * finished. ++ */ ++ if (queued && !running) ++ btrfs_put_block_group(block_group); + + spin_unlock(&discard_ctl->lock); + +@@ -212,10 +231,12 @@ again: + if (block_group && now >= block_group->discard_eligible_time) { + if (block_group->discard_index == BTRFS_DISCARD_INDEX_UNUSED && + block_group->used != 0) { +- if (btrfs_is_block_group_data_only(block_group)) ++ if (btrfs_is_block_group_data_only(block_group)) { + __add_to_discard_list(discard_ctl, block_group); +- else ++ } else { + list_del_init(&block_group->discard_list); ++ btrfs_put_block_group(block_group); ++ } + goto again; + } + if (block_group->discard_state == BTRFS_DISCARD_RESET_CURSOR) { +@@ -502,6 +523,15 @@ static void btrfs_discard_workfn(struct + spin_lock(&discard_ctl->lock); + discard_ctl->prev_discard = trimmed; + discard_ctl->prev_discard_time = now; ++ /* ++ * If the block group was removed from the discard list while it was ++ * running in this workfn, then we didn't deref it, since this function ++ * still owned that reference. But we set the discard_ctl->block_group ++ * back to NULL, so we can use that condition to know that now we need ++ * to deref the block_group. ++ */ ++ if (discard_ctl->block_group == NULL) ++ btrfs_put_block_group(block_group); + discard_ctl->block_group = NULL; + __btrfs_discard_schedule_work(discard_ctl, now, false); + spin_unlock(&discard_ctl->lock); +@@ -638,8 +668,12 @@ void btrfs_discard_punt_unused_bgs_list( + list_for_each_entry_safe(block_group, next, &fs_info->unused_bgs, + bg_list) { + list_del_init(&block_group->bg_list); +- btrfs_put_block_group(block_group); + btrfs_discard_queue_work(&fs_info->discard_ctl, block_group); ++ /* ++ * This put is for the get done by btrfs_mark_bg_unused. ++ * Queueing discard incremented it for discard's reference. ++ */ ++ btrfs_put_block_group(block_group); + } + spin_unlock(&fs_info->unused_bgs_lock); + } +@@ -669,6 +703,7 @@ static void btrfs_discard_purge_list(str + if (block_group->used == 0) + btrfs_mark_bg_unused(block_group); + spin_lock(&discard_ctl->lock); ++ btrfs_put_block_group(block_group); + } + } + spin_unlock(&discard_ctl->lock); diff --git a/queue-5.15/ksmbd-do-not-allow-the-actual-frame-length-to-be-smaller-than-the-rfc1002-length.patch b/queue-5.15/ksmbd-do-not-allow-the-actual-frame-length-to-be-smaller-than-the-rfc1002-length.patch new file mode 100644 index 00000000000..bf91df000dd --- /dev/null +++ b/queue-5.15/ksmbd-do-not-allow-the-actual-frame-length-to-be-smaller-than-the-rfc1002-length.patch @@ -0,0 +1,58 @@ +From fb533473d1595fe79ecb528fda1de33552b07178 Mon Sep 17 00:00:00 2001 +From: Namjae Jeon +Date: Sat, 11 Feb 2023 00:27:34 +0900 +Subject: ksmbd: do not allow the actual frame length to be smaller than the rfc1002 length + +From: Namjae Jeon + +commit fb533473d1595fe79ecb528fda1de33552b07178 upstream. + +ksmbd allowed the actual frame length to be smaller than the rfc1002 +length. If allowed, it is possible to allocates a large amount of memory +that can be limited by credit management and can eventually cause memory +exhaustion problem. This patch do not allow it except SMB2 Negotiate +request which will be validated when message handling proceeds. +Also, Allow a message that padded to 8byte boundary. + +Fixes: e2f34481b24d ("cifsd: add server-side procedures for SMB3") +Cc: stable@vger.kernel.org +Signed-off-by: Namjae Jeon +Signed-off-by: Steve French +Signed-off-by: Greg Kroah-Hartman +--- + fs/ksmbd/smb2misc.c | 21 ++++++++++----------- + 1 file changed, 10 insertions(+), 11 deletions(-) + +--- a/fs/ksmbd/smb2misc.c ++++ b/fs/ksmbd/smb2misc.c +@@ -414,20 +414,19 @@ int ksmbd_smb2_check_message(struct ksmb + goto validate_credit; + + /* +- * windows client also pad up to 8 bytes when compounding. +- * If pad is longer than eight bytes, log the server behavior +- * (once), since may indicate a problem but allow it and +- * continue since the frame is parseable. ++ * SMB2 NEGOTIATE request will be validated when message ++ * handling proceeds. + */ +- if (clc_len < len) { +- ksmbd_debug(SMB, +- "cli req padded more than expected. Length %d not %d for cmd:%d mid:%llu\n", +- len, clc_len, command, +- le64_to_cpu(hdr->MessageId)); ++ if (command == SMB2_NEGOTIATE_HE) + goto validate_credit; +- } + +- ksmbd_debug(SMB, ++ /* ++ * Allow a message that padded to 8byte boundary. ++ */ ++ if (clc_len < len && (len - clc_len) < 8) ++ goto validate_credit; ++ ++ pr_err_ratelimited( + "cli req too short, len %d not %d. cmd:%d mid:%llu\n", + len, clc_len, command, + le64_to_cpu(hdr->MessageId)); diff --git a/queue-5.15/ksmbd-fix-wrong-data-area-length-for-smb2-lock-request.patch b/queue-5.15/ksmbd-fix-wrong-data-area-length-for-smb2-lock-request.patch new file mode 100644 index 00000000000..f085304b7dd --- /dev/null +++ b/queue-5.15/ksmbd-fix-wrong-data-area-length-for-smb2-lock-request.patch @@ -0,0 +1,47 @@ +From 8f8c43b125882ac14372f8dca0c8e50a59e78d79 Mon Sep 17 00:00:00 2001 +From: Namjae Jeon +Date: Wed, 8 Feb 2023 09:50:46 +0900 +Subject: ksmbd: fix wrong data area length for smb2 lock request + +From: Namjae Jeon + +commit 8f8c43b125882ac14372f8dca0c8e50a59e78d79 upstream. + +When turning debug mode on, The following error message from +ksmbd_smb2_check_message() is coming. + +ksmbd: cli req padded more than expected. Length 112 not 88 for cmd:10 mid:14 + +data area length calculation for smb2 lock request in smb2_get_data_area_len() is +incorrect. + +Fixes: e2f34481b24d ("cifsd: add server-side procedures for SMB3") +Cc: stable@vger.kernel.org +Signed-off-by: Namjae Jeon +Signed-off-by: Steve French +Signed-off-by: Greg Kroah-Hartman +--- + fs/ksmbd/smb2misc.c | 10 +++------- + 1 file changed, 3 insertions(+), 7 deletions(-) + +--- a/fs/ksmbd/smb2misc.c ++++ b/fs/ksmbd/smb2misc.c +@@ -150,15 +150,11 @@ static int smb2_get_data_area_len(unsign + break; + case SMB2_LOCK: + { +- int lock_count; ++ unsigned short lock_count; + +- /* +- * smb2_lock request size is 48 included single +- * smb2_lock_element structure size. +- */ +- lock_count = le16_to_cpu(((struct smb2_lock_req *)hdr)->LockCount) - 1; ++ lock_count = le16_to_cpu(((struct smb2_lock_req *)hdr)->LockCount); + if (lock_count > 0) { +- *off = __SMB2_HEADER_STRUCTURE_SIZE + 48; ++ *off = offsetof(struct smb2_lock_req, locks); + *len = sizeof(struct smb2_lock_element) * lock_count; + } + break; diff --git a/queue-5.15/locking-rwsem-prevent-non-first-waiter-from-spinning-in-down_write-slowpath.patch b/queue-5.15/locking-rwsem-prevent-non-first-waiter-from-spinning-in-down_write-slowpath.patch new file mode 100644 index 00000000000..bb92904fe3e --- /dev/null +++ b/queue-5.15/locking-rwsem-prevent-non-first-waiter-from-spinning-in-down_write-slowpath.patch @@ -0,0 +1,99 @@ +From b613c7f31476c44316bfac1af7cac714b7d6bef9 Mon Sep 17 00:00:00 2001 +From: Waiman Long +Date: Wed, 25 Jan 2023 19:36:25 -0500 +Subject: locking/rwsem: Prevent non-first waiter from spinning in down_write() slowpath + +From: Waiman Long + +commit b613c7f31476c44316bfac1af7cac714b7d6bef9 upstream. + +A non-first waiter can potentially spin in the for loop of +rwsem_down_write_slowpath() without sleeping but fail to acquire the +lock even if the rwsem is free if the following sequence happens: + + Non-first RT waiter First waiter Lock holder + ------------------- ------------ ----------- + Acquire wait_lock + rwsem_try_write_lock(): + Set handoff bit if RT or + wait too long + Set waiter->handoff_set + Release wait_lock + Acquire wait_lock + Inherit waiter->handoff_set + Release wait_lock + Clear owner + Release lock + if (waiter.handoff_set) { + rwsem_spin_on_owner((); + if (OWNER_NULL) + goto trylock_again; + } + trylock_again: + Acquire wait_lock + rwsem_try_write_lock(): + if (first->handoff_set && (waiter != first)) + return false; + Release wait_lock + +A non-first waiter cannot really acquire the rwsem even if it mistakenly +believes that it can spin on OWNER_NULL value. If that waiter happens +to be an RT task running on the same CPU as the first waiter, it can +block the first waiter from acquiring the rwsem leading to live lock. +Fix this problem by making sure that a non-first waiter cannot spin in +the slowpath loop without sleeping. + +Fixes: d257cc8cb8d5 ("locking/rwsem: Make handoff bit handling more consistent") +Signed-off-by: Waiman Long +Signed-off-by: Ingo Molnar +Tested-by: Mukesh Ojha +Reviewed-by: Mukesh Ojha +Cc: stable@vger.kernel.org +Link: https://lore.kernel.org/r/20230126003628.365092-2-longman@redhat.com +Signed-off-by: Greg Kroah-Hartman +--- + kernel/locking/rwsem.c | 19 +++++++++---------- + 1 file changed, 9 insertions(+), 10 deletions(-) + +--- a/kernel/locking/rwsem.c ++++ b/kernel/locking/rwsem.c +@@ -586,18 +586,16 @@ static inline bool rwsem_try_write_lock( + */ + if (first->handoff_set && (waiter != first)) + return false; +- +- /* +- * First waiter can inherit a previously set handoff +- * bit and spin on rwsem if lock acquisition fails. +- */ +- if (waiter == first) +- waiter->handoff_set = true; + } + + new = count; + + if (count & RWSEM_LOCK_MASK) { ++ /* ++ * A waiter (first or not) can set the handoff bit ++ * if it is an RT task or wait in the wait queue ++ * for too long. ++ */ + if (has_handoff || (!rt_task(waiter->task) && + !time_after(jiffies, waiter->timeout))) + return false; +@@ -613,11 +611,12 @@ static inline bool rwsem_try_write_lock( + } while (!atomic_long_try_cmpxchg_acquire(&sem->count, &count, new)); + + /* +- * We have either acquired the lock with handoff bit cleared or +- * set the handoff bit. ++ * We have either acquired the lock with handoff bit cleared or set ++ * the handoff bit. Only the first waiter can have its handoff_set ++ * set here to enable optimistic spinning in slowpath loop. + */ + if (new & RWSEM_FLAG_HANDOFF) { +- waiter->handoff_set = true; ++ first->handoff_set = true; + lockevent_inc(rwsem_wlock_handoff); + return false; + } diff --git a/queue-5.15/series b/queue-5.15/series index 0f76f5d3fcd..7c9cd5b6c1e 100644 --- a/queue-5.15/series +++ b/queue-5.15/series @@ -439,3 +439,8 @@ s390-discard-.interp-section.patch s390-kprobes-fix-irq-mask-clobbering-on-kprobe-reenter-from-post_handler.patch s390-kprobes-fix-current_kprobe-never-cleared-after-kprobes-reenter.patch cifs-fix-uninitialized-memory-read-in-smb3_qfs_tcon.patch +btrfs-hold-block-group-refcount-during-async-discard.patch +locking-rwsem-prevent-non-first-waiter-from-spinning-in-down_write-slowpath.patch +ksmbd-fix-wrong-data-area-length-for-smb2-lock-request.patch +ksmbd-do-not-allow-the-actual-frame-length-to-be-smaller-than-the-rfc1002-length.patch +arm-dts-exynos-correct-hdmi-phy-compatible-in-exynos4.patch -- 2.47.3