]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
7.1-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 21 Jul 2026 09:54:07 +0000 (11:54 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 21 Jul 2026 09:54:07 +0000 (11:54 +0200)
added patches:
alsa-hda-tas2781-cancel-async-firmware-request-at-unbind.patch
alsa-scarlett2-allow-selecting-config_set-by-firmware-version.patch
alsa-scarlett2-update-offsets-for-2i2-gen-4-firmware-2417.patch
binder-cache-secctx-size-before-release-zeroes-it.patch
binder-use-list_head-to-initialize-on-stack-list-head.patch
bluetooth-6lowpan-fix-cyclic-locking-warning-on-netdev-unregister.patch
bluetooth-l2cap-fix-use-after-free-in-l2cap_sock_new_connection_cb.patch
bpf-reject-negative-const-offsets-for-buffer-pointers.patch
device-property-initialize-the-remaining-fields-of-fwnode_handle-in-fwnode_init.patch
f2fs-fix-listxattr-handling-of-corrupted-xattr-entries.patch
f2fs-fix-potential-deadlock-in-f2fs_balance_fs.patch
f2fs-fix-potential-deadlock-in-gc_merge-path-of-f2fs_balance_fs.patch
firmware_loader-add-cancel-helper-for-async-requests.patch
iio-hid-sensor-rotation-fix-stale-or-zero-output-when-reading-raw-values.patch
ksmbd-fix-path-resolution-in-ksmbd_vfs_kern_path_create.patch
ksmbd-use-opener-credentials-for-fsctl-mutations.patch
liveupdate-validate-session-type-before-performing-operation.patch
mm-damon-core-trace-esz-at-first-setup.patch
samples-damon-mtier-fail-early-if-address-range-parameters-are-invalid.patch
smb-move-compression-definitions-into-common-fscc.h.patch
usb-atm-ueagle-atm-remove-function-entry-exit-debug-messages.patch
usb-atm-ueagle-atm-use-dev_dbg-for-device-found-message.patch
usb-atm-ueagle-atm-wait-for-pre-firmware-load-in-.disconnect.patch
xfs-add-newly-added-rtgs-to-the-free-pool-in-growfs.patch
xfs-factor-out-a-xfs_zone_mark_free-helper.patch

26 files changed:
queue-7.1/alsa-hda-tas2781-cancel-async-firmware-request-at-unbind.patch [new file with mode: 0644]
queue-7.1/alsa-scarlett2-allow-selecting-config_set-by-firmware-version.patch [new file with mode: 0644]
queue-7.1/alsa-scarlett2-update-offsets-for-2i2-gen-4-firmware-2417.patch [new file with mode: 0644]
queue-7.1/binder-cache-secctx-size-before-release-zeroes-it.patch [new file with mode: 0644]
queue-7.1/binder-use-list_head-to-initialize-on-stack-list-head.patch [new file with mode: 0644]
queue-7.1/bluetooth-6lowpan-fix-cyclic-locking-warning-on-netdev-unregister.patch [new file with mode: 0644]
queue-7.1/bluetooth-l2cap-fix-use-after-free-in-l2cap_sock_new_connection_cb.patch [new file with mode: 0644]
queue-7.1/bpf-reject-negative-const-offsets-for-buffer-pointers.patch [new file with mode: 0644]
queue-7.1/device-property-initialize-the-remaining-fields-of-fwnode_handle-in-fwnode_init.patch [new file with mode: 0644]
queue-7.1/f2fs-fix-listxattr-handling-of-corrupted-xattr-entries.patch [new file with mode: 0644]
queue-7.1/f2fs-fix-potential-deadlock-in-f2fs_balance_fs.patch [new file with mode: 0644]
queue-7.1/f2fs-fix-potential-deadlock-in-gc_merge-path-of-f2fs_balance_fs.patch [new file with mode: 0644]
queue-7.1/firmware_loader-add-cancel-helper-for-async-requests.patch [new file with mode: 0644]
queue-7.1/iio-hid-sensor-rotation-fix-stale-or-zero-output-when-reading-raw-values.patch [new file with mode: 0644]
queue-7.1/ksmbd-fix-path-resolution-in-ksmbd_vfs_kern_path_create.patch [new file with mode: 0644]
queue-7.1/ksmbd-use-opener-credentials-for-fsctl-mutations.patch [new file with mode: 0644]
queue-7.1/liveupdate-validate-session-type-before-performing-operation.patch [new file with mode: 0644]
queue-7.1/mm-damon-core-trace-esz-at-first-setup.patch [new file with mode: 0644]
queue-7.1/samples-damon-mtier-fail-early-if-address-range-parameters-are-invalid.patch [new file with mode: 0644]
queue-7.1/series
queue-7.1/smb-move-compression-definitions-into-common-fscc.h.patch [new file with mode: 0644]
queue-7.1/usb-atm-ueagle-atm-remove-function-entry-exit-debug-messages.patch [new file with mode: 0644]
queue-7.1/usb-atm-ueagle-atm-use-dev_dbg-for-device-found-message.patch [new file with mode: 0644]
queue-7.1/usb-atm-ueagle-atm-wait-for-pre-firmware-load-in-.disconnect.patch [new file with mode: 0644]
queue-7.1/xfs-add-newly-added-rtgs-to-the-free-pool-in-growfs.patch [new file with mode: 0644]
queue-7.1/xfs-factor-out-a-xfs_zone_mark_free-helper.patch [new file with mode: 0644]

diff --git a/queue-7.1/alsa-hda-tas2781-cancel-async-firmware-request-at-unbind.patch b/queue-7.1/alsa-hda-tas2781-cancel-async-firmware-request-at-unbind.patch
new file mode 100644 (file)
index 0000000..2685539
--- /dev/null
@@ -0,0 +1,65 @@
+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);
diff --git a/queue-7.1/alsa-scarlett2-allow-selecting-config_set-by-firmware-version.patch b/queue-7.1/alsa-scarlett2-allow-selecting-config_set-by-firmware-version.patch
new file mode 100644 (file)
index 0000000..9a5dd7b
--- /dev/null
@@ -0,0 +1,340 @@
+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)
diff --git a/queue-7.1/alsa-scarlett2-update-offsets-for-2i2-gen-4-firmware-2417.patch b/queue-7.1/alsa-scarlett2-update-offsets-for-2i2-gen-4-firmware-2417.patch
new file mode 100644 (file)
index 0000000..c41def1
--- /dev/null
@@ -0,0 +1,103 @@
+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,
diff --git a/queue-7.1/binder-cache-secctx-size-before-release-zeroes-it.patch b/queue-7.1/binder-cache-secctx-size-before-release-zeroes-it.patch
new file mode 100644 (file)
index 0000000..eda43fe
--- /dev/null
@@ -0,0 +1,105 @@
+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)) {
diff --git a/queue-7.1/binder-use-list_head-to-initialize-on-stack-list-head.patch b/queue-7.1/binder-use-list_head-to-initialize-on-stack-list-head.patch
new file mode 100644 (file)
index 0000000..902d164
--- /dev/null
@@ -0,0 +1,52 @@
+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;
diff --git a/queue-7.1/bluetooth-6lowpan-fix-cyclic-locking-warning-on-netdev-unregister.patch b/queue-7.1/bluetooth-6lowpan-fix-cyclic-locking-warning-on-netdev-unregister.patch
new file mode 100644 (file)
index 0000000..29e397f
--- /dev/null
@@ -0,0 +1,101 @@
+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);
+       }
+ }
diff --git a/queue-7.1/bluetooth-l2cap-fix-use-after-free-in-l2cap_sock_new_connection_cb.patch b/queue-7.1/bluetooth-l2cap-fix-use-after-free-in-l2cap_sock_new_connection_cb.patch
new file mode 100644 (file)
index 0000000..224fdb8
--- /dev/null
@@ -0,0 +1,542 @@
+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;
diff --git a/queue-7.1/bpf-reject-negative-const-offsets-for-buffer-pointers.patch b/queue-7.1/bpf-reject-negative-const-offsets-for-buffer-pointers.patch
new file mode 100644 (file)
index 0000000..74b5048
--- /dev/null
@@ -0,0 +1,112 @@
+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;
+ }
diff --git a/queue-7.1/device-property-initialize-the-remaining-fields-of-fwnode_handle-in-fwnode_init.patch b/queue-7.1/device-property-initialize-the-remaining-fields-of-fwnode_handle-in-fwnode_init.patch
new file mode 100644 (file)
index 0000000..e644768
--- /dev/null
@@ -0,0 +1,49 @@
+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,
diff --git a/queue-7.1/f2fs-fix-listxattr-handling-of-corrupted-xattr-entries.patch b/queue-7.1/f2fs-fix-listxattr-handling-of-corrupted-xattr-entries.patch
new file mode 100644 (file)
index 0000000..2d08a79
--- /dev/null
@@ -0,0 +1,51 @@
+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;
diff --git a/queue-7.1/f2fs-fix-potential-deadlock-in-f2fs_balance_fs.patch b/queue-7.1/f2fs-fix-potential-deadlock-in-f2fs_balance_fs.patch
new file mode 100644 (file)
index 0000000..ba8f7b8
--- /dev/null
@@ -0,0 +1,253 @@
+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);
diff --git a/queue-7.1/f2fs-fix-potential-deadlock-in-gc_merge-path-of-f2fs_balance_fs.patch b/queue-7.1/f2fs-fix-potential-deadlock-in-gc_merge-path-of-f2fs_balance_fs.patch
new file mode 100644 (file)
index 0000000..10081b7
--- /dev/null
@@ -0,0 +1,85 @@
+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);
diff --git a/queue-7.1/firmware_loader-add-cancel-helper-for-async-requests.patch b/queue-7.1/firmware_loader-add-cancel-helper-for-async-requests.patch
new file mode 100644 (file)
index 0000000..8690062
--- /dev/null
@@ -0,0 +1,180 @@
+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)
+ {
+ }
diff --git a/queue-7.1/iio-hid-sensor-rotation-fix-stale-or-zero-output-when-reading-raw-values.patch b/queue-7.1/iio-hid-sensor-rotation-fix-stale-or-zero-output-when-reading-raw-values.patch
new file mode 100644 (file)
index 0000000..e05799a
--- /dev/null
@@ -0,0 +1,89 @@
+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
diff --git a/queue-7.1/ksmbd-fix-path-resolution-in-ksmbd_vfs_kern_path_create.patch b/queue-7.1/ksmbd-fix-path-resolution-in-ksmbd_vfs_kern_path_create.patch
new file mode 100644 (file)
index 0000000..0fbdf69
--- /dev/null
@@ -0,0 +1,139 @@
+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;
+ }
diff --git a/queue-7.1/ksmbd-use-opener-credentials-for-fsctl-mutations.patch b/queue-7.1/ksmbd-use-opener-credentials-for-fsctl-mutations.patch
new file mode 100644 (file)
index 0000000..3c69b8d
--- /dev/null
@@ -0,0 +1,86 @@
+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,
diff --git a/queue-7.1/liveupdate-validate-session-type-before-performing-operation.patch b/queue-7.1/liveupdate-validate-session-type-before-performing-operation.patch
new file mode 100644 (file)
index 0000000..7e506c8
--- /dev/null
@@ -0,0 +1,122 @@
+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;
+ }
+-
diff --git a/queue-7.1/mm-damon-core-trace-esz-at-first-setup.patch b/queue-7.1/mm-damon-core-trace-esz-at-first-setup.patch
new file mode 100644 (file)
index 0000000..cc6197e
--- /dev/null
@@ -0,0 +1,57 @@
+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 */
diff --git a/queue-7.1/samples-damon-mtier-fail-early-if-address-range-parameters-are-invalid.patch b/queue-7.1/samples-damon-mtier-fail-early-if-address-range-parameters-are-invalid.patch
new file mode 100644 (file)
index 0000000..4fc1c9a
--- /dev/null
@@ -0,0 +1,74 @@
+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;
index cc8e2f4624dbbd4be4b5c1b20017c5204af8c19b..6db93ab7296f91c47d024dfe164e0ddf03e58c6f 100644 (file)
@@ -2053,3 +2053,28 @@ mmc-sdhci-esdhc-imx-disable-irq-during-suspend-to-fix-unhandled-interrupt.patch
 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
