From: Greg Kroah-Hartman Date: Sat, 21 Mar 2026 15:04:45 +0000 (+0100) Subject: 5.15-stable patches X-Git-Tag: v6.1.167~49 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=1400b5b737484fae2430b705fa024ae2e041fe08;p=thirdparty%2Fkernel%2Fstable-queue.git 5.15-stable patches added patches: ata-libata-scsi-drop-dprintk-calls-for-cdb-translation.patch batman-adv-avoid-ogm-aggregation-when-skb-tailroom-is-insufficient.patch drm-amd-display-use-gfp_atomic-in-dc_create_stream_for_sink.patch ext4-always-allocate-blocks-only-from-groups-inode-can-use.patch ext4-don-t-set-ext4_get_blocks_convert-when-splitting-before-submitting-i-o.patch ext4-drop-extent-cache-when-splitting-extent-fails.patch ext4-fix-dirtyclusters-double-decrement-on-fs-shutdown.patch ext4-fix-e4b-bitmap-inconsistency-reports.patch ksmbd-call-ksmbd_vfs_kern_path_end_removing-on-some-error-paths.patch ksmbd-fix-null-pointer-dereference-error-in-generate_encryptionkey.patch mptcp-pm-avoid-sending-rm_addr-over-same-subflow.patch net-phy-register-phy-led_triggers-during-probe-to-avoid-ab-ba-deadlock.patch pmdomain-bcm-bcm2835-power-increase-asb-control-timeout.patch rdma-irdma-fix-kernel-stack-leak-in-irdma_create_user_ah.patch smb-client-don-t-log-plaintext-credentials-in-cifs_set_cifscreds.patch wifi-cfg80211-cancel-rfkill_block-work-in-wiphy_unregister.patch wifi-cfg80211-move-scan-done-work-to-wiphy-work.patch wifi-libertas-fix-use-after-free-in-lbs_free_adapter.patch --- diff --git a/queue-5.15/ata-libata-scsi-drop-dprintk-calls-for-cdb-translation.patch b/queue-5.15/ata-libata-scsi-drop-dprintk-calls-for-cdb-translation.patch new file mode 100644 index 0000000000..82372370ea --- /dev/null +++ b/queue-5.15/ata-libata-scsi-drop-dprintk-calls-for-cdb-translation.patch @@ -0,0 +1,127 @@ +From stable+bounces-219683-greg=kroah.com@vger.kernel.org Wed Feb 25 19:10:43 2026 +From: Sasha Levin +Date: Wed, 25 Feb 2026 13:10:32 -0500 +Subject: ata: libata-scsi: drop DPRINTK calls for cdb translation +To: stable@vger.kernel.org +Cc: Hannes Reinecke , Damien Le Moal , Sasha Levin +Message-ID: <20260225181034.910635-2-sashal@kernel.org> + +From: Hannes Reinecke + +[ Upstream commit 1fe9fb71b2ffcedd794daacf4db2056a6cb5199e ] + +Drop DPRINTK calls for cdb translation as they are already covered +by other traces, and also drop the DPRINTK calls in ata_scsi_hotplug(). + +Signed-off-by: Hannes Reinecke +Signed-off-by: Damien Le Moal +Stable-dep-of: bb3a8154b1a1 ("ata: libata-scsi: refactor ata_scsi_translate()") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/ata/libata-scsi.c | 20 +------------------- + 1 file changed, 1 insertion(+), 19 deletions(-) + +diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c +index b57027206ae1e..22c45bc64a95e 100644 +--- a/drivers/ata/libata-scsi.c ++++ b/drivers/ata/libata-scsi.c +@@ -1472,9 +1472,6 @@ static unsigned int ata_scsi_verify_xlat(struct ata_queued_cmd *qc) + head = track % dev->heads; + sect = (u32)block % dev->sectors + 1; + +- DPRINTK("block %u track %u cyl %u head %u sect %u\n", +- (u32)block, track, cyl, head, sect); +- + /* Check whether the converted CHS can fit. + Cylinder: 0-65535 + Head: 0-15 +@@ -1597,7 +1594,6 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc) + goto invalid_fld; + break; + default: +- DPRINTK("no-byte command\n"); + fp = 0; + goto invalid_fld; + } +@@ -1751,7 +1747,6 @@ static int ata_scsi_translate(struct ata_device *dev, struct scsi_cmnd *cmd, + early_finish: + ata_qc_free(qc); + scsi_done(cmd); +- DPRINTK("EXIT - early finish (good or error)\n"); + return 0; + + err_did: +@@ -1759,12 +1754,10 @@ static int ata_scsi_translate(struct ata_device *dev, struct scsi_cmnd *cmd, + cmd->result = (DID_ERROR << 16); + scsi_done(cmd); + err_mem: +- DPRINTK("EXIT - internal\n"); + return 0; + + defer: + ata_qc_free(qc); +- DPRINTK("EXIT - defer\n"); + if (rc == ATA_DEFER_LINK) + return SCSI_MLQUEUE_DEVICE_BUSY; + else +@@ -2491,8 +2484,6 @@ static void atapi_request_sense(struct ata_queued_cmd *qc) + struct ata_port *ap = qc->ap; + struct scsi_cmnd *cmd = qc->scsicmd; + +- DPRINTK("ATAPI request sense\n"); +- + memset(cmd->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE); + + #ifdef CONFIG_ATA_SFF +@@ -2531,8 +2522,6 @@ static void atapi_request_sense(struct ata_queued_cmd *qc) + qc->complete_fn = atapi_sense_complete; + + ata_qc_issue(qc); +- +- DPRINTK("EXIT\n"); + } + + /* +@@ -2642,7 +2631,6 @@ static unsigned int atapi_xlat(struct ata_queued_cmd *qc) + qc->tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE; + if (scmd->sc_data_direction == DMA_TO_DEVICE) { + qc->tf.flags |= ATA_TFLAG_WRITE; +- DPRINTK("direction: write\n"); + } + + qc->tf.command = ATA_CMD_PACKET; +@@ -4065,8 +4053,6 @@ int __ata_scsi_queuecmd(struct scsi_cmnd *scmd, struct ata_device *dev) + return 0; + + bad_cdb_len: +- DPRINTK("bad CDB len=%u, scsi_op=0x%02x, max=%u\n", +- scmd->cmd_len, scsi_op, dev->cdb_len); + scmd->result = DID_ERROR << 16; + scsi_done(scmd); + return 0; +@@ -4532,12 +4518,9 @@ void ata_scsi_hotplug(struct work_struct *work) + container_of(work, struct ata_port, hotplug_task.work); + int i; + +- if (ap->pflags & ATA_PFLAG_UNLOADING) { +- DPRINTK("ENTER/EXIT - unloading\n"); ++ if (ap->pflags & ATA_PFLAG_UNLOADING) + return; +- } + +- DPRINTK("ENTER\n"); + mutex_lock(&ap->scsi_scan_mutex); + + /* Unplug detached devices. We cannot use link iterator here +@@ -4553,7 +4536,6 @@ void ata_scsi_hotplug(struct work_struct *work) + ata_scsi_scan_host(ap, 0); + + mutex_unlock(&ap->scsi_scan_mutex); +- DPRINTK("EXIT\n"); + } + + /** +-- +2.51.0 + diff --git a/queue-5.15/batman-adv-avoid-ogm-aggregation-when-skb-tailroom-is-insufficient.patch b/queue-5.15/batman-adv-avoid-ogm-aggregation-when-skb-tailroom-is-insufficient.patch new file mode 100644 index 0000000000..103604d262 --- /dev/null +++ b/queue-5.15/batman-adv-avoid-ogm-aggregation-when-skb-tailroom-is-insufficient.patch @@ -0,0 +1,50 @@ +From stable+bounces-227506-greg=kroah.com@vger.kernel.org Fri Mar 20 11:18:51 2026 +From: Sven Eckelmann +Date: Fri, 20 Mar 2026 11:15:40 +0100 +Subject: batman-adv: avoid OGM aggregation when skb tailroom is insufficient +To: stable@vger.kernel.org +Cc: Yang Yang , Yifan Wu , Juefei Pu , Yuan Tan , Xin Liu , Sven Eckelmann , Simon Wunderlich +Message-ID: <20260320101540.1580645-1-sven@narfation.org> + +From: Yang Yang + +commit 0d4aef630be9d5f9c1227d07669c26c4383b5ad0 upstream. + +When OGM aggregation state is toggled at runtime, an existing forwarded +packet may have been allocated with only packet_len bytes, while a later +packet can still be selected for aggregation. Appending in this case can +hit skb_put overflow conditions. + +Reject aggregation when the target skb tailroom cannot accommodate the new +packet. The caller then falls back to creating a new forward packet +instead of appending. + +Fixes: c6c8fea29769 ("net: Add batman-adv meshing protocol") +Cc: stable@vger.kernel.org +Reported-by: Yifan Wu +Reported-by: Juefei Pu +Signed-off-by: Yuan Tan +Signed-off-by: Xin Liu +Signed-off-by: Ao Zhou +Signed-off-by: Yang Yang +Signed-off-by: Sven Eckelmann +Signed-off-by: Simon Wunderlich +[ Adjust context ] +Signed-off-by: Sven Eckelmann +Signed-off-by: Greg Kroah-Hartman +--- + net/batman-adv/bat_iv_ogm.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/net/batman-adv/bat_iv_ogm.c ++++ b/net/batman-adv/bat_iv_ogm.c +@@ -465,6 +465,9 @@ batadv_iv_ogm_can_aggregate(const struct + !time_after_eq(aggregation_end_time, forw_packet->send_time)) + return false; + ++ if (skb_tailroom(forw_packet->skb) < packet_len) ++ return false; ++ + if (aggregated_bytes > BATADV_MAX_AGGREGATION_BYTES) + return false; + diff --git a/queue-5.15/drm-amd-display-use-gfp_atomic-in-dc_create_stream_for_sink.patch b/queue-5.15/drm-amd-display-use-gfp_atomic-in-dc_create_stream_for_sink.patch new file mode 100644 index 0000000000..7f60c7b40b --- /dev/null +++ b/queue-5.15/drm-amd-display-use-gfp_atomic-in-dc_create_stream_for_sink.patch @@ -0,0 +1,40 @@ +From stable+bounces-223677-greg=kroah.com@vger.kernel.org Mon Mar 9 15:55:19 2026 +From: Sasha Levin +Date: Mon, 9 Mar 2026 10:49:54 -0400 +Subject: drm/amd/display: Use GFP_ATOMIC in dc_create_stream_for_sink +To: stable@vger.kernel.org +Cc: Natalie Vock , Alex Deucher , Sasha Levin +Message-ID: <20260309144954.1220459-1-sashal@kernel.org> + +From: Natalie Vock + +[ Upstream commit 28dfe4317541e57fe52f9a290394cd29c348228b ] + +This can be called while preemption is disabled, for example by +dcn32_internal_validate_bw which is called with the FPU active. + +Fixes "BUG: scheduling while atomic" messages I encounter on my Navi31 +machine. + +Signed-off-by: Natalie Vock +Signed-off-by: Alex Deucher +(cherry picked from commit b42dae2ebc5c84a68de63ec4ffdfec49362d53f1) +Cc: stable@vger.kernel.org +[ Context ] +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpu/drm/amd/display/dc/core/dc_stream.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c ++++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +@@ -167,7 +167,7 @@ struct dc_stream_state *dc_create_stream + if (sink == NULL) + return NULL; + +- stream = kzalloc(sizeof(struct dc_stream_state), GFP_KERNEL); ++ stream = kzalloc(sizeof(struct dc_stream_state), GFP_ATOMIC); + if (stream == NULL) + goto alloc_fail; + diff --git a/queue-5.15/ext4-always-allocate-blocks-only-from-groups-inode-can-use.patch b/queue-5.15/ext4-always-allocate-blocks-only-from-groups-inode-can-use.patch new file mode 100644 index 0000000000..34132db8e7 --- /dev/null +++ b/queue-5.15/ext4-always-allocate-blocks-only-from-groups-inode-can-use.patch @@ -0,0 +1,71 @@ +From stable+bounces-219699-greg=kroah.com@vger.kernel.org Wed Feb 25 21:09:15 2026 +From: Sasha Levin +Date: Wed, 25 Feb 2026 15:09:09 -0500 +Subject: ext4: always allocate blocks only from groups inode can use +To: stable@vger.kernel.org +Cc: Jan Kara , Baokun Li , Zhang Yi , Pedro Falcato , stable@kernel.org, Theodore Ts'o , Sasha Levin +Message-ID: <20260225200909.1054153-1-sashal@kernel.org> + +From: Jan Kara + +[ Upstream commit 4865c768b563deff1b6a6384e74a62f143427b42 ] + +For filesystems with more than 2^32 blocks inodes using indirect block +based format cannot use blocks beyond the 32-bit limit. +ext4_mb_scan_groups_linear() takes care to not select these unsupported +groups for such inodes however other functions selecting groups for +allocation don't. So far this is harmless because the other selection +functions are used only with mb_optimize_scan and this is currently +disabled for inodes with indirect blocks however in the following patch +we want to enable mb_optimize_scan regardless of inode format. + +Reviewed-by: Baokun Li +Reviewed-by: Zhang Yi +Signed-off-by: Jan Kara +Acked-by: Pedro Falcato +Cc: stable@kernel.org +Link: https://patch.msgid.link/20260114182836.14120-3-jack@suse.cz +Signed-off-by: Theodore Ts'o +[ Drop a few hunks not needed in older trees ] +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + fs/ext4/mballoc.c | 20 ++++++++++++++++---- + 1 file changed, 16 insertions(+), 4 deletions(-) + +--- a/fs/ext4/mballoc.c ++++ b/fs/ext4/mballoc.c +@@ -885,6 +885,21 @@ mb_update_avg_fragment_size(struct super + write_unlock(&sbi->s_mb_rb_lock); + } + ++static ext4_group_t ext4_get_allocation_groups_count( ++ struct ext4_allocation_context *ac) ++{ ++ ext4_group_t ngroups = ext4_get_groups_count(ac->ac_sb); ++ ++ /* non-extent files are limited to low blocks/groups */ ++ if (!(ext4_test_inode_flag(ac->ac_inode, EXT4_INODE_EXTENTS))) ++ ngroups = EXT4_SB(ac->ac_sb)->s_blockfile_groups; ++ ++ /* Pairs with smp_wmb() in ext4_update_super() */ ++ smp_rmb(); ++ ++ return ngroups; ++} ++ + /* + * Choose next group by traversing largest_free_order lists. Updates *new_cr if + * cr level needs an update. +@@ -2701,10 +2716,7 @@ ext4_mb_regular_allocator(struct ext4_al + + sb = ac->ac_sb; + sbi = EXT4_SB(sb); +- ngroups = ext4_get_groups_count(sb); +- /* non-extent files are limited to low blocks/groups */ +- if (!(ext4_test_inode_flag(ac->ac_inode, EXT4_INODE_EXTENTS))) +- ngroups = sbi->s_blockfile_groups; ++ ngroups = ext4_get_allocation_groups_count(ac); + + BUG_ON(ac->ac_status == AC_STATUS_FOUND); + diff --git a/queue-5.15/ext4-don-t-set-ext4_get_blocks_convert-when-splitting-before-submitting-i-o.patch b/queue-5.15/ext4-don-t-set-ext4_get_blocks_convert-when-splitting-before-submitting-i-o.patch new file mode 100644 index 0000000000..2b88013ffc --- /dev/null +++ b/queue-5.15/ext4-don-t-set-ext4_get_blocks_convert-when-splitting-before-submitting-i-o.patch @@ -0,0 +1,97 @@ +From stable+bounces-219160-greg=kroah.com@vger.kernel.org Wed Feb 25 04:06:55 2026 +From: Sasha Levin +Date: Tue, 24 Feb 2026 22:06:46 -0500 +Subject: ext4: don't set EXT4_GET_BLOCKS_CONVERT when splitting before submitting I/O +To: stable@vger.kernel.org +Cc: Zhang Yi , Ojaswin Mujoo , Baokun Li , stable@kernel.org, Theodore Ts'o , Sasha Levin +Message-ID: <20260225030646.3846438-1-sashal@kernel.org> + +From: Zhang Yi + +[ Upstream commit feaf2a80e78f89ee8a3464126077ba8683b62791 ] + +When allocating blocks during within-EOF DIO and writeback with +dioread_nolock enabled, EXT4_GET_BLOCKS_PRE_IO was set to split an +existing large unwritten extent. However, EXT4_GET_BLOCKS_CONVERT was +set when calling ext4_split_convert_extents(), which may potentially +result in stale data issues. + +Assume we have an unwritten extent, and then DIO writes the second half. + + [UUUUUUUUUUUUUUUU] on-disk extent U: unwritten extent + [UUUUUUUUUUUUUUUU] extent status tree + |<- ->| ----> dio write this range + +First, ext4_iomap_alloc() call ext4_map_blocks() with +EXT4_GET_BLOCKS_PRE_IO, EXT4_GET_BLOCKS_UNWRIT_EXT and +EXT4_GET_BLOCKS_CREATE flags set. ext4_map_blocks() find this extent and +call ext4_split_convert_extents() with EXT4_GET_BLOCKS_CONVERT and the +above flags set. + +Then, ext4_split_convert_extents() calls ext4_split_extent() with +EXT4_EXT_MAY_ZEROOUT, EXT4_EXT_MARK_UNWRIT2 and EXT4_EXT_DATA_VALID2 +flags set, and it calls ext4_split_extent_at() to split the second half +with EXT4_EXT_DATA_VALID2, EXT4_EXT_MARK_UNWRIT1, EXT4_EXT_MAY_ZEROOUT +and EXT4_EXT_MARK_UNWRIT2 flags set. However, ext4_split_extent_at() +failed to insert extent since a temporary lack -ENOSPC. It zeroes out +the first half but convert the entire on-disk extent to written since +the EXT4_EXT_DATA_VALID2 flag set, but left the second half as unwritten +in the extent status tree. + + [0000000000SSSSSS] data S: stale data, 0: zeroed + [WWWWWWWWWWWWWWWW] on-disk extent W: written extent + [WWWWWWWWWWUUUUUU] extent status tree + +Finally, if the DIO failed to write data to the disk, the stale data in +the second half will be exposed once the cached extent entry is gone. + +Fix this issue by not passing EXT4_GET_BLOCKS_CONVERT when splitting +an unwritten extent before submitting I/O, and make +ext4_split_convert_extents() to zero out the entire extent range +to zero for this case, and also mark the extent in the extent status +tree for consistency. + +Fixes: b8a8684502a0 ("ext4: Introduce FALLOC_FL_ZERO_RANGE flag for fallocate") +Signed-off-by: Zhang Yi +Reviewed-by: Ojaswin Mujoo +Reviewed-by: Baokun Li +Cc: stable@kernel.org +Message-ID: <20251129103247.686136-4-yi.zhang@huaweicloud.com> +Signed-off-by: Theodore Ts'o +[ different function signatures ] +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + fs/ext4/extents.c | 12 ++++++++---- + 1 file changed, 8 insertions(+), 4 deletions(-) + +--- a/fs/ext4/extents.c ++++ b/fs/ext4/extents.c +@@ -3711,11 +3711,15 @@ static int ext4_split_convert_extents(ha + /* Convert to unwritten */ + if (flags & EXT4_GET_BLOCKS_CONVERT_UNWRITTEN) { + split_flag |= EXT4_EXT_DATA_VALID1; +- /* Convert to initialized */ +- } else if (flags & EXT4_GET_BLOCKS_CONVERT) { ++ /* Split the existing unwritten extent */ ++ } else if (flags & (EXT4_GET_BLOCKS_UNWRIT_EXT | ++ EXT4_GET_BLOCKS_CONVERT)) { + split_flag |= ee_block + ee_len <= eof_block ? + EXT4_EXT_MAY_ZEROOUT : 0; +- split_flag |= (EXT4_EXT_MARK_UNWRIT2 | EXT4_EXT_DATA_VALID2); ++ split_flag |= EXT4_EXT_MARK_UNWRIT2; ++ /* Convert to initialized */ ++ if (flags & EXT4_GET_BLOCKS_CONVERT) ++ split_flag |= EXT4_EXT_DATA_VALID2; + } + flags |= EXT4_GET_BLOCKS_PRE_IO; + return ext4_split_extent(handle, inode, ppath, map, split_flag, flags); +@@ -3880,7 +3884,7 @@ ext4_ext_handle_unwritten_extents(handle + /* get_block() before submitting IO, split the extent */ + if (flags & EXT4_GET_BLOCKS_PRE_IO) { + ret = ext4_split_convert_extents(handle, inode, map, ppath, +- flags | EXT4_GET_BLOCKS_CONVERT); ++ flags); + if (ret < 0) { + err = ret; + goto out2; diff --git a/queue-5.15/ext4-drop-extent-cache-when-splitting-extent-fails.patch b/queue-5.15/ext4-drop-extent-cache-when-splitting-extent-fails.patch new file mode 100644 index 0000000000..f03070849d --- /dev/null +++ b/queue-5.15/ext4-drop-extent-cache-when-splitting-extent-fails.patch @@ -0,0 +1,63 @@ +From stable+bounces-219623-greg=kroah.com@vger.kernel.org Wed Feb 25 14:51:50 2026 +From: Sasha Levin +Date: Wed, 25 Feb 2026 08:46:56 -0500 +Subject: ext4: drop extent cache when splitting extent fails +To: stable@vger.kernel.org +Cc: Zhang Yi , Baokun Li , stable@kernel.org, Ojaswin Mujoo , Theodore Ts'o , Sasha Levin +Message-ID: <20260225134656.309822-1-sashal@kernel.org> + +From: Zhang Yi + +[ Upstream commit 79b592e8f1b435796cbc2722190368e3e8ffd7a1 ] + +When the split extent fails, we might leave some extents still being +processed and return an error directly, which will result in stale +extent entries remaining in the extent status tree. So drop all of the +remaining potentially stale extents if the splitting fails. + +Signed-off-by: Zhang Yi +Reviewed-by: Baokun Li +Cc: stable@kernel.org +Reviewed-by: Ojaswin Mujoo +Message-ID: <20251129103247.686136-8-yi.zhang@huaweicloud.com> +Signed-off-by: Theodore Ts'o +[ bring error handling pattern closer to upstream ] +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + fs/ext4/extents.c | 10 ++++++++-- + 1 file changed, 8 insertions(+), 2 deletions(-) + +--- a/fs/ext4/extents.c ++++ b/fs/ext4/extents.c +@@ -3236,7 +3236,9 @@ static int ext4_split_extent_at(handle_t + ext4_ext_mark_unwritten(ex2); + + err = ext4_ext_insert_extent(handle, inode, ppath, &newex, flags); +- if (err != -ENOSPC && err != -EDQUOT && err != -ENOMEM) ++ if (err && err != -ENOSPC && err != -EDQUOT && err != -ENOMEM) ++ goto out_err; ++ if (!err) + goto out; + + /* +@@ -3252,7 +3254,8 @@ static int ext4_split_extent_at(handle_t + if (IS_ERR(path)) { + EXT4_ERROR_INODE(inode, "Failed split extent on %u, err %ld", + split, PTR_ERR(path)); +- return PTR_ERR(path); ++ err = PTR_ERR(path); ++ goto out_err; + } + depth = ext_depth(inode); + ex = path[depth].p_ext; +@@ -3308,6 +3311,9 @@ fix_extent_len: + */ + ext4_ext_dirty(handle, inode, path + path->p_depth); + return err; ++out_err: ++ /* Remove all remaining potentially stale extents. */ ++ ext4_es_remove_extent(inode, ee_block, ee_len); + out: + ext4_ext_show_leaf(inode, *ppath); + return err; diff --git a/queue-5.15/ext4-fix-dirtyclusters-double-decrement-on-fs-shutdown.patch b/queue-5.15/ext4-fix-dirtyclusters-double-decrement-on-fs-shutdown.patch new file mode 100644 index 0000000000..154b1d3b9d --- /dev/null +++ b/queue-5.15/ext4-fix-dirtyclusters-double-decrement-on-fs-shutdown.patch @@ -0,0 +1,109 @@ +From stable+bounces-219643-greg=kroah.com@vger.kernel.org Wed Feb 25 15:57:47 2026 +From: Sasha Levin +Date: Wed, 25 Feb 2026 09:52:32 -0500 +Subject: ext4: fix dirtyclusters double decrement on fs shutdown +To: stable@vger.kernel.org +Cc: Brian Foster , Baokun Li , Theodore Ts'o , stable@kernel.org, Sasha Levin +Message-ID: <20260225145232.546260-1-sashal@kernel.org> + +From: Brian Foster + +[ Upstream commit 94a8cea54cd935c54fa2fba70354757c0fc245e3 ] + +fstests test generic/388 occasionally reproduces a warning in +ext4_put_super() associated with the dirty clusters count: + + WARNING: CPU: 7 PID: 76064 at fs/ext4/super.c:1324 ext4_put_super+0x48c/0x590 [ext4] + +Tracing the failure shows that the warning fires due to an +s_dirtyclusters_counter value of -1. IOW, this appears to be a +spurious decrement as opposed to some sort of leak. Further tracing +of the dirty cluster count deltas and an LLM scan of the resulting +output identified the cause as a double decrement in the error path +between ext4_mb_mark_diskspace_used() and the caller +ext4_mb_new_blocks(). + +First, note that generic/388 is a shutdown vs. fsstress test and so +produces a random set of operations and shutdown injections. In the +problematic case, the shutdown triggers an error return from the +ext4_handle_dirty_metadata() call(s) made from +ext4_mb_mark_context(). The changed value is non-zero at this point, +so ext4_mb_mark_diskspace_used() does not exit after the error +bubbles up from ext4_mb_mark_context(). Instead, the former +decrements both cluster counters and returns the error up to +ext4_mb_new_blocks(). The latter falls into the !ar->len out path +which decrements the dirty clusters counter a second time, creating +the inconsistency. + +To avoid this problem and simplify ownership of the cluster +reservation in this codepath, lift the counter reduction to a single +place in the caller. This makes it more clear that +ext4_mb_new_blocks() is responsible for acquiring cluster +reservation (via ext4_claim_free_clusters()) in the !delalloc case +as well as releasing it, regardless of whether it ends up consumed +or returned due to failure. + +Fixes: 0087d9fb3f29 ("ext4: Fix s_dirty_blocks_counter if block allocation failed with nodelalloc") +Signed-off-by: Brian Foster +Reviewed-by: Baokun Li +Link: https://patch.msgid.link/20260113171905.118284-1-bfoster@redhat.com +Signed-off-by: Theodore Ts'o +Cc: stable@kernel.org +[ Drop mballoc-test changes ] +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + fs/ext4/mballoc.c | 21 +++++---------------- + 1 file changed, 5 insertions(+), 16 deletions(-) + +--- a/fs/ext4/mballoc.c ++++ b/fs/ext4/mballoc.c +@@ -3835,8 +3835,7 @@ void ext4_exit_mballoc(void) + * Returns 0 if success or error code + */ + static noinline_for_stack int +-ext4_mb_mark_diskspace_used(struct ext4_allocation_context *ac, +- handle_t *handle, unsigned int reserv_clstrs) ++ext4_mb_mark_diskspace_used(struct ext4_allocation_context *ac, handle_t *handle) + { + struct buffer_head *bitmap_bh = NULL; + struct ext4_group_desc *gdp; +@@ -3924,13 +3923,6 @@ ext4_mb_mark_diskspace_used(struct ext4_ + + ext4_unlock_group(sb, ac->ac_b_ex.fe_group); + percpu_counter_sub(&sbi->s_freeclusters_counter, ac->ac_b_ex.fe_len); +- /* +- * Now reduce the dirty block count also. Should not go negative +- */ +- if (!(ac->ac_flags & EXT4_MB_DELALLOC_RESERVED)) +- /* release all the reserved blocks if non delalloc */ +- percpu_counter_sub(&sbi->s_dirtyclusters_counter, +- reserv_clstrs); + + if (sbi->s_log_groups_per_flex) { + ext4_group_t flex_group = ext4_flex_group(sbi, +@@ -5802,7 +5794,7 @@ repeat: + ext4_mb_pa_free(ac); + } + if (likely(ac->ac_status == AC_STATUS_FOUND)) { +- *errp = ext4_mb_mark_diskspace_used(ac, handle, reserv_clstrs); ++ *errp = ext4_mb_mark_diskspace_used(ac, handle); + if (*errp) { + ext4_discard_allocated_blocks(ac); + goto errout; +@@ -5834,12 +5826,9 @@ out: + kmem_cache_free(ext4_ac_cachep, ac); + if (inquota && ar->len < inquota) + dquot_free_block(ar->inode, EXT4_C2B(sbi, inquota - ar->len)); +- if (!ar->len) { +- if ((ar->flags & EXT4_MB_DELALLOC_RESERVED) == 0) +- /* release all the reserved blocks if non delalloc */ +- percpu_counter_sub(&sbi->s_dirtyclusters_counter, +- reserv_clstrs); +- } ++ /* release any reserved blocks */ ++ if (reserv_clstrs) ++ percpu_counter_sub(&sbi->s_dirtyclusters_counter, reserv_clstrs); + + trace_ext4_allocate_blocks(ar, (unsigned long long)block); + diff --git a/queue-5.15/ext4-fix-e4b-bitmap-inconsistency-reports.patch b/queue-5.15/ext4-fix-e4b-bitmap-inconsistency-reports.patch new file mode 100644 index 0000000000..22ec735a05 --- /dev/null +++ b/queue-5.15/ext4-fix-e4b-bitmap-inconsistency-reports.patch @@ -0,0 +1,127 @@ +From stable+bounces-219635-greg=kroah.com@vger.kernel.org Wed Feb 25 15:38:14 2026 +From: Sasha Levin +Date: Wed, 25 Feb 2026 09:33:49 -0500 +Subject: ext4: fix e4b bitmap inconsistency reports +To: stable@vger.kernel.org +Cc: Yongjian Sun , Zhang Yi , Baokun Li , Jan Kara , Theodore Ts'o , stable@kernel.org, Sasha Levin +Message-ID: <20260225143349.471932-1-sashal@kernel.org> + +From: Yongjian Sun + +[ Upstream commit bdc56a9c46b2a99c12313122b9352b619a2e719e ] + +A bitmap inconsistency issue was observed during stress tests under +mixed huge-page workloads. Ext4 reported multiple e4b bitmap check +failures like: + +ext4_mb_complex_scan_group:2508: group 350, 8179 free clusters as +per group info. But got 8192 blocks + +Analysis and experimentation confirmed that the issue is caused by a +race condition between page migration and bitmap modification. Although +this timing window is extremely narrow, it is still hit in practice: + +folio_lock ext4_mb_load_buddy +__migrate_folio + check ref count + folio_mc_copy __filemap_get_folio + folio_try_get(folio) + ...... + mb_mark_used + ext4_mb_unload_buddy + __folio_migrate_mapping + folio_ref_freeze +folio_unlock + +The root cause of this issue is that the fast path of load_buddy only +increments the folio's reference count, which is insufficient to prevent +concurrent folio migration. We observed that the folio migration process +acquires the folio lock. Therefore, we can determine whether to take the +fast path in load_buddy by checking the lock status. If the folio is +locked, we opt for the slow path (which acquires the lock) to close this +concurrency window. + +Additionally, this change addresses the following issues: + +When the DOUBLE_CHECK macro is enabled to inspect bitmap-related +issues, the following error may be triggered: + +corruption in group 324 at byte 784(6272): f in copy != ff on +disk/prealloc + +Analysis reveals that this is a false positive. There is a specific race +window where the bitmap and the group descriptor become momentarily +inconsistent, leading to this error report: + +ext4_mb_load_buddy ext4_mb_load_buddy + __filemap_get_folio(create|lock) + folio_lock + ext4_mb_init_cache + folio_mark_uptodate + __filemap_get_folio(no lock) + ...... + mb_mark_used + mb_mark_used_double + mb_cmp_bitmaps + mb_set_bits(e4b->bd_bitmap) + folio_unlock + +The original logic assumed that since mb_cmp_bitmaps is called when the +bitmap is newly loaded from disk, the folio lock would be sufficient to +prevent concurrent access. However, this overlooks a specific race +condition: if another process attempts to load buddy and finds the folio +is already in an uptodate state, it will immediately begin using it without +holding folio lock. + +Signed-off-by: Yongjian Sun +Reviewed-by: Zhang Yi +Reviewed-by: Baokun Li +Reviewed-by: Jan Kara +Link: https://patch.msgid.link/20260106090820.836242-1-sunyongjian@huaweicloud.com +Signed-off-by: Theodore Ts'o +Cc: stable@kernel.org +[ folio -> page ] +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + fs/ext4/mballoc.c | 21 +++++++++++---------- + 1 file changed, 11 insertions(+), 10 deletions(-) + +--- a/fs/ext4/mballoc.c ++++ b/fs/ext4/mballoc.c +@@ -1568,16 +1568,17 @@ ext4_mb_load_buddy_gfp(struct super_bloc + /* we could use find_or_create_page(), but it locks page + * what we'd like to avoid in fast path ... */ + page = find_get_page_flags(inode->i_mapping, pnum, FGP_ACCESSED); +- if (page == NULL || !PageUptodate(page)) { ++ if (page == NULL || !PageUptodate(page) || PageLocked(page)) { ++ /* ++ * PageLocked is employed to detect ongoing page ++ * migrations, since concurrent migrations can lead to ++ * bitmap inconsistency. And if we are not uptodate that ++ * implies somebody just created the page but is yet to ++ * initialize it. We can drop the page reference and ++ * try to get the page with lock in both cases to avoid ++ * concurrency. ++ */ + if (page) +- /* +- * drop the page reference and try +- * to get the page with lock. If we +- * are not uptodate that implies +- * somebody just created the page but +- * is yet to initialize the same. So +- * wait for it to initialize. +- */ + put_page(page); + page = find_or_create_page(inode->i_mapping, pnum, gfp); + if (page) { +@@ -1612,7 +1613,7 @@ ext4_mb_load_buddy_gfp(struct super_bloc + poff = block % blocks_per_page; + + page = find_get_page_flags(inode->i_mapping, pnum, FGP_ACCESSED); +- if (page == NULL || !PageUptodate(page)) { ++ if (page == NULL || !PageUptodate(page) || PageLocked(page)) { + if (page) + put_page(page); + page = find_or_create_page(inode->i_mapping, pnum, gfp); diff --git a/queue-5.15/ksmbd-call-ksmbd_vfs_kern_path_end_removing-on-some-error-paths.patch b/queue-5.15/ksmbd-call-ksmbd_vfs_kern_path_end_removing-on-some-error-paths.patch new file mode 100644 index 0000000000..caee19c868 --- /dev/null +++ b/queue-5.15/ksmbd-call-ksmbd_vfs_kern_path_end_removing-on-some-error-paths.patch @@ -0,0 +1,68 @@ +From stable+bounces-219136-greg=kroah.com@vger.kernel.org Wed Feb 25 03:35:14 2026 +From: Sasha Levin +Date: Tue, 24 Feb 2026 21:35:05 -0500 +Subject: ksmbd: call ksmbd_vfs_kern_path_end_removing() on some error paths +To: stable@vger.kernel.org +Cc: Fedor Pchelkin , Namjae Jeon , Steve French , Sasha Levin +Message-ID: <20260225023506.3815115-1-sashal@kernel.org> + +From: Fedor Pchelkin + +[ Upstream commit a09dc10d1353f0e92c21eae2a79af1c2b1ddcde8 ] + +There are two places where ksmbd_vfs_kern_path_end_removing() needs to be +called in order to balance what the corresponding successful call to +ksmbd_vfs_kern_path_start_removing() has done, i.e. drop inode locks and +put the taken references. Otherwise there might be potential deadlocks +and unbalanced locks which are caught like: + +BUG: workqueue leaked lock or atomic: kworker/5:21/0x00000000/7596 + last function: handle_ksmbd_work +2 locks held by kworker/5:21/7596: + #0: ffff8881051ae448 (sb_writers#3){.+.+}-{0:0}, at: ksmbd_vfs_kern_path_locked+0x142/0x660 + #1: ffff888130e966c0 (&type->i_mutex_dir_key#3/1){+.+.}-{4:4}, at: ksmbd_vfs_kern_path_locked+0x17d/0x660 +CPU: 5 PID: 7596 Comm: kworker/5:21 Not tainted 6.1.162-00456-gc29b353f383b #138 +Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.17.0-debian-1.17.0-1 04/01/2014 +Workqueue: ksmbd-io handle_ksmbd_work +Call Trace: + + dump_stack_lvl+0x44/0x5b + process_one_work.cold+0x57/0x5c + worker_thread+0x82/0x600 + kthread+0x153/0x190 + ret_from_fork+0x22/0x30 + + +Found by Linux Verification Center (linuxtesting.org). + +Fixes: d5fc1400a34b ("smb/server: avoid deadlock when linking with ReplaceIfExists") +Cc: stable@vger.kernel.org +Signed-off-by: Fedor Pchelkin +Acked-by: Namjae Jeon +Signed-off-by: Steve French +[ ksmbd_vfs_kern_path_end_removing() call -> ksmbd_vfs_kern_path_unlock() ] +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + fs/ksmbd/smb2pdu.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/fs/ksmbd/smb2pdu.c ++++ b/fs/ksmbd/smb2pdu.c +@@ -5652,14 +5652,14 @@ static int smb2_create_link(struct ksmbd + rc = -EINVAL; + ksmbd_debug(SMB, "cannot delete %s\n", + link_name); +- goto out; + } + } else { + rc = -EEXIST; + ksmbd_debug(SMB, "link already exists\n"); +- goto out; + } + ksmbd_vfs_kern_path_unlock(&parent_path, &path); ++ if (rc) ++ goto out; + } + rc = ksmbd_vfs_link(work, target_name, link_name); + if (rc) diff --git a/queue-5.15/ksmbd-fix-null-pointer-dereference-error-in-generate_encryptionkey.patch b/queue-5.15/ksmbd-fix-null-pointer-dereference-error-in-generate_encryptionkey.patch new file mode 100644 index 0000000000..1d320fe15e --- /dev/null +++ b/queue-5.15/ksmbd-fix-null-pointer-dereference-error-in-generate_encryptionkey.patch @@ -0,0 +1,64 @@ +From alvalan9@foxmail.com Wed Feb 25 11:34:13 2026 +From: Alva Lan +Date: Wed, 25 Feb 2026 18:33:45 +0800 +Subject: ksmbd: fix null pointer dereference error in generate_encryptionkey +To: stable@vger.kernel.org, gregkh@linuxfoundation.org +Cc: Namjae Jeon , zdi-disclosures@trendmicro.com, Steve French , Alva Lan +Message-ID: + +From: Namjae Jeon + +[ Upstream commit 9b493ab6f35178afd8d619800df9071992f715de ] + +If client send two session setups with krb5 authenticate to ksmbd, +null pointer dereference error in generate_encryptionkey could happen. +sess->Preauth_HashValue is set to NULL if session is valid. +So this patch skip generate encryption key if session is valid. + +Cc: stable@vger.kernel.org +Reported-by: zdi-disclosures@trendmicro.com # ZDI-CAN-27654 +Signed-off-by: Namjae Jeon +Signed-off-by: Steve French +Signed-off-by: Alva Lan +Signed-off-by: Greg Kroah-Hartman +--- + fs/ksmbd/smb2pdu.c | 18 ++++++++++++++++-- + 1 file changed, 16 insertions(+), 2 deletions(-) + +--- a/fs/ksmbd/smb2pdu.c ++++ b/fs/ksmbd/smb2pdu.c +@@ -1628,11 +1628,24 @@ static int krb5_authenticate(struct ksmb + } + rsp->SecurityBufferLength = cpu_to_le16(out_len); + +- if ((conn->sign || server_conf.enforced_signing) || ++ /* ++ * If session state is SMB2_SESSION_VALID, We can assume ++ * that it is reauthentication. And the user/password ++ * has been verified, so return it here. ++ */ ++ if (sess->state == SMB2_SESSION_VALID) { ++ if (conn->binding) ++ goto binding_session; ++ return 0; ++ } ++ ++ if ((rsp->SessionFlags != SMB2_SESSION_FLAG_IS_GUEST_LE && ++ (conn->sign || server_conf.enforced_signing)) || + (req->SecurityMode & SMB2_NEGOTIATE_SIGNING_REQUIRED)) + sess->sign = true; + +- if (smb3_encryption_negotiated(conn)) { ++ if (smb3_encryption_negotiated(conn) && ++ !(req->Flags & SMB2_SESSION_REQ_FLAG_BINDING)) { + retval = conn->ops->generate_encryptionkey(conn, sess); + if (retval) { + ksmbd_debug(SMB, +@@ -1645,6 +1658,7 @@ static int krb5_authenticate(struct ksmb + sess->sign = false; + } + ++binding_session: + if (conn->dialect >= SMB30_PROT_ID) { + chann = lookup_chann_list(sess, conn); + if (!chann) { diff --git a/queue-5.15/mptcp-pm-avoid-sending-rm_addr-over-same-subflow.patch b/queue-5.15/mptcp-pm-avoid-sending-rm_addr-over-same-subflow.patch new file mode 100644 index 0000000000..7062345326 --- /dev/null +++ b/queue-5.15/mptcp-pm-avoid-sending-rm_addr-over-same-subflow.patch @@ -0,0 +1,143 @@ +From stable+bounces-223697-greg=kroah.com@vger.kernel.org Mon Mar 9 17:21:31 2026 +From: Sasha Levin +Date: Mon, 9 Mar 2026 12:06:22 -0400 +Subject: mptcp: pm: avoid sending RM_ADDR over same subflow +To: stable@vger.kernel.org +Cc: "Matthieu Baerts (NGI0)" , Frank Lorenz , Mat Martineau , Jakub Kicinski , Sasha Levin +Message-ID: <20260309160622.1298481-1-sashal@kernel.org> + +From: "Matthieu Baerts (NGI0)" + +[ Upstream commit fb8d0bccb221080630efcd9660c9f9349e53cc9e ] + +RM_ADDR are sent over an active subflow, the first one in the subflows +list. There is then a high chance the initial subflow is picked. With +the in-kernel PM, when an endpoint is removed, a RM_ADDR is sent, then +linked subflows are closed. This is done for each active MPTCP +connection. + +MPTCP endpoints are likely removed because the attached network is no +longer available or usable. In this case, it is better to avoid sending +this RM_ADDR over the subflow that is going to be removed, but prefer +sending it over another active and non stale subflow, if any. + +This modification avoids situations where the other end is not notified +when a subflow is no longer usable: typically when the endpoint linked +to the initial subflow is removed, especially on the server side. + +Fixes: 8dd5efb1f91b ("mptcp: send ack for rm_addr") +Cc: stable@vger.kernel.org +Reported-by: Frank Lorenz +Closes: https://github.com/multipath-tcp/mptcp_net-next/issues/612 +Reviewed-by: Mat Martineau +Signed-off-by: Matthieu Baerts (NGI0) +Link: https://patch.msgid.link/20260303-net-mptcp-misc-fixes-7-0-rc2-v1-2-4b5462b6f016@kernel.org +Signed-off-by: Jakub Kicinski +[ pm.c => pm_netlink.c + replaced subflow_get_local_id() with subflow->local_id ] +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + net/mptcp/pm.c | 2 - + net/mptcp/pm_netlink.c | 57 +++++++++++++++++++++++++++++++++++++++---------- + net/mptcp/protocol.h | 2 + + 3 files changed, 49 insertions(+), 12 deletions(-) + +--- a/net/mptcp/pm.c ++++ b/net/mptcp/pm.c +@@ -55,7 +55,7 @@ int mptcp_pm_remove_addr(struct mptcp_so + msk->pm.rm_list_tx = *rm_list; + rm_addr |= BIT(MPTCP_RM_ADDR_SIGNAL); + WRITE_ONCE(msk->pm.addr_signal, rm_addr); +- mptcp_pm_nl_addr_send_ack(msk); ++ mptcp_pm_nl_addr_send_ack_avoid_list(msk, rm_list); + return 0; + } + +--- a/net/mptcp/pm_netlink.c ++++ b/net/mptcp/pm_netlink.c +@@ -753,9 +753,23 @@ bool mptcp_pm_nl_is_init_remote_addr(str + return addresses_equal(&mpc_remote, remote, remote->port); + } + +-void mptcp_pm_nl_addr_send_ack(struct mptcp_sock *msk) ++static bool subflow_in_rm_list(const struct mptcp_subflow_context *subflow, ++ const struct mptcp_rm_list *rm_list) ++{ ++ u8 i, id = subflow->local_id; ++ ++ for (i = 0; i < rm_list->nr; i++) { ++ if (rm_list->ids[i] == id) ++ return true; ++ } ++ ++ return false; ++} ++ ++void mptcp_pm_nl_addr_send_ack_avoid_list(struct mptcp_sock *msk, ++ const struct mptcp_rm_list *rm_list) + { +- struct mptcp_subflow_context *subflow; ++ struct mptcp_subflow_context *subflow, *same_id = NULL; + + msk_owned_by_me(msk); + lockdep_assert_held(&msk->pm.lock); +@@ -766,18 +780,39 @@ void mptcp_pm_nl_addr_send_ack(struct mp + + __mptcp_flush_join_list(msk); + mptcp_for_each_subflow(msk, subflow) { +- if (__mptcp_subflow_active(subflow)) { +- struct sock *ssk = mptcp_subflow_tcp_sock(subflow); ++ if (!__mptcp_subflow_active(subflow)) ++ continue; + +- spin_unlock_bh(&msk->pm.lock); +- pr_debug("send ack for %s\n", +- mptcp_pm_should_add_signal(msk) ? "add_addr" : "rm_addr"); +- +- mptcp_subflow_send_ack(ssk); +- spin_lock_bh(&msk->pm.lock); +- break; ++ if (unlikely(rm_list && ++ subflow_in_rm_list(subflow, rm_list))) { ++ if (!same_id) ++ same_id = subflow; ++ } else { ++ goto send_ack; + } + } ++ ++ if (same_id) ++ subflow = same_id; ++ else ++ return; ++ ++send_ack: ++ { ++ struct sock *ssk = mptcp_subflow_tcp_sock(subflow); ++ ++ spin_unlock_bh(&msk->pm.lock); ++ pr_debug("send ack for %s\n", ++ mptcp_pm_should_add_signal(msk) ? "add_addr" : "rm_addr"); ++ ++ mptcp_subflow_send_ack(ssk); ++ spin_lock_bh(&msk->pm.lock); ++ } ++} ++ ++void mptcp_pm_nl_addr_send_ack(struct mptcp_sock *msk) ++{ ++ mptcp_pm_nl_addr_send_ack_avoid_list(msk, NULL); + } + + int mptcp_pm_nl_mp_prio_send_ack(struct mptcp_sock *msk, +--- a/net/mptcp/protocol.h ++++ b/net/mptcp/protocol.h +@@ -753,6 +753,8 @@ void mptcp_pm_add_addr_send_ack(struct m + bool mptcp_pm_nl_is_init_remote_addr(struct mptcp_sock *msk, + const struct mptcp_addr_info *remote); + void mptcp_pm_nl_addr_send_ack(struct mptcp_sock *msk); ++void mptcp_pm_nl_addr_send_ack_avoid_list(struct mptcp_sock *msk, ++ const struct mptcp_rm_list *rm_list); + void mptcp_pm_rm_addr_received(struct mptcp_sock *msk, + const struct mptcp_rm_list *rm_list); + void mptcp_pm_mp_prio_received(struct sock *sk, u8 bkup); diff --git a/queue-5.15/net-phy-register-phy-led_triggers-during-probe-to-avoid-ab-ba-deadlock.patch b/queue-5.15/net-phy-register-phy-led_triggers-during-probe-to-avoid-ab-ba-deadlock.patch new file mode 100644 index 0000000000..f2a97f6c20 --- /dev/null +++ b/queue-5.15/net-phy-register-phy-led_triggers-during-probe-to-avoid-ab-ba-deadlock.patch @@ -0,0 +1,111 @@ +From stable+bounces-223661-greg=kroah.com@vger.kernel.org Mon Mar 9 15:02:23 2026 +From: Sasha Levin +Date: Mon, 9 Mar 2026 09:59:58 -0400 +Subject: net: phy: register phy led_triggers during probe to avoid AB-BA deadlock +To: stable@vger.kernel.org +Cc: Andrew Lunn , Shiji Yang , Paolo Abeni , Sasha Levin +Message-ID: <20260309135959.1064428-1-sashal@kernel.org> + +From: Andrew Lunn + +[ Upstream commit c8dbdc6e380e7e96a51706db3e4b7870d8a9402d ] + +There is an AB-BA deadlock when both LEDS_TRIGGER_NETDEV and +LED_TRIGGER_PHY are enabled: + +[ 1362.049207] [<8054e4b8>] led_trigger_register+0x5c/0x1fc <-- Trying to get lock "triggers_list_lock" via down_write(&triggers_list_lock); +[ 1362.054536] [<80662830>] phy_led_triggers_register+0xd0/0x234 +[ 1362.060329] [<8065e200>] phy_attach_direct+0x33c/0x40c +[ 1362.065489] [<80651fc4>] phylink_fwnode_phy_connect+0x15c/0x23c +[ 1362.071480] [<8066ee18>] mtk_open+0x7c/0xba0 +[ 1362.075849] [<806d714c>] __dev_open+0x280/0x2b0 +[ 1362.080384] [<806d7668>] __dev_change_flags+0x244/0x24c +[ 1362.085598] [<806d7698>] dev_change_flags+0x28/0x78 +[ 1362.090528] [<807150e4>] dev_ioctl+0x4c0/0x654 <-- Hold lock "rtnl_mutex" by calling rtnl_lock(); +[ 1362.094985] [<80694360>] sock_ioctl+0x2f4/0x4e0 +[ 1362.099567] [<802e9c4c>] sys_ioctl+0x32c/0xd8c +[ 1362.104022] [<80014504>] syscall_common+0x34/0x58 + +Here LED_TRIGGER_PHY is registering LED triggers during phy_attach +while holding RTNL and then taking triggers_list_lock. + +[ 1362.191101] [<806c2640>] register_netdevice_notifier+0x60/0x168 <-- Trying to get lock "rtnl_mutex" via rtnl_lock(); +[ 1362.197073] [<805504ac>] netdev_trig_activate+0x194/0x1e4 +[ 1362.202490] [<8054e28c>] led_trigger_set+0x1d4/0x360 <-- Hold lock "triggers_list_lock" by down_read(&triggers_list_lock); +[ 1362.207511] [<8054eb38>] led_trigger_write+0xd8/0x14c +[ 1362.212566] [<80381d98>] sysfs_kf_bin_write+0x80/0xbc +[ 1362.217688] [<8037fcd8>] kernfs_fop_write_iter+0x17c/0x28c +[ 1362.223174] [<802cbd70>] vfs_write+0x21c/0x3c4 +[ 1362.227712] [<802cc0c4>] ksys_write+0x78/0x12c +[ 1362.232164] [<80014504>] syscall_common+0x34/0x58 + +Here LEDS_TRIGGER_NETDEV is being enabled on an LED. It first takes +triggers_list_lock and then RTNL. A classical AB-BA deadlock. + +phy_led_triggers_registers() does not require the RTNL, it does not +make any calls into the network stack which require protection. There +is also no requirement the PHY has been attached to a MAC, the +triggers only make use of phydev state. This allows the call to +phy_led_triggers_registers() to be placed elsewhere. PHY probe() and +release() don't hold RTNL, so solving the AB-BA deadlock. + +Reported-by: Shiji Yang +Closes: https://lore.kernel.org/all/OS7PR01MB13602B128BA1AD3FA38B6D1FFBC69A@OS7PR01MB13602.jpnprd01.prod.outlook.com/ +Fixes: 06f502f57d0d ("leds: trigger: Introduce a NETDEV trigger") +Cc: stable@vger.kernel.org +Signed-off-by: Andrew Lunn +Tested-by: Shiji Yang +Link: https://patch.msgid.link/20260222152601.1978655-1-andrew@lunn.ch +Signed-off-by: Paolo Abeni +[ dropped `is_on_sfp_module` guards and `CONFIG_PHYLIB_LEDS`/`of_phy_leds` logic ] +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/phy/phy_device.c | 13 ++++++++----- + 1 file changed, 8 insertions(+), 5 deletions(-) + +--- a/drivers/net/phy/phy_device.c ++++ b/drivers/net/phy/phy_device.c +@@ -1508,7 +1508,6 @@ int phy_attach_direct(struct net_device + return err; + + phy_resume(phydev); +- phy_led_triggers_register(phydev); + + return err; + +@@ -1765,8 +1764,6 @@ void phy_detach(struct phy_device *phyde + } + phydev->phylink = NULL; + +- phy_led_triggers_unregister(phydev); +- + if (phydev->mdio.dev.driver) + module_put(phydev->mdio.dev.driver->owner); + +@@ -3120,10 +3117,14 @@ static int phy_probe(struct device *dev) + /* Set the state to READY by default */ + phydev->state = PHY_READY; + ++ /* Register the PHY LED triggers */ ++ phy_led_triggers_register(phydev); ++ ++ return 0; ++ + out: + /* Re-assert the reset signal on error */ +- if (err) +- phy_device_reset(phydev, 1); ++ phy_device_reset(phydev, 1); + + return err; + } +@@ -3134,6 +3135,8 @@ static int phy_remove(struct device *dev + + cancel_delayed_work_sync(&phydev->state_queue); + ++ phy_led_triggers_unregister(phydev); ++ + phydev->state = PHY_DOWN; + + sfp_bus_del_upstream(phydev->sfp_bus); diff --git a/queue-5.15/pmdomain-bcm-bcm2835-power-increase-asb-control-timeout.patch b/queue-5.15/pmdomain-bcm-bcm2835-power-increase-asb-control-timeout.patch new file mode 100644 index 0000000000..f3ff92b758 --- /dev/null +++ b/queue-5.15/pmdomain-bcm-bcm2835-power-increase-asb-control-timeout.patch @@ -0,0 +1,97 @@ +From stable+bounces-227765-greg=kroah.com@vger.kernel.org Sat Mar 21 13:41:32 2026 +From: Sasha Levin +Date: Sat, 21 Mar 2026 08:41:08 -0400 +Subject: pmdomain: bcm: bcm2835-power: Increase ASB control timeout +To: stable@vger.kernel.org +Cc: "Maíra Canal" , "Stefan Wahren" , "Ulf Hansson" , "Sasha Levin" +Message-ID: <20260321124108.268680-1-sashal@kernel.org> + +From: Maíra Canal + +[ Upstream commit b826d2c0b0ecb844c84431ba6b502e744f5d919a ] + +The bcm2835_asb_control() function uses a tight polling loop to wait +for the ASB bridge to acknowledge a request. During intensive workloads, +this handshake intermittently fails for V3D's master ASB on BCM2711, +resulting in "Failed to disable ASB master for v3d" errors during +runtime PM suspend. As a consequence, the failed power-off leaves V3D in +a broken state, leading to bus faults or system hangs on later accesses. + +As the timeout is insufficient in some scenarios, increase the polling +timeout from 1us to 5us, which is still negligible in the context of a +power domain transition. Also, replace the open-coded ktime_get_ns()/ +cpu_relax() polling loop with readl_poll_timeout_atomic(). + +Cc: stable@vger.kernel.org +Fixes: 670c672608a1 ("soc: bcm: bcm2835-pm: Add support for power domains under a new binding.") +Signed-off-by: Maíra Canal +Reviewed-by: Stefan Wahren +Signed-off-by: Ulf Hansson +[ adapted unified bcm2835_asb_control() function changes to separate bcm2835_asb_enable() and bcm2835_asb_disable() functions ] +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/soc/bcm/bcm2835-power.c | 27 +++++++++++---------------- + 1 file changed, 11 insertions(+), 16 deletions(-) + +--- a/drivers/soc/bcm/bcm2835-power.c ++++ b/drivers/soc/bcm/bcm2835-power.c +@@ -9,6 +9,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -150,40 +151,34 @@ struct bcm2835_power { + + static int bcm2835_asb_enable(struct bcm2835_power *power, u32 reg) + { +- u64 start; ++ u32 val; + + if (!reg) + return 0; + +- start = ktime_get_ns(); +- + /* Enable the module's async AXI bridges. */ + ASB_WRITE(reg, ASB_READ(reg) & ~ASB_REQ_STOP); +- while (ASB_READ(reg) & ASB_ACK) { +- cpu_relax(); +- if (ktime_get_ns() - start >= 1000) +- return -ETIMEDOUT; +- } ++ ++ if (readl_poll_timeout_atomic(power->asb + reg, val, ++ !(val & ASB_ACK), 0, 5)) ++ return -ETIMEDOUT; + + return 0; + } + + static int bcm2835_asb_disable(struct bcm2835_power *power, u32 reg) + { +- u64 start; ++ u32 val; + + if (!reg) + return 0; + +- start = ktime_get_ns(); +- + /* Enable the module's async AXI bridges. */ + ASB_WRITE(reg, ASB_READ(reg) | ASB_REQ_STOP); +- while (!(ASB_READ(reg) & ASB_ACK)) { +- cpu_relax(); +- if (ktime_get_ns() - start >= 1000) +- return -ETIMEDOUT; +- } ++ ++ if (readl_poll_timeout_atomic(power->asb + reg, val, ++ !!(val & ASB_ACK), 0, 5)) ++ return -ETIMEDOUT; + + return 0; + } diff --git a/queue-5.15/rdma-irdma-fix-kernel-stack-leak-in-irdma_create_user_ah.patch b/queue-5.15/rdma-irdma-fix-kernel-stack-leak-in-irdma_create_user_ah.patch new file mode 100644 index 0000000000..961d50b2c1 --- /dev/null +++ b/queue-5.15/rdma-irdma-fix-kernel-stack-leak-in-irdma_create_user_ah.patch @@ -0,0 +1,44 @@ +From stable+bounces-223648-greg=kroah.com@vger.kernel.org Mon Mar 9 14:29:31 2026 +From: Sasha Levin +Date: Mon, 9 Mar 2026 09:27:39 -0400 +Subject: RDMA/irdma: Fix kernel stack leak in irdma_create_user_ah() +To: stable@vger.kernel.org +Cc: Jason Gunthorpe , Jason Gunthorpe , Leon Romanovsky , Sasha Levin +Message-ID: <20260309132739.944769-1-sashal@kernel.org> + +From: Jason Gunthorpe + +[ Upstream commit 74586c6da9ea222a61c98394f2fc0a604748438c ] + +struct irdma_create_ah_resp { // 8 bytes, no padding + __u32 ah_id; // offset 0 - SET (uresp.ah_id = ah->sc_ah.ah_info.ah_idx) + __u8 rsvd[4]; // offset 4 - NEVER SET <- LEAK +}; + +rsvd[4]: 4 bytes of stack memory leaked unconditionally. Only ah_id is assigned before ib_respond_udata(). + +The reserved members of the structure were not zeroed. + +Cc: stable@vger.kernel.org +Fixes: b48c24c2d710 ("RDMA/irdma: Implement device supported verb APIs") +Signed-off-by: Jason Gunthorpe +Link: https://patch.msgid.link/3-v1-83e918d69e73+a9-rdma_udata_rc_jgg@nvidia.com +Signed-off-by: Leon Romanovsky +[ adapted fix to combined irdma_create_ah() ] +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/infiniband/hw/irdma/verbs.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/infiniband/hw/irdma/verbs.c ++++ b/drivers/infiniband/hw/irdma/verbs.c +@@ -4170,7 +4170,7 @@ static int irdma_create_ah(struct ib_ah + struct irdma_sc_ah *sc_ah; + u32 ah_id = 0; + struct irdma_ah_info *ah_info; +- struct irdma_create_ah_resp uresp; ++ struct irdma_create_ah_resp uresp = {}; + union { + struct sockaddr saddr; + struct sockaddr_in saddr_in; diff --git a/queue-5.15/series b/queue-5.15/series index 397c7444e3..71e32858ec 100644 --- a/queue-5.15/series +++ b/queue-5.15/series @@ -223,3 +223,21 @@ gve-defer-interrupt-enabling-until-napi-registration.patch drm-exynos-vidi-use-priv-vidi_dev-for-ctx-lookup-in-vidi_connection_ioctl.patch drm-exynos-vidi-fix-to-avoid-directly-dereferencing-user-pointer.patch drm-exynos-vidi-use-ctx-lock-to-protect-struct-vidi_context-member-variables-related-to-memory-alloc-free.patch +ksmbd-call-ksmbd_vfs_kern_path_end_removing-on-some-error-paths.patch +ext4-don-t-set-ext4_get_blocks_convert-when-splitting-before-submitting-i-o.patch +ext4-drop-extent-cache-when-splitting-extent-fails.patch +ext4-fix-e4b-bitmap-inconsistency-reports.patch +ext4-fix-dirtyclusters-double-decrement-on-fs-shutdown.patch +ksmbd-fix-null-pointer-dereference-error-in-generate_encryptionkey.patch +ext4-always-allocate-blocks-only-from-groups-inode-can-use.patch +wifi-libertas-fix-use-after-free-in-lbs_free_adapter.patch +wifi-cfg80211-move-scan-done-work-to-wiphy-work.patch +wifi-cfg80211-cancel-rfkill_block-work-in-wiphy_unregister.patch +rdma-irdma-fix-kernel-stack-leak-in-irdma_create_user_ah.patch +smb-client-don-t-log-plaintext-credentials-in-cifs_set_cifscreds.patch +net-phy-register-phy-led_triggers-during-probe-to-avoid-ab-ba-deadlock.patch +drm-amd-display-use-gfp_atomic-in-dc_create_stream_for_sink.patch +mptcp-pm-avoid-sending-rm_addr-over-same-subflow.patch +pmdomain-bcm-bcm2835-power-increase-asb-control-timeout.patch +batman-adv-avoid-ogm-aggregation-when-skb-tailroom-is-insufficient.patch +ata-libata-scsi-drop-dprintk-calls-for-cdb-translation.patch diff --git a/queue-5.15/smb-client-don-t-log-plaintext-credentials-in-cifs_set_cifscreds.patch b/queue-5.15/smb-client-don-t-log-plaintext-credentials-in-cifs_set_cifscreds.patch new file mode 100644 index 0000000000..7b1a537c0f --- /dev/null +++ b/queue-5.15/smb-client-don-t-log-plaintext-credentials-in-cifs_set_cifscreds.patch @@ -0,0 +1,37 @@ +From stable+bounces-223662-greg=kroah.com@vger.kernel.org Mon Mar 9 15:00:27 2026 +From: Sasha Levin +Date: Mon, 9 Mar 2026 10:00:09 -0400 +Subject: smb: client: Don't log plaintext credentials in cifs_set_cifscreds +To: stable@vger.kernel.org +Cc: Thorsten Blum , "Paulo Alcantara (Red Hat)" , Steve French , Sasha Levin +Message-ID: <20260309140009.1065571-1-sashal@kernel.org> + +From: Thorsten Blum + +[ Upstream commit 2f37dc436d4e61ff7ae0b0353cf91b8c10396e4d ] + +When debug logging is enabled, cifs_set_cifscreds() logs the key +payload and exposes the plaintext username and password. Remove the +debug log to avoid exposing credentials. + +Fixes: 8a8798a5ff90 ("cifs: fetch credentials out of keyring for non-krb5 auth multiuser mounts") +Cc: stable@vger.kernel.org +Acked-by: Paulo Alcantara (Red Hat) +Signed-off-by: Thorsten Blum +Signed-off-by: Steve French +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + fs/cifs/connect.c | 1 - + 1 file changed, 1 deletion(-) + +--- a/fs/cifs/connect.c ++++ b/fs/cifs/connect.c +@@ -1874,7 +1874,6 @@ cifs_set_cifscreds(struct smb3_fs_contex + /* find first : in payload */ + payload = upayload->data; + delim = strnchr(payload, upayload->datalen, ':'); +- cifs_dbg(FYI, "payload=%s\n", payload); + if (!delim) { + cifs_dbg(FYI, "Unable to find ':' in payload (datalen=%d)\n", + upayload->datalen); diff --git a/queue-5.15/wifi-cfg80211-cancel-rfkill_block-work-in-wiphy_unregister.patch b/queue-5.15/wifi-cfg80211-cancel-rfkill_block-work-in-wiphy_unregister.patch new file mode 100644 index 0000000000..1160a53a21 --- /dev/null +++ b/queue-5.15/wifi-cfg80211-cancel-rfkill_block-work-in-wiphy_unregister.patch @@ -0,0 +1,61 @@ +From stable+bounces-223620-greg=kroah.com@vger.kernel.org Mon Mar 9 12:44:02 2026 +From: Sasha Levin +Date: Mon, 9 Mar 2026 07:42:24 -0400 +Subject: wifi: cfg80211: cancel rfkill_block work in wiphy_unregister() +To: stable@vger.kernel.org +Cc: Daniil Dulov , Johannes Berg , Sasha Levin +Message-ID: <20260309114224.831897-2-sashal@kernel.org> + +From: Daniil Dulov + +[ Upstream commit 767d23ade706d5fa51c36168e92a9c5533c351a1 ] + +There is a use-after-free error in cfg80211_shutdown_all_interfaces found +by syzkaller: + +BUG: KASAN: use-after-free in cfg80211_shutdown_all_interfaces+0x213/0x220 +Read of size 8 at addr ffff888112a78d98 by task kworker/0:5/5326 +CPU: 0 UID: 0 PID: 5326 Comm: kworker/0:5 Not tainted 6.19.0-rc2 #2 PREEMPT(voluntary) +Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.15.0-1 04/01/2014 +Workqueue: events cfg80211_rfkill_block_work +Call Trace: + + dump_stack_lvl+0x116/0x1f0 + print_report+0xcd/0x630 + kasan_report+0xe0/0x110 + cfg80211_shutdown_all_interfaces+0x213/0x220 + cfg80211_rfkill_block_work+0x1e/0x30 + process_one_work+0x9cf/0x1b70 + worker_thread+0x6c8/0xf10 + kthread+0x3c5/0x780 + ret_from_fork+0x56d/0x700 + ret_from_fork_asm+0x1a/0x30 + + +The problem arises due to the rfkill_block work is not cancelled when wiphy +is being unregistered. In order to fix the issue cancel the corresponding +work in wiphy_unregister(). + +Found by Linux Verification Center (linuxtesting.org) with Syzkaller. + +Fixes: 1f87f7d3a3b4 ("cfg80211: add rfkill support") +Cc: stable@vger.kernel.org +Signed-off-by: Daniil Dulov +Link: https://patch.msgid.link/20260211082024.1967588-1-d.dulov@aladdin.ru +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + net/wireless/core.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/net/wireless/core.c ++++ b/net/wireless/core.c +@@ -1104,6 +1104,7 @@ void wiphy_unregister(struct wiphy *wiph + /* this has nothing to do now but make sure it's gone */ + cancel_work_sync(&rdev->wiphy_work); + ++ cancel_work_sync(&rdev->rfkill_block); + cancel_work_sync(&rdev->conn_work); + flush_work(&rdev->event_work); + cancel_delayed_work_sync(&rdev->dfs_update_channels_wk); diff --git a/queue-5.15/wifi-cfg80211-move-scan-done-work-to-wiphy-work.patch b/queue-5.15/wifi-cfg80211-move-scan-done-work-to-wiphy-work.patch new file mode 100644 index 0000000000..f51e061d3b --- /dev/null +++ b/queue-5.15/wifi-cfg80211-move-scan-done-work-to-wiphy-work.patch @@ -0,0 +1,95 @@ +From stable+bounces-223619-greg=kroah.com@vger.kernel.org Mon Mar 9 12:42:29 2026 +From: Sasha Levin +Date: Mon, 9 Mar 2026 07:42:23 -0400 +Subject: wifi: cfg80211: move scan done work to wiphy work +To: stable@vger.kernel.org +Cc: Johannes Berg , Sasha Levin +Message-ID: <20260309114224.831897-1-sashal@kernel.org> + +From: Johannes Berg + +[ Upstream commit fe0af9fe54d0ff53aa49eef390c8962355b274e2 ] + +Move the scan done work to the new wiphy work to +simplify the code a bit. + +Signed-off-by: Johannes Berg +Stable-dep-of: 767d23ade706 ("wifi: cfg80211: cancel rfkill_block work in wiphy_unregister()") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + net/wireless/core.c | 3 +-- + net/wireless/core.h | 4 ++-- + net/wireless/scan.c | 14 ++++---------- + 3 files changed, 7 insertions(+), 14 deletions(-) + +--- a/net/wireless/core.c ++++ b/net/wireless/core.c +@@ -525,7 +525,7 @@ use_default_name: + spin_lock_init(&rdev->bss_lock); + INIT_LIST_HEAD(&rdev->bss_list); + INIT_LIST_HEAD(&rdev->sched_scan_req_list); +- INIT_WORK(&rdev->scan_done_wk, __cfg80211_scan_done); ++ wiphy_work_init(&rdev->scan_done_wk, __cfg80211_scan_done); + INIT_DELAYED_WORK(&rdev->dfs_update_channels_wk, + cfg80211_dfs_channels_update_work); + #ifdef CONFIG_CFG80211_WEXT +@@ -1104,7 +1104,6 @@ void wiphy_unregister(struct wiphy *wiph + /* this has nothing to do now but make sure it's gone */ + cancel_work_sync(&rdev->wiphy_work); + +- flush_work(&rdev->scan_done_wk); + cancel_work_sync(&rdev->conn_work); + flush_work(&rdev->event_work); + cancel_delayed_work_sync(&rdev->dfs_update_channels_wk); +--- a/net/wireless/core.h ++++ b/net/wireless/core.h +@@ -75,7 +75,7 @@ struct cfg80211_registered_device { + struct sk_buff *scan_msg; + struct list_head sched_scan_req_list; + time64_t suspend_at; +- struct work_struct scan_done_wk; ++ struct wiphy_work scan_done_wk; + + struct genl_info *cur_cmd_info; + +@@ -445,7 +445,7 @@ bool cfg80211_valid_key_idx(struct cfg80 + int cfg80211_validate_key_settings(struct cfg80211_registered_device *rdev, + struct key_params *params, int key_idx, + bool pairwise, const u8 *mac_addr); +-void __cfg80211_scan_done(struct work_struct *wk); ++void __cfg80211_scan_done(struct wiphy *wiphy, struct wiphy_work *wk); + void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev, + bool send_message); + void cfg80211_add_sched_scan_req(struct cfg80211_registered_device *rdev, +--- a/net/wireless/scan.c ++++ b/net/wireless/scan.c +@@ -1079,16 +1079,9 @@ void ___cfg80211_scan_done(struct cfg802 + nl80211_send_scan_msg(rdev, msg); + } + +-void __cfg80211_scan_done(struct work_struct *wk) ++void __cfg80211_scan_done(struct wiphy *wiphy, struct wiphy_work *wk) + { +- struct cfg80211_registered_device *rdev; +- +- rdev = container_of(wk, struct cfg80211_registered_device, +- scan_done_wk); +- +- wiphy_lock(&rdev->wiphy); +- ___cfg80211_scan_done(rdev, true); +- wiphy_unlock(&rdev->wiphy); ++ ___cfg80211_scan_done(wiphy_to_rdev(wiphy), true); + } + + void cfg80211_scan_done(struct cfg80211_scan_request *request, +@@ -1114,7 +1107,8 @@ void cfg80211_scan_done(struct cfg80211_ + } + + request->notified = true; +- queue_work(cfg80211_wq, &wiphy_to_rdev(request->wiphy)->scan_done_wk); ++ wiphy_work_queue(request->wiphy, ++ &wiphy_to_rdev(request->wiphy)->scan_done_wk); + } + EXPORT_SYMBOL(cfg80211_scan_done); + diff --git a/queue-5.15/wifi-libertas-fix-use-after-free-in-lbs_free_adapter.patch b/queue-5.15/wifi-libertas-fix-use-after-free-in-lbs_free_adapter.patch new file mode 100644 index 0000000000..914dfb3433 --- /dev/null +++ b/queue-5.15/wifi-libertas-fix-use-after-free-in-lbs_free_adapter.patch @@ -0,0 +1,59 @@ +From stable+bounces-223611-greg=kroah.com@vger.kernel.org Mon Mar 9 12:26:56 2026 +From: Sasha Levin +Date: Mon, 9 Mar 2026 07:21:38 -0400 +Subject: wifi: libertas: fix use-after-free in lbs_free_adapter() +To: stable@vger.kernel.org +Cc: Daniel Hodges , Johannes Berg , Sasha Levin +Message-ID: <20260309112138.816064-1-sashal@kernel.org> + +From: Daniel Hodges + +[ Upstream commit 03cc8f90d0537fcd4985c3319b4fafbf2e3fb1f0 ] + +The lbs_free_adapter() function uses timer_delete() (non-synchronous) +for both command_timer and tx_lockup_timer before the structure is +freed. This is incorrect because timer_delete() does not wait for +any running timer callback to complete. + +If a timer callback is executing when lbs_free_adapter() is called, +the callback will access freed memory since lbs_cfg_free() frees the +containing structure immediately after lbs_free_adapter() returns. + +Both timer callbacks (lbs_cmd_timeout_handler and lbs_tx_lockup_handler) +access priv->driver_lock, priv->cur_cmd, priv->dev, and other fields, +which would all be use-after-free violations. + +Use timer_delete_sync() instead to ensure any running timer callback +has completed before returning. + +This bug was introduced in commit 8f641d93c38a ("libertas: detect TX +lockups and reset hardware") where del_timer() was used instead of +del_timer_sync() in the cleanup path. The command_timer has had the +same issue since the driver was first written. + +Fixes: 8f641d93c38a ("libertas: detect TX lockups and reset hardware") +Fixes: 954ee164f4f4 ("[PATCH] libertas: reorganize and simplify init sequence") +Cc: stable@vger.kernel.org +Signed-off-by: Daniel Hodges +Link: https://patch.msgid.link/20260206195356.15647-1-git@danielhodges.dev +Signed-off-by: Johannes Berg +[ del_timer() => timer_delete_sync() ] +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/wireless/marvell/libertas/main.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/net/wireless/marvell/libertas/main.c ++++ b/drivers/net/wireless/marvell/libertas/main.c +@@ -882,8 +882,8 @@ static void lbs_free_adapter(struct lbs_ + { + lbs_free_cmd_buffer(priv); + kfifo_free(&priv->event_fifo); +- del_timer(&priv->command_timer); +- del_timer(&priv->tx_lockup_timer); ++ timer_delete_sync(&priv->command_timer); ++ timer_delete_sync(&priv->tx_lockup_timer); + del_timer(&priv->auto_deepsleep_timer); + } +