--- /dev/null
+From stable+bounces-274107-greg=kroah.com@vger.kernel.org Tue Jul 14 05:33:20 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 13 Jul 2026 23:32:56 -0400
+Subject: ALSA: hda/tas2781: Cancel async firmware request at unbind
+To: stable@vger.kernel.org
+Cc: "Cássio Gabriel" <cassiogabrielcontato@gmail.com>, "Takashi Iwai" <tiwai@suse.de>, "Danilo Krummrich" <dakr@kernel.org>, "Sasha Levin" <sashal@kernel.org>
+Message-ID: <20260714033256.2396704-2-sashal@kernel.org>
+
+From: Cássio Gabriel <cassiogabrielcontato@gmail.com>
+
+[ Upstream commit 5367e2ad14f0ae9350a7aaf2e77c87de39a43ae9 ]
+
+TAS2781 HDA I2C and SPI queue RCA firmware loading from component
+bind with request_firmware_nowait(). The firmware loader keeps the
+callback module pinned and holds a device reference, but the callback
+still uses driver-private HDA state.
+
+Component unbind removes controls and DSP state immediately. Later
+device removal tears down the TAS2781 private data, including
+codec_lock. If the async firmware callback runs after unbind has
+started, it can operate on state that is being torn down.
+
+Cancel or synchronize the async firmware request before removing
+controls and DSP state. A queued callback is cancelled, and an
+already-running callback is allowed to finish before unbind continues.
+
+Fixes: 5be27f1e3ec9 ("ALSA: hda/tas2781: Add tas2781 HDA driver")
+Fixes: bb5f86ea50ff ("ALSA: hda/tas2781: Add tas2781 hda SPI driver")
+Cc: stable@vger.kernel.org
+Signed-off-by: Cássio Gabriel <cassiogabrielcontato@gmail.com>
+Reviewed-by: Takashi Iwai <tiwai@suse.de>
+Acked-by: Danilo Krummrich <dakr@kernel.org>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Link: https://patch.msgid.link/20260505-alsa-hda-tas2781-fw-callback-teardown-v4-2-e7c4bf930dc8@gmail.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ sound/hda/codecs/side-codecs/tas2781_hda_i2c.c | 3 +++
+ sound/hda/codecs/side-codecs/tas2781_hda_spi.c | 3 +++
+ 2 files changed, 6 insertions(+)
+
+--- a/sound/hda/codecs/side-codecs/tas2781_hda_i2c.c
++++ b/sound/hda/codecs/side-codecs/tas2781_hda_i2c.c
+@@ -588,6 +588,9 @@ static void tas2781_hda_unbind(struct de
+ comp->playback_hook = NULL;
+ }
+
++ request_firmware_nowait_cancel(tas_hda->priv->dev, tas_hda->priv,
++ tasdev_fw_ready);
++
+ tas2781_hda_remove_controls(tas_hda);
+
+ tasdevice_config_info_remove(tas_hda->priv);
+--- a/sound/hda/codecs/side-codecs/tas2781_hda_spi.c
++++ b/sound/hda/codecs/side-codecs/tas2781_hda_spi.c
+@@ -750,6 +750,9 @@ static void tas2781_hda_unbind(struct de
+ comp->playback_hook = NULL;
+ }
+
++ request_firmware_nowait_cancel(tas_priv->dev, tas_priv,
++ tasdev_fw_ready);
++
+ tas2781_hda_remove_controls(tas_hda);
+
+ tasdevice_config_info_remove(tas_priv);
--- /dev/null
+From stable+bounces-274055-greg=kroah.com@vger.kernel.org Tue Jul 14 03:16:29 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 13 Jul 2026 21:16:22 -0400
+Subject: ALSA: scarlett2: Allow selecting config_set by firmware version
+To: stable@vger.kernel.org
+Cc: "Geoffrey D. Bennett" <g@b4.vu>, Takashi Iwai <tiwai@suse.de>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260714011623.2188610-1-sashal@kernel.org>
+
+From: "Geoffrey D. Bennett" <g@b4.vu>
+
+[ Upstream commit 732a6397a526c025cd29c3c9309b0db6a2c08837 ]
+
+The Scarlett 2i2 Gen 4 firmware 2417 moved the direct monitor gain
+parameters, so we now need to allow each device to list multiple
+scarlett2_config_set entries, one per applicable firmware version
+range, and pick the matching one at probe time.
+
+No functional change yet: each device gets a single config_sets
+entry whose from_firmware_version matches the existing
+min_firmware_version (0 where none was set). This both prepares for
+selection and lets a follow-up commit remove the now-redundant
+min_firmware_version field.
+
+scarlett2_count_io() depends on the resolved config_set so it moves
+out of scarlett2_init_private() into snd_scarlett2_controls_create()
+after the firmware version has been read.
+
+Signed-off-by: Geoffrey D. Bennett <g@b4.vu>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Link: https://patch.msgid.link/ae1695b4c4825f365b4c86b22174035f742807e3.1777151532.git.g@b4.vu
+Stable-dep-of: 3ca15754b561 ("ALSA: scarlett2: Update offsets for 2i2 Gen 4 firmware 2417")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ sound/usb/mixer_scarlett2.c | 143 +++++++++++++++++++++++++++++++++++++-------
+ 1 file changed, 121 insertions(+), 22 deletions(-)
+
+--- a/sound/usb/mixer_scarlett2.c
++++ b/sound/usb/mixer_scarlett2.c
+@@ -612,6 +612,20 @@ struct scarlett2_config_set {
+ const struct scarlett2_config items[SCARLETT2_CONFIG_COUNT];
+ };
+
++/* Map firmware versions to config sets per-device.
++ *
++ * Each device lists one or more entries, sorted in ascending order of
++ * from_firmware_version. At probe time the running firmware version
++ * is looked up against this list and the last entry whose
++ * from_firmware_version is <= the running version is selected.
++ *
++ * The list is terminated by a sentinel entry with config_set == NULL.
++ */
++struct scarlett2_config_set_entry {
++ u16 from_firmware_version;
++ const struct scarlett2_config_set *config_set;
++};
++
+ /* Input gain TLV dB ranges */
+
+ static const DECLARE_TLV_DB_MINMAX(
+@@ -1100,8 +1114,8 @@ struct scarlett2_meter_entry {
+ };
+
+ struct scarlett2_device_info {
+- /* which set of configuration parameters the device uses */
+- const struct scarlett2_config_set *config_set;
++ /* which sets of configuration parameters the device uses */
++ const struct scarlett2_config_set_entry *config_sets;
+
+ /* minimum firmware version required */
+ u16 min_firmware_version;
+@@ -1343,7 +1357,10 @@ struct scarlett2_data {
+ /*** Model-specific data ***/
+
+ static const struct scarlett2_device_info s6i6_gen2_info = {
+- .config_set = &scarlett2_config_set_gen2a,
++ .config_sets = (const struct scarlett2_config_set_entry[]) {
++ { 0, &scarlett2_config_set_gen2a },
++ { }
++ },
+ .level_input_count = 2,
+ .pad_input_count = 2,
+
+@@ -1393,7 +1410,10 @@ static const struct scarlett2_device_inf
+ };
+
+ static const struct scarlett2_device_info s18i8_gen2_info = {
+- .config_set = &scarlett2_config_set_gen2a,
++ .config_sets = (const struct scarlett2_config_set_entry[]) {
++ { 0, &scarlett2_config_set_gen2a },
++ { }
++ },
+ .level_input_count = 2,
+ .pad_input_count = 4,
+
+@@ -1446,7 +1466,10 @@ static const struct scarlett2_device_inf
+ };
+
+ static const struct scarlett2_device_info s18i20_gen2_info = {
+- .config_set = &scarlett2_config_set_gen2b,
++ .config_sets = (const struct scarlett2_config_set_entry[]) {
++ { 0, &scarlett2_config_set_gen2b },
++ { }
++ },
+
+ .line_out_descrs = {
+ "Monitor L",
+@@ -1503,7 +1526,10 @@ static const struct scarlett2_device_inf
+ };
+
+ static const struct scarlett2_device_info solo_gen3_info = {
+- .config_set = &scarlett2_config_set_gen3a,
++ .config_sets = (const struct scarlett2_config_set_entry[]) {
++ { 0, &scarlett2_config_set_gen3a },
++ { }
++ },
+ .level_input_count = 1,
+ .level_input_first = 1,
+ .air_input_count = 1,
+@@ -1513,7 +1539,10 @@ static const struct scarlett2_device_inf
+ };
+
+ static const struct scarlett2_device_info s2i2_gen3_info = {
+- .config_set = &scarlett2_config_set_gen3a,
++ .config_sets = (const struct scarlett2_config_set_entry[]) {
++ { 0, &scarlett2_config_set_gen3a },
++ { }
++ },
+ .level_input_count = 2,
+ .air_input_count = 2,
+ .phantom_count = 1,
+@@ -1522,7 +1551,10 @@ static const struct scarlett2_device_inf
+ };
+
+ static const struct scarlett2_device_info s4i4_gen3_info = {
+- .config_set = &scarlett2_config_set_gen3b,
++ .config_sets = (const struct scarlett2_config_set_entry[]) {
++ { 0, &scarlett2_config_set_gen3b },
++ { }
++ },
+ .level_input_count = 2,
+ .pad_input_count = 2,
+ .air_input_count = 2,
+@@ -1571,7 +1603,10 @@ static const struct scarlett2_device_inf
+ };
+
+ static const struct scarlett2_device_info s8i6_gen3_info = {
+- .config_set = &scarlett2_config_set_gen3b,
++ .config_sets = (const struct scarlett2_config_set_entry[]) {
++ { 0, &scarlett2_config_set_gen3b },
++ { }
++ },
+ .level_input_count = 2,
+ .pad_input_count = 2,
+ .air_input_count = 2,
+@@ -1637,7 +1672,10 @@ static const char * const scarlett2_spdi
+ };
+
+ static const struct scarlett2_device_info s18i8_gen3_info = {
+- .config_set = &scarlett2_config_set_gen3c,
++ .config_sets = (const struct scarlett2_config_set_entry[]) {
++ { 0, &scarlett2_config_set_gen3c },
++ { }
++ },
+ .has_speaker_switching = 1,
+ .level_input_count = 2,
+ .pad_input_count = 4,
+@@ -1729,7 +1767,10 @@ static const char * const scarlett2_spdi
+ };
+
+ static const struct scarlett2_device_info s18i20_gen3_info = {
+- .config_set = &scarlett2_config_set_gen3c,
++ .config_sets = (const struct scarlett2_config_set_entry[]) {
++ { 0, &scarlett2_config_set_gen3c },
++ { }
++ },
+ .has_speaker_switching = 1,
+ .has_talkback = 1,
+ .level_input_count = 2,
+@@ -1803,7 +1844,10 @@ static const struct scarlett2_device_inf
+ };
+
+ static const struct scarlett2_device_info vocaster_one_info = {
+- .config_set = &scarlett2_config_set_vocaster,
++ .config_sets = (const struct scarlett2_config_set_entry[]) {
++ { 1769, &scarlett2_config_set_vocaster },
++ { }
++ },
+ .min_firmware_version = 1769,
+ .has_devmap = 1,
+
+@@ -1847,7 +1891,10 @@ static const struct scarlett2_device_inf
+ };
+
+ static const struct scarlett2_device_info vocaster_two_info = {
+- .config_set = &scarlett2_config_set_vocaster,
++ .config_sets = (const struct scarlett2_config_set_entry[]) {
++ { 1769, &scarlett2_config_set_vocaster },
++ { }
++ },
+ .min_firmware_version = 1769,
+ .has_devmap = 1,
+
+@@ -1892,7 +1939,10 @@ static const struct scarlett2_device_inf
+ };
+
+ static const struct scarlett2_device_info solo_gen4_info = {
+- .config_set = &scarlett2_config_set_gen4_solo,
++ .config_sets = (const struct scarlett2_config_set_entry[]) {
++ { 2115, &scarlett2_config_set_gen4_solo },
++ { }
++ },
+ .min_firmware_version = 2115,
+ .has_devmap = 1,
+
+@@ -1947,7 +1997,10 @@ static const struct scarlett2_device_inf
+ };
+
+ static const struct scarlett2_device_info s2i2_gen4_info = {
+- .config_set = &scarlett2_config_set_gen4_2i2,
++ .config_sets = (const struct scarlett2_config_set_entry[]) {
++ { 2115, &scarlett2_config_set_gen4_2i2 },
++ { }
++ },
+ .min_firmware_version = 2115,
+ .has_devmap = 1,
+
+@@ -2002,7 +2055,10 @@ static const struct scarlett2_device_inf
+ };
+
+ static const struct scarlett2_device_info s4i4_gen4_info = {
+- .config_set = &scarlett2_config_set_gen4_4i4,
++ .config_sets = (const struct scarlett2_config_set_entry[]) {
++ { 2089, &scarlett2_config_set_gen4_4i4 },
++ { }
++ },
+ .min_firmware_version = 2089,
+ .has_devmap = 1,
+
+@@ -2051,7 +2107,10 @@ static const struct scarlett2_device_inf
+ };
+
+ static const struct scarlett2_device_info clarett_2pre_info = {
+- .config_set = &scarlett2_config_set_clarett,
++ .config_sets = (const struct scarlett2_config_set_entry[]) {
++ { 0, &scarlett2_config_set_clarett },
++ { }
++ },
+ .level_input_count = 2,
+ .air_input_count = 2,
+
+@@ -2107,7 +2166,10 @@ static const char * const scarlett2_spdi
+ };
+
+ static const struct scarlett2_device_info clarett_4pre_info = {
+- .config_set = &scarlett2_config_set_clarett,
++ .config_sets = (const struct scarlett2_config_set_entry[]) {
++ { 0, &scarlett2_config_set_clarett },
++ { }
++ },
+ .level_input_count = 2,
+ .air_input_count = 4,
+
+@@ -2163,7 +2225,10 @@ static const struct scarlett2_device_inf
+ };
+
+ static const struct scarlett2_device_info clarett_8pre_info = {
+- .config_set = &scarlett2_config_set_clarett,
++ .config_sets = (const struct scarlett2_config_set_entry[]) {
++ { 0, &scarlett2_config_set_clarett },
++ { }
++ },
+ .level_input_count = 2,
+ .air_input_count = 8,
+
+@@ -8211,10 +8276,32 @@ static void scarlett2_private_suspend(st
+
+ /*** Initialisation ***/
+
++/* Select the config_set matching the running firmware version.
++ *
++ * The device info's config_sets array is ordered by ascending
++ * from_firmware_version; pick the last entry whose version is <= the
++ * running firmware version. If the running firmware is older than the
++ * first entry's from_firmware_version (i.e. older than the driver's
++ * minimum supported version for this device), the first entry's
++ * config_set is selected anyway so firmware updates can still be done
++ * (requires only the ACK handler), but the usual mixer controls
++ * aren't created.
++ */
++static void scarlett2_resolve_config_set(struct scarlett2_data *private)
++{
++ const struct scarlett2_config_set_entry *entry =
++ private->info->config_sets;
++
++ private->config_set = entry->config_set;
++ for (entry++; entry->config_set; entry++)
++ if (entry->from_firmware_version <= private->firmware_version)
++ private->config_set = entry->config_set;
++}
++
+ static void scarlett2_count_io(struct scarlett2_data *private)
+ {
+ const struct scarlett2_device_info *info = private->info;
+- const struct scarlett2_config_set *config_set = info->config_set;
++ const struct scarlett2_config_set *config_set = private->config_set;
+ const int (*port_count)[SCARLETT2_PORT_DIRNS] = info->port_count;
+ int port_type, srcs = 0, dsts = 0, i;
+
+@@ -8311,9 +8398,14 @@ static int scarlett2_init_private(struct
+ mixer->private_suspend = scarlett2_private_suspend;
+
+ private->info = entry->info;
+- private->config_set = entry->info->config_set;
++
++ /* Set config_set to the first entry's config_set so the
++ * notify handler has a valid pointer while USB init runs; it
++ * is re-resolved once the firmware version has been read.
++ */
++ private->config_set = entry->info->config_sets[0].config_set;
++
+ private->series_name = entry->series_name;
+- scarlett2_count_io(private);
+ private->scarlett2_seq = 0;
+ private->mixer = mixer;
+
+@@ -8717,6 +8809,13 @@ static int snd_scarlett2_controls_create
+ if (err < 0)
+ return err;
+
++ /* Now that the firmware version is known, pick the matching
++ * config_set
++ */
++ scarlett2_resolve_config_set(private);
++
++ scarlett2_count_io(private);
++
+ /* Get the upgrade & settings flash segment numbers */
+ err = scarlett2_get_flash_segment_nums(mixer);
+ if (err < 0)
--- /dev/null
+From stable+bounces-274056-greg=kroah.com@vger.kernel.org Tue Jul 14 03:16:35 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 13 Jul 2026 21:16:23 -0400
+Subject: ALSA: scarlett2: Update offsets for 2i2 Gen 4 firmware 2417
+To: stable@vger.kernel.org
+Cc: "Geoffrey D. Bennett" <g@b4.vu>, Takashi Iwai <tiwai@suse.de>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260714011623.2188610-2-sashal@kernel.org>
+
+From: "Geoffrey D. Bennett" <g@b4.vu>
+
+[ Upstream commit 3ca15754b561483aa7a1bce51677d6389f8ff5bb ]
+
+Firmware 2417 for the Scarlett 4th Gen 2i2 moved the direct monitor gain
+parameters, so add a second config_set with the shifted offset and
+select it for firmware versions >= 2417.
+
+Fixes: 4e809a299677 ("ALSA: scarlett2: Add support for Solo, 2i2, and 4i4 Gen 4")
+Cc: stable@vger.kernel.org # ALSA: scarlett2: Allow selecting config_set by firmware version
+Cc: stable@vger.kernel.org # ALSA: scarlett2: Fold min_firmware_version into config_sets
+Cc: stable@vger.kernel.org
+Signed-off-by: Geoffrey D. Bennett <g@b4.vu>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Link: https://patch.msgid.link/ad0fc5a131e76eb656a24e0e198382f7134068fe.1777151532.git.g@b4.vu
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ sound/usb/mixer_scarlett2.c | 58 ++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 58 insertions(+)
+
+--- a/sound/usb/mixer_scarlett2.c
++++ b/sound/usb/mixer_scarlett2.c
+@@ -937,6 +937,63 @@ static const struct scarlett2_config_set
+ }
+ };
+
++/* 2i2 Gen 4, firmware version 2417 and above
++ *
++ * Firmware 2417 shifted DIRECT_MONITOR_GAIN by 4 bytes; all other
++ * offsets are unchanged from scarlett2_config_set_gen4_2i2.
++ */
++static const struct scarlett2_config_set scarlett2_config_set_gen4_2i2_2417 = {
++ .notifications = scarlett4_2i2_notifications,
++ .param_buf_addr = 0xfc,
++ .input_gain_tlv = db_scale_gen4_gain,
++ .autogain_status_texts = scarlett2_autogain_status_gen4,
++ .items = {
++ [SCARLETT2_CONFIG_MSD_SWITCH] = {
++ .offset = 0x49, .size = 8, .activate = 4 },
++
++ [SCARLETT2_CONFIG_DIRECT_MONITOR] = {
++ .offset = 0x14a, .size = 8, .activate = 16, .pbuf = 1 },
++
++ [SCARLETT2_CONFIG_AUTOGAIN_SWITCH] = {
++ .offset = 0x135, .size = 8, .activate = 10, .pbuf = 1 },
++
++ [SCARLETT2_CONFIG_AUTOGAIN_STATUS] = {
++ .offset = 0x137, .size = 8 },
++
++ [SCARLETT2_CONFIG_AG_MEAN_TARGET] = {
++ .offset = 0x131, .size = 8, .activate = 29, .pbuf = 1 },
++
++ [SCARLETT2_CONFIG_AG_PEAK_TARGET] = {
++ .offset = 0x132, .size = 8, .activate = 30, .pbuf = 1 },
++
++ [SCARLETT2_CONFIG_PHANTOM_SWITCH] = {
++ .offset = 0x48, .size = 8, .activate = 11, .pbuf = 1,
++ .mute = 1 },
++
++ [SCARLETT2_CONFIG_INPUT_GAIN] = {
++ .offset = 0x4b, .size = 8, .activate = 12, .pbuf = 1 },
++
++ [SCARLETT2_CONFIG_LEVEL_SWITCH] = {
++ .offset = 0x3c, .size = 8, .activate = 13, .pbuf = 1,
++ .mute = 1 },
++
++ [SCARLETT2_CONFIG_SAFE_SWITCH] = {
++ .offset = 0x147, .size = 8, .activate = 14, .pbuf = 1 },
++
++ [SCARLETT2_CONFIG_AIR_SWITCH] = {
++ .offset = 0x3e, .size = 8, .activate = 15, .pbuf = 1 },
++
++ [SCARLETT2_CONFIG_INPUT_SELECT_SWITCH] = {
++ .offset = 0x14b, .size = 8, .activate = 17, .pbuf = 1 },
++
++ [SCARLETT2_CONFIG_INPUT_LINK_SWITCH] = {
++ .offset = 0x14e, .size = 8, .activate = 18, .pbuf = 1 },
++
++ [SCARLETT2_CONFIG_DIRECT_MONITOR_GAIN] = {
++ .offset = 0x2a4, .size = 16, .activate = 36 }
++ }
++};
++
+ /* 4i4 Gen 4 */
+ static const struct scarlett2_config_set scarlett2_config_set_gen4_4i4 = {
+ .notifications = scarlett4_4i4_notifications,
+@@ -1999,6 +2056,7 @@ static const struct scarlett2_device_inf
+ static const struct scarlett2_device_info s2i2_gen4_info = {
+ .config_sets = (const struct scarlett2_config_set_entry[]) {
+ { 2115, &scarlett2_config_set_gen4_2i2 },
++ { 2417, &scarlett2_config_set_gen4_2i2_2417 },
+ { }
+ },
+ .min_firmware_version = 2115,
--- /dev/null
+From sashal@kernel.org Tue Jul 14 15:40:10 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 14 Jul 2026 09:40:06 -0400
+Subject: binder: cache secctx size before release zeroes it
+To: stable@vger.kernel.org
+Cc: Chris Mason <clm@meta.com>, stable <stable@kernel.org>, Alice Ryhl <aliceryhl@google.com>, Carlos Llamas <cmllamas@google.com>, Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260714134006.2674552-2-sashal@kernel.org>
+
+From: Chris Mason <clm@meta.com>
+
+[ Upstream commit b34826e55aad3520ec813f1f367c11b24b29dc9f ]
+
+binder_transaction() bounds the scatter-gather buffer area with
+sg_buf_end_offset and subtracts the aligned LSM context size because
+the secctx is written at the tail of that area. The subtraction reads
+lsmctx.len, but that field has already been cleared by the time the
+line runs:
+
+ security_secid_to_secctx(secid, &lsmctx) /* lsmctx.len set */
+ lsmctx_aligned_size = ALIGN(lsmctx.len, sizeof(u64))
+ extra_buffers_size += lsmctx_aligned_size
+ ...
+ security_release_secctx(&lsmctx) /* memset zeroes len */
+ ...
+ sg_buf_end_offset = sg_buf_offset + extra_buffers_size
+ - ALIGN(lsmctx.len, sizeof(u64)) /* ALIGN(0,8) */
+
+security_release_secctx() does memset(cp, 0, sizeof(*cp)), so lsmctx.len
+reads back as 0 and the subtraction contributes nothing, leaving
+sg_buf_end_offset too large by the aligned secctx size on every
+transaction to a txn_security_ctx node.
+
+Each BINDER_TYPE_PTR object then derives buf_left = sg_buf_end_offset -
+sg_buf_offset as the sole upper bound on its copy, so the inflated end
+offset lets the copy run into the bytes that already hold the secctx.
+
+The aligned size must therefore be cached before release rather than
+re-read from the now-cleared field. Fix by caching it in
+lsmctx_aligned_size at function scope when it is first computed and
+subtracting lsmctx_aligned_size instead of re-reading lsmctx.len after
+release. Reuse the same value for the earlier buf_offset computation.
+
+Fixes: 6fba89813ccf ("lsm: ensure the correct LSM context releaser")
+Cc: stable <stable@kernel.org>
+Assisted-by: kres:claude-opus-4-8
+Signed-off-by: Chris Mason <clm@meta.com>
+Reviewed-by: Alice Ryhl <aliceryhl@google.com>
+Acked-by: Carlos Llamas <cmllamas@google.com>
+Link: https://patch.msgid.link/20260603174506.1957278-1-clm@meta.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/android/binder.c | 12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+--- a/drivers/android/binder.c
++++ b/drivers/android/binder.c
+@@ -3097,6 +3097,7 @@ static void binder_transaction(struct bi
+ int t_debug_id = atomic_inc_return(&binder_last_id);
+ ktime_t t_start_time = ktime_get();
+ struct lsm_context lsmctx = { };
++ size_t lsmctx_aligned_size = 0;
+ LIST_HEAD(sgc_head);
+ LIST_HEAD(pf_head);
+ const void __user *user_buffer = (const void __user *)
+@@ -3363,7 +3364,6 @@ static void binder_transaction(struct bi
+
+ if (target_node && target_node->txn_security_ctx) {
+ u32 secid;
+- size_t added_size;
+
+ security_cred_getsecid(proc->cred, &secid);
+ ret = security_secid_to_secctx(secid, &lsmctx);
+@@ -3375,9 +3375,9 @@ static void binder_transaction(struct bi
+ return_error_line = __LINE__;
+ goto err_get_secctx_failed;
+ }
+- added_size = ALIGN(lsmctx.len, sizeof(u64));
+- extra_buffers_size += added_size;
+- if (extra_buffers_size < added_size) {
++ lsmctx_aligned_size = ALIGN(lsmctx.len, sizeof(u64));
++ extra_buffers_size += lsmctx_aligned_size;
++ if (extra_buffers_size < lsmctx_aligned_size) {
+ binder_txn_error("%d:%d integer overflow of extra_buffers_size\n",
+ thread->pid, proc->pid);
+ return_error = BR_FAILED_REPLY;
+@@ -3414,7 +3414,7 @@ static void binder_transaction(struct bi
+ size_t buf_offset = ALIGN(tr->data_size, sizeof(void *)) +
+ ALIGN(tr->offsets_size, sizeof(void *)) +
+ ALIGN(extra_buffers_size, sizeof(void *)) -
+- ALIGN(lsmctx.len, sizeof(u64));
++ lsmctx_aligned_size;
+
+ t->security_ctx = t->buffer->user_data + buf_offset;
+ err = binder_alloc_copy_to_buffer(&target_proc->alloc,
+@@ -3469,7 +3469,7 @@ static void binder_transaction(struct bi
+ off_end_offset = off_start_offset + tr->offsets_size;
+ sg_buf_offset = ALIGN(off_end_offset, sizeof(void *));
+ sg_buf_end_offset = sg_buf_offset + extra_buffers_size -
+- ALIGN(lsmctx.len, sizeof(u64));
++ lsmctx_aligned_size;
+ off_min = 0;
+ for (buffer_offset = off_start_offset; buffer_offset < off_end_offset;
+ buffer_offset += sizeof(binder_size_t)) {
--- /dev/null
+From stable+bounces-274249-greg=kroah.com@vger.kernel.org Tue Jul 14 15:40:13 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 14 Jul 2026 09:40:05 -0400
+Subject: binder: Use LIST_HEAD() to initialize on stack list head
+To: stable@vger.kernel.org
+Cc: Jisheng Zhang <jszhang@kernel.org>, Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260714134006.2674552-1-sashal@kernel.org>
+
+From: Jisheng Zhang <jszhang@kernel.org>
+
+[ Upstream commit 91f818b184b44b105b1c92859ea8d2d6f47912a9 ]
+
+Use LIST_HEAD to initialize on stack list head. No intentional
+functional impact.
+
+Change generated with below coccinelle script:
+
+@@
+identifier name;
+@@
+- struct list_head name;
++ LIST_HEAD(name);
+... when != name
+- INIT_LIST_HEAD(&name);
+
+Signed-off-by: Jisheng Zhang <jszhang@kernel.org>
+Link: https://patch.msgid.link/20260519055623.13142-1-jszhang@kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Stable-dep-of: b34826e55aad ("binder: cache secctx size before release zeroes it")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/android/binder.c | 6 ++----
+ 1 file changed, 2 insertions(+), 4 deletions(-)
+
+--- a/drivers/android/binder.c
++++ b/drivers/android/binder.c
+@@ -3097,12 +3097,10 @@ static void binder_transaction(struct bi
+ int t_debug_id = atomic_inc_return(&binder_last_id);
+ ktime_t t_start_time = ktime_get();
+ struct lsm_context lsmctx = { };
+- struct list_head sgc_head;
+- struct list_head pf_head;
++ LIST_HEAD(sgc_head);
++ LIST_HEAD(pf_head);
+ const void __user *user_buffer = (const void __user *)
+ (uintptr_t)tr->data.ptr.buffer;
+- INIT_LIST_HEAD(&sgc_head);
+- INIT_LIST_HEAD(&pf_head);
+
+ e = binder_transaction_log_add(&binder_transaction_log);
+ e->debug_id = t_debug_id;
--- /dev/null
+From stable+bounces-275034-greg=kroah.com@vger.kernel.org Wed Jul 15 22:50:26 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 15 Jul 2026 16:49:39 -0400
+Subject: Bluetooth: 6lowpan: fix cyclic locking warning on netdev unregister
+To: stable@vger.kernel.org
+Cc: Pauli Virtanen <pav@iki.fi>, Luiz Augusto von Dentz <luiz.von.dentz@intel.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260715204940.205049-1-sashal@kernel.org>
+
+From: Pauli Virtanen <pav@iki.fi>
+
+[ Upstream commit 9707a015fe8f3ba8ec7c270f3b2b8efb38823d6b ]
+
+6lowpan.c has theoretically conflicting lock orderings, which lockdep
+complains about:
+
+ a) rtnl_lock > hdev->workqueue
+
+ from 6lowpan.c:delete_netdev -> rtnl_lock -> device_del
+ -> put_device(parent) -> hci_release_dev -> destroy_workqueue
+
+ b) hdev->workqueue > l2cap_conn->lock > chan->lock > rtnl_lock
+
+ from hci_rx_work -> 6lowpan.c:chan_ready_cb
+ -> lowpan_register_netdev, ifup -> rtnl_lock
+
+Actual deadlock appears not possible, as hci_rx_work is disabled and
+l2cap_conn flushed already on hdev unregister. Hence, do minimal thing
+to make lockdep happy by breaking chain a) by holding hdev refcount
+until after netdev put in 6lowpan.c.
+
+Fixes the lockdep complaint:
+WARNING: possible circular locking dependency detected.
+kworker/0:1/11 is trying to acquire lock:
+ffff8880023b3940 ((wq_completion)hci0#2){+.+.}-{0:0}, at: touch_wq_lockdep_map+0x8b/0x130
+but task is already holding lock:
+ffffffff95e4f9c0 (rtnl_mutex){+.+.}-{4:4}, at: lowpan_unregister_netdev+0xd/0x30
+Workqueue: events delete_netdev
+
+Signed-off-by: Pauli Virtanen <pav@iki.fi>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Stable-dep-of: 6fef032af009 ("Bluetooth: L2CAP: Fix use-after-free in l2cap_sock_new_connection_cb()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/bluetooth/6lowpan.c | 25 +++++++++++++++++++++++--
+ 1 file changed, 23 insertions(+), 2 deletions(-)
+
+--- a/net/bluetooth/6lowpan.c
++++ b/net/bluetooth/6lowpan.c
+@@ -760,13 +760,33 @@ static inline struct l2cap_chan *chan_ne
+ return chan;
+ }
+
++static void unregister_dev(struct lowpan_btle_dev *dev)
++{
++ struct hci_dev *hdev = READ_ONCE(dev->hdev);
++
++ /* If netdev holds last reference to hci_dev (its parent device), this
++ * leads to theoretical cyclic locking on lowpan_unregister_netdev:
++ *
++ * rtnl_lock -> put_device(parent) -> hci_release_dev ->
++ * destroy_workqueue -> hci_rx_work -> l2cap_recv_acldata ->
++ * chan_ready_cb -> ifup -> rtnl_lock
++ *
++ * However, hci_rx_work is disabled in hci_unregister_dev, so this
++ * should not occur. Make lockdep happy by postponing hdev release after
++ * netdev put.
++ */
++ hci_dev_hold(hdev);
++ lowpan_unregister_netdev(dev->netdev);
++ hci_dev_put(hdev);
++}
++
+ static void delete_netdev(struct work_struct *work)
+ {
+ struct lowpan_btle_dev *entry = container_of(work,
+ struct lowpan_btle_dev,
+ delete_netdev);
+
+- lowpan_unregister_netdev(entry->netdev);
++ unregister_dev(entry);
+
+ /* The entry pointer is deleted by the netdev destructor. */
+ }
+@@ -1230,6 +1250,7 @@ static void disconnect_devices(void)
+ break;
+
+ new_dev->netdev = entry->netdev;
++ new_dev->hdev = entry->hdev;
+ INIT_LIST_HEAD(&new_dev->list);
+
+ list_add_rcu(&new_dev->list, &devices);
+@@ -1241,7 +1262,7 @@ static void disconnect_devices(void)
+ ifdown(entry->netdev);
+ BT_DBG("Unregistering netdev %s %p",
+ entry->netdev->name, entry->netdev);
+- lowpan_unregister_netdev(entry->netdev);
++ unregister_dev(entry);
+ kfree(entry);
+ }
+ }
--- /dev/null
+From stable+bounces-275035-greg=kroah.com@vger.kernel.org Wed Jul 15 22:50:33 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 15 Jul 2026 16:49:40 -0400
+Subject: Bluetooth: L2CAP: Fix use-after-free in l2cap_sock_new_connection_cb()
+To: stable@vger.kernel.org
+Cc: Siwei Zhang <oss@fourdim.xyz>, stable@kernel.org, Luiz Augusto von Dentz <luiz.von.dentz@intel.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260715204940.205049-2-sashal@kernel.org>
+
+From: Siwei Zhang <oss@fourdim.xyz>
+
+[ Upstream commit 6fef032af0092ed5ccb767239a9ac1bc38c08a40 ]
+
+l2cap_sock_new_connection_cb() returned l2cap_pi(sk)->chan after
+release_sock(parent). Once the parent lock is dropped the newly
+enqueued child socket sk is reachable via the accept queue, so another
+task can accept and free it before the callback dereferences sk,
+resulting in a use-after-free.
+
+Rework the ->new_connection() op so the core, rather than the callback,
+owns the child channel's lifetime. The op now receives a pre-allocated
+new_chan and returns an errno instead of allocating and returning a
+channel. l2cap_new_connection() allocates the child channel and links
+it into the conn list via __l2cap_chan_add() before invoking the
+callback, so the conn-list reference keeps the channel alive once
+release_sock(parent) exposes the socket to other tasks.
+
+Channel configuration that was duplicated in l2cap_sock_init() and the
+various new_connection callbacks is consolidated into
+l2cap_chan_set_defaults(), which now inherits from the parent channel
+when one is supplied.
+
+Fixes: 8ffb929098a5 ("Bluetooth: Remove parent socket usage from l2cap_core.c")
+Cc: stable@kernel.org
+Assisted-by: Claude:claude-opus-4-8
+Signed-off-by: Siwei Zhang <oss@fourdim.xyz>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ include/net/bluetooth/l2cap.h | 10 ++--
+ net/bluetooth/6lowpan.c | 18 -------
+ net/bluetooth/l2cap_core.c | 78 ++++++++++++++++++++++++++-----
+ net/bluetooth/l2cap_sock.c | 103 +++++++++++++++++++-----------------------
+ net/bluetooth/smp.c | 27 ++---------
+ 5 files changed, 127 insertions(+), 109 deletions(-)
+
+--- a/include/net/bluetooth/l2cap.h
++++ b/include/net/bluetooth/l2cap.h
+@@ -620,7 +620,8 @@ struct l2cap_chan {
+ struct l2cap_ops {
+ char *name;
+
+- struct l2cap_chan *(*new_connection) (struct l2cap_chan *chan);
++ int (*new_connection)(struct l2cap_chan *chan,
++ struct l2cap_chan *new_chan);
+ int (*recv) (struct l2cap_chan * chan,
+ struct sk_buff *skb);
+ void (*teardown) (struct l2cap_chan *chan, int err);
+@@ -885,9 +886,10 @@ static inline __u16 __next_seq(struct l2
+ return (seq + 1) % (chan->tx_win_max + 1);
+ }
+
+-static inline struct l2cap_chan *l2cap_chan_no_new_connection(struct l2cap_chan *chan)
++static inline int l2cap_chan_no_new_connection(struct l2cap_chan *chan,
++ struct l2cap_chan *new_chan)
+ {
+- return NULL;
++ return -EOPNOTSUPP;
+ }
+
+ static inline int l2cap_chan_no_recv(struct l2cap_chan *chan, struct sk_buff *skb)
+@@ -964,7 +966,7 @@ int l2cap_chan_send(struct l2cap_chan *c
+ void l2cap_chan_busy(struct l2cap_chan *chan, int busy);
+ void l2cap_chan_rx_avail(struct l2cap_chan *chan, ssize_t rx_avail);
+ int l2cap_chan_check_security(struct l2cap_chan *chan, bool initiator);
+-void l2cap_chan_set_defaults(struct l2cap_chan *chan);
++void l2cap_chan_set_defaults(struct l2cap_chan *chan, struct l2cap_chan *pchan);
+ int l2cap_ertm_init(struct l2cap_chan *chan);
+ void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan);
+ void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan);
+--- a/net/bluetooth/6lowpan.c
++++ b/net/bluetooth/6lowpan.c
+@@ -632,7 +632,7 @@ static struct l2cap_chan *chan_create(vo
+ if (!chan)
+ return NULL;
+
+- l2cap_chan_set_defaults(chan);
++ l2cap_chan_set_defaults(chan, NULL);
+
+ chan->chan_type = L2CAP_CHAN_CONN_ORIENTED;
+ chan->mode = L2CAP_MODE_LE_FLOWCTL;
+@@ -745,21 +745,6 @@ static inline void chan_ready_cb(struct
+ ifup(dev->netdev);
+ }
+
+-static inline struct l2cap_chan *chan_new_conn_cb(struct l2cap_chan *pchan)
+-{
+- struct l2cap_chan *chan;
+-
+- chan = chan_create();
+- if (!chan)
+- return NULL;
+-
+- chan->ops = pchan->ops;
+-
+- BT_DBG("chan %p pchan %p", chan, pchan);
+-
+- return chan;
+-}
+-
+ static void unregister_dev(struct lowpan_btle_dev *dev)
+ {
+ struct hci_dev *hdev = READ_ONCE(dev->hdev);
+@@ -889,7 +874,6 @@ static long chan_get_sndtimeo_cb(struct
+
+ static const struct l2cap_ops bt_6lowpan_chan_ops = {
+ .name = "L2CAP 6LoWPAN channel",
+- .new_connection = chan_new_conn_cb,
+ .recv = chan_recv_cb,
+ .close = chan_close_cb,
+ .state_change = chan_state_change_cb,
+--- a/net/bluetooth/l2cap_core.c
++++ b/net/bluetooth/l2cap_core.c
+@@ -525,7 +525,10 @@ void l2cap_chan_put(struct l2cap_chan *c
+ }
+ EXPORT_SYMBOL_GPL(l2cap_chan_put);
+
+-void l2cap_chan_set_defaults(struct l2cap_chan *chan)
++/* Initialise @chan with default values, inheriting from the parent channel
++ * @pchan when it is given.
++ */
++void l2cap_chan_set_defaults(struct l2cap_chan *chan, struct l2cap_chan *pchan)
+ {
+ chan->fcs = L2CAP_FCS_CRC16;
+ chan->max_tx = L2CAP_DEFAULT_MAX_TX;
+@@ -539,6 +542,31 @@ void l2cap_chan_set_defaults(struct l2ca
+ chan->retrans_timeout = L2CAP_DEFAULT_RETRANS_TO;
+ chan->monitor_timeout = L2CAP_DEFAULT_MONITOR_TO;
+
++ if (pchan) {
++ BT_DBG("chan %p pchan %p", chan, pchan);
++
++ chan->chan_type = pchan->chan_type;
++ chan->imtu = pchan->imtu;
++ chan->omtu = pchan->omtu;
++ chan->mode = pchan->mode;
++ chan->fcs = pchan->fcs;
++ chan->max_tx = pchan->max_tx;
++ chan->tx_win = pchan->tx_win;
++ chan->tx_win_max = pchan->tx_win_max;
++ chan->sec_level = pchan->sec_level;
++ chan->conf_state = pchan->conf_state;
++ chan->flags = pchan->flags;
++ chan->tx_credits = pchan->tx_credits;
++ chan->rx_credits = pchan->rx_credits;
++
++ if (chan->chan_type == L2CAP_CHAN_FIXED) {
++ chan->scid = pchan->scid;
++ chan->dcid = pchan->scid;
++ }
++
++ return;
++ }
++
+ chan->conf_state = 0;
+ set_bit(CONF_NOT_COMPLETE, &chan->conf_state);
+
+@@ -4027,6 +4055,38 @@ static inline int l2cap_command_rej(stru
+ return 0;
+ }
+
++/* Allocate and initialise a channel for an incoming connection.
++ *
++ * The channel inherits its configuration from @pchan and is linked into @conn
++ * before ->new_connection() runs, so the conn list reference keeps it alive if
++ * the callback exposes it (e.g. via the socket accept queue) before this
++ * returns. The l2cap_chan_create() reference is taken over by the subsystem on
++ * success and dropped here on failure.
++ */
++static struct l2cap_chan *l2cap_new_connection(struct l2cap_conn *conn,
++ struct l2cap_chan *pchan)
++{
++ struct l2cap_chan *chan;
++
++ chan = l2cap_chan_create();
++ if (!chan)
++ return NULL;
++
++ l2cap_chan_set_defaults(chan, pchan);
++ chan->ops = pchan->ops;
++
++ __l2cap_chan_add(conn, chan);
++
++ if (pchan->ops->new_connection &&
++ pchan->ops->new_connection(pchan, chan) < 0) {
++ l2cap_chan_del(chan, 0);
++ l2cap_chan_put(chan);
++ return NULL;
++ }
++
++ return chan;
++}
++
+ static void l2cap_connect(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd,
+ u8 *data, u8 rsp_code)
+ {
+@@ -4073,7 +4133,7 @@ static void l2cap_connect(struct l2cap_c
+ goto response;
+ }
+
+- chan = pchan->ops->new_connection(pchan);
++ chan = l2cap_new_connection(conn, pchan);
+ if (!chan)
+ goto response;
+
+@@ -4091,8 +4151,6 @@ static void l2cap_connect(struct l2cap_c
+ chan->psm = psm;
+ chan->dcid = scid;
+
+- __l2cap_chan_add(conn, chan);
+-
+ dcid = chan->scid;
+
+ __set_chan_timer(chan, chan->ops->get_sndtimeo(chan));
+@@ -4976,7 +5034,7 @@ static int l2cap_le_connect_req(struct l
+ goto response_unlock;
+ }
+
+- chan = pchan->ops->new_connection(pchan);
++ chan = l2cap_new_connection(conn, pchan);
+ if (!chan) {
+ result = L2CAP_CR_LE_NO_MEM;
+ goto response_unlock;
+@@ -4991,8 +5049,6 @@ static int l2cap_le_connect_req(struct l
+ chan->omtu = mtu;
+ chan->remote_mps = mps;
+
+- __l2cap_chan_add(conn, chan);
+-
+ l2cap_le_flowctl_init(chan, __le16_to_cpu(req->credits));
+
+ dcid = chan->scid;
+@@ -5200,7 +5256,7 @@ static inline int l2cap_ecred_conn_req(s
+ continue;
+ }
+
+- chan = pchan->ops->new_connection(pchan);
++ chan = l2cap_new_connection(conn, pchan);
+ if (!chan) {
+ result = L2CAP_CR_LE_NO_MEM;
+ continue;
+@@ -5215,8 +5271,6 @@ static inline int l2cap_ecred_conn_req(s
+ chan->omtu = mtu;
+ chan->remote_mps = mps;
+
+- __l2cap_chan_add(conn, chan);
+-
+ l2cap_ecred_init(chan, __le16_to_cpu(req->credits));
+
+ /* Init response */
+@@ -7501,14 +7555,12 @@ static void l2cap_connect_cfm(struct hci
+ goto next;
+
+ l2cap_chan_lock(pchan);
+- chan = pchan->ops->new_connection(pchan);
++ chan = l2cap_new_connection(conn, pchan);
+ if (chan) {
+ bacpy(&chan->src, &hcon->src);
+ bacpy(&chan->dst, &hcon->dst);
+ chan->src_type = bdaddr_src_type(hcon);
+ chan->dst_type = dst_type;
+-
+- __l2cap_chan_add(conn, chan);
+ }
+
+ l2cap_chan_unlock(pchan);
+--- a/net/bluetooth/l2cap_sock.c
++++ b/net/bluetooth/l2cap_sock.c
+@@ -45,7 +45,8 @@ static struct bt_sock_list l2cap_sk_list
+ static const struct proto_ops l2cap_sock_ops;
+ static void l2cap_sock_init(struct sock *sk, struct sock *parent);
+ static struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock,
+- int proto, gfp_t prio, int kern);
++ int proto, gfp_t prio, int kern,
++ struct l2cap_chan *chan);
+ static void l2cap_sock_cleanup_listen(struct sock *parent);
+
+ bool l2cap_is_socket(struct socket *sock)
+@@ -1274,6 +1275,23 @@ done:
+ return err;
+ }
+
++/* Release the sock's ref on chan and clear the pointer so that the ref is
++ * dropped exactly once even if both l2cap_sock_kill() and
++ * l2cap_sock_destruct() run. Setting chan->data to NULL first stops any other
++ * task from dereferencing the now-dead sock pointer.
++ */
++static void l2cap_sock_put_chan(struct sock *sk)
++{
++ struct l2cap_chan *chan = l2cap_pi(sk)->chan;
++
++ if (!chan)
++ return;
++
++ chan->data = NULL;
++ l2cap_pi(sk)->chan = NULL;
++ l2cap_chan_put(chan);
++}
++
+ /* Kill socket (only if zapped and orphan)
+ * Must be called on unlocked socket, with l2cap channel lock.
+ */
+@@ -1284,13 +1302,9 @@ static void l2cap_sock_kill(struct sock
+
+ BT_DBG("sk %p state %s", sk, state_to_string(sk->sk_state));
+
+- /* Sock is dead, so set chan data to NULL, avoid other task use invalid
+- * sock pointer.
+- */
+- l2cap_pi(sk)->chan->data = NULL;
+- /* Kill poor orphan */
++ l2cap_sock_put_chan(sk);
+
+- l2cap_chan_put(l2cap_pi(sk)->chan);
++ /* Kill poor orphan */
+ sock_set_flag(sk, SOCK_DEAD);
+ sock_put(sk);
+ }
+@@ -1533,12 +1547,13 @@ static void l2cap_sock_cleanup_listen(st
+ }
+ }
+
+-static struct l2cap_chan *l2cap_sock_new_connection_cb(struct l2cap_chan *chan)
++static int l2cap_sock_new_connection_cb(struct l2cap_chan *chan,
++ struct l2cap_chan *new_chan)
+ {
+ struct sock *sk, *parent = chan->data;
+
+ if (!parent)
+- return NULL;
++ return -EINVAL;
+
+ lock_sock(parent);
+
+@@ -1546,25 +1561,28 @@ static struct l2cap_chan *l2cap_sock_new
+ if (sk_acceptq_is_full(parent)) {
+ BT_DBG("backlog full %d", parent->sk_ack_backlog);
+ release_sock(parent);
+- return NULL;
++ return -ENOBUFS;
+ }
+
+ sk = l2cap_sock_alloc(sock_net(parent), NULL, BTPROTO_L2CAP,
+- GFP_ATOMIC, 0);
++ GFP_ATOMIC, 0, new_chan);
+ if (!sk) {
+ release_sock(parent);
+- return NULL;
+- }
++ return -ENOMEM;
++ }
+
+ bt_sock_reclassify_lock(sk, BTPROTO_L2CAP);
+
+ l2cap_sock_init(sk, parent);
+
++ /* The conn list reference taken by l2cap_new_connection() keeps new_chan
++ * alive once release_sock() lets another task free this socket.
++ */
+ bt_accept_enqueue(parent, sk, false);
+
+ release_sock(parent);
+
+- return l2cap_pi(sk)->chan;
++ return 0;
+ }
+
+ static int l2cap_sock_recv_cb(struct l2cap_chan *chan, struct sk_buff *skb)
+@@ -1861,10 +1879,7 @@ static void l2cap_sock_destruct(struct s
+
+ BT_DBG("sk %p", sk);
+
+- if (l2cap_pi(sk)->chan) {
+- l2cap_pi(sk)->chan->data = NULL;
+- l2cap_chan_put(l2cap_pi(sk)->chan);
+- }
++ l2cap_sock_put_chan(sk);
+
+ list_for_each_entry_safe(rx_busy, next, &l2cap_pi(sk)->rx_busy, list) {
+ kfree_skb(rx_busy->skb);
+@@ -1897,30 +1912,12 @@ static void l2cap_sock_init(struct sock
+ BT_DBG("sk %p", sk);
+
+ if (parent) {
+- struct l2cap_chan *pchan = l2cap_pi(parent)->chan;
+-
+ sk->sk_type = parent->sk_type;
+ bt_sk(sk)->flags = bt_sk(parent)->flags;
+
+- chan->chan_type = pchan->chan_type;
+- chan->imtu = pchan->imtu;
+- chan->omtu = pchan->omtu;
+- chan->conf_state = pchan->conf_state;
+- chan->mode = pchan->mode;
+- chan->fcs = pchan->fcs;
+- chan->max_tx = pchan->max_tx;
+- chan->tx_win = pchan->tx_win;
+- chan->tx_win_max = pchan->tx_win_max;
+- chan->sec_level = pchan->sec_level;
+- chan->flags = pchan->flags;
+- chan->tx_credits = pchan->tx_credits;
+- chan->rx_credits = pchan->rx_credits;
+-
+- if (chan->chan_type == L2CAP_CHAN_FIXED) {
+- chan->scid = pchan->scid;
+- chan->dcid = pchan->scid;
+- }
+-
++ /* Channel configuration is inherited from the parent by
++ * l2cap_new_connection().
++ */
+ security_sk_clone(parent, sk);
+ } else {
+ switch (sk->sk_type) {
+@@ -1946,7 +1943,7 @@ static void l2cap_sock_init(struct sock
+ chan->mode = L2CAP_MODE_BASIC;
+ }
+
+- l2cap_chan_set_defaults(chan);
++ l2cap_chan_set_defaults(chan, NULL);
+ }
+
+ /* Default config options */
+@@ -1965,10 +1962,10 @@ static struct proto l2cap_proto = {
+ };
+
+ static struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock,
+- int proto, gfp_t prio, int kern)
++ int proto, gfp_t prio, int kern,
++ struct l2cap_chan *chan)
+ {
+ struct sock *sk;
+- struct l2cap_chan *chan;
+
+ sk = bt_sock_alloc(net, sock, &l2cap_proto, proto, prio, kern);
+ if (!sk)
+@@ -1979,16 +1976,7 @@ static struct sock *l2cap_sock_alloc(str
+
+ INIT_LIST_HEAD(&l2cap_pi(sk)->rx_busy);
+
+- chan = l2cap_chan_create();
+- if (!chan) {
+- sk_free(sk);
+- if (sock)
+- sock->sk = NULL;
+- return NULL;
+- }
+-
+- l2cap_chan_hold(chan);
+-
++ /* The sock takes ownership of the caller's reference on chan. */
+ l2cap_pi(sk)->chan = chan;
+
+ return sk;
+@@ -1998,6 +1986,7 @@ static int l2cap_sock_create(struct net
+ int kern)
+ {
+ struct sock *sk;
++ struct l2cap_chan *chan;
+
+ BT_DBG("sock %p", sock);
+
+@@ -2012,10 +2001,16 @@ static int l2cap_sock_create(struct net
+
+ sock->ops = &l2cap_sock_ops;
+
+- sk = l2cap_sock_alloc(net, sock, protocol, GFP_ATOMIC, kern);
+- if (!sk)
++ chan = l2cap_chan_create();
++ if (!chan)
+ return -ENOMEM;
+
++ sk = l2cap_sock_alloc(net, sock, protocol, GFP_ATOMIC, kern, chan);
++ if (!sk) {
++ l2cap_chan_put(chan);
++ return -ENOMEM;
++ }
++
+ l2cap_sock_init(sk, NULL);
+ bt_sock_link(&l2cap_sk_list, sk);
+ return 0;
+--- a/net/bluetooth/smp.c
++++ b/net/bluetooth/smp.c
+@@ -3234,34 +3234,19 @@ static const struct l2cap_ops smp_chan_o
+ .get_sndtimeo = l2cap_chan_no_get_sndtimeo,
+ };
+
+-static inline struct l2cap_chan *smp_new_conn_cb(struct l2cap_chan *pchan)
++static inline int smp_new_conn_cb(struct l2cap_chan *chan,
++ struct l2cap_chan *new_chan)
+ {
+- struct l2cap_chan *chan;
+-
+- BT_DBG("pchan %p", pchan);
+-
+- chan = l2cap_chan_create();
+- if (!chan)
+- return NULL;
+-
+- chan->chan_type = pchan->chan_type;
+- chan->ops = &smp_chan_ops;
+- chan->scid = pchan->scid;
+- chan->dcid = chan->scid;
+- chan->imtu = pchan->imtu;
+- chan->omtu = pchan->omtu;
+- chan->mode = pchan->mode;
++ new_chan->ops = &smp_chan_ops;
+
+ /* Other L2CAP channels may request SMP routines in order to
+ * change the security level. This means that the SMP channel
+ * lock must be considered in its own category to avoid lockdep
+ * warnings.
+ */
+- atomic_set(&chan->nesting, L2CAP_NESTING_SMP);
+-
+- BT_DBG("created chan %p", chan);
++ atomic_set(&new_chan->nesting, L2CAP_NESTING_SMP);
+
+- return chan;
++ return 0;
+ }
+
+ static const struct l2cap_ops smp_root_chan_ops = {
+@@ -3332,7 +3317,7 @@ create_chan:
+
+ l2cap_add_scid(chan, cid);
+
+- l2cap_chan_set_defaults(chan);
++ l2cap_chan_set_defaults(chan, NULL);
+
+ if (cid == L2CAP_CID_SMP) {
+ u8 bdaddr_type;
--- /dev/null
+From fd4cfa8c8f9a17cdec0539334d28754bc1d8a5d9 Mon Sep 17 00:00:00 2001
+From: Sun Jian <sun.jian.kdev@gmail.com>
+Date: Tue, 14 Jul 2026 02:38:45 -0700
+Subject: bpf: Reject negative const offsets for buffer pointers
+
+From: Sun Jian <sun.jian.kdev@gmail.com>
+
+commit fd4cfa8c8f9a17cdec0539334d28754bc1d8a5d9 upstream.
+
+The verifier rejects variable offsets for PTR_TO_TP_BUFFER and PTR_TO_BUF
+accesses, but it currently accepts a constant negative offset produced by
+pointer arithmetic.
+
+Commit 022ac0750883 ("bpf: use reg->var_off instead of reg->off for
+pointers") moved constant pointer offsets from reg->off to reg->var_off.
+However, __check_buffer_access() continued to check only the instruction
+offset. An access with reg->var_off equal to -8 and an instruction offset
+of zero therefore passes verification.
+
+For writable raw tracepoints, the access end is also calculated from the
+unsigned reg->var_off.value. An eight-byte access starting at -8 wraps
+the calculated end to zero, allowing the program to load and attach
+without increasing max_tp_access.
+
+After ensuring that reg->var_off is constant, calculate the effective
+access start using signed arithmetic and reject it when it is negative.
+Use the validated start to calculate the access end for both
+PTR_TO_TP_BUFFER and PTR_TO_BUF.
+
+Fixes: 022ac0750883 ("bpf: use reg->var_off instead of reg->off for pointers")
+Signed-off-by: Sun Jian <sun.jian.kdev@gmail.com>
+Acked-by: Shung-Hsi Yu <shung-hsi.yu@suse.com>
+Cc: stable@vger.kernel.org # 5.2.0
+Link: https://patch.msgid.link/20260714093846.18159-2-sun.jian.kdev@gmail.com
+Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ kernel/bpf/verifier.c | 31 +++++++++++++++++++------------
+ 1 file changed, 19 insertions(+), 12 deletions(-)
+
+--- a/kernel/bpf/verifier.c
++++ b/kernel/bpf/verifier.c
+@@ -5559,14 +5559,11 @@ static int check_max_stack_depth(struct
+ static int __check_buffer_access(struct bpf_verifier_env *env,
+ const char *buf_info,
+ const struct bpf_reg_state *reg,
+- int regno, int off, int size)
++ int regno, int off, int size,
++ u32 *access_end)
+ {
+- if (off < 0) {
+- verbose(env,
+- "R%d invalid %s buffer access: off=%d, size=%d\n",
+- regno, buf_info, off, size);
+- return -EACCES;
+- }
++ s64 start;
++
+ if (!tnum_is_const(reg->var_off)) {
+ char tn_buf[48];
+
+@@ -5577,6 +5574,15 @@ static int __check_buffer_access(struct
+ return -EACCES;
+ }
+
++ start = (s64)reg->var_off.value + off;
++ if (start < 0) {
++ verbose(env,
++ "R%d invalid negative %s buffer offset: off=%d, var_off=%lld\n",
++ regno, buf_info, off, (s64)reg->var_off.value);
++ return -EACCES;
++ }
++
++ *access_end = start + size;
+ return 0;
+ }
+
+@@ -5584,14 +5590,14 @@ static int check_tp_buffer_access(struct
+ const struct bpf_reg_state *reg,
+ int regno, int off, int size)
+ {
++ u32 access_end;
+ int err;
+
+- err = __check_buffer_access(env, "tracepoint", reg, regno, off, size);
++ err = __check_buffer_access(env, "tracepoint", reg, regno, off, size, &access_end);
+ if (err)
+ return err;
+
+- env->prog->aux->max_tp_access = max(reg->var_off.value + off + size,
+- env->prog->aux->max_tp_access);
++ env->prog->aux->max_tp_access = max(access_end, env->prog->aux->max_tp_access);
+
+ return 0;
+ }
+@@ -5603,13 +5609,14 @@ static int check_buffer_access(struct bp
+ u32 *max_access)
+ {
+ const char *buf_info = type_is_rdonly_mem(reg->type) ? "rdonly" : "rdwr";
++ u32 access_end;
+ int err;
+
+- err = __check_buffer_access(env, buf_info, reg, regno, off, size);
++ err = __check_buffer_access(env, buf_info, reg, regno, off, size, &access_end);
+ if (err)
+ return err;
+
+- *max_access = max(reg->var_off.value + off + size, *max_access);
++ *max_access = max(access_end, *max_access);
+
+ return 0;
+ }
--- /dev/null
+From stable+bounces-270539-greg=kroah.com@vger.kernel.org Thu Jul 2 16:33:38 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 2 Jul 2026 10:29:56 -0400
+Subject: device property: initialize the remaining fields of fwnode_handle in fwnode_init()
+To: stable@vger.kernel.org
+Cc: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>, Sakari Ailus <sakari.ailus@linux.intel.com>, "Rafael J. Wysocki (Intel)" <rafael@kernel.org>, Andy Shevchenko <andriy.shevchenko@linux.intel.com>, Danilo Krummrich <dakr@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260702142956.3485868-1-sashal@kernel.org>
+
+From: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
+
+[ Upstream commit 7eba000621fff223dd7bab484d48918c7c77a307 ]
+
+If a firmware node is allocated on the stack (for instance: temporary
+software node whose life-time we control) or on the heap - but using a
+non-zeroing allocation function - and initialized using fwnode_init(),
+its secondary pointer will contain uninitialized memory which likely
+will be neither NULL nor IS_ERR() and so may end up being dereferenced
+(for example: in dev_to_swnode()). Set fwnode->secondary to NULL on
+initialization. While at it: initialize the remaining fields of struct
+fwnode_handle too just to be sure.
+
+Cc: stable@vger.kernel.org
+Fixes: 01bb86b380a3 ("driver core: Add fwnode_init()")
+Reviewed-by: Sakari Ailus <sakari.ailus@linux.intel.com>
+Reviewed-by: Rafael J. Wysocki (Intel) <rafael@kernel.org>
+Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
+Link: https://patch.msgid.link/20260511074927.9473-1-bartosz.golaszewski@oss.qualcomm.com
+[ Fix typo in commit message. - Danilo ]
+Signed-off-by: Danilo Krummrich <dakr@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ include/linux/fwnode.h | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/include/linux/fwnode.h
++++ b/include/linux/fwnode.h
+@@ -210,8 +210,10 @@ static inline void fwnode_init(struct fw
+ {
+ fwnode->secondary = NULL;
+ fwnode->ops = ops;
++ fwnode->dev = NULL;
+ INIT_LIST_HEAD(&fwnode->consumers);
+ INIT_LIST_HEAD(&fwnode->suppliers);
++ fwnode->flags = 0;
+ }
+
+ static inline void fwnode_set_flag(struct fwnode_handle *fwnode,
--- /dev/null
+From stable+bounces-271849-greg=kroah.com@vger.kernel.org Fri Jul 3 20:30:08 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 3 Jul 2026 14:24:22 -0400
+Subject: f2fs: fix listxattr handling of corrupted xattr entries
+To: stable@vger.kernel.org
+Cc: Keshav Verma <iganschel@gmail.com>, stable@kernel.org, Chao Yu <chao@kernel.org>, Jaegeuk Kim <jaegeuk@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260703182422.255104-1-sashal@kernel.org>
+
+From: Keshav Verma <iganschel@gmail.com>
+
+[ Upstream commit 5ef5bc304f23c3fe255d4936472378dcb74d0e94 ]
+
+Validate the xattr entry before reading its fields in f2fs_listxattr().
+Return -EFSCORRUPTED when the entry is outside the valid xattr storage
+area instead of returning a successful partial result.
+
+Fixes: 688078e7f36c ("f2fs: fix to avoid memory leakage in f2fs_listxattr")
+Cc: stable@kernel.org
+Reviewed-by: Chao Yu <chao@kernel.org>
+Signed-off-by: Keshav Verma <iganschel@gmail.com>
+Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/f2fs/xattr.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+--- a/fs/f2fs/xattr.c
++++ b/fs/f2fs/xattr.c
+@@ -581,8 +581,6 @@ ssize_t f2fs_listxattr(struct dentry *de
+ size_t prefix_len;
+ size_t size;
+
+- prefix = f2fs_xattr_prefix(entry->e_name_index, dentry);
+-
+ if ((void *)(entry) + sizeof(__u32) > last_base_addr ||
+ (void *)XATTR_NEXT_ENTRY(entry) > last_base_addr) {
+ f2fs_err(F2FS_I_SB(inode), "list inode (%llu) has corrupted xattr",
+@@ -590,9 +588,11 @@ ssize_t f2fs_listxattr(struct dentry *de
+ set_sbi_flag(F2FS_I_SB(inode), SBI_NEED_FSCK);
+ f2fs_handle_error(F2FS_I_SB(inode),
+ ERROR_CORRUPTED_XATTR);
+- break;
++ error = -EFSCORRUPTED;
++ goto cleanup;
+ }
+
++ prefix = f2fs_xattr_prefix(entry->e_name_index, dentry);
+ if (!prefix)
+ continue;
+
--- /dev/null
+From stable+bounces-271803-greg=kroah.com@vger.kernel.org Fri Jul 3 16:35:38 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 3 Jul 2026 10:26:29 -0400
+Subject: f2fs: fix potential deadlock in f2fs_balance_fs()
+To: stable@vger.kernel.org
+Cc: Ruipeng Qi <ruipengqi3@gmail.com>, Chao Yu <chao@kernel.org>, Jaegeuk Kim <jaegeuk@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260703142630.55436-1-sashal@kernel.org>
+
+From: Ruipeng Qi <ruipengqi3@gmail.com>
+
+[ Upstream commit dd3114870771562036fdcf5abe813956f36d224d ]
+
+When the f2fs filesystem space is nearly exhausted, we encounter deadlock
+issues as below:
+
+INFO: task A:1890 blocked for more than 120 seconds.
+ Tainted: G O 6.12.41-g3fe07ddf05ab #1
+"echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
+task:A state:D stack:0 pid:1890 tgid:1626 ppid:1153 flags:0x00000204
+Call trace:
+ __switch_to+0xf4/0x158
+ __schedule+0x27c/0x908
+ schedule+0x3c/0x118
+ io_schedule+0x44/0x68
+ folio_wait_bit_common+0x174/0x370
+ folio_wait_bit+0x20/0x38
+ folio_wait_writeback+0x54/0xc8
+ truncate_inode_partial_folio+0x70/0x1e0
+ truncate_inode_pages_range+0x1b0/0x450
+ truncate_pagecache+0x54/0x88
+ f2fs_file_write_iter+0x3e8/0xb80
+ do_iter_readv_writev+0xf0/0x1e0
+ vfs_writev+0x138/0x2c8
+ do_writev+0x88/0x130
+ __arm64_sys_writev+0x28/0x40
+ invoke_syscall+0x50/0x120
+ el0_svc_common.constprop.0+0xc8/0xf0
+ do_el0_svc+0x24/0x38
+ el0_svc+0x30/0xf8
+ el0t_64_sync_handler+0x120/0x130
+ el0t_64_sync+0x190/0x198
+
+INFO: task kworker/u8:11:2680853 blocked for more than 120 seconds.
+ Tainted: G O 6.12.41-g3fe07ddf05ab #1
+"echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
+task:kworker/u8:11 state:D stack:0 pid:2680853 tgid:2680853 ppid:2 flags:0x00000208
+Workqueue: writeback wb_workfn (flush-254:0)
+Call trace:
+ __switch_to+0xf4/0x158
+ __schedule+0x27c/0x908
+ schedule+0x3c/0x118
+ io_schedule+0x44/0x68
+ folio_wait_bit_common+0x174/0x370
+ __filemap_get_folio+0x214/0x348
+ pagecache_get_page+0x20/0x70
+ f2fs_get_read_data_page+0x150/0x3e8
+ f2fs_get_lock_data_page+0x2c/0x160
+ move_data_page+0x50/0x478
+ do_garbage_collect+0xd38/0x1528
+ f2fs_gc+0x240/0x7e0
+ f2fs_balance_fs+0x1a0/0x208
+ f2fs_write_single_data_page+0x6e4/0x730
+ f2fs_write_cache_pages+0x378/0x9b0
+ f2fs_write_data_pages+0x2e4/0x388
+ do_writepages+0x8c/0x2c8
+ __writeback_single_inode+0x4c/0x498
+ writeback_sb_inodes+0x234/0x4a8
+ __writeback_inodes_wb+0x58/0x118
+ wb_writeback+0x2f8/0x3c0
+ wb_workfn+0x2c4/0x508
+ process_one_work+0x180/0x408
+ worker_thread+0x258/0x368
+ kthread+0x118/0x128
+ ret_from_fork+0x10/0x200
+
+INFO: task kworker/u8:8:2641297 blocked for more than 120 seconds.
+ Tainted: G O 6.12.41-g3fe07ddf05ab #1
+"echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
+task:kworker/u8:8 state:D stack:0 pid:2641297 tgid:2641297 ppid:2 flags:0x00000208
+Workqueue: writeback wb_workfn (flush-254:0)
+Call trace:
+ __switch_to+0xf4/0x158
+ __schedule+0x27c/0x908
+ rt_mutex_schedule+0x30/0x60
+ __rt_mutex_slowlock_locked.constprop.0+0x460/0x8a8
+ rwbase_write_lock+0x24c/0x378
+ down_write+0x1c/0x30
+ f2fs_balance_fs+0x184/0x208
+ f2fs_write_inode+0xf4/0x328
+ __writeback_single_inode+0x370/0x498
+ writeback_sb_inodes+0x234/0x4a8
+ __writeback_inodes_wb+0x58/0x118
+ wb_writeback+0x2f8/0x3c0
+ wb_workfn+0x2c4/0x508
+ process_one_work+0x180/0x408
+ worker_thread+0x258/0x368
+ kthread+0x118/0x128
+ ret_from_fork+0x10/0x20
+
+INFO: task B:1902 blocked for more than 120 seconds.
+ Tainted: G O 6.12.41-g3fe07ddf05ab #1
+"echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
+task:B state:D stack:0 pid:1902 tgid:1626 ppid:1153 flags:0x0000020c
+Call trace:
+ __switch_to+0xf4/0x158
+ __schedule+0x27c/0x908
+ rt_mutex_schedule+0x30/0x60
+ __rt_mutex_slowlock_locked.constprop.0+0x460/0x8a8
+ rwbase_write_lock+0x24c/0x378
+ down_write+0x1c/0x30
+ f2fs_balance_fs+0x184/0x208
+ f2fs_map_blocks+0x94c/0x1110
+ f2fs_file_write_iter+0x228/0xb80
+ do_iter_readv_writev+0xf0/0x1e0
+ vfs_writev+0x138/0x2c8
+ do_writev+0x88/0x130
+ __arm64_sys_writev+0x28/0x40
+ invoke_syscall+0x50/0x120
+ el0_svc_common.constprop.0+0xc8/0xf0
+ do_el0_svc+0x24/0x38
+ el0_svc+0x30/0xf8
+ el0t_64_sync_handler+0x120/0x130
+ el0t_64_sync+0x190/0x198
+
+INFO: task sync:2769849 blocked for more than 120 seconds.
+ Tainted: G O 6.12.41-g3fe07ddf05ab #1
+"echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
+task:sync state:D stack:0 pid:2769849 tgid:2769849 ppid:736 flags:0x0000020c
+Call trace:
+ __switch_to+0xf4/0x158
+ __schedule+0x27c/0x908
+ schedule+0x3c/0x118
+ wb_wait_for_completion+0xb0/0xe8
+ sync_inodes_sb+0xc8/0x2b0
+ sync_inodes_one_sb+0x24/0x38
+ iterate_supers+0xa8/0x138
+ ksys_sync+0x54/0xc8
+ __arm64_sys_sync+0x18/0x30
+ invoke_syscall+0x50/0x120
+ el0_svc_common.constprop.0+0xc8/0xf0
+ do_el0_svc+0x24/0x38
+ el0_svc+0x30/0xf8
+ el0t_64_sync_handler+0x120/0x130
+ el0t_64_sync+0x190/0x198
+
+The root cause is a potential deadlock between the following tasks:
+
+kworker/u8:11 Thread A
+- f2fs_write_single_data_page
+ - f2fs_do_write_data_page
+ - folio_start_writeback(X)
+ - f2fs_outplace_write_data
+ - bio_add_folio(X)
+ - folio_unlock(X)
+ - truncate_inode_pages_range
+ - __filemap_get_folio(X, FGP_LOCK)
+ - truncate_inode_partial_folio(X)
+ - folio_wait_writeback(X)
+ - f2fs_balance_fs
+ - f2fs_gc
+ - do_garbage_collect
+ - move_data_page
+ - f2fs_get_lock_data_page
+ - __filemap_get_folio(X, FGP_LOCK)
+
+Both threads try to access folio X. Thread A holds the lock but waits
+for writeback, while kworker waits for the lock. This causes a deadlock.
+
+Other threads also enter D state, waiting for locks such as gc_lock and
+writepages.
+
+OPU/IPU DATA folio are all affected by this issue. To avoid such
+potential deadlocks, always commit these cached folios before
+triggering f2fs_gc() in f2fs_balance_fs().
+
+Suggested-by: Chao Yu <chao@kernel.org>
+Reviewed-by: Chao Yu <chao@kernel.org>
+Signed-off-by: Ruipeng Qi <ruipengqi3@gmail.com>
+Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
+Stable-dep-of: 8b4468ec023d ("f2fs: fix potential deadlock in gc_merge path of f2fs_balance_fs()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/f2fs/data.c | 29 +++++++++++++++++++++++++++++
+ fs/f2fs/f2fs.h | 1 +
+ fs/f2fs/segment.c | 8 ++++++++
+ 3 files changed, 38 insertions(+)
+
+--- a/fs/f2fs/data.c
++++ b/fs/f2fs/data.c
+@@ -943,6 +943,35 @@ void f2fs_submit_merged_ipu_write(struct
+ }
+ }
+
++void f2fs_submit_all_merged_ipu_writes(struct f2fs_sb_info *sbi)
++{
++ struct bio_entry *be, *tmp;
++ struct f2fs_bio_info *io;
++ enum temp_type temp;
++
++ for (temp = HOT; temp < NR_TEMP_TYPE; temp++) {
++ LIST_HEAD(list);
++
++ io = sbi->write_io[DATA] + temp;
++
++ /* A lockless list_empty() check is safe here: any bios from
++ * other kworkers that we miss will be submitted by those
++ * kworkers accordingly.
++ */
++ if (list_empty(&io->bio_list))
++ continue;
++
++ f2fs_down_write(&io->bio_list_lock);
++ list_splice_init(&io->bio_list, &list);
++ f2fs_up_write(&io->bio_list_lock);
++
++ list_for_each_entry_safe(be, tmp, &list, list) {
++ f2fs_submit_write_bio(sbi, be->bio, DATA);
++ del_bio_entry(be);
++ }
++ }
++}
++
+ int f2fs_merge_page_bio(struct f2fs_io_info *fio)
+ {
+ struct bio *bio = *fio->bio;
+--- a/fs/f2fs/f2fs.h
++++ b/fs/f2fs/f2fs.h
+@@ -4154,6 +4154,7 @@ void f2fs_submit_merged_write_folio(stru
+ struct folio *folio, enum page_type type);
+ void f2fs_submit_merged_ipu_write(struct f2fs_sb_info *sbi,
+ struct bio **bio, struct folio *folio);
++void f2fs_submit_all_merged_ipu_writes(struct f2fs_sb_info *sbi);
+ void f2fs_flush_merged_writes(struct f2fs_sb_info *sbi);
+ int f2fs_submit_page_bio(struct f2fs_io_info *fio);
+ int f2fs_merge_page_bio(struct f2fs_io_info *fio);
+--- a/fs/f2fs/segment.c
++++ b/fs/f2fs/segment.c
+@@ -462,6 +462,14 @@ void f2fs_balance_fs(struct f2fs_sb_info
+ .should_migrate_blocks = false,
+ .err_gc_skipped = false,
+ .nr_free_secs = 1 };
++
++ /*
++ * Submit all cached OPU/IPU DATA bios before triggering
++ * foreground GC to avoid potential deadlocks.
++ */
++ f2fs_submit_merged_write(sbi, DATA);
++ f2fs_submit_all_merged_ipu_writes(sbi);
++
+ f2fs_down_write_trace(&sbi->gc_lock, &gc_control.lc);
+ stat_inc_gc_call_count(sbi, FOREGROUND);
+ f2fs_gc(sbi, &gc_control);
--- /dev/null
+From stable+bounces-271804-greg=kroah.com@vger.kernel.org Fri Jul 3 16:35:31 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 3 Jul 2026 10:26:30 -0400
+Subject: f2fs: fix potential deadlock in gc_merge path of f2fs_balance_fs()
+To: stable@vger.kernel.org
+Cc: Chao Yu <chao@kernel.org>, stable@kernel.org, Ruipeng Qi <ruipengqi3@gmail.com>, Chao Yu <chaseyu@google.com>, Jaegeuk Kim <jaegeuk@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260703142630.55436-2-sashal@kernel.org>
+
+From: Chao Yu <chao@kernel.org>
+
+[ Upstream commit 8b4468ec023d0d1b4669dfb867588997cc03a06b ]
+
+When we mount device w/ gc_merge mount option, we may suffer below
+potential deadlock:
+
+Kworker GC trehad Truncator
+- f2fs_write_cache_pages
+ - f2fs_write_single_data_page
+ - f2fs_do_write_data_page
+ - folio_start_writeback --- set writeback flag on folio
+ - f2fs_outplace_write_data
+ : cached folio in internal bio cache
+ - f2fs_balance_fs
+ - wake_up(gc_thread)
+ : wake up gc thread to run foreground GC
+ - finish_wait(fggc_wq)
+ : wait on the waitqueue --- wait on GC thread to finish the work
+ - truncate_inode_pages_range
+ - __filemap_get_folio(, FGP_LOCK) --- lock folio
+ - truncate_inode_partial_folio
+ - folio_wait_writeback --- wait on writeback being cleared
+ - do_garbage_collect
+ - move_data_page
+ - f2fs_get_lock_data_folio
+ - lock on folio --- blocked on folio's lock
+
+In order to avoid such deadlock, let's call below functions to commit
+cached bios in GC_MERGE path of f2fs_balance_fs() as the same as we did
+in NOGC_MERGE path.
+- f2fs_submit_merged_write(sbi, DATA);
+- f2fs_submit_all_merged_ipu_writes(sbi);
+
+Cc: stable@kernel.org
+Fixes: 351df4b20115 ("f2fs: add segment operations")
+Cc: Ruipeng Qi <ruipengqi3@gmail.com>
+Reported: Sandeep Dhavale <dhavale@google.com>
+Signed-off-by: Chao Yu <chao@kernel.org>
+Signed-off-by: Chao Yu <chaseyu@google.com>
+Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/f2fs/segment.c | 14 +++++++-------
+ 1 file changed, 7 insertions(+), 7 deletions(-)
+
+--- a/fs/f2fs/segment.c
++++ b/fs/f2fs/segment.c
+@@ -444,6 +444,13 @@ void f2fs_balance_fs(struct f2fs_sb_info
+ if (has_enough_free_secs(sbi, 0, 0))
+ return;
+
++ /*
++ * Submit all cached OPU/IPU DATA bios before triggering
++ * foreground GC to avoid potential deadlocks.
++ */
++ f2fs_submit_merged_write(sbi, DATA);
++ f2fs_submit_all_merged_ipu_writes(sbi);
++
+ if (test_opt(sbi, GC_MERGE) && sbi->gc_thread &&
+ sbi->gc_thread->f2fs_gc_task) {
+ DEFINE_WAIT(wait);
+@@ -463,13 +470,6 @@ void f2fs_balance_fs(struct f2fs_sb_info
+ .err_gc_skipped = false,
+ .nr_free_secs = 1 };
+
+- /*
+- * Submit all cached OPU/IPU DATA bios before triggering
+- * foreground GC to avoid potential deadlocks.
+- */
+- f2fs_submit_merged_write(sbi, DATA);
+- f2fs_submit_all_merged_ipu_writes(sbi);
+-
+ f2fs_down_write_trace(&sbi->gc_lock, &gc_control.lc);
+ stat_inc_gc_call_count(sbi, FOREGROUND);
+ f2fs_gc(sbi, &gc_control);
--- /dev/null
+From stable+bounces-274106-greg=kroah.com@vger.kernel.org Tue Jul 14 05:33:02 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 13 Jul 2026 23:32:55 -0400
+Subject: firmware_loader: Add cancel helper for async requests
+To: stable@vger.kernel.org
+Cc: "Cássio Gabriel" <cassiogabrielcontato@gmail.com>, "Takashi Iwai" <tiwai@suse.de>, "Danilo Krummrich" <dakr@kernel.org>, "Sasha Levin" <sashal@kernel.org>
+Message-ID: <20260714033256.2396704-1-sashal@kernel.org>
+
+From: Cássio Gabriel <cassiogabrielcontato@gmail.com>
+
+[ Upstream commit b9bdd68b8b979c7e9de58b2e7d21e1d7d932c755 ]
+
+request_firmware_nowait() keeps the callback module pinned and holds
+a device reference until the firmware work completes.
+
+Callers still have no way to cancel or synchronize the queued callback
+before tearing down their driver-private state.
+
+Track scheduled async firmware work in an internal list and add
+request_firmware_nowait_cancel(). The helper cancels work matching the
+device, callback context and callback function. It cancels work that has
+not started yet and waits for an already-running callback to return. If
+the request has already completed, it is a no-op.
+
+Keep the existing request_firmware_nowait() lifetime model manual. A
+devres-managed variant can be layered on top separately if needed.
+
+Signed-off-by: Cássio Gabriel <cassiogabrielcontato@gmail.com>
+Reviewed-by: Takashi Iwai <tiwai@suse.de>
+Acked-by: Danilo Krummrich <dakr@kernel.org>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Link: https://patch.msgid.link/20260505-alsa-hda-tas2781-fw-callback-teardown-v4-1-e7c4bf930dc8@gmail.com
+Stable-dep-of: 5367e2ad14f0 ("ALSA: hda/tas2781: Cancel async firmware request at unbind")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/base/firmware_loader/main.c | 68 +++++++++++++++++++++++++++++++++---
+ include/linux/firmware.h | 10 +++++
+ 2 files changed, 74 insertions(+), 4 deletions(-)
+
+--- a/drivers/base/firmware_loader/main.c
++++ b/drivers/base/firmware_loader/main.c
+@@ -1132,6 +1132,7 @@ EXPORT_SYMBOL(release_firmware);
+ /* Async support */
+ struct firmware_work {
+ struct work_struct work;
++ struct list_head list;
+ struct module *module;
+ const char *name;
+ struct device *device;
+@@ -1140,6 +1141,17 @@ struct firmware_work {
+ u32 opt_flags;
+ };
+
++static LIST_HEAD(firmware_work_list);
++static DEFINE_SPINLOCK(firmware_work_lock);
++
++static void firmware_work_free(struct firmware_work *fw_work)
++{
++ put_device(fw_work->device); /* taken in request_firmware_nowait() */
++ module_put(fw_work->module);
++ kfree_const(fw_work->name);
++ kfree(fw_work);
++}
++
+ static void request_firmware_work_func(struct work_struct *work)
+ {
+ struct firmware_work *fw_work;
+@@ -1150,11 +1162,15 @@ static void request_firmware_work_func(s
+ _request_firmware(&fw, fw_work->name, fw_work->device, NULL, 0, 0,
+ fw_work->opt_flags);
+ fw_work->cont(fw, fw_work->context);
+- put_device(fw_work->device); /* taken in request_firmware_nowait() */
+
+- module_put(fw_work->module);
+- kfree_const(fw_work->name);
+- kfree(fw_work);
++ spin_lock_irq(&firmware_work_lock);
++ if (!list_empty(&fw_work->list)) {
++ list_del_init(&fw_work->list);
++ spin_unlock_irq(&firmware_work_lock);
++ firmware_work_free(fw_work);
++ return;
++ }
++ spin_unlock_irq(&firmware_work_lock);
+ }
+
+
+@@ -1164,6 +1180,7 @@ static int _request_firmware_nowait(
+ void (*cont)(const struct firmware *fw, void *context), bool nowarn)
+ {
+ struct firmware_work *fw_work;
++ unsigned long flags;
+
+ fw_work = kzalloc_obj(struct firmware_work, gfp);
+ if (!fw_work)
+@@ -1196,7 +1213,12 @@ static int _request_firmware_nowait(
+
+ get_device(fw_work->device);
+ INIT_WORK(&fw_work->work, request_firmware_work_func);
++
++ spin_lock_irqsave(&firmware_work_lock, flags);
++ list_add_tail(&fw_work->list, &firmware_work_list);
+ schedule_work(&fw_work->work);
++ spin_unlock_irqrestore(&firmware_work_lock, flags);
++
+ return 0;
+ }
+
+@@ -1259,6 +1281,44 @@ int firmware_request_nowait_nowarn(
+ }
+ EXPORT_SYMBOL_GPL(firmware_request_nowait_nowarn);
+
++/**
++ * request_firmware_nowait_cancel() - cancel an async firmware request
++ * @device: device for which the firmware is being loaded
++ * @context: context passed to request_firmware_nowait()
++ * @cont: callback passed to request_firmware_nowait()
++ *
++ * Cancel a pending request_firmware_nowait() request for @device, @context
++ * and @cont. If the associated work has already started, this function waits
++ * until the callback has returned. If the callback has already completed, this
++ * function does nothing.
++ *
++ * This function may sleep.
++ */
++void request_firmware_nowait_cancel(struct device *device, void *context,
++ void (*cont)(const struct firmware *fw,
++ void *context))
++{
++ struct firmware_work *fw_work = NULL;
++ struct firmware_work *tmp;
++
++ spin_lock_irq(&firmware_work_lock);
++ list_for_each_entry_reverse(tmp, &firmware_work_list, list) {
++ if (tmp->device == device && tmp->context == context &&
++ tmp->cont == cont) {
++ fw_work = tmp;
++ list_del_init(&fw_work->list);
++ break;
++ }
++ }
++ spin_unlock_irq(&firmware_work_lock);
++
++ if (!fw_work)
++ return;
++ cancel_work_sync(&fw_work->work);
++ firmware_work_free(fw_work);
++}
++EXPORT_SYMBOL_GPL(request_firmware_nowait_cancel);
++
+ #ifdef CONFIG_FW_CACHE
+ static ASYNC_DOMAIN_EXCLUSIVE(fw_cache_domain);
+
+--- a/include/linux/firmware.h
++++ b/include/linux/firmware.h
+@@ -110,6 +110,9 @@ int request_firmware_nowait(
+ struct module *module, bool uevent,
+ const char *name, struct device *device, gfp_t gfp, void *context,
+ void (*cont)(const struct firmware *fw, void *context));
++void request_firmware_nowait_cancel(struct device *device, void *context,
++ void (*cont)(const struct firmware *fw,
++ void *context));
+ int request_firmware_direct(const struct firmware **fw, const char *name,
+ struct device *device);
+ int request_firmware_into_buf(const struct firmware **firmware_p,
+@@ -157,6 +160,13 @@ static inline int request_firmware_nowai
+ return -EINVAL;
+ }
+
++static inline void request_firmware_nowait_cancel(struct device *device,
++ void *context,
++ void (*cont)(const struct firmware *fw,
++ void *context))
++{
++}
++
+ static inline void release_firmware(const struct firmware *fw)
+ {
+ }
--- /dev/null
+From stable+bounces-273928-greg=kroah.com@vger.kernel.org Mon Jul 13 19:54:51 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 13 Jul 2026 13:53:24 -0400
+Subject: iio: hid-sensor-rotation: Fix stale or zero output when reading raw values
+To: stable@vger.kernel.org
+Cc: Zhang Lixu <lixu.zhang@intel.com>, Andy Shevchenko <andriy.shevchenko@intel.com>, Stable@vger.kernel.org, Jonathan Cameron <jic23@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260713175324.1902799-2-sashal@kernel.org>
+
+From: Zhang Lixu <lixu.zhang@intel.com>
+
+[ Upstream commit 3ce8d099e0afc5a7da75a2007a67f67c4f5a4af1 ]
+
+When reading the raw quaternion attribute (in_rot_quaternion_raw), the
+driver currently returns either all zeros (if the sensor was never enabled)
+or stale data (if the sensor was previously enabled) because it reads from
+the internal buffer without explicitly requesting a new sample from the
+sensor.
+
+To fix this, power up the sensor, call sensor_hub_input_attr_read_values()
+to issue a synchronous GET_REPORT and receive the full quaternion data
+directly into a local buffer, then decode the four components.
+
+Fixes: fc18dddc0625 ("iio: hid-sensors: Added device rotation support")
+Signed-off-by: Zhang Lixu <lixu.zhang@intel.com>
+Reviewed-by: Andy Shevchenko <andriy.shevchenko@intel.com>
+Cc: <Stable@vger.kernel.org>
+Signed-off-by: Jonathan Cameron <jic23@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/iio/orientation/hid-sensor-rotation.c | 40 ++++++++++++++++++++++++--
+ 1 file changed, 38 insertions(+), 2 deletions(-)
+
+--- a/drivers/iio/orientation/hid-sensor-rotation.c
++++ b/drivers/iio/orientation/hid-sensor-rotation.c
+@@ -74,6 +74,13 @@ static int dev_rot_read_raw(struct iio_d
+ long mask)
+ {
+ struct dev_rot_state *rot_state = iio_priv(indio_dev);
++ struct hid_sensor_hub_device *hsdev = rot_state->common_attributes.hsdev;
++ struct hid_sensor_hub_attribute_info *info = &rot_state->quaternion;
++ u32 usage_id = HID_USAGE_SENSOR_ORIENT_QUATERNION;
++ union {
++ s16 val16[4];
++ s32 val32[4];
++ } raw_buf;
+ int ret_type;
+ int i;
+
+@@ -83,8 +90,37 @@ static int dev_rot_read_raw(struct iio_d
+ switch (mask) {
+ case IIO_CHAN_INFO_RAW:
+ if (size >= 4) {
+- for (i = 0; i < 4; ++i)
+- vals[i] = rot_state->scan.sampled_vals[i];
++ if (info->size <= 0 || info->size > sizeof(raw_buf))
++ return -EINVAL;
++
++ hid_sensor_power_state(&rot_state->common_attributes, true);
++
++ ret_type = sensor_hub_input_attr_read_values(hsdev,
++ hsdev->usage,
++ usage_id,
++ info->report_id,
++ SENSOR_HUB_SYNC,
++ info->size,
++ (u8 *)&raw_buf);
++
++ hid_sensor_power_state(&rot_state->common_attributes, false);
++
++ if (ret_type < 0)
++ return ret_type;
++
++ switch (info->size) {
++ case sizeof(raw_buf.val16):
++ for (i = 0; i < ARRAY_SIZE(raw_buf.val16); i++)
++ vals[i] = raw_buf.val16[i];
++ break;
++ case sizeof(raw_buf.val32):
++ for (i = 0; i < ARRAY_SIZE(raw_buf.val32); i++)
++ vals[i] = raw_buf.val32[i];
++ break;
++ default:
++ return -EINVAL;
++ }
++
+ ret_type = IIO_VAL_INT_MULTIPLE;
+ *val_len = 4;
+ } else
--- /dev/null
+From stable+bounces-275120-greg=kroah.com@vger.kernel.org Thu Jul 16 03:45:28 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 15 Jul 2026 21:45:17 -0400
+Subject: ksmbd: fix path resolution in ksmbd_vfs_kern_path_create
+To: stable@vger.kernel.org
+Cc: Davide Ornaghi <d.ornaghi97@gmail.com>, Namjae Jeon <linkinjeon@kernel.org>, Steve French <stfrench@microsoft.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260716014517.777818-1-sashal@kernel.org>
+
+From: Davide Ornaghi <d.ornaghi97@gmail.com>
+
+[ Upstream commit 1c8951963d8ed357f70f59e0ad4ddce2199d2016 ]
+
+The SMB2 open lookup is rooted at the share with LOOKUP_BENEATH, but the
+create/mkdir/hardlink sink is not: ksmbd_vfs_kern_path_create() builds an
+absolute path with convert_to_unix_name() and resolves it from AT_FDCWD
+via start_creating_path(), so a ".." component is walked from the real
+filesystem root and escapes the export.
+
+An authenticated client races a missing path component so the rooted open
+lookup returns -ENOENT (taking the create branch) while the same component
+is present (a directory) when the create walk runs; the create then
+resolves ".." out of the share.
+
+Root the create walk at the share like the lookup and rename paths already
+are: resolve the parent with vfs_path_parent_lookup(..., LOOKUP_BENEATH,
+&share_conf->vfs_path) and create the final component with
+start_creating_noperm(). convert_to_unix_name() then has no callers and is
+removed.
+
+Fixes: 265fd1991c1d ("ksmbd: use LOOKUP_BENEATH to prevent the out of share access")
+Cc: stable@vger.kernel.org
+Signed-off-by: Davide Ornaghi <d.ornaghi97@gmail.com>
+Acked-by: Namjae Jeon <linkinjeon@kernel.org>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/smb/server/misc.c | 33 ---------------------------------
+ fs/smb/server/misc.h | 1 -
+ fs/smb/server/vfs.c | 33 +++++++++++++++++++++++++++------
+ 3 files changed, 27 insertions(+), 40 deletions(-)
+
+--- a/fs/smb/server/misc.c
++++ b/fs/smb/server/misc.c
+@@ -283,39 +283,6 @@ char *ksmbd_extract_sharename(struct uni
+ return ksmbd_casefold_sharename(um, name);
+ }
+
+-/**
+- * convert_to_unix_name() - convert windows name to unix format
+- * @share: ksmbd_share_config pointer
+- * @name: file name that is relative to share
+- *
+- * Return: converted name on success, otherwise NULL
+- */
+-char *convert_to_unix_name(struct ksmbd_share_config *share, const char *name)
+-{
+- int no_slash = 0, name_len, path_len;
+- char *new_name;
+-
+- if (name[0] == '/')
+- name++;
+-
+- path_len = share->path_sz;
+- name_len = strlen(name);
+- new_name = kmalloc(path_len + name_len + 2, KSMBD_DEFAULT_GFP);
+- if (!new_name)
+- return new_name;
+-
+- memcpy(new_name, share->path, path_len);
+- if (new_name[path_len - 1] != '/') {
+- new_name[path_len] = '/';
+- no_slash = 1;
+- }
+-
+- memcpy(new_name + path_len + no_slash, name, name_len);
+- path_len += name_len + no_slash;
+- new_name[path_len] = 0x00;
+- return new_name;
+-}
+-
+ char *ksmbd_convert_dir_info_name(struct ksmbd_dir_info *d_info,
+ const struct nls_table *local_nls,
+ int *conv_len)
+--- a/fs/smb/server/misc.h
++++ b/fs/smb/server/misc.h
+@@ -25,7 +25,6 @@ void ksmbd_strip_last_slash(char *path);
+ void ksmbd_conv_path_to_windows(char *path);
+ char *ksmbd_casefold_sharename(struct unicode_map *um, const char *name);
+ char *ksmbd_extract_sharename(struct unicode_map *um, const char *treename);
+-char *convert_to_unix_name(struct ksmbd_share_config *share, const char *name);
+
+ #define KSMBD_DIR_INFO_ALIGNMENT 8
+ struct ksmbd_dir_info;
+--- a/fs/smb/server/vfs.c
++++ b/fs/smb/server/vfs.c
+@@ -1261,15 +1261,36 @@ struct dentry *ksmbd_vfs_kern_path_creat
+ unsigned int flags,
+ struct path *path)
+ {
+- char *abs_name;
++ struct ksmbd_share_config *share_conf = work->tcon->share_conf;
++ struct qstr last;
+ struct dentry *dent;
++ int err, type;
+
+- abs_name = convert_to_unix_name(work->tcon->share_conf, name);
+- if (!abs_name)
+- return ERR_PTR(-ENOMEM);
++ /* resolve the name beneath the share root so ".." cannot escape */
++ CLASS(filename_kernel, filename)(name);
+
+- dent = start_creating_path(AT_FDCWD, abs_name, path, flags);
+- kfree(abs_name);
++ err = vfs_path_parent_lookup(filename, flags | LOOKUP_BENEATH,
++ path, &last, &type,
++ &share_conf->vfs_path);
++ if (err)
++ return ERR_PTR(err);
++
++ if (unlikely(type != LAST_NORM)) {
++ path_put(path);
++ return ERR_PTR(-EINVAL);
++ }
++
++ err = mnt_want_write(path->mnt);
++ if (err) {
++ path_put(path);
++ return ERR_PTR(err);
++ }
++
++ dent = start_creating_noperm(path->dentry, &last);
++ if (IS_ERR(dent)) {
++ mnt_drop_write(path->mnt);
++ path_put(path);
++ }
+ return dent;
+ }
+
--- /dev/null
+From stable+bounces-275125-greg=kroah.com@vger.kernel.org Thu Jul 16 04:06:24 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 15 Jul 2026 22:05:58 -0400
+Subject: ksmbd: use opener credentials for FSCTL mutations
+To: stable@vger.kernel.org
+Cc: Namjae Jeon <linkinjeon@kernel.org>, Musaab Khan <musaab.khan@protonmail.com>, Steve French <stfrench@microsoft.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260716020558.818894-2-sashal@kernel.org>
+
+From: Namjae Jeon <linkinjeon@kernel.org>
+
+[ Upstream commit c6394bcaf254c5baf9aff43376020be5db6d3316 ]
+
+SET_SPARSE, SET_ZERO_DATA and SET_COMPRESSION operate on an open SMB
+handle but call VFS xattr, fallocate or fileattr helpers with the current
+ksmbd worker credentials. Those helpers can revalidate inode permissions,
+ownership and LSM policy independently of the SMB handle access mask.
+
+Run each operation with the credentials captured in the target file when
+the handle was opened. Keep credential handling local to these single-file
+FSCTLs rather than applying session credentials to the complete IOCTL
+handler, which also contains handle-less and multi-handle operations.
+
+Cc: stable@vger.kernel.org
+Reported-by: Musaab Khan <musaab.khan@protonmail.com>
+Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/smb/server/smb2pdu.c | 3 +++
+ fs/smb/server/vfs.c | 20 +++++++++++++-------
+ 2 files changed, 16 insertions(+), 7 deletions(-)
+
+--- a/fs/smb/server/smb2pdu.c
++++ b/fs/smb/server/smb2pdu.c
+@@ -8320,6 +8320,7 @@ static inline int fsctl_set_sparse(struc
+ if (fp->f_ci->m_fattr != old_fattr &&
+ test_share_config_flag(work->tcon->share_conf,
+ KSMBD_SHARE_FLAG_STORE_DOS_ATTRS)) {
++ const struct cred *saved_cred;
+ struct xattr_dos_attrib da;
+
+ ret = ksmbd_vfs_get_dos_attrib_xattr(idmap,
+@@ -8328,9 +8329,11 @@ static inline int fsctl_set_sparse(struc
+ goto out;
+
+ da.attr = le32_to_cpu(fp->f_ci->m_fattr);
++ saved_cred = override_creds(fp->filp->f_cred);
+ ret = ksmbd_vfs_set_dos_attrib_xattr(idmap,
+ &fp->filp->f_path,
+ &da, true);
++ revert_creds(saved_cred);
+ if (ret)
+ fp->f_ci->m_fattr = old_fattr;
+ }
+--- a/fs/smb/server/vfs.c
++++ b/fs/smb/server/vfs.c
+@@ -926,15 +926,21 @@ void ksmbd_vfs_set_fadvise(struct file *
+ int ksmbd_vfs_zero_data(struct ksmbd_work *work, struct ksmbd_file *fp,
+ loff_t off, loff_t len)
+ {
++ const struct cred *saved_cred;
++ int err;
++
+ smb_break_all_levII_oplock(work, fp, 1);
++ saved_cred = override_creds(fp->filp->f_cred);
+ if (fp->f_ci->m_fattr & FILE_ATTRIBUTE_SPARSE_FILE_LE)
+- return vfs_fallocate(fp->filp,
+- FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
+- off, len);
+-
+- return vfs_fallocate(fp->filp,
+- FALLOC_FL_ZERO_RANGE | FALLOC_FL_KEEP_SIZE,
+- off, len);
++ err = vfs_fallocate(fp->filp,
++ FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
++ off, len);
++ else
++ err = vfs_fallocate(fp->filp,
++ FALLOC_FL_ZERO_RANGE | FALLOC_FL_KEEP_SIZE,
++ off, len);
++ revert_creds(saved_cred);
++ return err;
+ }
+
+ int ksmbd_vfs_fqar_lseek(struct ksmbd_file *fp, loff_t start, loff_t length,
--- /dev/null
+From stable+bounces-278284-greg=kroah.com@vger.kernel.org Tue Jul 21 02:45:22 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 20 Jul 2026 20:45:13 -0400
+Subject: liveupdate: validate session type before performing operation
+To: stable@vger.kernel.org
+Cc: "Pratyush Yadav (Google)" <pratyush@kernel.org>, "Mike Rapoport (Microsoft)" <rppt@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260721004514.3421718-1-sashal@kernel.org>
+
+From: "Pratyush Yadav (Google)" <pratyush@kernel.org>
+
+[ Upstream commit 507e3b479f9c6d85135eb5e1a77fb3fddb259ad8 ]
+
+The sessions ioctls are not applicable to all session types. PRESERVE_FD
+is only applicable to outgoing sessions. RETRIEVE_FD and FINISH are only
+valid for incoming session. Calling a incoming ioctl on an outgoing
+session is invalid and can cause file handlers to run into unexpected
+errors.
+
+For example, a user can create a (outgoing) session, preserve a memfd,
+and then immediately do a retrieve without doing a kexec in between.
+This would result in memfd's retrieve handler to run. The handlers
+expects to be called from a post-kexec context, and will try to do a
+kho_restore_vmalloc() or kho_restore_folio() to try and restore memory.
+
+KHO catches this (thanks to KHO_PAGE_MAGIC) and returns an error, but
+since this is considered an internal error and KHO throws out a bunch of
+WARN()s.
+
+Associate a type with each ioctl op and validate the type in
+luo_session_ioctl() before dispatching the ioctl handler to make sure
+the op is being called for the right session type.
+
+Fixes: 16cec0d26521 ("liveupdate: luo_session: add ioctls for file preservation")
+Cc: stable@vger.kernel.org
+Signed-off-by: Pratyush Yadav (Google) <pratyush@kernel.org>
+Link: https://patch.msgid.link/20260519122428.2378446-1-pratyush@kernel.org
+Signed-off-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ kernel/liveupdate/luo_session.c | 37 ++++++++++++++++++++++++++++++++-----
+ 1 file changed, 32 insertions(+), 5 deletions(-)
+
+--- a/kernel/liveupdate/luo_session.c
++++ b/kernel/liveupdate/luo_session.c
+@@ -330,32 +330,58 @@ union ucmd_buffer {
+ struct liveupdate_session_retrieve_fd retrieve;
+ };
+
++/* Type of sessions the ioctl applies to. */
++enum luo_ioctl_type {
++ LUO_IOCTL_INCOMING,
++ LUO_IOCTL_OUTGOING,
++ LUO_IOCTL_ALL,
++};
++
+ struct luo_ioctl_op {
+ unsigned int size;
+ unsigned int min_size;
+ unsigned int ioctl_num;
++ enum luo_ioctl_type type;
+ int (*execute)(struct luo_session *session, struct luo_ucmd *ucmd);
+ };
+
+-#define IOCTL_OP(_ioctl, _fn, _struct, _last) \
++#define IOCTL_OP(_ioctl, _fn, _struct, _last, _type) \
+ [_IOC_NR(_ioctl) - LIVEUPDATE_CMD_SESSION_BASE] = { \
+ .size = sizeof(_struct) + \
+ BUILD_BUG_ON_ZERO(sizeof(union ucmd_buffer) < \
+ sizeof(_struct)), \
+ .min_size = offsetofend(_struct, _last), \
+ .ioctl_num = _ioctl, \
++ .type = _type, \
+ .execute = _fn, \
+ }
+
+ static const struct luo_ioctl_op luo_session_ioctl_ops[] = {
+ IOCTL_OP(LIVEUPDATE_SESSION_FINISH, luo_session_finish,
+- struct liveupdate_session_finish, reserved),
++ struct liveupdate_session_finish, reserved, LUO_IOCTL_INCOMING),
+ IOCTL_OP(LIVEUPDATE_SESSION_PRESERVE_FD, luo_session_preserve_fd,
+- struct liveupdate_session_preserve_fd, token),
++ struct liveupdate_session_preserve_fd, token, LUO_IOCTL_OUTGOING),
+ IOCTL_OP(LIVEUPDATE_SESSION_RETRIEVE_FD, luo_session_retrieve_fd,
+- struct liveupdate_session_retrieve_fd, token),
++ struct liveupdate_session_retrieve_fd, token, LUO_IOCTL_INCOMING),
+ };
+
++static bool luo_ioctl_type_valid(struct luo_session *session,
++ const struct luo_ioctl_op *op)
++{
++ switch (op->type) {
++ case LUO_IOCTL_INCOMING:
++ /* Retrieved is only set on incoming sessions */
++ return session->retrieved;
++ case LUO_IOCTL_OUTGOING:
++ return !session->retrieved;
++ case LUO_IOCTL_ALL:
++ return true;
++ }
++
++ /* Catch-all. */
++ return false;
++}
++
+ static long luo_session_ioctl(struct file *filep, unsigned int cmd,
+ unsigned long arg)
+ {
+@@ -380,6 +406,8 @@ static long luo_session_ioctl(struct fil
+ op = &luo_session_ioctl_ops[nr - LIVEUPDATE_CMD_SESSION_BASE];
+ if (op->ioctl_num != cmd)
+ return -ENOIOCTLCMD;
++ if (!luo_ioctl_type_valid(session, op))
++ return -EINVAL;
+ if (ucmd.user_size < op->min_size)
+ return -EINVAL;
+
+@@ -659,4 +687,3 @@ err_undo:
+
+ return err;
+ }
+-
--- /dev/null
+From 7e6cc35f5283eab81a14231a64ecd640b690c48c Mon Sep 17 00:00:00 2001
+From: SeongJae Park <sj@kernel.org>
+Date: Wed, 20 May 2026 08:03:10 -0700
+Subject: mm/damon/core: trace esz at first setup
+
+From: SeongJae Park <sj@kernel.org>
+
+commit 7e6cc35f5283eab81a14231a64ecd640b690c48c upstream.
+
+DAMON traces effective size quota from the second update, only if a change
+has been made by the update. Tracing only changed updates was an
+intentional decision to avoid unnecessary same value tracing. Always
+skipping the first value is just an unintended mistake.
+
+The mistake makes the tracepoint based investigation incomplete, because
+the first effective size quota is never traced. It is not a big issue
+when the 'consist' quota tuner is used, because it keeps changing the
+quota in the usual setup.
+
+However, when the 'temporal' tuner is used, the quota value is not changed
+before the goal achievement status is completely changed. For example, if
+the DAMOS scheme is started with an under-achieved goal, the quota is set
+to the maximum value, and kept the same value until the goal is achieved.
+Because DAMON skips the first value, the user cannot know what effective
+quota the current scheme is using. Only after the goal is achieved, the
+effective quota is changed to zero, and traced.
+
+Unconditionally trace the initial quota value to fix this problem.
+
+Note that the 'temporal' quota tuner was introduced by commit af738a6a00c1
+("mm/damon/core: introduce DAMOS_QUOTA_GOAL_TUNER_TEMPORAL"), which was
+added to 7.1-rc1. But even with the 'consist' quota tuner, the tracing is
+unintentionally incomplete. Hence this commit marks the introduction of
+the trace event as the broken commit.
+
+Link: https://lore.kernel.org/20260520150311.80925-1-sj@kernel.org
+Fixes: a86d695193bf ("mm/damon: add trace event for effective size quota")
+Signed-off-by: SeongJae Park <sj@kernel.org>
+Cc: <stable@vger.kernel.org> # 6.17.x
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: SJ Park <sj@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ mm/damon/core.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/mm/damon/core.c
++++ b/mm/damon/core.c
+@@ -2492,6 +2492,8 @@ static void damos_adjust_quota(struct da
+ if (!quota->total_charged_sz && !quota->charged_from) {
+ quota->charged_from = jiffies;
+ damos_set_effective_quota(quota, c);
++ if (trace_damos_esz_enabled())
++ damos_trace_esz(c, s, quota);
+ }
+
+ /* New charge window starts */
--- /dev/null
+From 7746d72c64054976887928d64d2caf25c5a6dcc0 Mon Sep 17 00:00:00 2001
+From: Zenghui Yu <yuzenghui@huawei.com>
+Date: Mon, 29 Jun 2026 07:44:31 -0700
+Subject: samples/damon/mtier: fail early if address range parameters are invalid
+
+From: Zenghui Yu <yuzenghui@huawei.com>
+
+commit 7746d72c64054976887928d64d2caf25c5a6dcc0 upstream.
+
+The comment on top of `struct damon_region` clearly says that
+
+ For any use case, @ar should be non-zero positive size.
+
+which is now verified in damon_verify_new_region() if the kernel is built
+with DAMON_DEBUG_SANITY.
+
+The WARN_ONCE() can be triggered if the mtier sample module is enabled
+before node{0,1}_{start,end}_addr have been properly initialized, which is
+obviously not good.
+
+ ------------[ cut here ]------------
+ start 0 >= end 0
+ WARNING: mm/damon/core.c:217 at damon_new_region+0xf4/0x118, CPU#59: bash/341468
+ Call trace:
+ damon_new_region+0xf4/0x118 (P)
+ damon_set_regions+0xfc/0x3c0
+ damon_sample_mtier_build_ctx+0xe8/0x3a8
+ damon_sample_mtier_start+0x1c/0x90
+ damon_sample_mtier_enable_store+0x98/0xb0
+ param_attr_store+0xb4/0x128
+ module_attr_store+0x2c/0x50
+ sysfs_kf_write+0x58/0x90
+ kernfs_fop_write_iter+0x16c/0x238
+ vfs_write+0x2c0/0x370
+ ksys_write+0x74/0x118
+ __arm64_sys_write+0x24/0x38
+ invoke_syscall+0xa8/0x118
+ el0_svc_common.constprop.0+0x48/0xf0
+ do_el0_svc+0x24/0x38
+ el0_svc+0x54/0x370
+ el0t_64_sync_handler+0xa0/0xe8
+ el0t_64_sync+0x1ac/0x1b0
+ ---[ end trace 0000000000000000 ]---
+
+Note that the same issue can happen if detect_node_addresses is true, and
+node 0 or 1 is memoryless. Fix it together by checking the validity of
+parameters right before damon_new_region() and fail early if they're
+invalid.
+
+Link: https://lore.kernel.org/20260629144432.133962-1-sj@kernel.org
+Fixes: 82a08bde3cf7 ("samples/damon: implement a DAMON module for memory tiering")
+Signed-off-by: Zenghui Yu <yuzenghui@huawei.com>
+Signed-off-by: SJ Park <sj@kernel.org>
+Reviewed-by: SJ Park <sj@kernel.org>
+Cc: <stable@vger.kernel.org> # 6.16.x
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: SJ Park <sj@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ samples/damon/mtier.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/samples/damon/mtier.c
++++ b/samples/damon/mtier.c
+@@ -120,6 +120,9 @@ static struct damon_ctx *damon_sample_mt
+ addr.end = promote ? node1_end_addr : node0_end_addr;
+ }
+
++ if (addr.start >= addr.end)
++ goto free_out;
++
+ region = damon_new_region(addr.start, addr.end);
+ if (!region)
+ goto free_out;
mmc-sdhci-esdhc-imx-use-pm_runtime_resume_and_get-in-suspend.patch
mmc-sdhci-esdhc-imx-make-non-fatal-errors-non-blocking-in-suspend.patch
mmc-sdhci-esdhc-imx-fix-resume-error-handling.patch
+bpf-reject-negative-const-offsets-for-buffer-pointers.patch
+mm-damon-core-trace-esz-at-first-setup.patch
+samples-damon-mtier-fail-early-if-address-range-parameters-are-invalid.patch
+device-property-initialize-the-remaining-fields-of-fwnode_handle-in-fwnode_init.patch
+f2fs-fix-potential-deadlock-in-f2fs_balance_fs.patch
+f2fs-fix-potential-deadlock-in-gc_merge-path-of-f2fs_balance_fs.patch
+f2fs-fix-listxattr-handling-of-corrupted-xattr-entries.patch
+iio-hid-sensor-rotation-fix-stale-or-zero-output-when-reading-raw-values.patch
+alsa-scarlett2-allow-selecting-config_set-by-firmware-version.patch
+alsa-scarlett2-update-offsets-for-2i2-gen-4-firmware-2417.patch
+firmware_loader-add-cancel-helper-for-async-requests.patch
+alsa-hda-tas2781-cancel-async-firmware-request-at-unbind.patch
+binder-use-list_head-to-initialize-on-stack-list-head.patch
+binder-cache-secctx-size-before-release-zeroes-it.patch
+bluetooth-6lowpan-fix-cyclic-locking-warning-on-netdev-unregister.patch
+bluetooth-l2cap-fix-use-after-free-in-l2cap_sock_new_connection_cb.patch
+ksmbd-fix-path-resolution-in-ksmbd_vfs_kern_path_create.patch
+smb-move-compression-definitions-into-common-fscc.h.patch
+ksmbd-use-opener-credentials-for-fsctl-mutations.patch
+xfs-factor-out-a-xfs_zone_mark_free-helper.patch
+xfs-add-newly-added-rtgs-to-the-free-pool-in-growfs.patch
+usb-atm-ueagle-atm-use-dev_dbg-for-device-found-message.patch
+usb-atm-ueagle-atm-remove-function-entry-exit-debug-messages.patch
+usb-atm-ueagle-atm-wait-for-pre-firmware-load-in-.disconnect.patch
+liveupdate-validate-session-type-before-performing-operation.patch
--- /dev/null
+From stable+bounces-275124-greg=kroah.com@vger.kernel.org Thu Jul 16 04:06:08 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 15 Jul 2026 22:05:57 -0400
+Subject: smb: move compression definitions into common/fscc.h
+To: stable@vger.kernel.org
+Cc: ChenXiaoSong <chenxiaosong@kylinos.cn>, Namjae Jeon <linkinjeon@kernel.org>, Steve French <stfrench@microsoft.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260716020558.818894-1-sashal@kernel.org>
+
+From: ChenXiaoSong <chenxiaosong@kylinos.cn>
+
+[ Upstream commit 9d357903ec9b0da60cccc4d311f99763ba0924a2 ]
+
+These definitions will also be used by ksmbd, move them into
+common header file.
+
+Signed-off-by: ChenXiaoSong <chenxiaosong@kylinos.cn>
+Acked-by: Namjae Jeon <linkinjeon@kernel.org>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+Stable-dep-of: c6394bcaf254 ("ksmbd: use opener credentials for FSCTL mutations")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/smb/client/smb1pdu.h | 5 -----
+ fs/smb/client/smb2pdu.h | 4 ----
+ fs/smb/common/fscc.h | 18 ++++++++++++++++++
+ fs/smb/server/smb2pdu.h | 3 ---
+ 4 files changed, 18 insertions(+), 12 deletions(-)
+
+--- a/fs/smb/client/smb1pdu.h
++++ b/fs/smb/client/smb1pdu.h
+@@ -1211,11 +1211,6 @@ typedef struct smb_com_transaction_compr
+ __le16 compression_state; /* See below for valid flags */
+ } __packed TRANSACT_COMPR_IOCTL_REQ;
+
+-/* compression state flags */
+-#define COMPRESSION_FORMAT_NONE 0x0000
+-#define COMPRESSION_FORMAT_DEFAULT 0x0001
+-#define COMPRESSION_FORMAT_LZNT1 0x0002
+-
+ typedef struct smb_com_transaction_ioctl_rsp {
+ struct smb_hdr hdr; /* wct = 19 */
+ __u8 Reserved[3];
+--- a/fs/smb/client/smb2pdu.h
++++ b/fs/smb/client/smb2pdu.h
+@@ -195,10 +195,6 @@ struct network_resiliency_req {
+
+ #define NO_FILE_ID 0xFFFFFFFFFFFFFFFFULL /* general ioctls to srv not to file */
+
+-struct compress_ioctl {
+- __le16 CompressionState; /* See cifspdu.h for possible flag values */
+-} __packed;
+-
+ /*
+ * Maximum number of iovs we need for an ioctl request.
+ * [0] : struct smb2_ioctl_req
+--- a/fs/smb/common/fscc.h
++++ b/fs/smb/common/fscc.h
+@@ -100,6 +100,24 @@ struct duplicate_extents_to_file_ex {
+ __le32 Reserved;
+ } __packed;
+
++/*
++ * compression state flags
++ * See MS-FSCC 2.3.18
++ * MS-FSCC 2.3.67
++ * MS-FSCC 2.4.9
++ */
++#define COMPRESSION_FORMAT_NONE 0x0000
++#define COMPRESSION_FORMAT_DEFAULT 0x0001
++#define COMPRESSION_FORMAT_LZNT1 0x0002
++
++/*
++ * See MS-FSCC 2.3.18
++ * MS-FSCC 2.3.67
++ */
++struct compress_ioctl {
++ __le16 CompressionState;
++} __packed;
++
+ /* See MS-FSCC 2.3.20 */
+ struct fsctl_get_integrity_information_rsp {
+ __le16 ChecksumAlgorithm;
+--- a/fs/smb/server/smb2pdu.h
++++ b/fs/smb/server/smb2pdu.h
+@@ -230,9 +230,6 @@ struct smb2_file_mode_info {
+ __le32 Mode;
+ } __packed;
+
+-#define COMPRESSION_FORMAT_NONE 0x0000
+-#define COMPRESSION_FORMAT_LZNT1 0x0002
+-
+ struct smb2_file_comp_info {
+ __le64 CompressedFileSize;
+ __le16 CompressionFormat;
--- /dev/null
+From stable+bounces-277393-greg=kroah.com@vger.kernel.org Sat Jul 18 23:50:41 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 18 Jul 2026 17:50:32 -0400
+Subject: usb: atm: ueagle-atm: remove function entry/exit debug messages
+To: stable@vger.kernel.org
+Cc: Mauricio Faria de Oliveira <mfo@igalia.com>, Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Stanislaw Gruszka <stf_xl@wp.pl>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260718215033.3447737-2-sashal@kernel.org>
+
+From: Mauricio Faria de Oliveira <mfo@igalia.com>
+
+[ Upstream commit 1414b2242c2e9d670c4d8b83480f13db57627ba9 ]
+
+Remove the driver-internal function entry/exit debug messages
+in favor of existing kernel-level function tracing mechanisms.
+
+Suggested-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Link: https://lore.kernel.org/all/2026051657-scruffy-embark-45ea@gregkh/
+Signed-off-by: Mauricio Faria de Oliveira <mfo@igalia.com>
+Acked-by: Stanislaw Gruszka <stf_xl@wp.pl>
+Link: https://patch.msgid.link/20260520-ueagle-atm-cleanup-v1-2-010c8bc7b214@igalia.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Stable-dep-of: e2674dfbed8a ("usb: atm: ueagle-atm: wait for pre-firmware load in .disconnect()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/atm/ueagle-atm.c | 56 ++++---------------------------------------
+ 1 file changed, 6 insertions(+), 50 deletions(-)
+
+--- a/drivers/usb/atm/ueagle-atm.c
++++ b/drivers/usb/atm/ueagle-atm.c
+@@ -51,12 +51,6 @@
+ "[ueagle-atm vdbg] " format, ##args); \
+ } while (0)
+
+-#define uea_enters(usb_dev) \
+- uea_vdbg(usb_dev, "entering %s\n" , __func__)
+-
+-#define uea_leaves(usb_dev) \
+- uea_vdbg(usb_dev, "leaving %s\n" , __func__)
+-
+ #define uea_err(usb_dev, format, args...) \
+ dev_err(&(usb_dev)->dev , "[UEAGLE-ATM] " format , ##args)
+
+@@ -606,7 +600,6 @@ static void uea_upload_pre_firmware(cons
+ u32 crc = 0;
+ int ret, size;
+
+- uea_enters(usb);
+ if (!fw_entry) {
+ uea_err(usb, "firmware is not available\n");
+ goto err;
+@@ -670,7 +663,6 @@ err_fw_corrupted:
+ uea_err(usb, "firmware is corrupted\n");
+ err:
+ release_firmware(fw_entry);
+- uea_leaves(usb);
+ }
+
+ /*
+@@ -681,7 +673,6 @@ static int uea_load_firmware(struct usb_
+ int ret;
+ char *fw_name = EAGLE_FIRMWARE;
+
+- uea_enters(usb);
+ uea_info(usb, "pre-firmware device, uploading firmware\n");
+
+ switch (ver) {
+@@ -710,7 +701,6 @@ static int uea_load_firmware(struct usb_
+ else
+ uea_info(usb, "loading firmware %s\n", fw_name);
+
+- uea_leaves(usb);
+ return ret;
+ }
+
+@@ -1137,7 +1127,6 @@ static int uea_cmv_e1(struct uea_softc *
+ struct cmv_e1 cmv;
+ int ret;
+
+- uea_enters(INS_TO_USBDEV(sc));
+ uea_vdbg(INS_TO_USBDEV(sc), "Function : %d-%d, Address : %c%c%c%c, "
+ "offset : 0x%04x, data : 0x%08x\n",
+ E1_FUNCTION_TYPE(function),
+@@ -1164,9 +1153,8 @@ static int uea_cmv_e1(struct uea_softc *
+ sizeof(cmv), &cmv);
+ if (ret < 0)
+ return ret;
+- ret = wait_cmv_ack(sc);
+- uea_leaves(INS_TO_USBDEV(sc));
+- return ret;
++
++ return wait_cmv_ack(sc);
+ }
+
+ static int uea_cmv_e4(struct uea_softc *sc,
+@@ -1175,7 +1163,6 @@ static int uea_cmv_e4(struct uea_softc *
+ struct cmv_e4 cmv;
+ int ret;
+
+- uea_enters(INS_TO_USBDEV(sc));
+ memset(&cmv, 0, sizeof(cmv));
+
+ uea_vdbg(INS_TO_USBDEV(sc), "Function : %d-%d, Group : 0x%04x, "
+@@ -1199,9 +1186,8 @@ static int uea_cmv_e4(struct uea_softc *
+ sizeof(cmv), &cmv);
+ if (ret < 0)
+ return ret;
+- ret = wait_cmv_ack(sc);
+- uea_leaves(INS_TO_USBDEV(sc));
+- return ret;
++
++ return wait_cmv_ack(sc);
+ }
+
+ static inline int uea_read_cmv_e1(struct uea_softc *sc,
+@@ -1295,7 +1281,6 @@ static int uea_stat_e1(struct uea_softc
+ u32 data;
+ int ret;
+
+- uea_enters(INS_TO_USBDEV(sc));
+ data = sc->stats.phy.state;
+
+ ret = uea_read_cmv_e1(sc, E1_SA_STAT, 0, &sc->stats.phy.state);
+@@ -1438,7 +1423,6 @@ static int uea_stat_e4(struct uea_softc
+ u32 tmp_arr[2];
+ int ret;
+
+- uea_enters(INS_TO_USBDEV(sc));
+ data = sc->stats.phy.state;
+
+ /* XXX only need to be done before operationnal... */
+@@ -1805,7 +1789,6 @@ static int uea_start_reset(struct uea_so
+ u16 zero = 0; /* ;-) */
+ int ret;
+
+- uea_enters(INS_TO_USBDEV(sc));
+ uea_info(INS_TO_USBDEV(sc), "(re)booting started\n");
+
+ /* mask interrupt */
+@@ -1873,7 +1856,6 @@ static int uea_start_reset(struct uea_so
+ return ret;
+
+ sc->reset = 0;
+- uea_leaves(INS_TO_USBDEV(sc));
+ return ret;
+ }
+
+@@ -1889,7 +1871,6 @@ static int uea_kthread(void *data)
+ int ret = -EAGAIN;
+
+ set_freezable();
+- uea_enters(INS_TO_USBDEV(sc));
+ while (!kthread_should_stop()) {
+ if (ret < 0 || sc->reset)
+ ret = uea_start_reset(sc);
+@@ -1898,7 +1879,7 @@ static int uea_kthread(void *data)
+ if (ret != -EAGAIN)
+ uea_wait(sc, 0, msecs_to_jiffies(1000));
+ }
+- uea_leaves(INS_TO_USBDEV(sc));
++
+ return ret;
+ }
+
+@@ -1911,8 +1892,6 @@ static int load_XILINX_firmware(struct u
+ u8 value;
+ char *fw_name = FPGA930_FIRMWARE;
+
+- uea_enters(INS_TO_USBDEV(sc));
+-
+ ret = request_firmware(&fw_entry, fw_name, &sc->usb_dev->dev);
+ if (ret) {
+ uea_err(INS_TO_USBDEV(sc), "firmware %s is not available\n",
+@@ -1956,7 +1935,6 @@ static int load_XILINX_firmware(struct u
+ err1:
+ release_firmware(fw_entry);
+ err0:
+- uea_leaves(INS_TO_USBDEV(sc));
+ return ret;
+ }
+
+@@ -1966,7 +1944,6 @@ static void uea_dispatch_cmv_e1(struct u
+ struct cmv_dsc_e1 *dsc = &sc->cmv_dsc.e1;
+ struct cmv_e1 *cmv = &intr->u.e1.s2.cmv;
+
+- uea_enters(INS_TO_USBDEV(sc));
+ if (le16_to_cpu(cmv->wPreamble) != E1_PREAMBLE)
+ goto bad1;
+
+@@ -1990,7 +1967,6 @@ static void uea_dispatch_cmv_e1(struct u
+ if (cmv->bFunction == E1_MAKEFUNCTION(E1_ADSLDIRECTIVE,
+ E1_MODEMREADY)) {
+ wake_up_cmv_ack(sc);
+- uea_leaves(INS_TO_USBDEV(sc));
+ return;
+ }
+
+@@ -2004,7 +1980,6 @@ static void uea_dispatch_cmv_e1(struct u
+ sc->data = sc->data << 16 | sc->data >> 16;
+
+ wake_up_cmv_ack(sc);
+- uea_leaves(INS_TO_USBDEV(sc));
+ return;
+
+ bad2:
+@@ -2012,14 +1987,12 @@ bad2:
+ "Function : %d, Subfunction : %d\n",
+ E1_FUNCTION_TYPE(cmv->bFunction),
+ E1_FUNCTION_SUBTYPE(cmv->bFunction));
+- uea_leaves(INS_TO_USBDEV(sc));
+ return;
+
+ bad1:
+ uea_err(INS_TO_USBDEV(sc), "invalid cmv received, "
+ "wPreamble %d, bDirection %d\n",
+ le16_to_cpu(cmv->wPreamble), cmv->bDirection);
+- uea_leaves(INS_TO_USBDEV(sc));
+ }
+
+ /* The modem send us an ack. First with check if it right */
+@@ -2028,7 +2001,6 @@ static void uea_dispatch_cmv_e4(struct u
+ struct cmv_dsc_e4 *dsc = &sc->cmv_dsc.e4;
+ struct cmv_e4 *cmv = &intr->u.e4.s2.cmv;
+
+- uea_enters(INS_TO_USBDEV(sc));
+ uea_dbg(INS_TO_USBDEV(sc), "cmv %x %x %x %x %x %x\n",
+ be16_to_cpu(cmv->wGroup), be16_to_cpu(cmv->wFunction),
+ be16_to_cpu(cmv->wOffset), be16_to_cpu(cmv->wAddress),
+@@ -2040,7 +2012,6 @@ static void uea_dispatch_cmv_e4(struct u
+ if (be16_to_cpu(cmv->wFunction) == E4_MAKEFUNCTION(E4_ADSLDIRECTIVE,
+ E4_MODEMREADY, 1)) {
+ wake_up_cmv_ack(sc);
+- uea_leaves(INS_TO_USBDEV(sc));
+ return;
+ }
+
+@@ -2053,7 +2024,6 @@ static void uea_dispatch_cmv_e4(struct u
+ sc->data = be32_to_cpu(cmv->dwData[0]);
+ sc->data1 = be32_to_cpu(cmv->dwData[1]);
+ wake_up_cmv_ack(sc);
+- uea_leaves(INS_TO_USBDEV(sc));
+ return;
+
+ bad2:
+@@ -2061,7 +2031,6 @@ bad2:
+ "Function : %d, Subfunction : %d\n",
+ E4_FUNCTION_TYPE(cmv->wFunction),
+ E4_FUNCTION_SUBTYPE(cmv->wFunction));
+- uea_leaves(INS_TO_USBDEV(sc));
+ return;
+ }
+
+@@ -2089,8 +2058,6 @@ static void uea_intr(struct urb *urb)
+ struct intr_pkt *intr = urb->transfer_buffer;
+ int status = urb->status;
+
+- uea_enters(INS_TO_USBDEV(sc));
+-
+ if (unlikely(status < 0)) {
+ uea_err(INS_TO_USBDEV(sc), "uea_intr() failed with %d\n",
+ status);
+@@ -2130,8 +2097,6 @@ static int uea_boot(struct uea_softc *sc
+ int ret = -ENOMEM;
+ int size;
+
+- uea_enters(INS_TO_USBDEV(sc));
+-
+ if (UEA_CHIP_VERSION(sc) == EAGLE_IV) {
+ size = E4_INTR_PKT_SIZE;
+ sc->dispatch_cmv = uea_dispatch_cmv_e4;
+@@ -2188,7 +2153,6 @@ static int uea_boot(struct uea_softc *sc
+ goto err2;
+ }
+
+- uea_leaves(INS_TO_USBDEV(sc));
+ return 0;
+
+ err2:
+@@ -2198,7 +2162,6 @@ err1:
+ sc->urb_int = NULL;
+ kfree(intr);
+ err0:
+- uea_leaves(INS_TO_USBDEV(sc));
+ return ret;
+ }
+
+@@ -2208,7 +2171,7 @@ err0:
+ static void uea_stop(struct uea_softc *sc)
+ {
+ int ret;
+- uea_enters(INS_TO_USBDEV(sc));
++
+ ret = kthread_stop(sc->kthread);
+ uea_dbg(INS_TO_USBDEV(sc), "kthread finish with status %d\n", ret);
+
+@@ -2222,7 +2185,6 @@ static void uea_stop(struct uea_softc *s
+ flush_work(&sc->task);
+
+ release_firmware(sc->dsp_firm);
+- uea_leaves(INS_TO_USBDEV(sc));
+ }
+
+ /* syfs interface */
+@@ -2495,8 +2457,6 @@ static int uea_bind(struct usbatm_data *
+ int ret, ifnum = intf->altsetting->desc.bInterfaceNumber;
+ unsigned int alt;
+
+- uea_enters(usb);
+-
+ /* interface 0 is for firmware/monitoring */
+ if (ifnum != UEA_INTR_IFACE_NO)
+ return -ENODEV;
+@@ -2589,7 +2549,6 @@ static int uea_probe(struct usb_interfac
+ struct usb_device *usb = interface_to_usbdev(intf);
+ int ret;
+
+- uea_enters(usb);
+ uea_dbg(usb, "ADSL device found with vid (%#X) pid (%#X) Rev (%#X): %s\n",
+ le16_to_cpu(usb->descriptor.idVendor),
+ le16_to_cpu(usb->descriptor.idProduct),
+@@ -2620,7 +2579,6 @@ static void uea_disconnect(struct usb_in
+ {
+ struct usb_device *usb = interface_to_usbdev(intf);
+ int ifnum = intf->altsetting->desc.bInterfaceNumber;
+- uea_enters(usb);
+
+ /* ADI930 has 2 interfaces and eagle 3 interfaces.
+ * Pre-firmware device has one interface
+@@ -2631,8 +2589,6 @@ static void uea_disconnect(struct usb_in
+ mutex_unlock(&uea_mutex);
+ uea_info(usb, "ADSL device removed\n");
+ }
+-
+- uea_leaves(usb);
+ }
+
+ /*
--- /dev/null
+From sashal@kernel.org Sat Jul 18 23:50:36 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 18 Jul 2026 17:50:31 -0400
+Subject: usb: atm: ueagle-atm: use dev_dbg() for 'device found' message
+To: stable@vger.kernel.org
+Cc: Mauricio Faria de Oliveira <mfo@igalia.com>, Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Stanislaw Gruszka <stf_xl@wp.pl>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260718215033.3447737-1-sashal@kernel.org>
+
+From: Mauricio Faria de Oliveira <mfo@igalia.com>
+
+[ Upstream commit 05c5075c3115010f97434c53d353d9a0d4b0e64e ]
+
+Convert dev_info() to dev_dbg().
+
+Per 'Documentation/process/coding-style.rst':
+
+ 13) Printing kernel messages
+
+ ... When drivers are working properly they are quiet,
+ so prefer to use dev_dbg/pr_debug unless something is wrong.
+
+While in there, correct the verb form and add 'with' for clarity.
+
+Suggested-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Link: https://lore.kernel.org/all/2026051628-squatter-stature-c0e0@gregkh/
+Signed-off-by: Mauricio Faria de Oliveira <mfo@igalia.com>
+Acked-by: Stanislaw Gruszka <stf_xl@wp.pl>
+Link: https://patch.msgid.link/20260520-ueagle-atm-cleanup-v1-1-010c8bc7b214@igalia.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Stable-dep-of: e2674dfbed8a ("usb: atm: ueagle-atm: wait for pre-firmware load in .disconnect()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/atm/ueagle-atm.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/usb/atm/ueagle-atm.c
++++ b/drivers/usb/atm/ueagle-atm.c
+@@ -2590,7 +2590,7 @@ static int uea_probe(struct usb_interfac
+ int ret;
+
+ uea_enters(usb);
+- uea_info(usb, "ADSL device founded vid (%#X) pid (%#X) Rev (%#X): %s\n",
++ uea_dbg(usb, "ADSL device found with vid (%#X) pid (%#X) Rev (%#X): %s\n",
+ le16_to_cpu(usb->descriptor.idVendor),
+ le16_to_cpu(usb->descriptor.idProduct),
+ le16_to_cpu(usb->descriptor.bcdDevice),
--- /dev/null
+From stable+bounces-277394-greg=kroah.com@vger.kernel.org Sat Jul 18 23:51:42 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 18 Jul 2026 17:50:33 -0400
+Subject: usb: atm: ueagle-atm: wait for pre-firmware load in .disconnect()
+To: stable@vger.kernel.org
+Cc: Mauricio Faria de Oliveira <mfo@igalia.com>, stable <stable@kernel.org>, syzbot+ce1e5a1b4e086b43e56d@syzkaller.appspotmail.com, syzbot+306212936b13e520679d@syzkaller.appspotmail.com, syzbot+457452d30bcdda75ead2@syzkaller.appspotmail.com, Andrey Tsygunka <aitsygunka@yandex.ru>, Stanislaw Gruszka <stf_xl@wp.pl>, Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260718215033.3447737-3-sashal@kernel.org>
+
+From: Mauricio Faria de Oliveira <mfo@igalia.com>
+
+[ Upstream commit e2674dfbed8a30d57e2bc872c4bfa6c3eec918bf ]
+
+ueagle-atm uses the asynchronous request_firmware_nowait() in .probe(),
+but does not wait for its completion, not even in .disconnect(); so, if the
+device is unplugged meanwhile, its teardown runs concurrently with that.
+
+Even though this inconsistency is worth addressing on its own, it has also
+triggered several bug reports in syzbot over the years (some auto-closed)
+where the firmware sysfs fallback mechanism (CONFIG_FW_LOADER_USER_HELPER)
+creates a firmware subdirectory in the device directory during its removal,
+which might hit unexpected conditions in kernfs, apparently, depending at
+which point the add and remove operations raced. (See links.)
+
+The pattern is:
+
+usb ?-?: Direct firmware load for ueagle-atm/eagle?.fw failed with error -2
+usb ?-?: Falling back to sysfs fallback for: ueagle-atm/eagle?.fw
+<ERROR>
+Call trace:
+ ...
+ kernfs_create_dir_ns
+ sysfs_create_dir_ns
+ create_dir
+ kobject_add_internal
+ kobject_add_varg
+ kobject_add
+ class_dir_create_and_add
+ get_device_parent
+ device_add
+ fw_load_sysfs_fallback
+ fw_load_from_user_helper
+ firmware_fallback_sysfs
+ _request_firmware
+ request_firmware_work_func
+ ...
+
+(Some variations are observed, after fw_load_sysfs_fallback(), e.g., [1].)
+
+While the kernfs side is being looked at, the ueagle-atm side can be fixed
+by waiting for the pre-firmware load in the .disconnect() handler.
+
+This change has a similar approach to previous work by Andrey Tsygunka [2]
+(wait_for_completion() in .disconnect()), but it is relatively different in
+design/implementation; using the Originally-by tag for credit assignment.
+
+This has been tested with:
+- synthetic reproducer to check the error path;
+- USB gadget (virtual device) to check the firmware upload path;
+- QEMU device emulator to check the device ID re-enumeration path;
+(The latter two were written by Claude; no other code/text in this commit.)
+
+Links (year first reported):
+ 2025 https://syzbot.org/bug?extid=ce1e5a1b4e086b43e56d
+ 2025 https://syzbot.org/bug?extid=9af8471255ac36e34fd4
+ 2024 https://syzbot.org/bug?extid=306212936b13e520679d
+ 2023 https://syzkaller.appspot.com/bug?extid=457452d30bcdda75ead2
+ 2022 https://syzbot.org/bug?extid=782984d6f1701b526edb
+ 2021 https://syzbot.org/bug?id=f3f221579f4ef7e9691281f3c6f56c05f83e8490
+ 2021 https://syzbot.org/bug?id=84d86f0d71394829df6fc53daf6642c045983881
+ 2021 https://syzbot.org/bug?id=3302dc1c0e2b9c94f2e8edb404eabc9267bc6f90
+
+[1] https://syzkaller.appspot.com/bug?extid=457452d30bcdda75ead2
+[2] https://lore.kernel.org/lkml/20250410093146.3776801-2-aitsygunka@yandex.ru/
+
+Cc: stable <stable@kernel.org>
+Reported-by: syzbot+ce1e5a1b4e086b43e56d@syzkaller.appspotmail.com
+Closes: https://syzbot.org/bug?extid=ce1e5a1b4e086b43e56d
+Reported-by: syzbot+306212936b13e520679d@syzkaller.appspotmail.com
+Closes: https://syzbot.org/bug?extid=306212936b13e520679d
+Reported-by: syzbot+457452d30bcdda75ead2@syzkaller.appspotmail.com
+Closes: https://syzkaller.appspot.com/bug?extid=457452d30bcdda75ead2
+Originally-by: Andrey Tsygunka <aitsygunka@yandex.ru>
+Fixes: b72458a80c75 ("[PATCH] USB: Eagle and ADI 930 usb adsl modem driver")
+Assisted-by: Claude:claude-opus-4.7 # usb gadget & qemu device for testing
+Signed-off-by: Mauricio Faria de Oliveira <mfo@igalia.com>
+Acked-by: Stanislaw Gruszka <stf_xl@wp.pl>
+Link: https://patch.msgid.link/20260526-ueagle-atm_req-fw-sync-v3-1-93c01961daaf@igalia.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/atm/ueagle-atm.c | 36 +++++++++++++++++++++++++++++++-----
+ 1 file changed, 31 insertions(+), 5 deletions(-)
+
+--- a/drivers/usb/atm/ueagle-atm.c
++++ b/drivers/usb/atm/ueagle-atm.c
+@@ -594,7 +594,9 @@ static int uea_send_modem_cmd(struct usb
+ static void uea_upload_pre_firmware(const struct firmware *fw_entry,
+ void *context)
+ {
+- struct usb_device *usb = context;
++ struct usb_interface *intf = context;
++ struct usb_device *usb = interface_to_usbdev(intf);
++ struct completion *fw_done = usb_get_intfdata(intf);
+ const u8 *pfw;
+ u8 value;
+ u32 crc = 0;
+@@ -663,15 +665,17 @@ err_fw_corrupted:
+ uea_err(usb, "firmware is corrupted\n");
+ err:
+ release_firmware(fw_entry);
++ complete(fw_done);
+ }
+
+ /*
+ * uea_load_firmware - Load usb firmware for pre-firmware devices.
+ */
+-static int uea_load_firmware(struct usb_device *usb, unsigned int ver)
++static int uea_load_firmware(struct usb_interface *intf, unsigned int ver)
+ {
+ int ret;
+ char *fw_name = EAGLE_FIRMWARE;
++ struct usb_device *usb = interface_to_usbdev(intf);
+
+ uea_info(usb, "pre-firmware device, uploading firmware\n");
+
+@@ -694,7 +698,7 @@ static int uea_load_firmware(struct usb_
+ }
+
+ ret = request_firmware_nowait(THIS_MODULE, 1, fw_name, &usb->dev,
+- GFP_KERNEL, usb,
++ GFP_KERNEL, intf,
+ uea_upload_pre_firmware);
+ if (ret)
+ uea_err(usb, "firmware %s is not available\n", fw_name);
+@@ -2557,8 +2561,23 @@ static int uea_probe(struct usb_interfac
+
+ usb_reset_device(usb);
+
+- if (UEA_IS_PREFIRM(id))
+- return uea_load_firmware(usb, UEA_CHIP_VERSION(id));
++ if (UEA_IS_PREFIRM(id)) {
++ struct completion *fw_done;
++
++ /* Wait for the firmware load to be done, in .disconnect() */
++ fw_done = kzalloc_obj(*fw_done);
++ if (!fw_done)
++ return -ENOMEM;
++
++ init_completion(fw_done);
++ usb_set_intfdata(intf, fw_done);
++
++ ret = uea_load_firmware(intf, UEA_CHIP_VERSION(id));
++ if (ret)
++ kfree(fw_done);
++
++ return ret;
++ }
+
+ ret = usbatm_usb_probe(intf, id, &uea_usbatm_driver);
+ if (ret == 0) {
+@@ -2588,6 +2607,13 @@ static void uea_disconnect(struct usb_in
+ usbatm_usb_disconnect(intf);
+ mutex_unlock(&uea_mutex);
+ uea_info(usb, "ADSL device removed\n");
++ } else if (usb->config->desc.bNumInterfaces == 1) {
++ struct completion *fw_done = usb_get_intfdata(intf);
++
++ uea_dbg(usb, "pre-firmware device, waiting firmware upload\n");
++ wait_for_completion(fw_done);
++ uea_dbg(usb, "pre-firmware device, finished waiting\n");
++ kfree(fw_done);
+ }
+ }
+
--- /dev/null
+From stable+bounces-277304-greg=kroah.com@vger.kernel.org Sat Jul 18 13:51:13 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 18 Jul 2026 07:51:03 -0400
+Subject: xfs: add newly added RTGs to the free pool in growfs
+To: stable@vger.kernel.org
+Cc: Christoph Hellwig <hch@lst.de>, Damien Le Moal <dlemoal@kernel.org>, "Darrick J. Wong" <djwong@kernel.org>, Carlos Maiolino <cem@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260718115103.3085836-2-sashal@kernel.org>
+
+From: Christoph Hellwig <hch@lst.de>
+
+[ Upstream commit ae3692c7f440c1ff577aae1a51202415ec4a794b ]
+
+When growing a zoned RT section, the newly added RTGs also need to be
+tagged as free in the radix tree and add to the nr_free_zones counters.
+Call xfs_add_free_zone to do that, otherwise using up the newly added
+space will wait for free zones forever.
+
+Fixes: 01b71e64bb87 ("xfs: support growfs on zoned file systems")
+Cc: stable@vger.kernel.org # v6.15
+Reviewed-by: Damien Le Moal <dlemoal@kernel.org>
+Reviewed-by: "Darrick J. Wong" <djwong@kernel.org>
+Signed-off-by: Christoph Hellwig <hch@lst.de>
+Signed-off-by: Carlos Maiolino <cem@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/xfs/xfs_rtalloc.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+--- a/fs/xfs/xfs_rtalloc.c
++++ b/fs/xfs/xfs_rtalloc.c
+@@ -933,6 +933,14 @@ xfs_growfs_rt_zoned(
+ mp->m_features |= XFS_FEAT_REALTIME;
+ xfs_rtrmapbt_compute_maxlevels(mp);
+ xfs_rtrefcountbt_compute_maxlevels(mp);
++
++ /*
++ * Finally add the newly added zone to the freelist and add the space
++ * to the available counter. The order is important here: only add
++ * the available space after the zones, as available space guarantees
++ * that zones to back it are available.
++ */
++ xfs_zone_mark_free(rtg);
+ xfs_zoned_add_available(mp, freed_rtx);
+ out_free:
+ kfree(nmp);
--- /dev/null
+From stable+bounces-277303-greg=kroah.com@vger.kernel.org Sat Jul 18 13:51:10 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 18 Jul 2026 07:51:02 -0400
+Subject: xfs: factor out a xfs_zone_mark_free helper
+To: stable@vger.kernel.org
+Cc: Christoph Hellwig <hch@lst.de>, Damien Le Moal <dlemoal@kernel.org>, "Darrick J. Wong" <djwong@kernel.org>, Carlos Maiolino <cem@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260718115103.3085836-1-sashal@kernel.org>
+
+From: Christoph Hellwig <hch@lst.de>
+
+[ Upstream commit 16fc9d358d12e6e9cc553162b4064ad58e7fa869 ]
+
+Add a helper for adding a zone to the free pool in preparation of adding
+another caller.
+
+Signed-off-by: Christoph Hellwig <hch@lst.de>
+Reviewed-by: Damien Le Moal <dlemoal@kernel.org>
+Reviewed-by: "Darrick J. Wong" <djwong@kernel.org>
+Signed-off-by: Carlos Maiolino <cem@kernel.org>
+Stable-dep-of: ae3692c7f440 ("xfs: add newly added RTGs to the free pool in growfs")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/xfs/xfs_zone_alloc.c | 11 +++++++++--
+ fs/xfs/xfs_zone_alloc.h | 1 +
+ fs/xfs/xfs_zone_gc.c | 4 +---
+ 3 files changed, 11 insertions(+), 5 deletions(-)
+
+--- a/fs/xfs/xfs_zone_alloc.c
++++ b/fs/xfs/xfs_zone_alloc.c
+@@ -944,6 +944,14 @@ xfs_zone_rgbno_is_valid(
+ rtg_rgno(rtg), XFS_RTG_FREE);
+ }
+
++void
++xfs_zone_mark_free(
++ struct xfs_rtgroup *rtg)
++{
++ xfs_group_set_mark(rtg_group(rtg), XFS_RTG_FREE);
++ atomic_inc(&rtg_mount(rtg)->m_zone_info->zi_nr_free_zones);
++}
++
+ static void
+ xfs_free_open_zones(
+ struct xfs_zone_info *zi)
+@@ -1082,8 +1090,7 @@ xfs_init_zone(
+
+ if (write_pointer == 0) {
+ /* zone is empty */
+- atomic_inc(&zi->zi_nr_free_zones);
+- xfs_group_set_mark(rtg_group(rtg), XFS_RTG_FREE);
++ xfs_zone_mark_free(rtg);
+ iz->available += rtg_blocks(rtg);
+ } else if (write_pointer < rtg_blocks(rtg)) {
+ /* zone is open */
+--- a/fs/xfs/xfs_zone_alloc.h
++++ b/fs/xfs/xfs_zone_alloc.h
+@@ -42,6 +42,7 @@ void xfs_zoned_wake_all(struct xfs_mount
+ bool xfs_zone_rgbno_is_valid(struct xfs_rtgroup *rtg, xfs_rgnumber_t rgbno);
+ void xfs_mark_rtg_boundary(struct iomap_ioend *ioend);
+
++void xfs_zone_mark_free(struct xfs_rtgroup *rtg);
+ uint64_t xfs_zoned_default_resblks(struct xfs_mount *mp,
+ enum xfs_free_counter ctr);
+ void xfs_zoned_show_stats(struct seq_file *m, struct xfs_mount *mp);
+--- a/fs/xfs/xfs_zone_gc.c
++++ b/fs/xfs/xfs_zone_gc.c
+@@ -924,9 +924,7 @@ xfs_zone_gc_finish_reset(
+ goto out;
+ }
+
+- xfs_group_set_mark(rtg_group(rtg), XFS_RTG_FREE);
+- atomic_inc(&zi->zi_nr_free_zones);
+-
++ xfs_zone_mark_free(rtg);
+ xfs_zoned_add_available(mp, rtg_blocks(rtg));
+
+ wake_up_all(&zi->zi_zone_wait);