diff --git a/queue-7.1/smb-move-compression-definitions-into-common-fscc.h.patch b/queue-7.1/smb-move-compression-definitions-into-common-fscc.h.patch
new file mode 100644 (file)
index 0000000..1ee7d15
--- /dev/null
@@ -0,0 +1,94 @@
+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;
diff --git a/queue-7.1/usb-atm-ueagle-atm-remove-function-entry-exit-debug-messages.patch b/queue-7.1/usb-atm-ueagle-atm-remove-function-entry-exit-debug-messages.patch
new file mode 100644 (file)
index 0000000..34a1edb
--- /dev/null
@@ -0,0 +1,337 @@
+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);
+ }
+ /*
diff --git a/queue-7.1/usb-atm-ueagle-atm-use-dev_dbg-for-device-found-message.patch b/queue-7.1/usb-atm-ueagle-atm-use-dev_dbg-for-device-found-message.patch
new file mode 100644 (file)
index 0000000..637dedb
--- /dev/null
@@ -0,0 +1,47 @@
+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),
diff --git a/queue-7.1/usb-atm-ueagle-atm-wait-for-pre-firmware-load-in-.disconnect.patch b/queue-7.1/usb-atm-ueagle-atm-wait-for-pre-firmware-load-in-.disconnect.patch
new file mode 100644 (file)
index 0000000..ab9ce6a
--- /dev/null
@@ -0,0 +1,175 @@
+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);
+       }
+ }
diff --git a/queue-7.1/xfs-add-newly-added-rtgs-to-the-free-pool-in-growfs.patch b/queue-7.1/xfs-add-newly-added-rtgs-to-the-free-pool-in-growfs.patch
new file mode 100644 (file)
index 0000000..174fc83
--- /dev/null
@@ -0,0 +1,46 @@
+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);
diff --git a/queue-7.1/xfs-factor-out-a-xfs_zone_mark_free-helper.patch b/queue-7.1/xfs-factor-out-a-xfs_zone_mark_free-helper.patch
new file mode 100644 (file)
index 0000000..1985209
--- /dev/null
@@ -0,0 +1,78 @@
+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);