From: Greg Kroah-Hartman Date: Tue, 21 Jul 2026 09:54:07 +0000 (+0200) Subject: 7.1-stable patches X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=4407dcf94fdcff42c848649ff2ee196a8b0a636c;p=thirdparty%2Fkernel%2Fstable-queue.git 7.1-stable patches 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 --- 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 index 0000000000..26855392fa --- /dev/null +++ b/queue-7.1/alsa-hda-tas2781-cancel-async-firmware-request-at-unbind.patch @@ -0,0 +1,65 @@ +From stable+bounces-274107-greg=kroah.com@vger.kernel.org Tue Jul 14 05:33:20 2026 +From: Sasha Levin +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" , "Takashi Iwai" , "Danilo Krummrich" , "Sasha Levin" +Message-ID: <20260714033256.2396704-2-sashal@kernel.org> + +From: Cássio Gabriel + +[ 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 +Reviewed-by: Takashi Iwai +Acked-by: Danilo Krummrich +Signed-off-by: Takashi Iwai +Link: https://patch.msgid.link/20260505-alsa-hda-tas2781-fw-callback-teardown-v4-2-e7c4bf930dc8@gmail.com +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..9a5dd7bda4 --- /dev/null +++ b/queue-7.1/alsa-scarlett2-allow-selecting-config_set-by-firmware-version.patch @@ -0,0 +1,340 @@ +From stable+bounces-274055-greg=kroah.com@vger.kernel.org Tue Jul 14 03:16:29 2026 +From: Sasha Levin +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" , Takashi Iwai , Sasha Levin +Message-ID: <20260714011623.2188610-1-sashal@kernel.org> + +From: "Geoffrey D. Bennett" + +[ 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 +Signed-off-by: Takashi Iwai +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 +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..c41def1b2d --- /dev/null +++ b/queue-7.1/alsa-scarlett2-update-offsets-for-2i2-gen-4-firmware-2417.patch @@ -0,0 +1,103 @@ +From stable+bounces-274056-greg=kroah.com@vger.kernel.org Tue Jul 14 03:16:35 2026 +From: Sasha Levin +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" , Takashi Iwai , Sasha Levin +Message-ID: <20260714011623.2188610-2-sashal@kernel.org> + +From: "Geoffrey D. Bennett" + +[ 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 +Signed-off-by: Takashi Iwai +Link: https://patch.msgid.link/ad0fc5a131e76eb656a24e0e198382f7134068fe.1777151532.git.g@b4.vu +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..eda43fed09 --- /dev/null +++ b/queue-7.1/binder-cache-secctx-size-before-release-zeroes-it.patch @@ -0,0 +1,105 @@ +From sashal@kernel.org Tue Jul 14 15:40:10 2026 +From: Sasha Levin +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 , stable , Alice Ryhl , Carlos Llamas , Greg Kroah-Hartman , Sasha Levin +Message-ID: <20260714134006.2674552-2-sashal@kernel.org> + +From: Chris Mason + +[ 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 +Assisted-by: kres:claude-opus-4-8 +Signed-off-by: Chris Mason +Reviewed-by: Alice Ryhl +Acked-by: Carlos Llamas +Link: https://patch.msgid.link/20260603174506.1957278-1-clm@meta.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..902d164277 --- /dev/null +++ b/queue-7.1/binder-use-list_head-to-initialize-on-stack-list-head.patch @@ -0,0 +1,52 @@ +From stable+bounces-274249-greg=kroah.com@vger.kernel.org Tue Jul 14 15:40:13 2026 +From: Sasha Levin +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 , Greg Kroah-Hartman , Sasha Levin +Message-ID: <20260714134006.2674552-1-sashal@kernel.org> + +From: Jisheng Zhang + +[ 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 +Link: https://patch.msgid.link/20260519055623.13142-1-jszhang@kernel.org +Signed-off-by: Greg Kroah-Hartman +Stable-dep-of: b34826e55aad ("binder: cache secctx size before release zeroes it") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..29e397fd7d --- /dev/null +++ b/queue-7.1/bluetooth-6lowpan-fix-cyclic-locking-warning-on-netdev-unregister.patch @@ -0,0 +1,101 @@ +From stable+bounces-275034-greg=kroah.com@vger.kernel.org Wed Jul 15 22:50:26 2026 +From: Sasha Levin +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 , Luiz Augusto von Dentz , Sasha Levin +Message-ID: <20260715204940.205049-1-sashal@kernel.org> + +From: Pauli Virtanen + +[ 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 +Signed-off-by: Luiz Augusto von Dentz +Stable-dep-of: 6fef032af009 ("Bluetooth: L2CAP: Fix use-after-free in l2cap_sock_new_connection_cb()") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..224fdb8e80 --- /dev/null +++ b/queue-7.1/bluetooth-l2cap-fix-use-after-free-in-l2cap_sock_new_connection_cb.patch @@ -0,0 +1,542 @@ +From stable+bounces-275035-greg=kroah.com@vger.kernel.org Wed Jul 15 22:50:33 2026 +From: Sasha Levin +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 , stable@kernel.org, Luiz Augusto von Dentz , Sasha Levin +Message-ID: <20260715204940.205049-2-sashal@kernel.org> + +From: Siwei Zhang + +[ 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 +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..74b50484b6 --- /dev/null +++ b/queue-7.1/bpf-reject-negative-const-offsets-for-buffer-pointers.patch @@ -0,0 +1,112 @@ +From fd4cfa8c8f9a17cdec0539334d28754bc1d8a5d9 Mon Sep 17 00:00:00 2001 +From: Sun Jian +Date: Tue, 14 Jul 2026 02:38:45 -0700 +Subject: bpf: Reject negative const offsets for buffer pointers + +From: Sun Jian + +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 +Acked-by: Shung-Hsi Yu +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 +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..e644768220 --- /dev/null +++ b/queue-7.1/device-property-initialize-the-remaining-fields-of-fwnode_handle-in-fwnode_init.patch @@ -0,0 +1,49 @@ +From stable+bounces-270539-greg=kroah.com@vger.kernel.org Thu Jul 2 16:33:38 2026 +From: Sasha Levin +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 , Sakari Ailus , "Rafael J. Wysocki (Intel)" , Andy Shevchenko , Danilo Krummrich , Sasha Levin +Message-ID: <20260702142956.3485868-1-sashal@kernel.org> + +From: Bartosz Golaszewski + +[ 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 +Reviewed-by: Rafael J. Wysocki (Intel) +Reviewed-by: Andy Shevchenko +Signed-off-by: Bartosz Golaszewski +Link: https://patch.msgid.link/20260511074927.9473-1-bartosz.golaszewski@oss.qualcomm.com +[ Fix typo in commit message. - Danilo ] +Signed-off-by: Danilo Krummrich +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..2d08a79644 --- /dev/null +++ b/queue-7.1/f2fs-fix-listxattr-handling-of-corrupted-xattr-entries.patch @@ -0,0 +1,51 @@ +From stable+bounces-271849-greg=kroah.com@vger.kernel.org Fri Jul 3 20:30:08 2026 +From: Sasha Levin +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 , stable@kernel.org, Chao Yu , Jaegeuk Kim , Sasha Levin +Message-ID: <20260703182422.255104-1-sashal@kernel.org> + +From: Keshav Verma + +[ 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 +Signed-off-by: Keshav Verma +Signed-off-by: Jaegeuk Kim +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..ba8f7b8f18 --- /dev/null +++ b/queue-7.1/f2fs-fix-potential-deadlock-in-f2fs_balance_fs.patch @@ -0,0 +1,253 @@ +From stable+bounces-271803-greg=kroah.com@vger.kernel.org Fri Jul 3 16:35:38 2026 +From: Sasha Levin +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 , Chao Yu , Jaegeuk Kim , Sasha Levin +Message-ID: <20260703142630.55436-1-sashal@kernel.org> + +From: Ruipeng Qi + +[ 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 +Reviewed-by: Chao Yu +Signed-off-by: Ruipeng Qi +Signed-off-by: Jaegeuk Kim +Stable-dep-of: 8b4468ec023d ("f2fs: fix potential deadlock in gc_merge path of f2fs_balance_fs()") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..10081b74c0 --- /dev/null +++ b/queue-7.1/f2fs-fix-potential-deadlock-in-gc_merge-path-of-f2fs_balance_fs.patch @@ -0,0 +1,85 @@ +From stable+bounces-271804-greg=kroah.com@vger.kernel.org Fri Jul 3 16:35:31 2026 +From: Sasha Levin +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 , stable@kernel.org, Ruipeng Qi , Chao Yu , Jaegeuk Kim , Sasha Levin +Message-ID: <20260703142630.55436-2-sashal@kernel.org> + +From: Chao Yu + +[ 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 +Reported: Sandeep Dhavale +Signed-off-by: Chao Yu +Signed-off-by: Chao Yu +Signed-off-by: Jaegeuk Kim +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..86900624a7 --- /dev/null +++ b/queue-7.1/firmware_loader-add-cancel-helper-for-async-requests.patch @@ -0,0 +1,180 @@ +From stable+bounces-274106-greg=kroah.com@vger.kernel.org Tue Jul 14 05:33:02 2026 +From: Sasha Levin +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" , "Takashi Iwai" , "Danilo Krummrich" , "Sasha Levin" +Message-ID: <20260714033256.2396704-1-sashal@kernel.org> + +From: Cássio Gabriel + +[ 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 +Reviewed-by: Takashi Iwai +Acked-by: Danilo Krummrich +Signed-off-by: Takashi Iwai +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 +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..e05799adb8 --- /dev/null +++ b/queue-7.1/iio-hid-sensor-rotation-fix-stale-or-zero-output-when-reading-raw-values.patch @@ -0,0 +1,89 @@ +From stable+bounces-273928-greg=kroah.com@vger.kernel.org Mon Jul 13 19:54:51 2026 +From: Sasha Levin +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 , Andy Shevchenko , Stable@vger.kernel.org, Jonathan Cameron , Sasha Levin +Message-ID: <20260713175324.1902799-2-sashal@kernel.org> + +From: Zhang Lixu + +[ 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 +Reviewed-by: Andy Shevchenko +Cc: +Signed-off-by: Jonathan Cameron +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..0fbdf69285 --- /dev/null +++ b/queue-7.1/ksmbd-fix-path-resolution-in-ksmbd_vfs_kern_path_create.patch @@ -0,0 +1,139 @@ +From stable+bounces-275120-greg=kroah.com@vger.kernel.org Thu Jul 16 03:45:28 2026 +From: Sasha Levin +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 , Namjae Jeon , Steve French , Sasha Levin +Message-ID: <20260716014517.777818-1-sashal@kernel.org> + +From: Davide Ornaghi + +[ 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 +Acked-by: Namjae Jeon +Signed-off-by: Steve French +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..3c69b8d013 --- /dev/null +++ b/queue-7.1/ksmbd-use-opener-credentials-for-fsctl-mutations.patch @@ -0,0 +1,86 @@ +From stable+bounces-275125-greg=kroah.com@vger.kernel.org Thu Jul 16 04:06:24 2026 +From: Sasha Levin +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 , Musaab Khan , Steve French , Sasha Levin +Message-ID: <20260716020558.818894-2-sashal@kernel.org> + +From: Namjae Jeon + +[ 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 +Signed-off-by: Namjae Jeon +Signed-off-by: Steve French +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..7e506c8e7f --- /dev/null +++ b/queue-7.1/liveupdate-validate-session-type-before-performing-operation.patch @@ -0,0 +1,122 @@ +From stable+bounces-278284-greg=kroah.com@vger.kernel.org Tue Jul 21 02:45:22 2026 +From: Sasha Levin +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)" , "Mike Rapoport (Microsoft)" , Sasha Levin +Message-ID: <20260721004514.3421718-1-sashal@kernel.org> + +From: "Pratyush Yadav (Google)" + +[ 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) +Link: https://patch.msgid.link/20260519122428.2378446-1-pratyush@kernel.org +Signed-off-by: Mike Rapoport (Microsoft) +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..cc6197eb80 --- /dev/null +++ b/queue-7.1/mm-damon-core-trace-esz-at-first-setup.patch @@ -0,0 +1,57 @@ +From 7e6cc35f5283eab81a14231a64ecd640b690c48c Mon Sep 17 00:00:00 2001 +From: SeongJae Park +Date: Wed, 20 May 2026 08:03:10 -0700 +Subject: mm/damon/core: trace esz at first setup + +From: SeongJae Park + +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 +Cc: # 6.17.x +Signed-off-by: Andrew Morton +Signed-off-by: SJ Park +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..4fc1c9ae2a --- /dev/null +++ b/queue-7.1/samples-damon-mtier-fail-early-if-address-range-parameters-are-invalid.patch @@ -0,0 +1,74 @@ +From 7746d72c64054976887928d64d2caf25c5a6dcc0 Mon Sep 17 00:00:00 2001 +From: Zenghui Yu +Date: Mon, 29 Jun 2026 07:44:31 -0700 +Subject: samples/damon/mtier: fail early if address range parameters are invalid + +From: Zenghui Yu + +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 +Signed-off-by: SJ Park +Reviewed-by: SJ Park +Cc: # 6.16.x +Signed-off-by: Andrew Morton +Signed-off-by: SJ Park +Signed-off-by: Greg Kroah-Hartman +--- + 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; diff --git a/queue-7.1/series b/queue-7.1/series index cc8e2f4624..6db93ab729 100644 --- a/queue-7.1/series +++ b/queue-7.1/series @@ -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 index 0000000000..1ee7d1569d --- /dev/null +++ b/queue-7.1/smb-move-compression-definitions-into-common-fscc.h.patch @@ -0,0 +1,94 @@ +From stable+bounces-275124-greg=kroah.com@vger.kernel.org Thu Jul 16 04:06:08 2026 +From: Sasha Levin +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 , Namjae Jeon , Steve French , Sasha Levin +Message-ID: <20260716020558.818894-1-sashal@kernel.org> + +From: ChenXiaoSong + +[ Upstream commit 9d357903ec9b0da60cccc4d311f99763ba0924a2 ] + +These definitions will also be used by ksmbd, move them into +common header file. + +Signed-off-by: ChenXiaoSong +Acked-by: Namjae Jeon +Signed-off-by: Steve French +Stable-dep-of: c6394bcaf254 ("ksmbd: use opener credentials for FSCTL mutations") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..34a1edb1ec --- /dev/null +++ b/queue-7.1/usb-atm-ueagle-atm-remove-function-entry-exit-debug-messages.patch @@ -0,0 +1,337 @@ +From stable+bounces-277393-greg=kroah.com@vger.kernel.org Sat Jul 18 23:50:41 2026 +From: Sasha Levin +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 , Greg Kroah-Hartman , Stanislaw Gruszka , Sasha Levin +Message-ID: <20260718215033.3447737-2-sashal@kernel.org> + +From: Mauricio Faria de Oliveira + +[ 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 +Link: https://lore.kernel.org/all/2026051657-scruffy-embark-45ea@gregkh/ +Signed-off-by: Mauricio Faria de Oliveira +Acked-by: Stanislaw Gruszka +Link: https://patch.msgid.link/20260520-ueagle-atm-cleanup-v1-2-010c8bc7b214@igalia.com +Signed-off-by: Greg Kroah-Hartman +Stable-dep-of: e2674dfbed8a ("usb: atm: ueagle-atm: wait for pre-firmware load in .disconnect()") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..637dedb46d --- /dev/null +++ b/queue-7.1/usb-atm-ueagle-atm-use-dev_dbg-for-device-found-message.patch @@ -0,0 +1,47 @@ +From sashal@kernel.org Sat Jul 18 23:50:36 2026 +From: Sasha Levin +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 , Greg Kroah-Hartman , Stanislaw Gruszka , Sasha Levin +Message-ID: <20260718215033.3447737-1-sashal@kernel.org> + +From: Mauricio Faria de Oliveira + +[ 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 +Link: https://lore.kernel.org/all/2026051628-squatter-stature-c0e0@gregkh/ +Signed-off-by: Mauricio Faria de Oliveira +Acked-by: Stanislaw Gruszka +Link: https://patch.msgid.link/20260520-ueagle-atm-cleanup-v1-1-010c8bc7b214@igalia.com +Signed-off-by: Greg Kroah-Hartman +Stable-dep-of: e2674dfbed8a ("usb: atm: ueagle-atm: wait for pre-firmware load in .disconnect()") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..ab9ce6a249 --- /dev/null +++ b/queue-7.1/usb-atm-ueagle-atm-wait-for-pre-firmware-load-in-.disconnect.patch @@ -0,0 +1,175 @@ +From stable+bounces-277394-greg=kroah.com@vger.kernel.org Sat Jul 18 23:51:42 2026 +From: Sasha Levin +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 , stable , syzbot+ce1e5a1b4e086b43e56d@syzkaller.appspotmail.com, syzbot+306212936b13e520679d@syzkaller.appspotmail.com, syzbot+457452d30bcdda75ead2@syzkaller.appspotmail.com, Andrey Tsygunka , Stanislaw Gruszka , Greg Kroah-Hartman , Sasha Levin +Message-ID: <20260718215033.3447737-3-sashal@kernel.org> + +From: Mauricio Faria de Oliveira + +[ 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 + +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 +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 +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 +Acked-by: Stanislaw Gruszka +Link: https://patch.msgid.link/20260526-ueagle-atm_req-fw-sync-v3-1-93c01961daaf@igalia.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..174fc839ac --- /dev/null +++ b/queue-7.1/xfs-add-newly-added-rtgs-to-the-free-pool-in-growfs.patch @@ -0,0 +1,46 @@ +From stable+bounces-277304-greg=kroah.com@vger.kernel.org Sat Jul 18 13:51:13 2026 +From: Sasha Levin +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 , Damien Le Moal , "Darrick J. Wong" , Carlos Maiolino , Sasha Levin +Message-ID: <20260718115103.3085836-2-sashal@kernel.org> + +From: Christoph Hellwig + +[ 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 +Reviewed-by: "Darrick J. Wong" +Signed-off-by: Christoph Hellwig +Signed-off-by: Carlos Maiolino +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..1985209d50 --- /dev/null +++ b/queue-7.1/xfs-factor-out-a-xfs_zone_mark_free-helper.patch @@ -0,0 +1,78 @@ +From stable+bounces-277303-greg=kroah.com@vger.kernel.org Sat Jul 18 13:51:10 2026 +From: Sasha Levin +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 , Damien Le Moal , "Darrick J. Wong" , Carlos Maiolino , Sasha Levin +Message-ID: <20260718115103.3085836-1-sashal@kernel.org> + +From: Christoph Hellwig + +[ 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 +Reviewed-by: Damien Le Moal +Reviewed-by: "Darrick J. Wong" +Signed-off-by: Carlos Maiolino +Stable-dep-of: ae3692c7f440 ("xfs: add newly added RTGs to the free pool in growfs") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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);