From: Greg Kroah-Hartman Date: Fri, 5 Jun 2026 15:53:25 +0000 (+0200) Subject: 7.0-stable patches X-Git-Tag: v6.12.93~28 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=37de090caf841dfc17f4671db15c7d8e2b1dc54b;p=thirdparty%2Fkernel%2Fstable-queue.git 7.0-stable patches added patches: alsa-hda-realtek-fix-mute-and-mic-mute-leds-for-hp-16-piston-omnibook-x.patch alsa-hda-realtek-fix-mute-and-mic-mute-leds-for-hp-envy-x360-15-fh0xxx.patch arm64-tlb-flush-walk-cache-when-unsharing-pmd-tables.patch hwmon-pmbus-add-support-for-guarded-pmbus-lock.patch hwmon-pmbus-adm1266-serialize-gpio-pmbus-accesses-with-pmbus_lock.patch hwmon-pmbus-adm1266-serialize-sequencer_state-debugfs-read-with-pmbus_lock.patch i2c-tegra-make-tegra_i2c_mutex_unlock-return-void.patch platform-x86-intel-vsec-fix-enable_cnt-imbalance-on-pcie-error-recovery.patch platform-x86-intel-vsec-make-driver_data-info-const.patch platform-x86-intel-vsec-refactor-base_addr-handling.patch revert-mm-hugetlbfs-update-hugetlbfs-to-use-mmap_prepare.patch rxrpc-fix-response-packet-verification-to-extract-skb-to-a-linear-buffer.patch --- diff --git a/queue-7.0/alsa-hda-realtek-fix-mute-and-mic-mute-leds-for-hp-16-piston-omnibook-x.patch b/queue-7.0/alsa-hda-realtek-fix-mute-and-mic-mute-leds-for-hp-16-piston-omnibook-x.patch new file mode 100644 index 0000000000..a344b74df8 --- /dev/null +++ b/queue-7.0/alsa-hda-realtek-fix-mute-and-mic-mute-leds-for-hp-16-piston-omnibook-x.patch @@ -0,0 +1,37 @@ +From stable+bounces-256826-greg=kroah.com@vger.kernel.org Sat May 30 01:40:16 2026 +From: Sasha Levin +Date: Fri, 29 May 2026 19:38:33 -0400 +Subject: ALSA: hda/realtek: Fix mute and mic-mute LEDs for HP 16 Piston OmniBook X +To: stable@vger.kernel.org +Cc: Zhang Heng , Takashi Iwai , Sasha Levin +Message-ID: <20260529233833.1909329-2-sashal@kernel.org> + +From: Zhang Heng + +[ Upstream commit 9e5fb6098d21e1f9be9982b46c3e5b8329d4e7d2 ] + +The ALC245 sound card on this machine requires the quirk +`ALC245_FIXUP_HP_ENVY_X360_15_FH0XXX` to fix the mic and mute LED. + +Link: https://bugzilla.kernel.org/show_bug.cgi?id=221509 +Cc: +Signed-off-by: Zhang Heng +Link: https://patch.msgid.link/20260519015535.891156-1-zhangheng@kylinos.cn +Signed-off-by: Takashi Iwai +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + sound/hda/codecs/realtek/alc269.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/sound/hda/codecs/realtek/alc269.c ++++ b/sound/hda/codecs/realtek/alc269.c +@@ -7182,7 +7182,7 @@ static const struct hda_quirk alc269_fix + SND_PCI_QUIRK(0x103c, 0x8da0, "HP 16 Clipper OmniBook 7(X360)", ALC287_FIXUP_CS35L41_I2C_2), + SND_PCI_QUIRK(0x103c, 0x8da1, "HP 16 Clipper OmniBook X", ALC287_FIXUP_CS35L41_I2C_2), + SND_PCI_QUIRK(0x103c, 0x8da7, "HP 14 Enstrom OmniBook X", ALC287_FIXUP_CS35L41_I2C_2), +- SND_PCI_QUIRK(0x103c, 0x8da8, "HP 16 Piston OmniBook X", ALC287_FIXUP_CS35L41_I2C_2), ++ SND_PCI_QUIRK(0x103c, 0x8da8, "HP 16 Piston OmniBook X", ALC245_FIXUP_HP_ENVY_X360_15_FH0XXX), + SND_PCI_QUIRK(0x103c, 0x8dc9, "HP Laptop 15-fc0xxx", ALC236_FIXUP_HP_DMIC), + SND_PCI_QUIRK(0x103c, 0x8dd4, "HP EliteStudio 8 AIO", ALC274_FIXUP_HP_AIO_BIND_DACS), + SND_PCI_QUIRK(0x103c, 0x8dd7, "HP Laptop 15-fd0xxx", ALC236_FIXUP_HP_MUTE_LED_COEFBIT2), diff --git a/queue-7.0/alsa-hda-realtek-fix-mute-and-mic-mute-leds-for-hp-envy-x360-15-fh0xxx.patch b/queue-7.0/alsa-hda-realtek-fix-mute-and-mic-mute-leds-for-hp-envy-x360-15-fh0xxx.patch new file mode 100644 index 0000000000..158520f28f --- /dev/null +++ b/queue-7.0/alsa-hda-realtek-fix-mute-and-mic-mute-leds-for-hp-envy-x360-15-fh0xxx.patch @@ -0,0 +1,64 @@ +From stable+bounces-256825-greg=kroah.com@vger.kernel.org Sat May 30 01:44:32 2026 +From: Sasha Levin +Date: Fri, 29 May 2026 19:38:32 -0400 +Subject: ALSA: hda/realtek: Fix mute and mic-mute LEDs for HP Envy X360 15-fh0xxx +To: stable@vger.kernel.org +Cc: Fernando Antunez Antonio , Takashi Iwai , Sasha Levin +Message-ID: <20260529233833.1909329-1-sashal@kernel.org> + +From: Fernando Antunez Antonio + +[ Upstream commit dc1e0172be54e742bccb28d5f14c0c395e28c098 ] + +This enables the mute and mic-mute LEDs on the HP Envy X360 15-fh0xxx +2-in-1 laptops. +The quirk 'ALC245_FIXUP_HP_ENVY_X360_15_FH0XXX' has been created and +is now enabled for this device. + +This is my first patch, and I'm still getting to grips with the code, +so there's probably a better way to implement this fix. +I apologize for any inconvenience caused by the constant release of +new versions of this patch. + +Signed-off-by: Fernando Antunez Antonio +Link: https://patch.msgid.link/20260504-hpenvy-muteled-fix-v3-1-5567fd9b3d25@gmail.com +Signed-off-by: Takashi Iwai +Stable-dep-of: 9e5fb6098d21 ("ALSA: hda/realtek: Fix mute and mic-mute LEDs for HP 16 Piston OmniBook X") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + sound/hda/codecs/realtek/alc269.c | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +--- a/sound/hda/codecs/realtek/alc269.c ++++ b/sound/hda/codecs/realtek/alc269.c +@@ -4132,6 +4132,7 @@ enum { + ALC245_FIXUP_ACER_MICMUTE_LED, + ALC245_FIXUP_CS35L41_I2C_2_MUTE_LED, + ALC236_FIXUP_HP_DMIC, ++ ALC245_FIXUP_HP_ENVY_X360_15_FH0XXX, + }; + + /* A special fixup for Lenovo C940 and Yoga Duet 7; +@@ -6678,6 +6679,12 @@ static const struct hda_fixup alc269_fix + { 0x12, 0x90a60160 }, /* use as internal mic */ + { } + }, ++ }, ++ [ALC245_FIXUP_HP_ENVY_X360_15_FH0XXX] = { ++ .type = HDA_FIXUP_FUNC, ++ .v.func = cs35l41_fixup_i2c_two, ++ .chained = true, ++ .chain_id = ALC245_FIXUP_HP_X360_MUTE_LEDS + } + }; + +@@ -7096,7 +7103,7 @@ static const struct hda_quirk alc269_fix + SND_PCI_QUIRK(0x103c, 0x8be6, "HP Envy 16", ALC287_FIXUP_CS35L41_I2C_2), + SND_PCI_QUIRK(0x103c, 0x8be7, "HP Envy 17", ALC287_FIXUP_CS35L41_I2C_2), + SND_PCI_QUIRK(0x103c, 0x8be8, "HP Envy 17", ALC287_FIXUP_CS35L41_I2C_2), +- SND_PCI_QUIRK(0x103c, 0x8be9, "HP Envy 15", ALC287_FIXUP_CS35L41_I2C_2), ++ SND_PCI_QUIRK(0x103c, 0x8be9, "HP Envy x360 2-in-1 Laptop 15-fh0xxx", ALC245_FIXUP_HP_ENVY_X360_15_FH0XXX), + SND_PCI_QUIRK(0x103c, 0x8bf0, "HP", ALC236_FIXUP_HP_GPIO_LED), + SND_PCI_QUIRK(0x103c, 0x8c15, "HP Spectre x360 2-in-1 Laptop 14-eu0xxx", ALC245_FIXUP_HP_SPECTRE_X360_EU0XXX), + SND_PCI_QUIRK(0x103c, 0x8c16, "HP Spectre x360 2-in-1 Laptop 16-aa0xxx", ALC245_FIXUP_HP_SPECTRE_X360_16_AA0XXX), diff --git a/queue-7.0/arm64-tlb-flush-walk-cache-when-unsharing-pmd-tables.patch b/queue-7.0/arm64-tlb-flush-walk-cache-when-unsharing-pmd-tables.patch new file mode 100644 index 0000000000..987deff912 --- /dev/null +++ b/queue-7.0/arm64-tlb-flush-walk-cache-when-unsharing-pmd-tables.patch @@ -0,0 +1,55 @@ +From stable+bounces-259315-greg=kroah.com@vger.kernel.org Sun May 31 02:24:01 2026 +From: Sasha Levin +Date: Sat, 30 May 2026 20:23:54 -0400 +Subject: arm64: tlb: Flush walk cache when unsharing PMD tables +To: stable@vger.kernel.org +Cc: Zeng Heng , Catalin Marinas , Sasha Levin +Message-ID: <20260531002354.3659423-1-sashal@kernel.org> + +From: Zeng Heng + +[ Upstream commit c2ff4764e03e7a8d758352f4aceb8fe1be6ac971 ] + +When huge_pmd_unshare() is called to unshare a PMD table, the +tlb_unshare_pmd_ptdesc() function sets tlb->unshared_tables=true +but the aarch64 tlb_flush() only checked tlb->freed_tables to +determine whether to use TLBF_NONE (vae1is, invalidates walk +cache) or TLBF_NOWALKCACHE (vale1is, leaf-only). + +This caused the stale PMD page table entry to remain in the walk cache +after unshare, potentially leading to incorrect page table walks. + +Fix by including unshared_tables in the check, so that when +unsharing tables, TLBF_NONE is used and the walk cache is properly +invalidated. + +Here is the detailed distinction between vae1is and vale1is: + +| Instruction Combination | Actual Invalidation Scope | +| ------------------------ | --------------------------------------------------| +| `VAE1IS` + TTL=`0` | All entries at all levels (full invalidation) | +| `VAE1IS` + TTL=`2` (L2) | Non-leaf at Level 0/1 + leaf at Level 2 | +| `VALE1IS` + TTL=`0` | Leaf entries at all levels (non-leaf not cleared) | +| `VALE1IS` + TTL=`2` (L2) | Leaf entry at Level 2 only | + +Signed-off-by: Zeng Heng +Fixes: 8ce720d5bd91 ("mm/hugetlb: fix excessive IPI broadcasts when unsharing PMD tables using mmu_gather") +Cc: +Signed-off-by: Catalin Marinas +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + arch/arm64/include/asm/tlb.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/arch/arm64/include/asm/tlb.h ++++ b/arch/arm64/include/asm/tlb.h +@@ -53,7 +53,7 @@ static inline int tlb_get_level(struct m + static inline void tlb_flush(struct mmu_gather *tlb) + { + struct vm_area_struct vma = TLB_FLUSH_VMA(tlb->mm, 0); +- bool last_level = !tlb->freed_tables; ++ bool last_level = !(tlb->freed_tables || tlb->unshared_tables); + unsigned long stride = tlb_get_unmap_size(tlb); + int tlb_level = tlb_get_level(tlb); + diff --git a/queue-7.0/hwmon-pmbus-add-support-for-guarded-pmbus-lock.patch b/queue-7.0/hwmon-pmbus-add-support-for-guarded-pmbus-lock.patch new file mode 100644 index 0000000000..32dcf9c4de --- /dev/null +++ b/queue-7.0/hwmon-pmbus-add-support-for-guarded-pmbus-lock.patch @@ -0,0 +1,67 @@ +From stable+bounces-259547-greg=kroah.com@vger.kernel.org Mon Jun 1 14:47:51 2026 +From: Sasha Levin +Date: Mon, 1 Jun 2026 08:37:12 -0400 +Subject: hwmon: (pmbus) Add support for guarded PMBus lock +To: stable@vger.kernel.org +Cc: Guenter Roeck , Sanman Pradhan , Sasha Levin +Message-ID: <20260601123713.718815-1-sashal@kernel.org> + +From: Guenter Roeck + +[ Upstream commit 1814f4d3ff358277a5b6957e7f133c2812dc80ec ] + +Add support for guard(pmbus_lock)() and scoped_guard(pmbus_lock)() +to be able to simplify the PMBus code. + +Also introduce pmbus_lock() as pre-requisite for supporting +guard(). + +Reviewed-by: Sanman Pradhan +Signed-off-by: Guenter Roeck +Stable-dep-of: 4e4af55aaca7 ("hwmon: (pmbus/adm1266) serialize sequencer_state debugfs read with pmbus_lock") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/hwmon/pmbus/pmbus.h | 5 +++++ + drivers/hwmon/pmbus/pmbus_core.c | 8 ++++++++ + 2 files changed, 13 insertions(+) + +--- a/drivers/hwmon/pmbus/pmbus.h ++++ b/drivers/hwmon/pmbus/pmbus.h +@@ -10,6 +10,7 @@ + #define PMBUS_H + + #include ++#include + #include + + /* +@@ -563,7 +564,11 @@ int pmbus_get_fan_rate_device(struct i2c + int pmbus_get_fan_rate_cached(struct i2c_client *client, int page, int id, + enum pmbus_fan_mode mode); + int pmbus_lock_interruptible(struct i2c_client *client); ++void pmbus_lock(struct i2c_client *client); + void pmbus_unlock(struct i2c_client *client); ++ ++DEFINE_GUARD(pmbus_lock, struct i2c_client *, pmbus_lock(_T), pmbus_unlock(_T)) ++ + int pmbus_update_fan(struct i2c_client *client, int page, int id, + u8 config, u8 mask, u16 command); + struct dentry *pmbus_get_debugfs_dir(struct i2c_client *client); +--- a/drivers/hwmon/pmbus/pmbus_core.c ++++ b/drivers/hwmon/pmbus/pmbus_core.c +@@ -3871,6 +3871,14 @@ struct dentry *pmbus_get_debugfs_dir(str + } + EXPORT_SYMBOL_NS_GPL(pmbus_get_debugfs_dir, "PMBUS"); + ++void pmbus_lock(struct i2c_client *client) ++{ ++ struct pmbus_data *data = i2c_get_clientdata(client); ++ ++ mutex_lock(&data->update_lock); ++} ++EXPORT_SYMBOL_NS_GPL(pmbus_lock, "PMBUS"); ++ + int pmbus_lock_interruptible(struct i2c_client *client) + { + struct pmbus_data *data = i2c_get_clientdata(client); diff --git a/queue-7.0/hwmon-pmbus-adm1266-serialize-gpio-pmbus-accesses-with-pmbus_lock.patch b/queue-7.0/hwmon-pmbus-adm1266-serialize-gpio-pmbus-accesses-with-pmbus_lock.patch new file mode 100644 index 0000000000..f43b37bc51 --- /dev/null +++ b/queue-7.0/hwmon-pmbus-adm1266-serialize-gpio-pmbus-accesses-with-pmbus_lock.patch @@ -0,0 +1,66 @@ +From stable+bounces-259561-greg=kroah.com@vger.kernel.org Mon Jun 1 15:41:33 2026 +From: Sasha Levin +Date: Mon, 1 Jun 2026 09:36:11 -0400 +Subject: hwmon: (pmbus/adm1266) serialize GPIO PMBus accesses with pmbus_lock +To: stable@vger.kernel.org +Cc: Abdurrahman Hussain , Bartosz Golaszewski , Guenter Roeck , Sasha Levin +Message-ID: <20260601133611.789541-2-sashal@kernel.org> + +From: Abdurrahman Hussain + +[ Upstream commit bab8c6fb5af8df7e753d196c1262cb78e92ca872 ] + +adm1266_gpio_get(), adm1266_gpio_get_multiple(), and +adm1266_gpio_dbg_show() all issue PMBus reads against the device but +none of them take pmbus_lock. The pmbus_core framework holds +pmbus_lock around its own multi-transaction sequences (notably the +"set PAGE, then read paged register" pattern used by hwmon +attributes), so an unlocked GPIO accessor can land between a PAGE +write and the subsequent paged read in another thread and corrupt +either side's view of the device state machine. + +Take pmbus_lock at the top of each of the three accessors via the +scope-based guard(). The lock is uncontended in the common case and +adds only a single mutex round-trip per call. + +Fixes: d98dfad35c38 ("hwmon: (pmbus/adm1266) Add support for GPIOs") +Cc: stable@vger.kernel.org +Signed-off-by: Abdurrahman Hussain +Reviewed-by: Bartosz Golaszewski +Link: https://lore.kernel.org/r/20260518-adm1266-gpio-fixes-v3-6-e425e4f88139@nexthop.ai +Signed-off-by: Guenter Roeck +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/hwmon/pmbus/adm1266.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +--- a/drivers/hwmon/pmbus/adm1266.c ++++ b/drivers/hwmon/pmbus/adm1266.c +@@ -173,6 +173,8 @@ static int adm1266_gpio_get(struct gpio_ + else + pmbus_cmd = ADM1266_PDIO_STATUS; + ++ guard(pmbus_lock)(data->client); ++ + ret = i2c_smbus_read_block_data(data->client, pmbus_cmd, read_buf); + if (ret < 0) + return ret; +@@ -195,6 +197,8 @@ static int adm1266_gpio_get_multiple(str + unsigned int gpio_nr; + int ret; + ++ guard(pmbus_lock)(data->client); ++ + ret = i2c_smbus_read_block_data(data->client, ADM1266_GPIO_STATUS, read_buf); + if (ret < 0) + return ret; +@@ -236,6 +240,8 @@ static void adm1266_gpio_dbg_show(struct + int ret; + int i; + ++ guard(pmbus_lock)(data->client); ++ + for (i = 0; i < ADM1266_GPIO_NR; i++) { + write_cmd = adm1266_gpio_mapping[i][1]; + ret = adm1266_pmbus_block_xfer(data, ADM1266_GPIO_CONFIG, 1, &write_cmd, read_buf); diff --git a/queue-7.0/hwmon-pmbus-adm1266-serialize-sequencer_state-debugfs-read-with-pmbus_lock.patch b/queue-7.0/hwmon-pmbus-adm1266-serialize-sequencer_state-debugfs-read-with-pmbus_lock.patch new file mode 100644 index 0000000000..6c4bd4e90a --- /dev/null +++ b/queue-7.0/hwmon-pmbus-adm1266-serialize-sequencer_state-debugfs-read-with-pmbus_lock.patch @@ -0,0 +1,48 @@ +From stable+bounces-259548-greg=kroah.com@vger.kernel.org Mon Jun 1 14:39:45 2026 +From: Sasha Levin +Date: Mon, 1 Jun 2026 08:37:13 -0400 +Subject: hwmon: (pmbus/adm1266) serialize sequencer_state debugfs read with pmbus_lock +To: stable@vger.kernel.org +Cc: Abdurrahman Hussain , Guenter Roeck , Sasha Levin +Message-ID: <20260601123713.718815-2-sashal@kernel.org> + +From: Abdurrahman Hussain + +[ Upstream commit 4e4af55aaca7f6d7673d5f9889ad0529db86a048 ] + +adm1266_state_read() backs the sequencer_state debugfs entry and +issues an i2c_smbus_read_word_data(client, ADM1266_READ_STATE) +against the device without taking pmbus_lock. pmbus_core holds +pmbus_lock around its own multi-transaction sequences (notably the +"set PAGE, then read paged register" pattern used by hwmon +attributes), so an unlocked debugfs reader can land between a PAGE +write and the subsequent paged read in another thread. READ_STATE +itself is not paged, so it cannot corrupt PAGE in flight, but the +same defensive serialisation that applies to the GPIO accessors +applies here: any direct device access from outside pmbus_core +should be ordered with respect to pmbus_core's own. + +Take pmbus_lock at the top of adm1266_state_read() via the +scope-based guard(). + +Fixes: ed1ff457e187 ("hwmon: (pmbus/adm1266) add debugfs for states") +Cc: stable@vger.kernel.org +Signed-off-by: Abdurrahman Hussain +Link: https://lore.kernel.org/r/20260518-adm1266-gpio-fixes-v3-8-e425e4f88139@nexthop.ai +Signed-off-by: Guenter Roeck +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/hwmon/pmbus/adm1266.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/hwmon/pmbus/adm1266.c ++++ b/drivers/hwmon/pmbus/adm1266.c +@@ -328,6 +328,7 @@ static int adm1266_state_read(struct seq + struct i2c_client *client = to_i2c_client(dev); + int ret; + ++ guard(pmbus_lock)(client); + ret = i2c_smbus_read_word_data(client, ADM1266_READ_STATE); + if (ret < 0) + return ret; diff --git a/queue-7.0/i2c-tegra-make-tegra_i2c_mutex_unlock-return-void.patch b/queue-7.0/i2c-tegra-make-tegra_i2c_mutex_unlock-return-void.patch new file mode 100644 index 0000000000..5039bb5e22 --- /dev/null +++ b/queue-7.0/i2c-tegra-make-tegra_i2c_mutex_unlock-return-void.patch @@ -0,0 +1,78 @@ +From stable+bounces-259391-greg=kroah.com@vger.kernel.org Mon Jun 1 02:40:56 2026 +From: Sasha Levin +Date: Sun, 31 May 2026 20:38:43 -0400 +Subject: i2c: tegra: make tegra_i2c_mutex_unlock() return void +To: stable@vger.kernel.org +Cc: Saurav Sachidanand , Jon Hunter , Thierry Reding , Andi Shyti , Sasha Levin +Message-ID: <20260601003844.82662-1-sashal@kernel.org> + +From: Saurav Sachidanand + +[ Upstream commit 30792d12842901f5276f466a960962d5bfa15cc8 ] + +tegra_i2c_mutex_unlock() returning an error that overwrites the transfer +result causes silent loss of I2C transfer errors. If the transfer failed +but the unlock succeeded, the error was lost and the function incorrectly +reported success. + +Rather than propagating the unlock error (which is not actionable by the +caller - the I2C message may have been sent regardless), convert the +function to return void and WARN on the unexpected condition. If the +unlock fails, subsequent lock attempts will fail anyway, making the error +visible on the next transfer. + +Fixes: 6077cfd716fb ("i2c: tegra: Add support for SW mutex register") +Signed-off-by: Saurav Sachidanand +Cc: # v7.0+ +Reviewed-by: Jon Hunter +Acked-by: Thierry Reding +Signed-off-by: Andi Shyti +Link: https://lore.kernel.org/r/20260507221145.62183-3-sauravsc@amazon.com +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/i2c/busses/i2c-tegra.c | 15 ++++++--------- + 1 file changed, 6 insertions(+), 9 deletions(-) + +--- a/drivers/i2c/busses/i2c-tegra.c ++++ b/drivers/i2c/busses/i2c-tegra.c +@@ -445,25 +445,22 @@ static int tegra_i2c_mutex_lock(struct t + return ret; + } + +-static int tegra_i2c_mutex_unlock(struct tegra_i2c_dev *i2c_dev) ++static void tegra_i2c_mutex_unlock(struct tegra_i2c_dev *i2c_dev) + { + unsigned int reg = tegra_i2c_reg_addr(i2c_dev, I2C_SW_MUTEX); + u32 val, id; + + if (!i2c_dev->hw->has_mutex) +- return 0; ++ return; + + val = readl(i2c_dev->base + reg); + + id = FIELD_GET(I2C_SW_MUTEX_GRANT, val); +- if (id && id != I2C_SW_MUTEX_ID_CCPLEX) { +- dev_warn(i2c_dev->dev, "unable to unlock mutex, mutex is owned by: %u\n", id); +- return -EPERM; +- } ++ if (WARN(id && id != I2C_SW_MUTEX_ID_CCPLEX, ++ "unable to unlock mutex, mutex is owned by: %u\n", id)) ++ return; + + writel(0, i2c_dev->base + reg); +- +- return 0; + } + + static void tegra_i2c_mask_irq(struct tegra_i2c_dev *i2c_dev, u32 mask) +@@ -1556,7 +1553,7 @@ static int tegra_i2c_xfer(struct i2c_ada + break; + } + +- ret = tegra_i2c_mutex_unlock(i2c_dev); ++ tegra_i2c_mutex_unlock(i2c_dev); + pm_runtime_put(i2c_dev->dev); + + return ret ?: i; diff --git a/queue-7.0/platform-x86-intel-vsec-fix-enable_cnt-imbalance-on-pcie-error-recovery.patch b/queue-7.0/platform-x86-intel-vsec-fix-enable_cnt-imbalance-on-pcie-error-recovery.patch new file mode 100644 index 0000000000..5a69e55bd3 --- /dev/null +++ b/queue-7.0/platform-x86-intel-vsec-fix-enable_cnt-imbalance-on-pcie-error-recovery.patch @@ -0,0 +1,131 @@ +From stable+bounces-256662-greg=kroah.com@vger.kernel.org Fri May 29 19:24:15 2026 +From: Sasha Levin +Date: Fri, 29 May 2026 12:51:40 -0400 +Subject: platform/x86/intel/vsec: Fix enable_cnt imbalance on PCIe error recovery +To: stable@vger.kernel.org +Cc: "Lukas Wunner" , "Ilpo Järvinen" , "Sasha Levin" +Message-ID: <20260529165140.1230013-3-sashal@kernel.org> + +From: Lukas Wunner + +[ Upstream commit 348ccc754d8939e21ca5956ff45720b81d6e407f ] + +After a PCIe Uncorrectable Error has been reported by a device with +Intel Vendor Specific Extended Capabilities and has been recovered +through a Secondary Bus Reset, its driver calls intel_vsec_pci_probe() +to rescan and reinitialize VSECs. + +intel_vsec_pci_probe() invokes pcim_enable_device() and thereby adds +another devm action which calls pcim_disable_device() on driver unbind. + +So once the driver unbinds, pcim_disable_device() will be called as many +times as an Uncorrectable Error occurred, plus one. This will lead to +an enable_cnt imbalance on driver unbind. + +Additionally, since commit dc957ab6aa05 ("platform/x86/intel/vsec: Add +private data for per-device data"), a devm_kzalloc() allocation is +leaked on every Uncorrectable Error. + +Avoid by splitting the VSEC rescan out of intel_vsec_pci_probe() into a +separate helper and calling that on PCIe error recovery. + +Fixes: 936874b77dd0 ("platform/x86/intel/vsec: Add PCI error recovery support to Intel PMT") +Signed-off-by: Lukas Wunner +Cc: stable@vger.kernel.org # v6.0+ +Link: https://patch.msgid.link/bd594d09fa866dc51dddc9a447c3b23f9b1402cc.1778736835.git.lukas@wunner.de +Reviewed-by: Ilpo Järvinen +Signed-off-by: Ilpo Järvinen +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/platform/x86/intel/vsec.c | 54 +++++++++++++++++++++----------------- + 1 file changed, 30 insertions(+), 24 deletions(-) + +--- a/drivers/platform/x86/intel/vsec.c ++++ b/drivers/platform/x86/intel/vsec.c +@@ -620,29 +620,13 @@ static void intel_vsec_skip_missing_depe + } + } + +-static int intel_vsec_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) ++static int intel_vsec_pci_init(struct pci_dev *pdev) + { +- const struct intel_vsec_platform_info *info; +- struct vsec_priv *priv; +- int num_caps, ret; ++ struct vsec_priv *priv = pci_get_drvdata(pdev); ++ const struct intel_vsec_platform_info *info = priv->info; + int run_once = 0; + bool found_any = false; +- +- ret = pcim_enable_device(pdev); +- if (ret) +- return ret; +- +- pci_save_state(pdev); +- info = (const struct intel_vsec_platform_info *)id->driver_data; +- if (!info) +- return -EINVAL; +- +- priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); +- if (!priv) +- return -ENOMEM; +- +- priv->info = info; +- pci_set_drvdata(pdev, priv); ++ int num_caps; + + num_caps = hweight_long(info->caps); + while (num_caps--) { +@@ -663,6 +647,31 @@ static int intel_vsec_pci_probe(struct p + return 0; + } + ++static int intel_vsec_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) ++{ ++ const struct intel_vsec_platform_info *info; ++ struct vsec_priv *priv; ++ int ret; ++ ++ ret = pcim_enable_device(pdev); ++ if (ret) ++ return ret; ++ ++ pci_save_state(pdev); ++ info = (const struct intel_vsec_platform_info *)id->driver_data; ++ if (!info) ++ return -EINVAL; ++ ++ priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ priv->info = info; ++ pci_set_drvdata(pdev, priv); ++ ++ return intel_vsec_pci_init(pdev); ++} ++ + int intel_vsec_set_mapping(struct oobmsm_plat_info *plat_info, + struct intel_vsec_device *vsec_dev) + { +@@ -800,7 +809,6 @@ static pci_ers_result_t intel_vsec_pci_s + { + struct intel_vsec_device *intel_vsec_dev; + pci_ers_result_t status = PCI_ERS_RESULT_DISCONNECT; +- const struct pci_device_id *pci_dev_id; + unsigned long index; + + dev_info(&pdev->dev, "Resetting PCI slot\n"); +@@ -821,10 +829,8 @@ static pci_ers_result_t intel_vsec_pci_s + devm_release_action(&pdev->dev, intel_vsec_remove_aux, + &intel_vsec_dev->auxdev); + } +- pci_disable_device(pdev); + pci_restore_state(pdev); +- pci_dev_id = pci_match_id(intel_vsec_pci_ids, pdev); +- intel_vsec_pci_probe(pdev, pci_dev_id); ++ intel_vsec_pci_init(pdev); + + out: + return status; diff --git a/queue-7.0/platform-x86-intel-vsec-make-driver_data-info-const.patch b/queue-7.0/platform-x86-intel-vsec-make-driver_data-info-const.patch new file mode 100644 index 0000000000..ec00ea78d4 --- /dev/null +++ b/queue-7.0/platform-x86-intel-vsec-make-driver_data-info-const.patch @@ -0,0 +1,144 @@ +From stable+bounces-256660-greg=kroah.com@vger.kernel.org Fri May 29 19:22:41 2026 +From: Sasha Levin +Date: Fri, 29 May 2026 12:51:39 -0400 +Subject: platform/x86/intel/vsec: Make driver_data info const +To: stable@vger.kernel.org +Cc: "David E. Box" , "Michael J. Ruhl" , "Ilpo Järvinen" , "Sasha Levin" +Message-ID: <20260529165140.1230013-2-sashal@kernel.org> + +From: "David E. Box" + +[ Upstream commit 9577c74c96f88d807d1ba005adbf5952e7127e55 ] + +Treat PCI id->driver_data (intel_vsec_platform_info) as read-only by making +vsec_priv->info a const pointer and updating all function signatures to +accept const intel_vsec_platform_info *. + +This improves const-correctness and clarifies that the platform info data +from the driver_data table is not meant to be modified at runtime. + +No functional changes intended. + +Signed-off-by: David E. Box +Reviewed-by: Michael J. Ruhl +Link: https://patch.msgid.link/20260313015202.3660072-3-david.e.box@linux.intel.com +Reviewed-by: Ilpo Järvinen +Signed-off-by: Ilpo Järvinen +Stable-dep-of: 348ccc754d89 ("platform/x86/intel/vsec: Fix enable_cnt imbalance on PCIe error recovery") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/platform/x86/intel/vsec.c | 20 ++++++++++---------- + include/linux/intel_vsec.h | 4 ++-- + 2 files changed, 12 insertions(+), 12 deletions(-) + +--- a/drivers/platform/x86/intel/vsec.c ++++ b/drivers/platform/x86/intel/vsec.c +@@ -42,7 +42,7 @@ enum vsec_device_state { + }; + + struct vsec_priv { +- struct intel_vsec_platform_info *info; ++ const struct intel_vsec_platform_info *info; + struct device *suppliers[VSEC_FEATURE_COUNT]; + struct oobmsm_plat_info plat_info; + enum vsec_device_state state[VSEC_FEATURE_COUNT]; +@@ -270,7 +270,7 @@ cleanup_aux: + EXPORT_SYMBOL_NS_GPL(intel_vsec_add_aux, "INTEL_VSEC"); + + static int intel_vsec_add_dev(struct pci_dev *pdev, struct intel_vsec_header *header, +- struct intel_vsec_platform_info *info, ++ const struct intel_vsec_platform_info *info, + unsigned long cap_id, u64 base_addr) + { + struct intel_vsec_device __free(kfree) *intel_vsec_dev = NULL; +@@ -406,7 +406,7 @@ static int get_cap_id(u32 header_id, uns + + static int intel_vsec_register_device(struct pci_dev *pdev, + struct intel_vsec_header *header, +- struct intel_vsec_platform_info *info, ++ const struct intel_vsec_platform_info *info, + u64 base_addr) + { + const struct vsec_feature_dependency *consumer_deps; +@@ -452,7 +452,7 @@ static int intel_vsec_register_device(st + } + + static bool intel_vsec_walk_header(struct pci_dev *pdev, +- struct intel_vsec_platform_info *info) ++ const struct intel_vsec_platform_info *info) + { + struct intel_vsec_header **header = info->headers; + bool have_devices = false; +@@ -468,7 +468,7 @@ static bool intel_vsec_walk_header(struc + } + + static bool intel_vsec_walk_dvsec(struct pci_dev *pdev, +- struct intel_vsec_platform_info *info) ++ const struct intel_vsec_platform_info *info) + { + bool have_devices = false; + int pos = 0; +@@ -519,7 +519,7 @@ static bool intel_vsec_walk_dvsec(struct + } + + static bool intel_vsec_walk_vsec(struct pci_dev *pdev, +- struct intel_vsec_platform_info *info) ++ const struct intel_vsec_platform_info *info) + { + bool have_devices = false; + int pos = 0; +@@ -565,7 +565,7 @@ static bool intel_vsec_walk_vsec(struct + } + + int intel_vsec_register(struct pci_dev *pdev, +- struct intel_vsec_platform_info *info) ++ const struct intel_vsec_platform_info *info) + { + if (!pdev || !info || !info->headers) + return -EINVAL; +@@ -578,7 +578,7 @@ int intel_vsec_register(struct pci_dev * + EXPORT_SYMBOL_NS_GPL(intel_vsec_register, "INTEL_VSEC"); + + static bool intel_vsec_get_features(struct pci_dev *pdev, +- struct intel_vsec_platform_info *info) ++ const struct intel_vsec_platform_info *info) + { + bool found = false; + +@@ -622,7 +622,7 @@ static void intel_vsec_skip_missing_depe + + static int intel_vsec_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) + { +- struct intel_vsec_platform_info *info; ++ const struct intel_vsec_platform_info *info; + struct vsec_priv *priv; + int num_caps, ret; + int run_once = 0; +@@ -633,7 +633,7 @@ static int intel_vsec_pci_probe(struct p + return ret; + + pci_save_state(pdev); +- info = (struct intel_vsec_platform_info *)id->driver_data; ++ info = (const struct intel_vsec_platform_info *)id->driver_data; + if (!info) + return -EINVAL; + +--- a/include/linux/intel_vsec.h ++++ b/include/linux/intel_vsec.h +@@ -200,13 +200,13 @@ static inline struct intel_vsec_device * + + #if IS_ENABLED(CONFIG_INTEL_VSEC) + int intel_vsec_register(struct pci_dev *pdev, +- struct intel_vsec_platform_info *info); ++ const struct intel_vsec_platform_info *info); + int intel_vsec_set_mapping(struct oobmsm_plat_info *plat_info, + struct intel_vsec_device *vsec_dev); + struct oobmsm_plat_info *intel_vsec_get_mapping(struct pci_dev *pdev); + #else + static inline int intel_vsec_register(struct pci_dev *pdev, +- struct intel_vsec_platform_info *info) ++ const struct intel_vsec_platform_info *info) + { + return -ENODEV; + } diff --git a/queue-7.0/platform-x86-intel-vsec-refactor-base_addr-handling.patch b/queue-7.0/platform-x86-intel-vsec-refactor-base_addr-handling.patch new file mode 100644 index 0000000000..a8d14447da --- /dev/null +++ b/queue-7.0/platform-x86-intel-vsec-refactor-base_addr-handling.patch @@ -0,0 +1,124 @@ +From stable+bounces-256661-greg=kroah.com@vger.kernel.org Fri May 29 19:22:54 2026 +From: Sasha Levin +Date: Fri, 29 May 2026 12:51:38 -0400 +Subject: platform/x86/intel/vsec: Refactor base_addr handling +To: stable@vger.kernel.org +Cc: "David E. Box" , "Michael J. Ruhl" , "Ilpo Järvinen" , "Sasha Levin" +Message-ID: <20260529165140.1230013-1-sashal@kernel.org> + +From: "David E. Box" + +[ Upstream commit 904b333fc51cc045941df9656302449a0fc9978e ] + +The base_addr field in intel_vsec_platform_info was originally added to +support devices that emulate PCI VSEC capabilities in MMIO. Previously, +the code would check at registration time whether base_addr was set, +falling back to the PCI BAR if not. + +Refactor this by making base_addr an explicit function parameter. This +clarifies ownership of the value and removes conditional logic from +intel_vsec_add_dev(). It also enables making intel_vsec_platform_info +const in a later patch, since the function no longer needs to write to +info->base_addr. + +No functional change intended. + +Signed-off-by: David E. Box +Reviewed-by: Michael J. Ruhl +Link: https://patch.msgid.link/20260313015202.3660072-2-david.e.box@linux.intel.com +Reviewed-by: Ilpo Järvinen +Signed-off-by: Ilpo Järvinen +Stable-dep-of: 348ccc754d89 ("platform/x86/intel/vsec: Fix enable_cnt imbalance on PCIe error recovery") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/platform/x86/intel/vsec.c | 23 ++++++++++------------- + 1 file changed, 10 insertions(+), 13 deletions(-) + +--- a/drivers/platform/x86/intel/vsec.c ++++ b/drivers/platform/x86/intel/vsec.c +@@ -271,14 +271,13 @@ EXPORT_SYMBOL_NS_GPL(intel_vsec_add_aux, + + static int intel_vsec_add_dev(struct pci_dev *pdev, struct intel_vsec_header *header, + struct intel_vsec_platform_info *info, +- unsigned long cap_id) ++ unsigned long cap_id, u64 base_addr) + { + struct intel_vsec_device __free(kfree) *intel_vsec_dev = NULL; + struct resource __free(kfree) *res = NULL; + struct resource *tmp; + struct device *parent; + unsigned long quirks = info->quirks; +- u64 base_addr; + int i; + + if (info->parent) +@@ -310,11 +309,6 @@ static int intel_vsec_add_dev(struct pci + if (quirks & VSEC_QUIRK_TABLE_SHIFT) + header->offset >>= TABLE_OFFSET_SHIFT; + +- if (info->base_addr) +- base_addr = info->base_addr; +- else +- base_addr = pdev->resource[header->tbir].start; +- + /* + * The DVSEC/VSEC contains the starting offset and count for a block of + * discovery tables. Create a resource array of these tables to the +@@ -412,7 +406,8 @@ static int get_cap_id(u32 header_id, uns + + static int intel_vsec_register_device(struct pci_dev *pdev, + struct intel_vsec_header *header, +- struct intel_vsec_platform_info *info) ++ struct intel_vsec_platform_info *info, ++ u64 base_addr) + { + const struct vsec_feature_dependency *consumer_deps; + struct vsec_priv *priv; +@@ -428,7 +423,7 @@ static int intel_vsec_register_device(st + * For others using the exported APIs, add the device directly. + */ + if (!pci_match_id(intel_vsec_pci_ids, pdev)) +- return intel_vsec_add_dev(pdev, header, info, cap_id); ++ return intel_vsec_add_dev(pdev, header, info, cap_id, base_addr); + + priv = pci_get_drvdata(pdev); + if (priv->state[cap_id] == STATE_REGISTERED || +@@ -444,7 +439,7 @@ static int intel_vsec_register_device(st + + consumer_deps = get_consumer_dependencies(priv, cap_id); + if (!consumer_deps || suppliers_ready(priv, consumer_deps, cap_id)) { +- ret = intel_vsec_add_dev(pdev, header, info, cap_id); ++ ret = intel_vsec_add_dev(pdev, header, info, cap_id, base_addr); + if (ret) + priv->state[cap_id] = STATE_SKIP; + else +@@ -464,7 +459,7 @@ static bool intel_vsec_walk_header(struc + int ret; + + for ( ; *header; header++) { +- ret = intel_vsec_register_device(pdev, *header, info); ++ ret = intel_vsec_register_device(pdev, *header, info, info->base_addr); + if (!ret) + have_devices = true; + } +@@ -512,7 +507,8 @@ static bool intel_vsec_walk_dvsec(struct + pci_read_config_dword(pdev, pos + PCI_DVSEC_HEADER2, &hdr); + header.id = PCI_DVSEC_HEADER2_ID(hdr); + +- ret = intel_vsec_register_device(pdev, &header, info); ++ ret = intel_vsec_register_device(pdev, &header, info, ++ pci_resource_start(pdev, header.tbir)); + if (ret) + continue; + +@@ -557,7 +553,8 @@ static bool intel_vsec_walk_vsec(struct + header.tbir = INTEL_DVSEC_TABLE_BAR(table); + header.offset = INTEL_DVSEC_TABLE_OFFSET(table); + +- ret = intel_vsec_register_device(pdev, &header, info); ++ ret = intel_vsec_register_device(pdev, &header, info, ++ pci_resource_start(pdev, header.tbir)); + if (ret) + continue; + diff --git a/queue-7.0/revert-mm-hugetlbfs-update-hugetlbfs-to-use-mmap_prepare.patch b/queue-7.0/revert-mm-hugetlbfs-update-hugetlbfs-to-use-mmap_prepare.patch new file mode 100644 index 0000000000..6274584677 --- /dev/null +++ b/queue-7.0/revert-mm-hugetlbfs-update-hugetlbfs-to-use-mmap_prepare.patch @@ -0,0 +1,408 @@ +From 83f9efcce93f8574be2279090ee2aec58b86cda7 Mon Sep 17 00:00:00 2001 +From: Lorenzo Stoakes +Date: Tue, 12 May 2026 17:06:43 +0100 +Subject: Revert "mm/hugetlbfs: update hugetlbfs to use mmap_prepare" + +From: Lorenzo Stoakes + +commit 83f9efcce93f8574be2279090ee2aec58b86cda7 upstream. + +This reverts commit ea52cb24cd3f ("mm/hugetlbfs: update hugetlbfs to use +mmap_prepare") with conflict resolution to account for changes in commit +ea52cb24cd3f ("mm/hugetlbfs: update hugetlbfs to use mmap_prepare"). + +The patch incorrectly handled hugetlb VMA lock allocation at the +mmap_prepare stage, where a failed allocation occurring after mmap_prepare +is called might result in the lock leaking. + +There is no risk of a merge causing a similar issues, as +VMA_DONTEXPAND_BIT is set for hugetlb mappings. + +As a first step in addressing this issue, simply revert the change so we +can rework how we do this having corrected the underlying issues. + +We maintain the VMA flags changes as best we can, accounting for the fact +that we were working with a VMA descriptor previously and propagating +like-for-like changes for this. + +Note that we invoke vma_set_flags() and do not call vma_start_write() as +vm_flags_set() does. This is OK as it's being done in an .mmap hook where +the VMA is not yet linked into the tree so nobody else can be accessing +it. + +Link: https://lore.kernel.org/20260512160643.266960-1-ljs@kernel.org +Fixes: ea52cb24cd3f ("mm/hugetlbfs: update hugetlbfs to use mmap_prepare") +Signed-off-by: Lorenzo Stoakes +Reported-by: Mingyu Wang <25181214217@stu.xidian.edu.cn> +Closes: https://lore.kernel.org/linux-mm/20260425070700.562229-1-25181214217@stu.xidian.edu.cn/ +Acked-by: Muchun Song +Acked-by: Oscar Salvador +Cc: David Hildenbrand +Cc: Liam R. Howlett +Cc: Pedro Falcato +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Lorenzo Stoakes +Signed-off-by: Greg Kroah-Hartman +--- + fs/hugetlbfs/inode.c | 46 +++++++------------------- + include/linux/hugetlb.h | 8 ---- + include/linux/hugetlb_inline.h | 12 ------ + mm/hugetlb.c | 71 ++++++++++++++++------------------------- + 4 files changed, 44 insertions(+), 93 deletions(-) + +--- a/fs/hugetlbfs/inode.c ++++ b/fs/hugetlbfs/inode.c +@@ -96,15 +96,8 @@ static const struct fs_parameter_spec hu + #define PGOFF_LOFFT_MAX \ + (((1UL << (PAGE_SHIFT + 1)) - 1) << (BITS_PER_LONG - (PAGE_SHIFT + 1))) + +-static int hugetlb_file_mmap_prepare_success(const struct vm_area_struct *vma) ++static int hugetlbfs_file_mmap(struct file *file, struct vm_area_struct *vma) + { +- /* Unfortunate we have to reassign vma->vm_private_data. */ +- return hugetlb_vma_lock_alloc((struct vm_area_struct *)vma); +-} +- +-static int hugetlbfs_file_mmap_prepare(struct vm_area_desc *desc) +-{ +- struct file *file = desc->file; + struct inode *inode = file_inode(file); + loff_t len, vma_len; + int ret; +@@ -119,8 +112,8 @@ static int hugetlbfs_file_mmap_prepare(s + * way when do_mmap unwinds (may be important on powerpc + * and ia64). + */ +- vma_desc_set_flags(desc, VMA_HUGETLB_BIT, VMA_DONTEXPAND_BIT); +- desc->vm_ops = &hugetlb_vm_ops; ++ vma_set_flags(vma, VMA_HUGETLB_BIT, VMA_DONTEXPAND_BIT); ++ vma->vm_ops = &hugetlb_vm_ops; + + /* + * page based offset in vm_pgoff could be sufficiently large to +@@ -129,16 +122,16 @@ static int hugetlbfs_file_mmap_prepare(s + * sizeof(unsigned long). So, only check in those instances. + */ + if (sizeof(unsigned long) == sizeof(loff_t)) { +- if (desc->pgoff & PGOFF_LOFFT_MAX) ++ if (vma->vm_pgoff & PGOFF_LOFFT_MAX) + return -EINVAL; + } + + /* must be huge page aligned */ +- if (desc->pgoff & (~huge_page_mask(h) >> PAGE_SHIFT)) ++ if (vma->vm_pgoff & (~huge_page_mask(h) >> PAGE_SHIFT)) + return -EINVAL; + +- vma_len = (loff_t)vma_desc_size(desc); +- len = vma_len + ((loff_t)desc->pgoff << PAGE_SHIFT); ++ vma_len = (loff_t)(vma->vm_end - vma->vm_start); ++ len = vma_len + ((loff_t)vma->vm_pgoff << PAGE_SHIFT); + /* check for overflow */ + if (len < vma_len) + return -EINVAL; +@@ -148,7 +141,7 @@ static int hugetlbfs_file_mmap_prepare(s + + ret = -ENOMEM; + +- vma_flags = desc->vma_flags; ++ vma_flags = vma->flags; + /* + * for SHM_HUGETLB, the pages are reserved in the shmget() call so skip + * reserving here. Note: only for SHM hugetlbfs file, the inode +@@ -158,30 +151,17 @@ static int hugetlbfs_file_mmap_prepare(s + vma_flags_set(&vma_flags, VMA_NORESERVE_BIT); + + if (hugetlb_reserve_pages(inode, +- desc->pgoff >> huge_page_order(h), +- len >> huge_page_shift(h), desc, +- vma_flags) < 0) ++ vma->vm_pgoff >> huge_page_order(h), ++ len >> huge_page_shift(h), vma, ++ vma_flags) < 0) + goto out; + + ret = 0; +- if (vma_desc_test_flags(desc, VMA_WRITE_BIT) && inode->i_size < len) ++ if (vma_flags_test(&vma->flags, VMA_WRITE_BIT) && inode->i_size < len) + i_size_write(inode, len); + out: + inode_unlock(inode); + +- if (!ret) { +- /* Allocate the VMA lock after we set it up. */ +- desc->action.success_hook = hugetlb_file_mmap_prepare_success; +- /* +- * We cannot permit the rmap finding this VMA in the time +- * between the VMA being inserted into the VMA tree and the +- * completion/success hook being invoked. +- * +- * This is because we establish a per-VMA hugetlb lock which can +- * be raced by rmap. +- */ +- desc->action.hide_from_rmap_until_complete = true; +- } + return ret; + } + +@@ -1238,7 +1218,7 @@ static void init_once(void *foo) + + static const struct file_operations hugetlbfs_file_operations = { + .read_iter = hugetlbfs_read_iter, +- .mmap_prepare = hugetlbfs_file_mmap_prepare, ++ .mmap = hugetlbfs_file_mmap, + .fsync = noop_fsync, + .get_unmapped_area = hugetlb_get_unmapped_area, + .llseek = default_llseek, +--- a/include/linux/hugetlb.h ++++ b/include/linux/hugetlb.h +@@ -148,7 +148,7 @@ int hugetlb_mfill_atomic_pte(pte_t *dst_ + struct folio **foliop); + #endif /* CONFIG_USERFAULTFD */ + long hugetlb_reserve_pages(struct inode *inode, long from, long to, +- struct vm_area_desc *desc, vma_flags_t vma_flags); ++ struct vm_area_struct *vma, vma_flags_t vma_flags); + long hugetlb_unreserve_pages(struct inode *inode, long start, long end, + long freed); + bool folio_isolate_hugetlb(struct folio *folio, struct list_head *list); +@@ -276,7 +276,6 @@ long hugetlb_change_protection(struct vm + void hugetlb_unshare_all_pmds(struct vm_area_struct *vma); + void fixup_hugetlb_reservations(struct vm_area_struct *vma); + void hugetlb_split(struct vm_area_struct *vma, unsigned long addr); +-int hugetlb_vma_lock_alloc(struct vm_area_struct *vma); + + unsigned int arch_hugetlb_cma_order(void); + +@@ -469,11 +468,6 @@ static inline void fixup_hugetlb_reserva + + static inline void hugetlb_split(struct vm_area_struct *vma, unsigned long addr) {} + +-static inline int hugetlb_vma_lock_alloc(struct vm_area_struct *vma) +-{ +- return 0; +-} +- + #endif /* !CONFIG_HUGETLB_PAGE */ + + #ifndef pgd_write +--- a/include/linux/hugetlb_inline.h ++++ b/include/linux/hugetlb_inline.h +@@ -6,11 +6,6 @@ + + #ifdef CONFIG_HUGETLB_PAGE + +-static inline bool is_vm_hugetlb_flags(vm_flags_t vm_flags) +-{ +- return !!(vm_flags & VM_HUGETLB); +-} +- + static inline bool is_vma_hugetlb_flags(const vma_flags_t *flags) + { + return vma_flags_test(flags, VMA_HUGETLB_BIT); +@@ -18,11 +13,6 @@ static inline bool is_vma_hugetlb_flags( + + #else + +-static inline bool is_vm_hugetlb_flags(vm_flags_t vm_flags) +-{ +- return false; +-} +- + static inline bool is_vma_hugetlb_flags(const vma_flags_t *flags) + { + return false; +@@ -32,7 +22,7 @@ static inline bool is_vma_hugetlb_flags( + + static inline bool is_vm_hugetlb_page(const struct vm_area_struct *vma) + { +- return is_vm_hugetlb_flags(vma->vm_flags); ++ return is_vma_hugetlb_flags(&vma->flags); + } + + #endif +--- a/mm/hugetlb.c ++++ b/mm/hugetlb.c +@@ -116,6 +116,7 @@ struct mutex *hugetlb_fault_mutex_table + /* Forward declaration */ + static int hugetlb_acct_memory(struct hstate *h, long delta); + static void hugetlb_vma_lock_free(struct vm_area_struct *vma); ++static void hugetlb_vma_lock_alloc(struct vm_area_struct *vma); + static void __hugetlb_vma_unlock_write_free(struct vm_area_struct *vma); + static void hugetlb_unshare_pmds(struct vm_area_struct *vma, + unsigned long start, unsigned long end, bool take_locks); +@@ -413,21 +414,17 @@ static void hugetlb_vma_lock_free(struct + } + } + +-/* +- * vma specific semaphore used for pmd sharing and fault/truncation +- * synchronization +- */ +-int hugetlb_vma_lock_alloc(struct vm_area_struct *vma) ++static void hugetlb_vma_lock_alloc(struct vm_area_struct *vma) + { + struct hugetlb_vma_lock *vma_lock; + + /* Only establish in (flags) sharable vmas */ + if (!vma || !(vma->vm_flags & VM_MAYSHARE)) +- return 0; ++ return; + + /* Should never get here with non-NULL vm_private_data */ + if (vma->vm_private_data) +- return -EINVAL; ++ return; + + vma_lock = kmalloc_obj(*vma_lock); + if (!vma_lock) { +@@ -442,15 +439,13 @@ int hugetlb_vma_lock_alloc(struct vm_are + * allocation failure. + */ + pr_warn_once("HugeTLB: unable to allocate vma specific lock\n"); +- return -EINVAL; ++ return; + } + + kref_init(&vma_lock->refs); + init_rwsem(&vma_lock->rw_sema); + vma_lock->vma = vma; + vma->vm_private_data = vma_lock; +- +- return 0; + } + + /* Helper that removes a struct file_region from the resv_map cache and returns +@@ -1183,28 +1178,20 @@ static struct resv_map *vma_resv_map(str + } + } + +-static void set_vma_resv_flags(struct vm_area_struct *vma, unsigned long flags) ++static void set_vma_resv_map(struct vm_area_struct *vma, struct resv_map *map) + { + VM_WARN_ON_ONCE_VMA(!is_vm_hugetlb_page(vma), vma); +- VM_WARN_ON_ONCE_VMA(vma->vm_flags & VM_MAYSHARE, vma); ++ VM_WARN_ON_ONCE_VMA(vma_flags_test(&vma->flags, VMA_MAYSHARE_BIT), vma); + +- set_vma_private_data(vma, get_vma_private_data(vma) | flags); ++ set_vma_private_data(vma, (unsigned long)map); + } + +-static void set_vma_desc_resv_map(struct vm_area_desc *desc, struct resv_map *map) +-{ +- VM_WARN_ON_ONCE(!is_vma_hugetlb_flags(&desc->vma_flags)); +- VM_WARN_ON_ONCE(vma_desc_test_flags(desc, VMA_MAYSHARE_BIT)); +- +- desc->private_data = map; +-} +- +-static void set_vma_desc_resv_flags(struct vm_area_desc *desc, unsigned long flags) ++static void set_vma_resv_flags(struct vm_area_struct *vma, unsigned long flags) + { +- VM_WARN_ON_ONCE(!is_vma_hugetlb_flags(&desc->vma_flags)); +- VM_WARN_ON_ONCE(vma_desc_test_flags(desc, VMA_MAYSHARE_BIT)); ++ VM_WARN_ON_ONCE_VMA(!is_vm_hugetlb_page(vma), vma); ++ VM_WARN_ON_ONCE_VMA(vma_flags_test(&vma->flags, VMA_MAYSHARE_BIT), vma); + +- desc->private_data = (void *)((unsigned long)desc->private_data | flags); ++ set_vma_private_data(vma, get_vma_private_data(vma) | flags); + } + + static int is_vma_resv_set(struct vm_area_struct *vma, unsigned long flag) +@@ -1214,13 +1201,6 @@ static int is_vma_resv_set(struct vm_are + return (get_vma_private_data(vma) & flag) != 0; + } + +-static bool is_vma_desc_resv_set(struct vm_area_desc *desc, unsigned long flag) +-{ +- VM_WARN_ON_ONCE(!is_vma_hugetlb_flags(&desc->vma_flags)); +- +- return ((unsigned long)desc->private_data) & flag; +-} +- + bool __vma_private_lock(struct vm_area_struct *vma) + { + return !(vma->vm_flags & VM_MAYSHARE) && +@@ -6572,7 +6552,7 @@ next: + + long hugetlb_reserve_pages(struct inode *inode, + long from, long to, +- struct vm_area_desc *desc, ++ struct vm_area_struct *vma, + vma_flags_t vma_flags) + { + long chg = -1, add = -1, spool_resv, gbl_resv; +@@ -6590,6 +6570,12 @@ long hugetlb_reserve_pages(struct inode + } + + /* ++ * vma specific semaphore used for pmd sharing and fault/truncation ++ * synchronization ++ */ ++ hugetlb_vma_lock_alloc(vma); ++ ++ /* + * Only apply hugepage reservation if asked. At fault time, an + * attempt will be made for VM_NORESERVE to allocate a page + * without using reserves +@@ -6601,9 +6587,9 @@ long hugetlb_reserve_pages(struct inode + * Shared mappings base their reservation on the number of pages that + * are already allocated on behalf of the file. Private mappings need + * to reserve the full area even if read-only as mprotect() may be +- * called to make the mapping read-write. Assume !desc is a shm mapping ++ * called to make the mapping read-write. Assume !vma is a shm mapping + */ +- if (!desc || vma_desc_test_flags(desc, VMA_MAYSHARE_BIT)) { ++ if (!vma || vma_flags_test(&vma->flags, VMA_MAYSHARE_BIT)) { + /* + * resv_map can not be NULL as hugetlb_reserve_pages is only + * called for inodes for which resv_maps were created (see +@@ -6622,8 +6608,8 @@ long hugetlb_reserve_pages(struct inode + + chg = to - from; + +- set_vma_desc_resv_map(desc, resv_map); +- set_vma_desc_resv_flags(desc, HPAGE_RESV_OWNER); ++ set_vma_resv_map(vma, resv_map); ++ set_vma_resv_flags(vma, HPAGE_RESV_OWNER); + } + + if (chg < 0) { +@@ -6637,7 +6623,7 @@ long hugetlb_reserve_pages(struct inode + if (err < 0) + goto out_err; + +- if (desc && !vma_desc_test_flags(desc, VMA_MAYSHARE_BIT) && h_cg) { ++ if (vma && !vma_flags_test(&vma->flags, VMA_MAYSHARE_BIT) && h_cg) { + /* For private mappings, the hugetlb_cgroup uncharge info hangs + * of the resv_map. + */ +@@ -6674,7 +6660,7 @@ long hugetlb_reserve_pages(struct inode + * consumed reservations are stored in the map. Hence, nothing + * else has to be done for private mappings here + */ +- if (!desc || vma_desc_test_flags(desc, VMA_MAYSHARE_BIT)) { ++ if (!vma || vma_flags_test(&vma->flags, VMA_MAYSHARE_BIT)) { + add = region_add(resv_map, from, to, regions_needed, h, h_cg); + + if (unlikely(add < 0)) { +@@ -6738,15 +6724,16 @@ out_uncharge_cgroup: + hugetlb_cgroup_uncharge_cgroup_rsvd(hstate_index(h), + chg * pages_per_huge_page(h), h_cg); + out_err: +- if (!desc || vma_desc_test_flags(desc, VMA_MAYSHARE_BIT)) ++ hugetlb_vma_lock_free(vma); ++ if (!vma || vma_flags_test(&vma->flags, VMA_MAYSHARE_BIT)) + /* Only call region_abort if the region_chg succeeded but the + * region_add failed or didn't run. + */ + if (chg >= 0 && add < 0) + region_abort(resv_map, from, to, regions_needed); +- if (desc && is_vma_desc_resv_set(desc, HPAGE_RESV_OWNER)) { ++ if (vma && is_vma_resv_set(vma, HPAGE_RESV_OWNER)) { + kref_put(&resv_map->refs, resv_map_release); +- set_vma_desc_resv_map(desc, NULL); ++ set_vma_resv_map(vma, NULL); + } + return err; + } diff --git a/queue-7.0/rxrpc-fix-response-packet-verification-to-extract-skb-to-a-linear-buffer.patch b/queue-7.0/rxrpc-fix-response-packet-verification-to-extract-skb-to-a-linear-buffer.patch new file mode 100644 index 0000000000..7e5d20278f --- /dev/null +++ b/queue-7.0/rxrpc-fix-response-packet-verification-to-extract-skb-to-a-linear-buffer.patch @@ -0,0 +1,614 @@ +From stable+bounces-256685-greg=kroah.com@vger.kernel.org Fri May 29 20:02:37 2026 +From: Sasha Levin +Date: Fri, 29 May 2026 13:50:22 -0400 +Subject: rxrpc: Fix RESPONSE packet verification to extract skb to a linear buffer +To: stable@vger.kernel.org +Cc: David Howells , Hyunwoo Kim , Simon Horman , Jiayuan Chen , linux-afs@lists.infradead.org, stable@kernel.org, Jeffrey Altman , Marc Dionne , Jakub Kicinski , Sasha Levin +Message-ID: <20260529175022.1450013-3-sashal@kernel.org> + +From: David Howells + +[ Upstream commit 8bfab4b6ffc2fe92da86300728fc8c3c7ebffb56 ] + +This improves the fix for CVE-2026-43500. + +Fix the verification of RESPONSE packets to avoid the problem of +overwriting a RESPONSE packet sent via splice to a local address by +extracting the contents of the UDP packet into a kmalloc'd linear buffer +rather than decrypting the data in place in the sk_buff (which may corrupt +the original buffer). + +Fixes: 24481a7f5733 ("rxrpc: Fix conn-level packet handling to unshare RESPONSE packets") +Reported-by: Hyunwoo Kim +Closes: https://lore.kernel.org/r/afKV2zGR6rrelPC7@v4bel/ +Signed-off-by: David Howells +cc: Simon Horman +cc: Jiayuan Chen +cc: linux-afs@lists.infradead.org +cc: stable@kernel.org +Reviewed-by: Jeffrey Altman +Tested-by: Marc Dionne +Link: https://patch.msgid.link/20260515230516.2718212-4-dhowells@redhat.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + net/rxrpc/ar-internal.h | 7 ++- + net/rxrpc/conn_event.c | 30 ++++++--------- + net/rxrpc/insecure.c | 5 +- + net/rxrpc/rxgk.c | 96 +++++++++++++++--------------------------------- + net/rxrpc/rxgk_app.c | 46 +++++++++-------------- + net/rxrpc/rxgk_common.h | 92 +--------------------------------------------- + net/rxrpc/rxkad.c | 29 +++++--------- + 7 files changed, 81 insertions(+), 224 deletions(-) + +--- a/net/rxrpc/ar-internal.h ++++ b/net/rxrpc/ar-internal.h +@@ -307,15 +307,16 @@ struct rxrpc_security { + struct sk_buff *challenge); + + /* verify a response */ +- int (*verify_response)(struct rxrpc_connection *, +- struct sk_buff *); ++ int (*verify_response)(struct rxrpc_connection *conn, ++ struct sk_buff *response_skb, ++ void *response, unsigned int len); + + /* clear connection security */ + void (*clear)(struct rxrpc_connection *); + + /* Default ticket -> key decoder */ + int (*default_decode_ticket)(struct rxrpc_connection *conn, struct sk_buff *skb, +- unsigned int ticket_offset, unsigned int ticket_len, ++ void *ticket, unsigned int ticket_len, + struct key **_key); + }; + +--- a/net/rxrpc/conn_event.c ++++ b/net/rxrpc/conn_event.c +@@ -243,28 +243,22 @@ static void rxrpc_call_is_secure(struct + static int rxrpc_verify_response(struct rxrpc_connection *conn, + struct sk_buff *skb) + { ++ unsigned int len = skb->len - sizeof(struct rxrpc_wire_header); ++ void *buffer; + int ret; + +- if (skb_cloned(skb) || skb_has_frag_list(skb) || +- skb_has_shared_frag(skb)) { +- /* Copy the packet if shared so that we can do in-place +- * decryption. +- */ +- struct sk_buff *nskb = skb_copy(skb, GFP_NOFS); ++ buffer = kmalloc(len, GFP_NOFS); ++ if (!buffer) ++ return -ENOMEM; + +- if (nskb) { +- rxrpc_new_skb(nskb, rxrpc_skb_new_unshared); +- ret = conn->security->verify_response(conn, nskb); +- rxrpc_free_skb(nskb, rxrpc_skb_put_response_copy); +- } else { +- /* OOM - Drop the packet. */ +- rxrpc_see_skb(skb, rxrpc_skb_see_unshare_nomem); +- ret = -ENOMEM; +- } +- } else { +- ret = conn->security->verify_response(conn, skb); +- } ++ ret = skb_copy_bits(skb, sizeof(struct rxrpc_wire_header), buffer, len); ++ if (ret < 0) ++ goto out; + ++ ret = conn->security->verify_response(conn, skb, buffer, len); ++ ++out: ++ kfree(buffer); + return ret; + } + +--- a/net/rxrpc/insecure.c ++++ b/net/rxrpc/insecure.c +@@ -54,9 +54,10 @@ static int none_sendmsg_respond_to_chall + } + + static int none_verify_response(struct rxrpc_connection *conn, +- struct sk_buff *skb) ++ struct sk_buff *response_skb, ++ void *response, unsigned int len) + { +- return rxrpc_abort_conn(conn, skb, RX_PROTOCOL_ERROR, -EPROTO, ++ return rxrpc_abort_conn(conn, response_skb, RX_PROTOCOL_ERROR, -EPROTO, + rxrpc_eproto_rxnull_response); + } + +--- a/net/rxrpc/rxgk.c ++++ b/net/rxrpc/rxgk.c +@@ -1084,11 +1084,12 @@ static int rxgk_sendmsg_respond_to_chall + * unsigned int call_numbers<>; + * }; + */ +-static int rxgk_do_verify_authenticator(struct rxrpc_connection *conn, +- const struct krb5_enctype *krb5, +- struct sk_buff *skb, +- __be32 *p, __be32 *end) ++static int rxgk_verify_authenticator(struct rxrpc_connection *conn, ++ const struct krb5_enctype *krb5, ++ struct sk_buff *skb, ++ void *auth, unsigned int auth_len) + { ++ __be32 *p = auth, *end = auth + auth_len; + u32 app_len, call_count, level, epoch, cid, i; + + _enter(""); +@@ -1152,37 +1153,6 @@ static int rxgk_do_verify_authenticator( + } + + /* +- * Extract the authenticator and verify it. +- */ +-static int rxgk_verify_authenticator(struct rxrpc_connection *conn, +- const struct krb5_enctype *krb5, +- struct sk_buff *skb, +- unsigned int auth_offset, unsigned int auth_len) +-{ +- void *auth; +- __be32 *p; +- int ret; +- +- auth = kmalloc(auth_len, GFP_NOFS); +- if (!auth) +- return -ENOMEM; +- +- ret = skb_copy_bits(skb, auth_offset, auth, auth_len); +- if (ret < 0) { +- ret = rxrpc_abort_conn(conn, skb, RXGK_NOTAUTH, -EPROTO, +- rxgk_abort_resp_short_auth); +- goto error; +- } +- +- p = auth; +- ret = rxgk_do_verify_authenticator(conn, krb5, skb, p, +- p + auth_len / sizeof(*p)); +-error: +- kfree(auth); +- return ret; +-} +- +-/* + * Verify a response. + * + * struct RXGK_Response { +@@ -1192,49 +1162,45 @@ error: + * }; + */ + static int rxgk_verify_response(struct rxrpc_connection *conn, +- struct sk_buff *skb) ++ struct sk_buff *skb, ++ void *buffer, unsigned int len) + { + const struct krb5_enctype *krb5; + struct rxrpc_key_token *token; + struct rxrpc_skb_priv *sp = rxrpc_skb(skb); +- struct rxgk_response rhdr; ++ struct rxgk_response *rhdr; + struct rxgk_context *gk; + struct key *key = NULL; +- unsigned int offset = sizeof(struct rxrpc_wire_header); +- unsigned int len = skb->len - sizeof(struct rxrpc_wire_header); +- unsigned int token_offset, token_len; +- unsigned int auth_offset, auth_len; ++ unsigned int resp_token_len, auth_len; ++ void *resp_token, *auth; + __be32 xauth_len; + int ret, ec; + + _enter("{%d}", conn->debug_id); + + /* Parse the RXGK_Response object */ +- if (sizeof(rhdr) + sizeof(__be32) > len) ++ if (len < sizeof(*rhdr) + sizeof(__be32)) + goto short_packet; +- +- if (skb_copy_bits(skb, offset, &rhdr, sizeof(rhdr)) < 0) +- goto short_packet; +- offset += sizeof(rhdr); +- len -= sizeof(rhdr); +- +- token_offset = offset; +- token_len = ntohl(rhdr.token_len); +- if (token_len > len || +- xdr_round_up(token_len) + sizeof(__be32) > len) ++ rhdr = buffer; ++ buffer += sizeof(*rhdr); ++ len -= sizeof(*rhdr); ++ ++ resp_token = buffer; ++ resp_token_len = ntohl(rhdr->token_len); ++ if (resp_token_len > len || ++ xdr_round_up(resp_token_len) + sizeof(__be32) > len) + goto short_packet; + +- trace_rxrpc_rx_response(conn, sp->hdr.serial, 0, sp->hdr.cksum, token_len); ++ trace_rxrpc_rx_response(conn, sp->hdr.serial, 0, sp->hdr.cksum, resp_token_len); + +- offset += xdr_round_up(token_len); +- len -= xdr_round_up(token_len); ++ buffer += xdr_round_up(resp_token_len); ++ len -= xdr_round_up(resp_token_len); + +- if (skb_copy_bits(skb, offset, &xauth_len, sizeof(xauth_len)) < 0) +- goto short_packet; +- offset += sizeof(xauth_len); ++ xauth_len = *(__be32 *)buffer; ++ buffer += sizeof(xauth_len); + len -= sizeof(xauth_len); + +- auth_offset = offset; ++ auth = buffer; + auth_len = ntohl(xauth_len); + if (auth_len > len) + goto short_packet; +@@ -1249,7 +1215,7 @@ static int rxgk_verify_response(struct r + * to the app to deal with - which might mean a round trip to + * userspace. + */ +- ret = rxgk_extract_token(conn, skb, token_offset, token_len, &key); ++ ret = rxgk_extract_token(conn, skb, resp_token, resp_token_len, &key); + if (ret < 0) + goto out; + +@@ -1263,7 +1229,7 @@ static int rxgk_verify_response(struct r + */ + token = key->payload.data[0]; + conn->security_level = token->rxgk->level; +- conn->rxgk.start_time = __be64_to_cpu(rhdr.start_time); ++ conn->rxgk.start_time = __be64_to_cpu(rhdr->start_time); + + gk = rxgk_generate_transport_key(conn, token->rxgk, sp->hdr.cksum, GFP_NOFS); + if (IS_ERR(gk)) { +@@ -1273,18 +1239,18 @@ static int rxgk_verify_response(struct r + + krb5 = gk->krb5; + +- trace_rxrpc_rx_response(conn, sp->hdr.serial, krb5->etype, sp->hdr.cksum, token_len); ++ trace_rxrpc_rx_response(conn, sp->hdr.serial, krb5->etype, sp->hdr.cksum, ++ resp_token_len); + + /* Decrypt, parse and verify the authenticator. */ +- ret = rxgk_decrypt_skb(krb5, gk->resp_enc, skb, +- &auth_offset, &auth_len, &ec); ++ ret = rxgk_decrypt(krb5, gk->resp_enc, &auth, &auth_len, &ec); + if (ret < 0) { + rxrpc_abort_conn(conn, skb, RXGK_SEALEDINCON, ret, + rxgk_abort_resp_auth_dec); + goto out_gk; + } + +- ret = rxgk_verify_authenticator(conn, krb5, skb, auth_offset, auth_len); ++ ret = rxgk_verify_authenticator(conn, krb5, skb, auth, auth_len); + if (ret < 0) + goto out_gk; + +--- a/net/rxrpc/rxgk_app.c ++++ b/net/rxrpc/rxgk_app.c +@@ -40,7 +40,7 @@ + * }; + */ + int rxgk_yfs_decode_ticket(struct rxrpc_connection *conn, struct sk_buff *skb, +- unsigned int ticket_offset, unsigned int ticket_len, ++ void *buffer, unsigned int ticket_len, + struct key **_key) + { + struct rxrpc_key_token *token; +@@ -49,7 +49,7 @@ int rxgk_yfs_decode_ticket(struct rxrpc_ + size_t pre_ticket_len, payload_len; + unsigned int klen, enctype; + void *payload, *ticket; +- __be32 *t, *p, *q, tmp[2]; ++ __be32 *t, *p, *q, *tmp; + int ret; + + _enter(""); +@@ -59,10 +59,7 @@ int rxgk_yfs_decode_ticket(struct rxrpc_ + rxgk_abort_resp_short_yfs_tkt); + + /* Get the session key length */ +- ret = skb_copy_bits(skb, ticket_offset, tmp, sizeof(tmp)); +- if (ret < 0) +- return rxrpc_abort_conn(conn, skb, RXGK_INCONSISTENCY, -EPROTO, +- rxgk_abort_resp_short_yfs_klen); ++ tmp = buffer; + enctype = ntohl(tmp[0]); + klen = ntohl(tmp[1]); + +@@ -84,12 +81,7 @@ int rxgk_yfs_decode_ticket(struct rxrpc_ + * it. + */ + ticket = payload + pre_ticket_len; +- ret = skb_copy_bits(skb, ticket_offset, ticket, ticket_len); +- if (ret < 0) { +- ret = rxrpc_abort_conn(conn, skb, RXGK_INCONSISTENCY, -EPROTO, +- rxgk_abort_resp_short_yfs_tkt); +- goto error; +- } ++ memcpy(ticket, buffer, ticket_len); + + /* Fill out the form header. */ + p = payload; +@@ -131,7 +123,7 @@ int rxgk_yfs_decode_ticket(struct rxrpc_ + goto error; + } + +- /* Ticket read in with skb_copy_bits above */ ++ /* Ticket appended above. */ + q += xdr_round_up(ticket_len) / 4; + if (WARN_ON((unsigned long)q - (unsigned long)payload != payload_len)) { + ret = -EIO; +@@ -182,14 +174,15 @@ error: + * [tools.ietf.org/html/draft-wilkinson-afs3-rxgk-afs-08 sec 6.1] + */ + int rxgk_extract_token(struct rxrpc_connection *conn, struct sk_buff *skb, +- unsigned int token_offset, unsigned int token_len, ++ void *token, unsigned int token_len, + struct key **_key) + { + const struct krb5_enctype *krb5; + const struct krb5_buffer *server_secret; + struct crypto_aead *token_enc = NULL; + struct key *server_key; +- unsigned int ticket_offset, ticket_len; ++ unsigned int ticket_len; ++ void *ticket; + u32 kvno, enctype; + int ret, ec = 0; + +@@ -197,24 +190,23 @@ int rxgk_extract_token(struct rxrpc_conn + __be32 kvno; + __be32 enctype; + __be32 token_len; +- } container; ++ } *container; + +- if (token_len < sizeof(container)) ++ if (token_len < sizeof(*container)) + goto short_packet; + + /* Decode the RXGK_TokenContainer object. This tells us which server + * key we should be using. We can then fetch the key, get the secret + * and set up the crypto to extract the token. + */ +- if (skb_copy_bits(skb, token_offset, &container, sizeof(container)) < 0) +- goto short_packet; ++ container = token; ++ token += sizeof(*container); + +- kvno = ntohl(container.kvno); +- enctype = ntohl(container.enctype); +- ticket_len = ntohl(container.token_len); +- ticket_offset = token_offset + sizeof(container); ++ kvno = ntohl(container->kvno); ++ enctype = ntohl(container->enctype); ++ ticket_len = ntohl(container->token_len); + +- if (ticket_len > xdr_round_down(token_len - sizeof(container))) ++ if (ticket_len > xdr_round_down(token_len - sizeof(*container))) + goto short_packet; + + _debug("KVNO %u", kvno); +@@ -237,8 +229,8 @@ int rxgk_extract_token(struct rxrpc_conn + * gain access to K0, from which we can derive the transport key and + * thence decode the authenticator. + */ +- ret = rxgk_decrypt_skb(krb5, token_enc, skb, +- &ticket_offset, &ticket_len, &ec); ++ ticket = token; ++ ret = rxgk_decrypt(krb5, token_enc, &ticket, &ticket_len, &ec); + crypto_free_aead(token_enc); + token_enc = NULL; + if (ret < 0) { +@@ -248,7 +240,7 @@ int rxgk_extract_token(struct rxrpc_conn + return ret; + } + +- ret = conn->security->default_decode_ticket(conn, skb, ticket_offset, ++ ret = conn->security->default_decode_ticket(conn, skb, ticket, + ticket_len, _key); + if (ret < 0) + goto cant_get_token; +--- a/net/rxrpc/rxgk_common.h ++++ b/net/rxrpc/rxgk_common.h +@@ -41,10 +41,10 @@ struct rxgk_context { + * rxgk_app.c + */ + int rxgk_yfs_decode_ticket(struct rxrpc_connection *conn, struct sk_buff *skb, +- unsigned int ticket_offset, unsigned int ticket_len, ++ void *ticket, unsigned int ticket_len, + struct key **_key); + int rxgk_extract_token(struct rxrpc_connection *conn, struct sk_buff *skb, +- unsigned int token_offset, unsigned int token_len, ++ void *token, unsigned int token_len, + struct key **_key); + + /* +@@ -62,50 +62,6 @@ int rxgk_set_up_token_cipher(const struc + gfp_t gfp); + + /* +- * Apply decryption and checksumming functions to part of an skbuff. The +- * offset and length are updated to reflect the actual content of the encrypted +- * region. +- */ +-static inline +-int rxgk_decrypt_skb(const struct krb5_enctype *krb5, +- struct crypto_aead *aead, +- struct sk_buff *skb, +- unsigned int *_offset, unsigned int *_len, +- int *_error_code) +-{ +- struct scatterlist sg[16]; +- size_t offset = 0, len = *_len; +- int nr_sg, ret; +- +- sg_init_table(sg, ARRAY_SIZE(sg)); +- nr_sg = skb_to_sgvec(skb, sg, *_offset, len); +- if (unlikely(nr_sg < 0)) +- return nr_sg; +- +- ret = crypto_krb5_decrypt(krb5, aead, sg, nr_sg, +- &offset, &len); +- switch (ret) { +- case 0: +- *_offset += offset; +- *_len = len; +- break; +- case -EBADMSG: /* Checksum mismatch. */ +- case -EPROTO: +- *_error_code = RXGK_SEALEDINCON; +- break; +- case -EMSGSIZE: +- *_error_code = RXGK_PACKETSHORT; +- break; +- case -ENOPKG: /* Would prefer RXGK_BADETYPE, but not available for YFS. */ +- default: +- *_error_code = RXGK_INCONSISTENCY; +- break; +- } +- +- return ret; +-} +- +-/* + * Apply decryption and checksumming functions a flat data buffer. The data + * point and length are updated to reflect the actual content of the encrypted + * region. +@@ -136,50 +92,6 @@ static inline int rxgk_decrypt(const str + case -EPROTO: + *_error_code = RXGK_SEALEDINCON; + break; +- case -EMSGSIZE: +- *_error_code = RXGK_PACKETSHORT; +- break; +- case -ENOPKG: /* Would prefer RXGK_BADETYPE, but not available for YFS. */ +- default: +- *_error_code = RXGK_INCONSISTENCY; +- break; +- } +- +- return ret; +-} +- +-/* +- * Check the MIC on a region of an skbuff. The offset and length are updated +- * to reflect the actual content of the secure region. +- */ +-static inline +-int rxgk_verify_mic_skb(const struct krb5_enctype *krb5, +- struct crypto_shash *shash, +- const struct krb5_buffer *metadata, +- struct sk_buff *skb, +- unsigned int *_offset, unsigned int *_len, +- u32 *_error_code) +-{ +- struct scatterlist sg[16]; +- size_t offset = 0, len = *_len; +- int nr_sg, ret; +- +- sg_init_table(sg, ARRAY_SIZE(sg)); +- nr_sg = skb_to_sgvec(skb, sg, *_offset, len); +- if (unlikely(nr_sg < 0)) +- return nr_sg; +- +- ret = crypto_krb5_verify_mic(krb5, shash, metadata, sg, nr_sg, +- &offset, &len); +- switch (ret) { +- case 0: +- *_offset += offset; +- *_len = len; +- break; +- case -EBADMSG: /* Checksum mismatch */ +- case -EPROTO: +- *_error_code = RXGK_SEALEDINCON; +- break; + case -EMSGSIZE: + *_error_code = RXGK_PACKETSHORT; + break; +--- a/net/rxrpc/rxkad.c ++++ b/net/rxrpc/rxkad.c +@@ -963,7 +963,6 @@ static int rxkad_decrypt_ticket(struct r + *_expiry = 0; + + ASSERT(server_key->payload.data[0] != NULL); +- ASSERTCMP((unsigned long) ticket & 7UL, ==, 0); + + memcpy(&iv, &server_key->payload.data[2], sizeof(iv)); + +@@ -1112,14 +1111,15 @@ unlock: + * verify a response + */ + static int rxkad_verify_response(struct rxrpc_connection *conn, +- struct sk_buff *skb) ++ struct sk_buff *skb, ++ void *buffer, unsigned int len) + { + struct rxkad_response *response; + struct rxrpc_skb_priv *sp = rxrpc_skb(skb); + struct rxrpc_crypt session_key; + struct key *server_key; + time64_t expiry; +- void *ticket = NULL; ++ void *ticket; + u32 version, kvno, ticket_len, level; + __be32 csum; + int ret, i; +@@ -1142,13 +1142,8 @@ static int rxkad_verify_response(struct + } + } + +- ret = -ENOMEM; +- response = kzalloc_obj(struct rxkad_response, GFP_NOFS); +- if (!response) +- goto error; +- +- if (skb_copy_bits(skb, sizeof(struct rxrpc_wire_header), +- response, sizeof(*response)) < 0) { ++ response = buffer; ++ if (len < sizeof(*response)) { + ret = rxrpc_abort_conn(conn, skb, RXKADPACKETSHORT, -EPROTO, + rxkad_abort_resp_short); + goto error; +@@ -1160,6 +1155,9 @@ static int rxkad_verify_response(struct + + trace_rxrpc_rx_response(conn, sp->hdr.serial, version, kvno, ticket_len); + ++ buffer += sizeof(*response); ++ len -= sizeof(*response); ++ + if (version != RXKAD_VERSION) { + ret = rxrpc_abort_conn(conn, skb, RXKADINCONSISTENCY, -EPROTO, + rxkad_abort_resp_version); +@@ -1179,13 +1177,8 @@ static int rxkad_verify_response(struct + } + + /* extract the kerberos ticket and decrypt and decode it */ +- ret = -ENOMEM; +- ticket = kmalloc(ticket_len, GFP_NOFS); +- if (!ticket) +- goto error; +- +- if (skb_copy_bits(skb, sizeof(struct rxrpc_wire_header) + sizeof(*response), +- ticket, ticket_len) < 0) { ++ ticket = buffer; ++ if (ticket_len > len) { + ret = rxrpc_abort_conn(conn, skb, RXKADPACKETSHORT, -EPROTO, + rxkad_abort_resp_short_tkt); + goto error; +@@ -1265,8 +1258,6 @@ static int rxkad_verify_response(struct + ret = rxrpc_get_server_data_key(conn, &session_key, expiry, kvno); + + error: +- kfree(ticket); +- kfree(response); + key_put(server_key); + _leave(" = %d", ret); + return ret; diff --git a/queue-7.0/series b/queue-7.0/series index 3f8af6ac7c..c3783d96f0 100644 --- a/queue-7.0/series +++ b/queue-7.0/series @@ -315,3 +315,15 @@ serial-zs-convert-to-use-a-platform-device.patch serial-core-introduce-guard-uart_port_lock_check_sysrq_irqsave.patch serial-8250-dispatch-sysrq-character-in-serial8250_handle_irq.patch serial-8250_dw-dispatch-sysrq-character-in-dw8250_handle_irq.patch +revert-mm-hugetlbfs-update-hugetlbfs-to-use-mmap_prepare.patch +platform-x86-intel-vsec-refactor-base_addr-handling.patch +platform-x86-intel-vsec-make-driver_data-info-const.patch +platform-x86-intel-vsec-fix-enable_cnt-imbalance-on-pcie-error-recovery.patch +rxrpc-fix-response-packet-verification-to-extract-skb-to-a-linear-buffer.patch +alsa-hda-realtek-fix-mute-and-mic-mute-leds-for-hp-envy-x360-15-fh0xxx.patch +alsa-hda-realtek-fix-mute-and-mic-mute-leds-for-hp-16-piston-omnibook-x.patch +arm64-tlb-flush-walk-cache-when-unsharing-pmd-tables.patch +i2c-tegra-make-tegra_i2c_mutex_unlock-return-void.patch +hwmon-pmbus-add-support-for-guarded-pmbus-lock.patch +hwmon-pmbus-adm1266-serialize-sequencer_state-debugfs-read-with-pmbus_lock.patch +hwmon-pmbus-adm1266-serialize-gpio-pmbus-accesses-with-pmbus_lock.patch