From: Sasha Levin Date: Mon, 27 Jul 2026 01:23:20 +0000 (-0400) Subject: Fixes for all trees X-Git-Url: http://git.ipfire.org/gitweb/index.cgi?a=commitdiff_plain;h=e17b4040a771c4de32621bb6cc8805747e34cbea;p=thirdparty%2Fkernel%2Fstable-queue.git Fixes for all trees Signed-off-by: Sasha Levin --- diff --git a/queue-5.10/asoc-meson-aiu-fifo-spdif-soft-reset-the-s-pdif-data.patch b/queue-5.10/asoc-meson-aiu-fifo-spdif-soft-reset-the-s-pdif-data.patch new file mode 100644 index 0000000000..72a34801f8 --- /dev/null +++ b/queue-5.10/asoc-meson-aiu-fifo-spdif-soft-reset-the-s-pdif-data.patch @@ -0,0 +1,64 @@ +From bc11fe4fb6c044fcebd82ed1bfc542b52ba0cd61 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 27 Jun 2026 13:12:05 +0000 +Subject: ASoC: meson: aiu: fifo-spdif: soft reset the S/PDIF datapath on + start/stop + +From: Christian Hewitt + +[ Upstream commit 6b59c53c8adc2b522327407af5e1793a65b67e4b ] + +The I2S FIFO soft-resets its fast domain on start (AIU_RST_SOFT bit 0 + +AIU_I2S_SYNC read in aiu_fifo_i2s_trigger), mirroring the downstream +vendor driver's audio_out_i2s_enable(). The S/PDIF FIFO has no equivalent: +it only toggles the IEC958 DCU, so a stale datapath FIFO can be replayed, +producing the "machine gun noise" buffer underrun - on start when switching +outputs, and on stop when playback ends. The latter is audible on devices +with an always-on S/PDIF-fed DAC (e.g. the ES7144 on the WeTek Play2). + +The vendor driver resets the IEC958 fast domain (AIU_RST_SOFT bit 2) on +both enable and disable (audio_hw_958_enable), and when reconfiguring +(audio_hw_958_reset clears AIU_958_DCU_FF_CTRL then resets). Do the same: +reset before enabling the DCU on start, and before disabling on stop. + +Fixes: 6ae9ca9ce986bf ("ASoC: meson: aiu: add i2s and spdif support") +Signed-off-by: Christian Hewitt +Reviewed-by: Martin Blumenstingl +Link: https://patch.msgid.link/20260627131205.808800-1-christianshewitt@gmail.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/meson/aiu-fifo-spdif.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/sound/soc/meson/aiu-fifo-spdif.c b/sound/soc/meson/aiu-fifo-spdif.c +index 44eb6faacf44d0..124d2d9ce71605 100644 +--- a/sound/soc/meson/aiu-fifo-spdif.c ++++ b/sound/soc/meson/aiu-fifo-spdif.c +@@ -24,6 +24,7 @@ + #define AIU_MEM_IEC958_CONTROL_MODE_16BIT BIT(7) + #define AIU_MEM_IEC958_CONTROL_MODE_LINEAR BIT(8) + #define AIU_MEM_IEC958_BUF_CNTL_INIT BIT(0) ++#define AIU_RST_SOFT_958_FAST BIT(2) + + #define AIU_FIFO_SPDIF_BLOCK 8 + +@@ -68,11 +69,15 @@ static int fifo_spdif_trigger(struct snd_pcm_substream *substream, int cmd, + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: ++ snd_soc_component_write(component, AIU_RST_SOFT, ++ AIU_RST_SOFT_958_FAST); + fifo_spdif_dcu_enable(component, true); + break; + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + case SNDRV_PCM_TRIGGER_STOP: ++ snd_soc_component_write(component, AIU_RST_SOFT, ++ AIU_RST_SOFT_958_FAST); + fifo_spdif_dcu_enable(component, false); + break; + default: +-- +2.53.0 + diff --git a/queue-5.10/asoc-tas2562-fix-deprecated-shut-down-gpio-always-cl.patch b/queue-5.10/asoc-tas2562-fix-deprecated-shut-down-gpio-always-cl.patch new file mode 100644 index 0000000000..b33211bcc1 --- /dev/null +++ b/queue-5.10/asoc-tas2562-fix-deprecated-shut-down-gpio-always-cl.patch @@ -0,0 +1,62 @@ +From 73f21627da7b212a9763d0935f525f808b4167c8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 6 Jul 2026 21:01:09 +0530 +Subject: ASoC: tas2562: fix deprecated 'shut-down' GPIO always cleared after + lookup + +From: Uday Khare + +[ Upstream commit 3238c634725afbb2a137fdda762208510828f71d ] + +In tas2562_parse_dt(), the fallback lookup for the deprecated +"shut-down" GPIO property is broken due to a missing pair of braces. + +The code intends to reset sdz_gpio to NULL only when the lookup +returns an error that is not -EPROBE_DEFER (so the driver gracefully +continues without a GPIO). However, without braces the statement: + + tas2562->sdz_gpio = NULL; + +falls outside the IS_ERR() check and is executed unconditionally +for every path through the if block, including a successful GPIO +lookup. + +This means any device using the deprecated 'shut-down' DT property +will always have sdz_gpio == NULL after probe, making the GPIO +completely non-functional. + +Fix this by adding the missing braces to scope the NULL assignment +inside the IS_ERR() branch, matching the pattern already used for +the primary 'shutdown' GPIO lookup above. + +Fixes: f78a97003b8b ("ASoC: tas2562: Update shutdown GPIO property") +Signed-off-by: Uday Khare +Link: https://patch.msgid.link/20260706153109.10953-1-udaykhare77@gmail.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/codecs/tas2562.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/sound/soc/codecs/tas2562.c b/sound/soc/codecs/tas2562.c +index f1ff204e3ad052..a2ddb692b8f697 100644 +--- a/sound/soc/codecs/tas2562.c ++++ b/sound/soc/codecs/tas2562.c +@@ -720,11 +720,12 @@ static int tas2562_parse_dt(struct tas2562_data *tas2562) + if (tas2562->sdz_gpio == NULL) { + tas2562->sdz_gpio = devm_gpiod_get_optional(dev, "shut-down", + GPIOD_OUT_HIGH); +- if (IS_ERR(tas2562->sdz_gpio)) ++ if (IS_ERR(tas2562->sdz_gpio)) { + if (PTR_ERR(tas2562->sdz_gpio) == -EPROBE_DEFER) + return -EPROBE_DEFER; + +- tas2562->sdz_gpio = NULL; ++ tas2562->sdz_gpio = NULL; ++ } + } + + if (tas2562->model_id == TAS2110) +-- +2.53.0 + diff --git a/queue-5.10/ata-sata_dwc_460ex-enable-sata-interrupts-only-after.patch b/queue-5.10/ata-sata_dwc_460ex-enable-sata-interrupts-only-after.patch new file mode 100644 index 0000000000..a94e92e834 --- /dev/null +++ b/queue-5.10/ata-sata_dwc_460ex-enable-sata-interrupts-only-after.patch @@ -0,0 +1,56 @@ +From d9998b0e53afc868b3f72aacd7bded4f2994d215 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 12 Jul 2026 14:37:26 -0700 +Subject: ata: sata_dwc_460ex: enable SATA interrupts only after IRQ handler is + registered + +From: Rosen Penev + +[ Upstream commit 4bbc16a353a98023e5ddfca7c1fc0e49971cf4d0 ] + +sata_dwc_enable_interrupts() is called before platform_get_irq() and +ata_host_activate(), leaving the SATA controller's interrupt mask +enabled without a registered handler. If a later step fails (irq +request, phy init, etc.) or if the controller asserts an interrupt +during probe, the irq line may fire with no handler, causing a +spurious interrupt storm. + +Move sata_dwc_enable_interrupts() after ata_host_activate() so that +interrupts are only unmasked once the handler is registered and the +core is fully initialized. + +Fixes: 62936009f35a ("[libata] Add 460EX on-chip SATA driver, sata_dwc_460ex") +Assisted-by: opencode:big-pickle +Signed-off-by: Rosen Penev +Signed-off-by: Damien Le Moal +Signed-off-by: Sasha Levin +--- + drivers/ata/sata_dwc_460ex.c | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c +index 464260f6687082..e9383db1b13a98 100644 +--- a/drivers/ata/sata_dwc_460ex.c ++++ b/drivers/ata/sata_dwc_460ex.c +@@ -1246,9 +1246,6 @@ static int sata_dwc_probe(struct platform_device *ofdev) + /* Save dev for later use in dev_xxx() routines */ + hsdev->dev = &ofdev->dev; + +- /* Enable SATA Interrupts */ +- sata_dwc_enable_interrupts(hsdev); +- + /* Get SATA interrupt number */ + irq = irq_of_parse_and_map(np, 0); + if (irq == NO_IRQ) { +@@ -1281,6 +1278,8 @@ static int sata_dwc_probe(struct platform_device *ofdev) + if (err) + dev_err(&ofdev->dev, "failed to activate host"); + ++ /* Enable SATA Interrupts */ ++ sata_dwc_enable_interrupts(hsdev); + return 0; + + error_out: +-- +2.53.0 + diff --git a/queue-5.10/ata-sata_dwc_460ex-fix-clear_interrupt_bit-clearing-.patch b/queue-5.10/ata-sata_dwc_460ex-fix-clear_interrupt_bit-clearing-.patch new file mode 100644 index 0000000000..23b6d7da72 --- /dev/null +++ b/queue-5.10/ata-sata_dwc_460ex-fix-clear_interrupt_bit-clearing-.patch @@ -0,0 +1,45 @@ +From d2db6dae7433407ef5753155580c2077b414143e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 12 Jul 2026 14:37:27 -0700 +Subject: ata: sata_dwc_460ex: fix clear_interrupt_bit() clearing all pending + interrupts + +From: Rosen Penev + +[ Upstream commit 66c4e310ad71f41e41736d33dd8a1fb5eaaec7f3 ] + +clear_interrupt_bit() ignores the bit argument and performs a +read-write-back of the entire INTPR register. If INTPR uses standard +Write-1-to-Clear semantics, this clears every pending interrupt bit, +not just the intended one. Coalesced interrupts (e.g. DMAT + NEWFP) +would be cleared together, silently losing the second event. + +Write only the specific bit to clear so that other pending interrupts +are preserved. + +Fixes: 62936009f35a ("[libata] Add 460EX on-chip SATA driver, sata_dwc_460ex") +Assisted-by: opencode:big-pickle +Signed-off-by: Rosen Penev +Signed-off-by: Damien Le Moal +Signed-off-by: Sasha Levin +--- + drivers/ata/sata_dwc_460ex.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c +index e9383db1b13a98..6a7e9aac4814e6 100644 +--- a/drivers/ata/sata_dwc_460ex.c ++++ b/drivers/ata/sata_dwc_460ex.c +@@ -443,8 +443,7 @@ static void clear_serror(struct ata_port *ap) + + static void clear_interrupt_bit(struct sata_dwc_device *hsdev, u32 bit) + { +- sata_dwc_writel(&hsdev->sata_dwc_regs->intpr, +- sata_dwc_readl(&hsdev->sata_dwc_regs->intpr)); ++ sata_dwc_writel(&hsdev->sata_dwc_regs->intpr, bit); + } + + static u32 qcmd_tag_to_mask(u8 tag) +-- +2.53.0 + diff --git a/queue-5.10/ata-sata_dwc_460ex-fix-infinite-loop-in-ncq-tag-comp.patch b/queue-5.10/ata-sata_dwc_460ex-fix-infinite-loop-in-ncq-tag-comp.patch new file mode 100644 index 0000000000..ee53f92f51 --- /dev/null +++ b/queue-5.10/ata-sata_dwc_460ex-fix-infinite-loop-in-ncq-tag-comp.patch @@ -0,0 +1,54 @@ +From db44edab779838378172e678065c800bb2dbceee Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 12 Jul 2026 14:37:28 -0700 +Subject: ata: sata_dwc_460ex: fix infinite loop in NCQ tag completion + bit-scanning + +From: Rosen Penev + +[ Upstream commit c2130f6553f4a5cbdc259de069600117a995f197 ] + +The hand-rolled bit-scanning loop in the NCQ completion path has an +infinite loop bug. When tag_mask has only high bits set (e.g. +0x80000000), the inner while loop left-shifts tag_mask until it +overflows to 0. At that point !(0 & 1) is always true and 0 <<= 1 +stays 0, causing an infinite loop in hardirq context with a spinlock +held. + +Replace the open-coded bit-scanning with __ffs() which correctly +finds the least significant set bit and is bounded by the width of +the argument. + +Fixes: 62936009f35a ("[libata] Add 460EX on-chip SATA driver, sata_dwc_460ex") +Assisted-by: opencode:big-pickle +Signed-off-by: Rosen Penev +Signed-off-by: Damien Le Moal +Signed-off-by: Sasha Levin +--- + drivers/ata/sata_dwc_460ex.c | 9 ++------- + 1 file changed, 2 insertions(+), 7 deletions(-) + +diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c +index 399d0766fd6d4c..26c3b287ac1f6f 100644 +--- a/drivers/ata/sata_dwc_460ex.c ++++ b/drivers/ata/sata_dwc_460ex.c +@@ -650,14 +650,9 @@ static irqreturn_t sata_dwc_isr(int irq, void *dev_instance) + status = ap->ops->sff_check_status(ap); + dev_dbg(ap->dev, "%s ATA status register=0x%x\n", __func__, status); + +- tag = 0; + while (tag_mask) { +- while (!(tag_mask & 0x00000001)) { +- tag++; +- tag_mask <<= 1; +- } +- +- tag_mask &= (~0x00000001); ++ tag = __ffs(tag_mask); ++ tag_mask &= ~(1U << tag); + qc = ata_qc_from_tag(ap, tag); + + /* To be picked up by completion functions */ +-- +2.53.0 + diff --git a/queue-5.10/ata-sata_dwc_460ex-remove-variable-num_processed.patch b/queue-5.10/ata-sata_dwc_460ex-remove-variable-num_processed.patch new file mode 100644 index 0000000000..9d43c88e2e --- /dev/null +++ b/queue-5.10/ata-sata_dwc_460ex-remove-variable-num_processed.patch @@ -0,0 +1,47 @@ +From bb15b867cd93162b4646290c757891cae5c16aab Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 24 Oct 2022 15:17:59 +0100 +Subject: ata: sata_dwc_460ex: remove variable num_processed + +From: Colin Ian King + +[ Upstream commit de58fd3d80f884f7f322a06bfe08465e49b47c5d ] + +Variable num_processed is just being incremented and it's never used +anywhere else. The variable and the increment are redundant so +remove it. + +Signed-off-by: Colin Ian King +Signed-off-by: Damien Le Moal +Stable-dep-of: c2130f6553f4 ("ata: sata_dwc_460ex: fix infinite loop in NCQ tag completion bit-scanning") +Signed-off-by: Sasha Levin +--- + drivers/ata/sata_dwc_460ex.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c +index 6a7e9aac4814e6..399d0766fd6d4c 100644 +--- a/drivers/ata/sata_dwc_460ex.c ++++ b/drivers/ata/sata_dwc_460ex.c +@@ -511,7 +511,7 @@ static irqreturn_t sata_dwc_isr(int irq, void *dev_instance) + struct ata_queued_cmd *qc; + unsigned long flags; + u8 status, tag; +- int handled, num_processed, port = 0; ++ int handled, port = 0; + uint intpr, sactive, sactive2, tag_mask; + struct sata_dwc_device_port *hsdevp; + hsdev->sactive_issued = 0; +@@ -651,9 +651,7 @@ static irqreturn_t sata_dwc_isr(int irq, void *dev_instance) + dev_dbg(ap->dev, "%s ATA status register=0x%x\n", __func__, status); + + tag = 0; +- num_processed = 0; + while (tag_mask) { +- num_processed++; + while (!(tag_mask & 0x00000001)) { + tag++; + tag_mask <<= 1; +-- +2.53.0 + diff --git a/queue-5.10/btrfs-reject-free-space-cache-with-more-entries-than.patch b/queue-5.10/btrfs-reject-free-space-cache-with-more-entries-than.patch new file mode 100644 index 0000000000..296564291d --- /dev/null +++ b/queue-5.10/btrfs-reject-free-space-cache-with-more-entries-than.patch @@ -0,0 +1,88 @@ +From db7073b013f2dfb0a0793096a01ec1edd51c5bb3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 10 Jun 2026 10:29:26 -0700 +Subject: btrfs: reject free space cache with more entries than pages + +From: Xiang Mei + +[ Upstream commit a2d8d5647ed854e38f941741aea45b9eb15a6350 ] + +When loading a v1 free space cache, __load_free_space_cache() takes +num_entries and num_bitmaps straight from the on-disk +btrfs_free_space_header. That header is stored in the tree_root under a key +with type 0, which the tree-checker has no case for, so neither count is +validated before the load trusts it. + +The load loops num_entries times and maps the next page whenever the current +one runs out, going through io_ctl_check_crc() -> io_ctl_map_page(), which +does io_ctl->pages[io_ctl->index++]. But pages[] is allocated in +io_ctl_init() from the cache inode's i_size, not from num_entries: + + num_pages = DIV_ROUND_UP(i_size_read(inode), PAGE_SIZE); + io_ctl->pages = kcalloc(num_pages, sizeof(struct page *), GFP_NOFS); + +So if num_entries claims more records than the pages can hold, io_ctl->index +runs off the end of pages[]. The write side never hits this because +io_ctl_add_entry() and io_ctl_add_bitmap() both stop once +io_ctl->index >= io_ctl->num_pages; the read side just never had the same +check. + +To trigger it, take a clean cache (num_entries = here), set num_entries +in the header to 0x10000, and fix up the leaf checksum so it still passes +the tree-checker. The cache inode has i_size = 65536, so num_pages is 16 and +pages[] is a 16-pointer (kmalloc-128) array. The load now tries to read +65536 entries, io_ctl->index walks up to 16, and pages[16] is read past the +array: + + BUG: KASAN: slab-out-of-bounds in io_ctl_check_crc (fs/btrfs/free-space-cache.c:420 fs/btrfs/free-space-cache.c:565) + Read of size 8 at addr ffff88800c833a80 by task kworker/u8:3/58 + io_ctl_check_crc (fs/btrfs/free-space-cache.c:420 fs/btrfs/free-space-cache.c:565) + __load_free_space_cache (fs/btrfs/free-space-cache.c:655 fs/btrfs/free-space-cache.c:820) + load_free_space_cache (fs/btrfs/free-space-cache.c:1017) + caching_thread (fs/btrfs/block-group.c:880) + btrfs_work_helper (fs/btrfs/async-thread.c:312) + process_one_work + worker_thread + kthread + ret_from_fork + +free-space-cache.c:420 is io_ctl_map_page(), inlined into io_ctl_check_crc() +at line 565, which is why that is the frame KASAN names. The out-of-bounds +slot is then treated as a struct page and handed to crc32c(), so the bad +read turns into a GP fault. + +Add the missing check to io_ctl_check_crc(), which is where both the entry +loop and the bitmap loop end up. When num_entries is too large the load now +fails like any corrupt cache: __load_free_space_cache() drops it and rebuilds +the free space from the extent tree, so a valid cache is never rejected. + +Reported-by: Weiming Shi +Fixes: 5b0e95bf607d ("Btrfs: inline checksums into the disk free space cache") +Link: https://lore.kernel.org/linux-btrfs/CAPpSM+RMPByMCKXvM5QFKToxsyNccfuFLWMdD0mfd0wh2Ja62w@mail.gmail.com/ +Assisted-by: Claude:claude-opus-4-8 +Reviewed-by: Qu Wenruo +Signed-off-by: Xiang Mei +Reviewed-by: David Sterba +Signed-off-by: David Sterba +Signed-off-by: Sasha Levin +--- + fs/btrfs/free-space-cache.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c +index 756a06f062fdf3..57e41ed899fe1d 100644 +--- a/fs/btrfs/free-space-cache.c ++++ b/fs/btrfs/free-space-cache.c +@@ -466,6 +466,9 @@ static int io_ctl_check_crc(struct btrfs_io_ctl *io_ctl, int index) + u32 crc = ~(u32)0; + unsigned offset = 0; + ++ if (index >= io_ctl->num_pages) ++ return -EIO; ++ + if (index == 0) + offset = sizeof(u32) * io_ctl->num_pages; + +-- +2.53.0 + diff --git a/queue-5.10/btrfs-remove-crc_check-logic-from-free-space.patch b/queue-5.10/btrfs-remove-crc_check-logic-from-free-space.patch new file mode 100644 index 0000000000..178f6ec84c --- /dev/null +++ b/queue-5.10/btrfs-remove-crc_check-logic-from-free-space.patch @@ -0,0 +1,126 @@ +From 68993fdc68c389de854a6a7e03ad6914e6506839 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 3 Dec 2020 10:09:48 +0200 +Subject: btrfs: remove crc_check logic from free space + +From: Nikolay Borisov + +[ Upstream commit 7dbdb443a7b49f66d9c4da0d810e2c54e0727d82 ] + +Following removal of the ino cache io_ctl_init will be called only on +behalf of the freespace inode. In this case we always want to check +CRCs so conditional code that depended on io_ctl::check_crc can be +removed. + +Signed-off-by: Nikolay Borisov +Reviewed-by: David Sterba +Signed-off-by: David Sterba +Stable-dep-of: a2d8d5647ed8 ("btrfs: reject free space cache with more entries than pages") +Signed-off-by: Sasha Levin +--- + fs/btrfs/free-space-cache.c | 37 +++++-------------------------------- + fs/btrfs/free-space-cache.h | 1 - + 2 files changed, 5 insertions(+), 33 deletions(-) + +diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c +index a779965d299054..756a06f062fdf3 100644 +--- a/fs/btrfs/free-space-cache.c ++++ b/fs/btrfs/free-space-cache.c +@@ -304,16 +304,11 @@ static int io_ctl_init(struct btrfs_io_ctl *io_ctl, struct inode *inode, + int write) + { + int num_pages; +- int check_crcs = 0; + + num_pages = DIV_ROUND_UP(i_size_read(inode), PAGE_SIZE); + +- if (btrfs_ino(BTRFS_I(inode)) != BTRFS_FREE_INO_OBJECTID) +- check_crcs = 1; +- + /* Make sure we can fit our crcs and generation into the first page */ +- if (write && check_crcs && +- (num_pages * sizeof(u32) + sizeof(u64)) > PAGE_SIZE) ++ if (write && (num_pages * sizeof(u32) + sizeof(u64)) > PAGE_SIZE) + return -ENOSPC; + + memset(io_ctl, 0, sizeof(struct btrfs_io_ctl)); +@@ -324,7 +319,6 @@ static int io_ctl_init(struct btrfs_io_ctl *io_ctl, struct inode *inode, + + io_ctl->num_pages = num_pages; + io_ctl->fs_info = btrfs_sb(inode->i_sb); +- io_ctl->check_crcs = check_crcs; + io_ctl->inode = inode; + + return 0; +@@ -419,13 +413,8 @@ static void io_ctl_set_generation(struct btrfs_io_ctl *io_ctl, u64 generation) + * Skip the csum areas. If we don't check crcs then we just have a + * 64bit chunk at the front of the first page. + */ +- if (io_ctl->check_crcs) { +- io_ctl->cur += (sizeof(u32) * io_ctl->num_pages); +- io_ctl->size -= sizeof(u64) + (sizeof(u32) * io_ctl->num_pages); +- } else { +- io_ctl->cur += sizeof(u64); +- io_ctl->size -= sizeof(u64) * 2; +- } ++ io_ctl->cur += (sizeof(u32) * io_ctl->num_pages); ++ io_ctl->size -= sizeof(u64) + (sizeof(u32) * io_ctl->num_pages); + + put_unaligned_le64(generation, io_ctl->cur); + io_ctl->cur += sizeof(u64); +@@ -439,14 +428,8 @@ static int io_ctl_check_generation(struct btrfs_io_ctl *io_ctl, u64 generation) + * Skip the crc area. If we don't check crcs then we just have a 64bit + * chunk at the front of the first page. + */ +- if (io_ctl->check_crcs) { +- io_ctl->cur += sizeof(u32) * io_ctl->num_pages; +- io_ctl->size -= sizeof(u64) + +- (sizeof(u32) * io_ctl->num_pages); +- } else { +- io_ctl->cur += sizeof(u64); +- io_ctl->size -= sizeof(u64) * 2; +- } ++ io_ctl->cur += sizeof(u32) * io_ctl->num_pages; ++ io_ctl->size -= sizeof(u64) + (sizeof(u32) * io_ctl->num_pages); + + cache_gen = get_unaligned_le64(io_ctl->cur); + if (cache_gen != generation) { +@@ -466,11 +449,6 @@ static void io_ctl_set_crc(struct btrfs_io_ctl *io_ctl, int index) + u32 crc = ~(u32)0; + unsigned offset = 0; + +- if (!io_ctl->check_crcs) { +- io_ctl_unmap_page(io_ctl); +- return; +- } +- + if (index == 0) + offset = sizeof(u32) * io_ctl->num_pages; + +@@ -488,11 +466,6 @@ static int io_ctl_check_crc(struct btrfs_io_ctl *io_ctl, int index) + u32 crc = ~(u32)0; + unsigned offset = 0; + +- if (!io_ctl->check_crcs) { +- io_ctl_map_page(io_ctl, 0); +- return 0; +- } +- + if (index == 0) + offset = sizeof(u32) * io_ctl->num_pages; + +diff --git a/fs/btrfs/free-space-cache.h b/fs/btrfs/free-space-cache.h +index e3d5e0ad8f8e4e..d8c2f3df5a0666 100644 +--- a/fs/btrfs/free-space-cache.h ++++ b/fs/btrfs/free-space-cache.h +@@ -76,7 +76,6 @@ struct btrfs_io_ctl { + int num_pages; + int entries; + int bitmaps; +- unsigned check_crcs:1; + }; + + struct inode *lookup_free_space_inode(struct btrfs_block_group *block_group, +-- +2.53.0 + diff --git a/queue-5.10/can-j1939-fix-lockless-local-destination-check.patch b/queue-5.10/can-j1939-fix-lockless-local-destination-check.patch new file mode 100644 index 0000000000..e08d34ce39 --- /dev/null +++ b/queue-5.10/can-j1939-fix-lockless-local-destination-check.patch @@ -0,0 +1,81 @@ +From a0d9f2c16b48486f847fb6162710cd0ef1b9e418 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 7 May 2026 10:22:26 +0200 +Subject: can: j1939: fix lockless local-destination check + +From: Shuhao Fu + +[ Upstream commit e4e8af62adab2fdcca230006f829407a953070cd ] + +j1939_priv.ents[].nusers is documented as protected by priv->lock, and +its updates already happen under that lock. j1939_can_recv() also reads +it under read_lock_bh(). However, j1939_session_skb_queue() and +j1939_tp_send() still read priv->ents[da].nusers without taking the +lock. + +Those transport-side checks decide whether to set J1939_ECU_LOCAL_DST, so +they can race with j1939_local_ecu_get() and j1939_local_ecu_put() while +userspace is binding or releasing sockets concurrently with TP traffic. +This can misclassify TP/ETP sessions as local or remote and take the wrong +transport path. + +Fix both transport paths by routing the destination-locality check through +a helper that reads ents[].nusers under read_lock_bh(&priv->lock). + +Fixes: 9d71dd0c7009 ("can: add support of SAE J1939 protocol") +Signed-off-by: Shuhao Fu +Tested-by: Oleksij Rempel +Acked-by: Oleksij Rempel +Link: https://patch.msgid.link/20260419140614.GA4041240@chcpu16 +Signed-off-by: Marc Kleine-Budde +Signed-off-by: Sasha Levin +--- + net/can/j1939/transport.c | 18 ++++++++++++++---- + 1 file changed, 14 insertions(+), 4 deletions(-) + +diff --git a/net/can/j1939/transport.c b/net/can/j1939/transport.c +index 9f77a730be4847..21a4a4b10fc080 100644 +--- a/net/can/j1939/transport.c ++++ b/net/can/j1939/transport.c +@@ -346,6 +346,18 @@ static void j1939_session_skb_drop_old(struct j1939_session *session) + } + } + ++static bool j1939_address_is_local(struct j1939_priv *priv, u8 addr) ++{ ++ bool local = false; ++ ++ read_lock_bh(&priv->lock); ++ if (j1939_address_is_unicast(addr) && priv->ents[addr].nusers) ++ local = true; ++ read_unlock_bh(&priv->lock); ++ ++ return local; ++} ++ + void j1939_session_skb_queue(struct j1939_session *session, + struct sk_buff *skb) + { +@@ -354,8 +366,7 @@ void j1939_session_skb_queue(struct j1939_session *session, + + j1939_ac_fixup(priv, skb); + +- if (j1939_address_is_unicast(skcb->addr.da) && +- priv->ents[skcb->addr.da].nusers) ++ if (j1939_address_is_local(priv, skcb->addr.da)) + skcb->flags |= J1939_ECU_LOCAL_DST; + + skcb->flags |= J1939_ECU_LOCAL_SRC; +@@ -1998,8 +2009,7 @@ struct j1939_session *j1939_tp_send(struct j1939_priv *priv, + return ERR_PTR(ret); + + /* fix DST flags, it may be used there soon */ +- if (j1939_address_is_unicast(skcb->addr.da) && +- priv->ents[skcb->addr.da].nusers) ++ if (j1939_address_is_local(priv, skcb->addr.da)) + skcb->flags |= J1939_ECU_LOCAL_DST; + + /* src is always local, I'm sending ... */ +-- +2.53.0 + diff --git a/queue-5.10/drm-i915-gt-use-correct-selftest-config-symbol.patch b/queue-5.10/drm-i915-gt-use-correct-selftest-config-symbol.patch new file mode 100644 index 0000000000..b5f5631ebb --- /dev/null +++ b/queue-5.10/drm-i915-gt-use-correct-selftest-config-symbol.patch @@ -0,0 +1,50 @@ +From e47cbbd752afe98e290483c7e0896960adfb6c1b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 5 Jul 2026 16:02:25 +0800 +Subject: drm/i915/gt: use correct selftest config symbol + +From: Pengpeng Hou + +[ Upstream commit a82f1bb8191aec98a971a2196136016ef70c0880 ] + +intel_engine_user.c checks CONFIG_DRM_I915_SELFTESTS before running +the engine UABI isolation check. Kconfig defines DRM_I915_SELFTEST, +without the trailing "S", and the rest of i915 uses +CONFIG_DRM_I915_SELFTEST. + +Because CONFIG_DRM_I915_SELFTESTS is not backed by any Kconfig symbol, +the IS_ENABLED() test is always false. Use the existing selftest symbol +so the debug/selftest guarded path can be reached when selftests are +enabled. + +This is a source-level fix. It does not claim dynamic hardware +reproduction; the evidence is the Kconfig definition and the inconsistent +guard in intel_engine_user.c. + +Fixes: 750e76b4f9f6 ("drm/i915/gt: Move the [class][inst] lookup for engines onto the GT") +Signed-off-by: Pengpeng Hou +Signed-off-by: Tvrtko Ursulin +Link: https://lore.kernel.org/r/20260705080225.436-1-pengpeng@iscas.ac.cn +(cherry picked from commit 14a2012a490258f3f93857bc4f1b203405964be7) +Signed-off-by: Rodrigo Vivi +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/i915/gt/intel_engine_user.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/i915/gt/intel_engine_user.c b/drivers/gpu/drm/i915/gt/intel_engine_user.c +index da21d2a10cc942..9aa7040e295ede 100644 +--- a/drivers/gpu/drm/i915/gt/intel_engine_user.c ++++ b/drivers/gpu/drm/i915/gt/intel_engine_user.c +@@ -232,7 +232,7 @@ void intel_engines_driver_register(struct drm_i915_private *i915) + p = &prev->rb_right; + } + +- if (IS_ENABLED(CONFIG_DRM_I915_SELFTESTS) && ++ if (IS_ENABLED(CONFIG_DRM_I915_SELFTEST) && + IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM)) { + struct intel_engine_cs *engine; + unsigned int isolation; +-- +2.53.0 + diff --git a/queue-5.10/drm-i915-selftests-fix-gt-pm-sort-comparators.patch b/queue-5.10/drm-i915-selftests-fix-gt-pm-sort-comparators.patch new file mode 100644 index 0000000000..c33b807d91 --- /dev/null +++ b/queue-5.10/drm-i915-selftests-fix-gt-pm-sort-comparators.patch @@ -0,0 +1,55 @@ +From de24d3e7bc2a092c61512e190ad3d15387a78ffd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 15 Jul 2026 01:04:30 +0300 +Subject: drm/i915/selftests: Fix GT PM sort comparators + +From: Emre Cecanpunar + +[ Upstream commit 612978b83f45bf7018815209db5395d759db6f26 ] + +Compare the sampled clock values instead of their addresses. Comparing +addresses leaves the samples unsorted, preventing the code from discarding +the minimum and maximum samples. + +Fixes: 1a5392479207 ("drm/i915/selftests: Measure CS_TIMESTAMP") +Signed-off-by: Emre Cecanpunar +Signed-off-by: Tvrtko Ursulin +Link: https://lore.kernel.org/r/20260714220430.238433-1-emreleno@gmail.com +(cherry picked from commit 682ea2d28d18bb06f9fc663cb5ab7e80dc0e606a) +Signed-off-by: Rodrigo Vivi +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/i915/gt/selftest_gt_pm.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/drivers/gpu/drm/i915/gt/selftest_gt_pm.c b/drivers/gpu/drm/i915/gt/selftest_gt_pm.c +index 6180a47c1b5114..9ec66ef774cf56 100644 +--- a/drivers/gpu/drm/i915/gt/selftest_gt_pm.c ++++ b/drivers/gpu/drm/i915/gt/selftest_gt_pm.c +@@ -17,9 +17,9 @@ static int cmp_u64(const void *A, const void *B) + { + const u64 *a = A, *b = B; + +- if (a < b) ++ if (*a < *b) + return -1; +- else if (a > b) ++ else if (*a > *b) + return 1; + else + return 0; +@@ -29,9 +29,9 @@ static int cmp_u32(const void *A, const void *B) + { + const u32 *a = A, *b = B; + +- if (a < b) ++ if (*a < *b) + return -1; +- else if (a > b) ++ else if (*a > *b) + return 1; + else + return 0; +-- +2.53.0 + diff --git a/queue-5.10/firmware-arm_scmi-rate-limit-queue-full-warnings-in-.patch b/queue-5.10/firmware-arm_scmi-rate-limit-queue-full-warnings-in-.patch new file mode 100644 index 0000000000..7b2684508a --- /dev/null +++ b/queue-5.10/firmware-arm_scmi-rate-limit-queue-full-warnings-in-.patch @@ -0,0 +1,54 @@ +From 49450c4b687db51b5aae1afaeb8370cf85edda32 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 8 Jul 2026 12:53:39 +0530 +Subject: firmware: arm_scmi: Rate-limit queue-full warnings in IRQ context + +From: Pushpendra Singh + +[ Upstream commit a4447c0693830d5ecadd6e755cb7fdc55d86aacc ] + +The scmi_notify() function is called from interrupt context to queue +received notification events onto a per-protocol kfifo. When the kfifo +is full, it logs a warning via dev_warn() for every dropped event. + +Under conditions where the platform sends a burst of SCMI notifications +faster than the deferred worker can drain the queue, this results in a +flood of dev_warn() calls from IRQ context. Each call acquires the +console lock and may execute blocking console writes, causing the CPU +to be held in interrupt context for an extended period and leading to +observable system stalls. + +Fix this by switching to dev_warn_ratelimited() to limit the frequency +of log messages when the notification queue is full. This reduces +console overhead in interrupt context and prevents CPU stalls caused by +excessive logging, while still preserving diagnostic visibility. + +Fixes: bd31b249692e ("firmware: arm_scmi: Add notification dispatch and delivery") +Signed-off-by: Pushpendra Singh +Link: https://patch.msgid.link/20260708072339.3021140-1-pushpendra.singh@oss.qualcomm.com +Signed-off-by: Sudeep Holla +Signed-off-by: Sasha Levin +--- + drivers/firmware/arm_scmi/notify.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/firmware/arm_scmi/notify.c b/drivers/firmware/arm_scmi/notify.c +index 66196b293b6c2a..99887349de2383 100644 +--- a/drivers/firmware/arm_scmi/notify.c ++++ b/drivers/firmware/arm_scmi/notify.c +@@ -594,9 +594,9 @@ int scmi_notify(const struct scmi_handle *handle, u8 proto_id, u8 evt_id, + return -EINVAL; + } + if (kfifo_avail(&r_evt->proto->equeue.kfifo) < sizeof(eh) + len) { +- dev_warn(handle->dev, +- "queue full, dropping proto_id:%d evt_id:%d ts:%lld\n", +- proto_id, evt_id, ktime_to_ns(ts)); ++ dev_warn_ratelimited(handle->dev, ++ "queue full, dropping proto_id:%d evt_id:%d ts:%lld\n", ++ proto_id, evt_id, ktime_to_ns(ts)); + return -ENOMEM; + } + +-- +2.53.0 + diff --git a/queue-5.10/ib-mad-drop-unmatched-rmpp-responses-before-reassemb.patch b/queue-5.10/ib-mad-drop-unmatched-rmpp-responses-before-reassemb.patch new file mode 100644 index 0000000000..9e1b9f94de --- /dev/null +++ b/queue-5.10/ib-mad-drop-unmatched-rmpp-responses-before-reassemb.patch @@ -0,0 +1,90 @@ +From 1cc0743acdf531b7b04e64e378635a6e8382c644 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 6 Jun 2026 16:01:55 -0400 +Subject: IB/mad: Drop unmatched RMPP responses before reassembly + +From: Michael Bommarito + +[ Upstream commit d2e52d610b9b09694261632340b801a421e0b0c5 ] + +Kernel-handled RMPP receive processing starts reassembly for active +DATA responses before the response is matched to an outstanding send. +The normal match happens later, after ib_process_rmpp_recv_wc() has +either assembled a complete message or consumed the segment. + +That ordering lets an unsolicited response that routes to a kernel +RMPP agent by the high TID bits allocate or extend RMPP receive state +before the full TID and source address are checked against a real +request. A reordered burst can therefore reach the receive-side +insertion path even though the response would not match any send. + +For kernel-handled RMPP DATA responses, require the existing +ib_find_send_mad() match before entering RMPP reassembly. The matcher +already checks the full TID, management class and source address/GID +against the agent wait, backlog and in-flight send lists. If there is +no match, drop the response without creating RMPP state. + +This leaves the RMPP window behavior unchanged and only rejects +responses that have no corresponding request. + +Fixes: fa619a77046b ("[PATCH] IB: Add RMPP implementation") +Assisted-by: Codex:gpt-5-5-xhigh +Signed-off-by: Michael Bommarito +Link: https://patch.msgid.link/3170ff3bc389a930bb1641f2caa394a0b2241579.1780774907.git.michael.bommarito@gmail.com +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + drivers/infiniband/core/mad.c | 30 ++++++++++++++++++++++++++++++ + 1 file changed, 30 insertions(+) + +diff --git a/drivers/infiniband/core/mad.c b/drivers/infiniband/core/mad.c +index e38ae4ac454f6b..10d29167b585c0 100644 +--- a/drivers/infiniband/core/mad.c ++++ b/drivers/infiniband/core/mad.c +@@ -1783,6 +1783,24 @@ void ib_mark_mad_done(struct ib_mad_send_wr_private *mad_send_wr) + &mad_send_wr->mad_agent_priv->done_list); + } + ++static bool is_kernel_rmpp_data_response(struct ib_mad_agent_private *agent, ++ struct ib_mad_recv_wc *mad_recv_wc) ++{ ++ const struct ib_mad_hdr *mad_hdr = &mad_recv_wc->recv_buf.mad->mad_hdr; ++ struct ib_rmpp_mad *rmpp_mad; ++ ++ if (!ib_mad_kernel_rmpp_agent(&agent->agent) || ++ !ib_response_mad(mad_hdr) || ++ !ib_is_mad_class_rmpp(mad_hdr->mgmt_class)) ++ return false; ++ ++ rmpp_mad = (struct ib_rmpp_mad *)mad_recv_wc->recv_buf.mad; ++ ++ return (ib_get_rmpp_flags(&rmpp_mad->rmpp_hdr) & ++ IB_MGMT_RMPP_FLAG_ACTIVE) && ++ rmpp_mad->rmpp_hdr.rmpp_type == IB_MGMT_RMPP_TYPE_DATA; ++} ++ + static void ib_mad_complete_recv(struct ib_mad_agent_private *mad_agent_priv, + struct ib_mad_recv_wc *mad_recv_wc) + { +@@ -1801,6 +1819,18 @@ static void ib_mad_complete_recv(struct ib_mad_agent_private *mad_agent_priv, + } + + list_add(&mad_recv_wc->recv_buf.list, &mad_recv_wc->rmpp_list); ++ if (is_kernel_rmpp_data_response(mad_agent_priv, mad_recv_wc)) { ++ spin_lock_irqsave(&mad_agent_priv->lock, flags); ++ mad_send_wr = ib_find_send_mad(mad_agent_priv, mad_recv_wc); ++ spin_unlock_irqrestore(&mad_agent_priv->lock, flags); ++ ++ if (!mad_send_wr) { ++ ib_free_recv_mad(mad_recv_wc); ++ deref_mad_agent(mad_agent_priv); ++ return; ++ } ++ } ++ + if (ib_mad_kernel_rmpp_agent(&mad_agent_priv->agent)) { + mad_recv_wc = ib_process_rmpp_recv_wc(mad_agent_priv, + mad_recv_wc); +-- +2.53.0 + diff --git a/queue-5.10/ipv4-fib-free-fib_alias-with-kfree_rcu-on-insert-err.patch b/queue-5.10/ipv4-fib-free-fib_alias-with-kfree_rcu-on-insert-err.patch new file mode 100644 index 0000000000..de5de1df66 --- /dev/null +++ b/queue-5.10/ipv4-fib-free-fib_alias-with-kfree_rcu-on-insert-err.patch @@ -0,0 +1,67 @@ +From e2d61b96d4ed8de0eae8f4bad66afc5378f6bad2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 4 Jul 2026 10:14:21 -0700 +Subject: ipv4: fib: free fib_alias with kfree_rcu() on insert error path + +From: Weiming Shi + +[ Upstream commit f2f152e94a67bc746afaf05a1b2702c195553112 ] + +fib_table_insert() publishes new_fa into the leaf's fa_list with +fib_insert_alias() before calling the fib entry notifiers. When a +notifier fails, the error path removes new_fa with fib_remove_alias() +(hlist_del_rcu) and frees it right away with kmem_cache_free(). + +fib_table_lookup() walks that list under rcu_read_lock() only, so a +concurrent lookup that already reached new_fa keeps reading it after the +free: + + BUG: KASAN: slab-use-after-free in fib_table_lookup (net/ipv4/fib_trie.c:1601) + Read of size 1 at addr ffff88810676d4eb by task exploit/297 + Call Trace: + fib_table_lookup (net/ipv4/fib_trie.c:1601) + ip_route_output_key_hash_rcu (net/ipv4/route.c:2814) + ip_route_output_key_hash (net/ipv4/route.c:2705) + __ip4_datagram_connect (net/ipv4/datagram.c:49) + udp_connect (net/ipv4/udp.c:2144) + __sys_connect (net/socket.c:2167) + __x64_sys_connect (net/socket.c:2173) + do_syscall_64 + entry_SYSCALL_64_after_hwframe + which belongs to the cache ip_fib_alias of size 56 + +Triggering the error path needs CAP_NET_ADMIN and a registered fib +notifier that can reject a route; a netdevsim device whose IPv4 FIB +resource is exhausted is enough. + +Free new_fa with alias_free_mem_rcu(), as fib_table_delete() already +does for a fib_alias removed from the trie. + +Fixes: a6c76c17df02 ("ipv4: Notify route after insertion to the routing table") +Reported-by: Xiang Mei +Assisted-by: Claude:claude-opus-4-8 +Signed-off-by: Weiming Shi +Reviewed-by: Ido Schimmel +Link: https://patch.msgid.link/20260704171421.1786806-1-bestswngs@gmail.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/ipv4/fib_trie.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c +index 5c75591bcce003..5c061dffc3795f 100644 +--- a/net/ipv4/fib_trie.c ++++ b/net/ipv4/fib_trie.c +@@ -1340,7 +1340,7 @@ int fib_table_insert(struct net *net, struct fib_table *tb, + out_remove_new_fa: + fib_remove_alias(t, tp, l, new_fa); + out_free_new_fa: +- kmem_cache_free(fn_alias_kmem, new_fa); ++ alias_free_mem_rcu(new_fa); + out: + fib_release_info(fi); + err: +-- +2.53.0 + diff --git a/queue-5.10/mac80211_hwsim-add-6ghz-channels.patch b/queue-5.10/mac80211_hwsim-add-6ghz-channels.patch new file mode 100644 index 0000000000..f8a12b72fa --- /dev/null +++ b/queue-5.10/mac80211_hwsim-add-6ghz-channels.patch @@ -0,0 +1,137 @@ +From ae6f1f99a124ea98776cb17334c8503b50e3398d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 27 Dec 2020 00:11:55 -0300 +Subject: mac80211_hwsim: add 6GHz channels + +From: Ramon Fontes + +[ Upstream commit 28881922abd786a1e62a4ca77394a84373dd5279 ] + +Advertise 6GHz channels to mac80211. + +Signed-off-by: Ramon Fontes +Link: https://lore.kernel.org/r/20201227031155.81161-1-ramonreisfontes@gmail.com +[reword commit message] +Signed-off-by: Johannes Berg +Stable-dep-of: 10a2b430f8f0 ("wifi: mac80211_hwsim: clamp virtio RX length before skb_put") +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/mac80211_hwsim.c | 74 ++++++++++++++++++++++++++- + 1 file changed, 73 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c +index 865bbe0293436c..d8b997859de063 100644 +--- a/drivers/net/wireless/mac80211_hwsim.c ++++ b/drivers/net/wireless/mac80211_hwsim.c +@@ -311,6 +311,12 @@ static struct net_device *hwsim_mon; /* global monitor netdev */ + .hw_value = (_freq), \ + } + ++#define CHAN6G(_freq) { \ ++ .band = NL80211_BAND_6GHZ, \ ++ .center_freq = (_freq), \ ++ .hw_value = (_freq), \ ++} ++ + static const struct ieee80211_channel hwsim_channels_2ghz[] = { + CHAN2G(2412), /* Channel 1 */ + CHAN2G(2417), /* Channel 2 */ +@@ -377,6 +383,68 @@ static const struct ieee80211_channel hwsim_channels_5ghz[] = { + CHAN5G(5925), /* Channel 185 */ + }; + ++static const struct ieee80211_channel hwsim_channels_6ghz[] = { ++ CHAN6G(5955), /* Channel 1 */ ++ CHAN6G(5975), /* Channel 5 */ ++ CHAN6G(5995), /* Channel 9 */ ++ CHAN6G(6015), /* Channel 13 */ ++ CHAN6G(6035), /* Channel 17 */ ++ CHAN6G(6055), /* Channel 21 */ ++ CHAN6G(6075), /* Channel 25 */ ++ CHAN6G(6095), /* Channel 29 */ ++ CHAN6G(6115), /* Channel 33 */ ++ CHAN6G(6135), /* Channel 37 */ ++ CHAN6G(6155), /* Channel 41 */ ++ CHAN6G(6175), /* Channel 45 */ ++ CHAN6G(6195), /* Channel 49 */ ++ CHAN6G(6215), /* Channel 53 */ ++ CHAN6G(6235), /* Channel 57 */ ++ CHAN6G(6255), /* Channel 61 */ ++ CHAN6G(6275), /* Channel 65 */ ++ CHAN6G(6295), /* Channel 69 */ ++ CHAN6G(6315), /* Channel 73 */ ++ CHAN6G(6335), /* Channel 77 */ ++ CHAN6G(6355), /* Channel 81 */ ++ CHAN6G(6375), /* Channel 85 */ ++ CHAN6G(6395), /* Channel 89 */ ++ CHAN6G(6415), /* Channel 93 */ ++ CHAN6G(6435), /* Channel 97 */ ++ CHAN6G(6455), /* Channel 181 */ ++ CHAN6G(6475), /* Channel 105 */ ++ CHAN6G(6495), /* Channel 109 */ ++ CHAN6G(6515), /* Channel 113 */ ++ CHAN6G(6535), /* Channel 117 */ ++ CHAN6G(6555), /* Channel 121 */ ++ CHAN6G(6575), /* Channel 125 */ ++ CHAN6G(6595), /* Channel 129 */ ++ CHAN6G(6615), /* Channel 133 */ ++ CHAN6G(6635), /* Channel 137 */ ++ CHAN6G(6655), /* Channel 141 */ ++ CHAN6G(6675), /* Channel 145 */ ++ CHAN6G(6695), /* Channel 149 */ ++ CHAN6G(6715), /* Channel 153 */ ++ CHAN6G(6735), /* Channel 157 */ ++ CHAN6G(6755), /* Channel 161 */ ++ CHAN6G(6775), /* Channel 165 */ ++ CHAN6G(6795), /* Channel 169 */ ++ CHAN6G(6815), /* Channel 173 */ ++ CHAN6G(6835), /* Channel 177 */ ++ CHAN6G(6855), /* Channel 181 */ ++ CHAN6G(6875), /* Channel 185 */ ++ CHAN6G(6895), /* Channel 189 */ ++ CHAN6G(6915), /* Channel 193 */ ++ CHAN6G(6935), /* Channel 197 */ ++ CHAN6G(6955), /* Channel 201 */ ++ CHAN6G(6975), /* Channel 205 */ ++ CHAN6G(6995), /* Channel 209 */ ++ CHAN6G(7015), /* Channel 213 */ ++ CHAN6G(7035), /* Channel 217 */ ++ CHAN6G(7055), /* Channel 221 */ ++ CHAN6G(7075), /* Channel 225 */ ++ CHAN6G(7095), /* Channel 229 */ ++ CHAN6G(7115), /* Channel 233 */ ++}; ++ + #define NUM_S1G_CHANS_US 51 + static struct ieee80211_channel hwsim_channels_s1g[NUM_S1G_CHANS_US]; + +@@ -548,6 +616,7 @@ struct mac80211_hwsim_data { + struct ieee80211_supported_band bands[NUM_NL80211_BANDS]; + struct ieee80211_channel channels_2ghz[ARRAY_SIZE(hwsim_channels_2ghz)]; + struct ieee80211_channel channels_5ghz[ARRAY_SIZE(hwsim_channels_5ghz)]; ++ struct ieee80211_channel channels_6ghz[ARRAY_SIZE(hwsim_channels_6ghz)]; + struct ieee80211_channel channels_s1g[ARRAY_SIZE(hwsim_channels_s1g)]; + struct ieee80211_rate rates[ARRAY_SIZE(hwsim_rates)]; + struct ieee80211_iface_combination if_combination; +@@ -579,7 +648,8 @@ struct mac80211_hwsim_data { + struct ieee80211_channel *channel; + unsigned long next_start, start, end; + } survey_data[ARRAY_SIZE(hwsim_channels_2ghz) + +- ARRAY_SIZE(hwsim_channels_5ghz)]; ++ ARRAY_SIZE(hwsim_channels_5ghz) + ++ ARRAY_SIZE(hwsim_channels_6ghz)]; + + struct ieee80211_channel *channel; + u64 beacon_int /* beacon interval in us */; +@@ -3187,6 +3257,8 @@ static int mac80211_hwsim_new_radio(struct genl_info *info, + sizeof(hwsim_channels_2ghz)); + memcpy(data->channels_5ghz, hwsim_channels_5ghz, + sizeof(hwsim_channels_5ghz)); ++ memcpy(data->channels_6ghz, hwsim_channels_6ghz, ++ sizeof(hwsim_channels_6ghz)); + memcpy(data->channels_s1g, hwsim_channels_s1g, + sizeof(hwsim_channels_s1g)); + memcpy(data->rates, hwsim_rates, sizeof(hwsim_rates)); +-- +2.53.0 + diff --git a/queue-5.10/mpls-fix-null-deref-in-mpls_valid_fib_dump_req-on-co.patch b/queue-5.10/mpls-fix-null-deref-in-mpls_valid_fib_dump_req-on-co.patch new file mode 100644 index 0000000000..05e0ba7b67 --- /dev/null +++ b/queue-5.10/mpls-fix-null-deref-in-mpls_valid_fib_dump_req-on-co.patch @@ -0,0 +1,68 @@ +From 6c3cbd6d609adaf9dd29fbf1150c3d0452a60f85 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 11 Jul 2026 04:50:00 -0700 +Subject: mpls: fix NULL deref in mpls_valid_fib_dump_req() on CONFIG_INET=n + +From: Weiming Shi + +[ Upstream commit 56d96fededd61192cd7cc8d2b0f36adfd59036c3 ] + +On CONFIG_INET=n builds, mpls_valid_fib_dump_req() walks the parsed +attribute table itself instead of calling ip_valid_fib_dump_req(). The +RTA_OIF arm passes tb[RTA_OIF] to nla_get_u32() without checking it is +present, so an RTM_GETROUTE dump for AF_MPLS with strict checking and no +RTA_OIF hits a NULL dereference. + +RTM_GETROUTE is RTNL_KIND_GET, which rtnetlink_rcv_msg() permits without +CAP_NET_ADMIN, so an unprivileged user can trigger it. + + Oops: general protection fault, probably for non-canonical address + 0xdffffc0000000000: 0000 [#1] SMP KASAN NOPTI + KASAN: null-ptr-deref in range [0x0000000000000000-0x0000000000000007] + RIP: 0010:mpls_valid_fib_dump_req (net/mpls/af_mpls.c:2189) + Call Trace: + mpls_dump_routes (net/mpls/af_mpls.c:2236) + netlink_dump (net/netlink/af_netlink.c:2331) + __netlink_dump_start (net/netlink/af_netlink.c:2446) + rtnetlink_rcv_msg (net/core/rtnetlink.c:7033) + netlink_rcv_skb (net/netlink/af_netlink.c:2556) + netlink_unicast (net/netlink/af_netlink.c:1345) + netlink_sendmsg (net/netlink/af_netlink.c:1900) + __sock_sendmsg (net/socket.c:790) + ____sys_sendmsg (net/socket.c:2684) + ___sys_sendmsg (net/socket.c:2738) + __sys_sendmsg (net/socket.c:2770) + do_syscall_64 (arch/x86/entry/syscall_64.c:94) + entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:121) + +Skip unset attributes, as ip_valid_fib_dump_req() does. + +Fixes: 196cfebf8972 ("net/mpls: Handle kernel side filtering of route dumps") +Assisted-by: Claude:claude-opus-4-8 +Reported-by: Xiang Mei +Signed-off-by: Weiming Shi +Reviewed-by: David Ahern +Link: https://patch.msgid.link/20260711114958.1009619-3-bestswngs@gmail.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/mpls/af_mpls.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/net/mpls/af_mpls.c b/net/mpls/af_mpls.c +index fa095bc8b0c1a6..66f498667ed892 100644 +--- a/net/mpls/af_mpls.c ++++ b/net/mpls/af_mpls.c +@@ -2144,6 +2144,9 @@ static int mpls_valid_fib_dump_req(struct net *net, const struct nlmsghdr *nlh, + int ifindex; + + if (i == RTA_OIF) { ++ if (!tb[i]) ++ continue; ++ + ifindex = nla_get_u32(tb[i]); + filter->dev = __dev_get_by_index(net, ifindex); + if (!filter->dev) +-- +2.53.0 + diff --git a/queue-5.10/mtd-mtdswap-remove-debugfs-stats-file-on-teardown.patch b/queue-5.10/mtd-mtdswap-remove-debugfs-stats-file-on-teardown.patch new file mode 100644 index 0000000000..6c6e33bd0e --- /dev/null +++ b/queue-5.10/mtd-mtdswap-remove-debugfs-stats-file-on-teardown.patch @@ -0,0 +1,57 @@ +From a3f9d3ce72d863659db2c3f84bde91247f1a5e43 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 23 Jun 2026 09:53:17 +0800 +Subject: mtd: mtdswap: remove debugfs stats file on teardown + +From: Pengpeng Hou + +[ Upstream commit 66fb31358108d10245b9e4ef0eef3e7d9747055e ] + +mtdswap_add_debugfs() creates an mtdswap_stats debugfs file under the +per-MTD debugfs directory, but mtdswap_remove_dev() never removes it +before freeing the mtdswap_dev. + +Store the returned dentry and remove it during device teardown before the +driver-private state is freed. + +Fixes: a32159024620 ("mtd: Add mtdswap block driver") +Signed-off-by: Pengpeng Hou +Signed-off-by: Miquel Raynal +Signed-off-by: Sasha Levin +--- + drivers/mtd/mtdswap.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/drivers/mtd/mtdswap.c b/drivers/mtd/mtdswap.c +index 58eefa43af1414..bd4ac120996243 100644 +--- a/drivers/mtd/mtdswap.c ++++ b/drivers/mtd/mtdswap.c +@@ -125,6 +125,7 @@ struct mtdswap_dev { + + char *page_buf; + char *oob_buf; ++ struct dentry *debugfs_stats; + }; + + struct mtdswap_oobdata { +@@ -1264,7 +1265,8 @@ static int mtdswap_add_debugfs(struct mtdswap_dev *d) + if (IS_ERR_OR_NULL(root)) + return -1; + +- debugfs_create_file("mtdswap_stats", S_IRUSR, root, d, &mtdswap_fops); ++ d->debugfs_stats = debugfs_create_file("mtdswap_stats", 0400, root, ++ d, &mtdswap_fops); + + return 0; + } +@@ -1465,6 +1467,7 @@ static void mtdswap_remove_dev(struct mtd_blktrans_dev *dev) + { + struct mtdswap_dev *d = MTDSWAP_MBD_TO_MTDSWAP(dev); + ++ debugfs_remove(d->debugfs_stats); + del_mtd_blktrans_dev(dev); + mtdswap_cleanup(d); + kfree(d); +-- +2.53.0 + diff --git a/queue-5.10/mtd-nand-mtk-ecc-stop-on-ecc-idle-timeouts.patch b/queue-5.10/mtd-nand-mtk-ecc-stop-on-ecc-idle-timeouts.patch new file mode 100644 index 0000000000..20f3d7c7d9 --- /dev/null +++ b/queue-5.10/mtd-nand-mtk-ecc-stop-on-ecc-idle-timeouts.patch @@ -0,0 +1,75 @@ +From 3b5dd720c4057885d45ad10f1f90e5a2614027ab Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 23 Jun 2026 21:57:29 +0800 +Subject: mtd: nand: mtk-ecc: stop on ECC idle timeouts + +From: Pengpeng Hou + +[ Upstream commit 16f7ec8d5dc100eafd2c8e06cd30340a30b104a1 ] + +mtk_ecc_wait_idle() logs when the encoder or decoder does not become +idle, but returns void. Callers can therefore configure a non-idle ECC +engine or read parity bytes after an unconfirmed encoder idle state. + +Return the idle poll result and propagate it from the enable and encode +paths that require the engine to be idle before continuing. + +Fixes: 1d6b1e464950 ("mtd: mediatek: driver for MTK Smart Device") +Signed-off-by: Pengpeng Hou +Signed-off-by: Miquel Raynal +Signed-off-by: Sasha Levin +--- + drivers/mtd/nand/raw/mtk_ecc.c | 16 ++++++++++++---- + 1 file changed, 12 insertions(+), 4 deletions(-) + +diff --git a/drivers/mtd/nand/raw/mtk_ecc.c b/drivers/mtd/nand/raw/mtk_ecc.c +index c115e03ede889b..c60e04cdf03a52 100644 +--- a/drivers/mtd/nand/raw/mtk_ecc.c ++++ b/drivers/mtd/nand/raw/mtk_ecc.c +@@ -116,8 +116,8 @@ static int mt7622_ecc_regs[] = { + [ECC_DECIRQ_STA] = 0x144, + }; + +-static inline void mtk_ecc_wait_idle(struct mtk_ecc *ecc, +- enum mtk_ecc_operation op) ++static inline int mtk_ecc_wait_idle(struct mtk_ecc *ecc, ++ enum mtk_ecc_operation op) + { + struct device *dev = ecc->dev; + u32 val; +@@ -129,6 +129,8 @@ static inline void mtk_ecc_wait_idle(struct mtk_ecc *ecc, + if (ret) + dev_warn(dev, "%s NOT idle\n", + op == ECC_ENCODE ? "encoder" : "decoder"); ++ ++ return ret; + } + + static irqreturn_t mtk_ecc_irq(int irq, void *id) +@@ -302,7 +304,11 @@ int mtk_ecc_enable(struct mtk_ecc *ecc, struct mtk_ecc_config *config) + return ret; + } + +- mtk_ecc_wait_idle(ecc, op); ++ ret = mtk_ecc_wait_idle(ecc, op); ++ if (ret) { ++ mutex_unlock(&ecc->lock); ++ return ret; ++ } + + ret = mtk_ecc_config(ecc, config); + if (ret) { +@@ -402,7 +408,9 @@ int mtk_ecc_encode(struct mtk_ecc *ecc, struct mtk_ecc_config *config, + if (ret) + goto timeout; + +- mtk_ecc_wait_idle(ecc, ECC_ENCODE); ++ ret = mtk_ecc_wait_idle(ecc, ECC_ENCODE); ++ if (ret) ++ goto timeout; + + /* Program ECC bytes to OOB: per sector oob = FDM + ECC + SPARE */ + len = (config->strength * ecc->caps->parity_bits + 7) >> 3; +-- +2.53.0 + diff --git a/queue-5.10/net-iucv-take-a-reference-on-the-socket-found-in-afi.patch b/queue-5.10/net-iucv-take-a-reference-on-the-socket-found-in-afi.patch new file mode 100644 index 0000000000..b482ec8e7e --- /dev/null +++ b/queue-5.10/net-iucv-take-a-reference-on-the-socket-found-in-afi.patch @@ -0,0 +1,55 @@ +From 806f2fc640f7518186a209ab490e51f51ec63989 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 5 Jul 2026 22:24:36 -0500 +Subject: net/iucv: take a reference on the socket found in afiucv_hs_rcv() + +From: Bryam Vargas + +[ Upstream commit 4fa349156043dc119721d067329714179f501749 ] + +afiucv_hs_rcv() looks up the destination socket under iucv_sk_list.lock, +drops the lock, and then passes the socket to the afiucv_hs_callback_*() +handlers without holding a reference. AF_IUCV sockets are not +RCU-protected and are freed synchronously by iucv_sock_kill() -> +sock_put(), so a concurrent close can free the socket in the window +between read_unlock() and the handler, which then dereferences freed +memory (for example sk->sk_data_ready() in afiucv_hs_callback_syn()). + +Take a reference with sock_hold() while the socket is still on the list +and release it with sock_put() once the handler has run. + +Fixes: 3881ac441f64 ("af_iucv: add HiperSockets transport") +Signed-off-by: Bryam Vargas +Reviewed-by: Hidayath Khan +Link: https://patch.msgid.link/20260705-b4-disp-fc79c0dc-v1-1-d2cdcb57afa9@proton.me +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/iucv/af_iucv.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c +index 8c08f07ce46551..3fb93840ec91bb 100644 +--- a/net/iucv/af_iucv.c ++++ b/net/iucv/af_iucv.c +@@ -2083,6 +2083,8 @@ static int afiucv_hs_rcv(struct sk_buff *skb, struct net_device *dev, + } + } + } ++ if (sk) ++ sock_hold(sk); + read_unlock(&iucv_sk_list.lock); + if (!iucv) + sk = NULL; +@@ -2132,6 +2134,8 @@ static int afiucv_hs_rcv(struct sk_buff *skb, struct net_device *dev, + kfree_skb(skb); + } + ++ if (sk) ++ sock_put(sk); + return err; + } + +-- +2.53.0 + diff --git a/queue-5.10/net-sched-act_tunnel_key-defer-dst_release-to-rcu-ca.patch b/queue-5.10/net-sched-act_tunnel_key-defer-dst_release-to-rcu-ca.patch new file mode 100644 index 0000000000..2788fc155a --- /dev/null +++ b/queue-5.10/net-sched-act_tunnel_key-defer-dst_release-to-rcu-ca.patch @@ -0,0 +1,176 @@ +From 3386833633a737894fb34a2591ef0688e7f15b51 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 11 Jul 2026 11:05:37 -0400 +Subject: net/sched: act_tunnel_key: Defer dst_release to RCU callback + +From: Jamal Hadi Salim + +[ Upstream commit f1f5c8a3955f8fda3f84ed883ac8daa1847e724c ] + +Fix a race-condition use-after-free in tunnel_key_release_params(). + +The function releases the metadata_dst of the old params synchronously +via dst_release() while deferring the params struct free with +kfree_rcu(). A concurrent tunnel_key_act() reader on the datapath may +still hold the old params pointer (under rcu_read_lock_bh) and proceed +to call dst_clone(¶ms->tcft_enc_metadata->dst) after the writer's +dst_release has already pushed the dst's rcuref to RCUREF_DEAD. + +zdi-disclosures@trendmicro.com produced a poc which i (and Victor) verified +that KASAN reports: + +================================================================== +BUG: KASAN: slab-use-after-free in instrument_atomic_read_write include/linux/instrumented.h:112 +BUG: KASAN: slab-use-after-free in atomic_sub_return_release include/linux/atomic/atomic-instrumented.h:326 +BUG: KASAN: slab-use-after-free in __rcuref_put include/linux/rcuref.h:109 +BUG: KASAN: slab-use-after-free in rcuref_put include/linux/rcuref.h:173 +BUG: KASAN: slab-use-after-free in dst_release+0x5b/0x370 net/core/dst.c:168 +Write of size 4 at addr ffff88806158de40 by task poc/9388 + +CPU: 0 UID: 0 PID: 9388 Comm: poc Tainted: G W 7.1.0-rc7 #7 PREEMPT(lazy) +Tainted: [W]=WARN +Hardware name: QEMU Ubuntu 25.10 PC v2 (i440FX + PIIX, + 10.1 machine, 1996), BIOS 1.16.3-debian-1.16.3-2 04/01/2014 +Call Trace: + + __dump_stack lib/dump_stack.c:94 + dump_stack_lvl+0x100/0x190 lib/dump_stack.c:120 + print_address_description mm/kasan/report.c:378 + print_report+0x139/0x4ad mm/kasan/report.c:482 + kasan_report+0xe4/0x1d0 mm/kasan/report.c:595 + check_region_inline mm/kasan/generic.c:186 + kasan_check_range+0x125/0x200 mm/kasan/generic.c:200 + instrument_atomic_read_write include/linux/instrumented.h:112 + atomic_sub_return_release include/linux/atomic/atomic-instrumented.h:326 + __rcuref_put include/linux/rcuref.h:109 + rcuref_put include/linux/rcuref.h:173 + dst_release+0x5b/0x370 net/core/dst.c:168 + refdst_drop include/net/dst.h:272 + skb_dst_drop include/net/dst.h:284 + skb_release_head_state+0x293/0x400 net/core/skbuff.c:1163 + skb_release_all net/core/skbuff.c:1187 +[..] +Allocated by task 9391: + kasan_save_stack+0x30/0x50 mm/kasan/common.c:57 + kasan_save_track+0x14/0x30 mm/kasan/common.c:78 + poison_kmalloc_redzone mm/kasan/common.c:398 + __kasan_kmalloc+0x9a/0xb0 mm/kasan/common.c:415 + kasan_kmalloc include/linux/kasan.h:263 + __do_kmalloc_node mm/slub.c:5296 + __kmalloc_noprof+0x2f1/0x830 mm/slub.c:5308 + kmalloc_noprof include/linux/slab.h:954 + kzalloc_noprof include/linux/slab.h:1188 + offload_action_alloc+0x2f/0x130 net/core/flow_offload.c:35 + tcf_action_offload_add_ex+0x1ba/0x880 net/sched/act_api.c:258 + tcf_action_offload_add net/sched/act_api.c:293 + tcf_action_init+0x66e/0xa20 net/sched/act_api.c:1547 + tcf_action_add+0xf6/0x5d0 net/sched/act_api.c:2101 +[..] +Freed by task 9391: + kasan_save_stack+0x30/0x50 mm/kasan/common.c:57 + kasan_save_track+0x14/0x30 mm/kasan/common.c:78 + kasan_save_free_info+0x3b/0x70 mm/kasan/generic.c:584 + poison_slab_object mm/kasan/common.c:253 + __kasan_slab_free+0x6b/0x90 mm/kasan/common.c:285 + kasan_slab_free include/linux/kasan.h:235 + slab_free_hook mm/slub.c:2689 + slab_free mm/slub.c:6251 + kfree+0x21f/0x6b0 mm/slub.c:6566 + tcf_action_offload_add_ex+0x4ad/0x880 net/sched/act_api.c:284 + tcf_action_offload_add net/sched/act_api.c:293 + tcf_action_init+0x66e/0xa20 net/sched/act_api.c:1547 + tcf_action_add+0xf6/0x5d0 net/sched/act_api.c:2101 + +The buggy address belongs to the object at ffff88806158de00 + which belongs to the cache kmalloc-256 of size 256 +The buggy address is located 64 bytes inside of + freed 256-byte region [ffff88806158de00, ffff88806158df00) + +The buggy address belongs to the physical page: +page: refcount:0 mapcount:0 mapping:0000000000000000 index:0xffff88806158d600 pfn:0x6158c +head: order:1 mapcount:0 entire_mapcount:0 nr_pages_mapped:0 pincount:0 +flags: 0x4fff00000000240(workingset|head|node=1|zone=1|lastcpupid=0x7ff) +page_type: f5(slab) +raw: 04fff00000000240 ffff88801c841b40 ffffea0001856290 ffffea0001856190 +raw: ffff88806158d600 0000000800100009 00000000f5000000 0000000000000000 +head: 04fff00000000240 ffff88801c841b40 ffffea0001856290 ffffea0001856190 +head: ffff88806158d600 0000000800100009 00000000f5000000 0000000000000000 +head: 04fff00000000001 ffffffffffffff81 00000000ffffffff 00000000ffffffff +head: ffffffffffffffff 0000000000000000 00000000ffffffff 0000000000000002 +page dumped because: kasan: bad access detected +page_owner tracks the page as allocated +page last allocated via order 1, migratetype Unmovable, gfp_mask 0xd2820(GFP_ATOMIC|__GFP_NOWARN|__GFP_NORETRY|__GFP_COMP|__GFP_NOMEMALLOC), pid 9391, tgid 9378 (poc), ts 123227323196, free_ts 0 + set_page_owner include/linux/page_owner.h:32 + post_alloc_hook+0xfe/0x140 mm/page_alloc.c:1853 + prep_new_page mm/page_alloc.c:1861 + get_page_from_freelist+0x110c/0x2fc0 mm/page_alloc.c:3941 + __alloc_frozen_pages_noprof+0x263/0x2bc0 mm/page_alloc.c:5221 + alloc_slab_page mm/slub.c:3278 + allocate_slab mm/slub.c:3467 + new_slab+0xa6/0x690 mm/slub.c:3525 + refill_objects+0x271/0x420 mm/slub.c:7272 + refill_sheaf mm/slub.c:2816 + __pcs_replace_empty_main+0x373/0x630 mm/slub.c:4652 + alloc_from_pcs mm/slub.c:4750 + slab_alloc_node mm/slub.c:4884 + __do_kmalloc_node mm/slub.c:5295 + __kmalloc_noprof+0x66d/0x830 mm/slub.c:5308 + kmalloc_noprof include/linux/slab.h:954 + metadata_dst_alloc+0x26/0x90 net/core/dst.c:298 + tun_rx_dst include/net/dst_metadata.h:144 + __ip_tun_set_dst include/net/dst_metadata.h:208 + tunnel_key_init+0xb01/0x1b90 net/sched/act_tunnel_key.c:451 + tcf_action_init_1+0x46b/0x6c0 net/sched/act_api.c:1428 + tcf_action_init+0x448/0xa20 net/sched/act_api.c:1503 + tcf_action_add+0xf6/0x5d0 net/sched/act_api.c:2101 +[..] +================================================================== + +Fix by moving dst_release() into a custom RCU callback that runs +after the grace period, matching the lifetime of the containing +params struct. Readers in the datapath therefore always find a live +rcuref when calling dst_clone(). + +Fixes: 9174c3df1cd18 ("net/sched: act_tunnel_key: fix memory leak in case of action replace") +Reported-by: zdi-disclosures@trendmicro.com +Tested-by: Victor Nogueira +Signed-off-by: Jamal Hadi Salim +Reviewed-by: Davide Caratti +Link: https://patch.msgid.link/20260711150537.7946-1-jhs@mojatatu.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/sched/act_tunnel_key.c | 14 ++++++++++---- + 1 file changed, 10 insertions(+), 4 deletions(-) + +diff --git a/net/sched/act_tunnel_key.c b/net/sched/act_tunnel_key.c +index 0d90349636f0e7..5a28adcd370a6a 100644 +--- a/net/sched/act_tunnel_key.c ++++ b/net/sched/act_tunnel_key.c +@@ -343,14 +343,20 @@ static const struct nla_policy tunnel_key_policy[TCA_TUNNEL_KEY_MAX + 1] = { + [TCA_TUNNEL_KEY_ENC_TTL] = { .type = NLA_U8 }, + }; + +-static void tunnel_key_release_params(struct tcf_tunnel_key_params *p) ++static void tunnel_key_release_params_rcu(struct rcu_head *head) + { +- if (!p) +- return; ++ struct tcf_tunnel_key_params *p = container_of(head, typeof(*p), rcu); ++ + if (p->tcft_action == TCA_TUNNEL_KEY_ACT_SET) + dst_release(&p->tcft_enc_metadata->dst); ++ kfree(p); ++} + +- kfree_rcu(p, rcu); ++static void tunnel_key_release_params(struct tcf_tunnel_key_params *p) ++{ ++ if (!p) ++ return; ++ call_rcu(&p->rcu, tunnel_key_release_params_rcu); + } + + static int tunnel_key_init(struct net *net, struct nlattr *nla, +-- +2.53.0 + diff --git a/queue-5.10/rdma-hns-fix-potential-integer-overflow-in-mhop-hem-.patch b/queue-5.10/rdma-hns-fix-potential-integer-overflow-in-mhop-hem-.patch new file mode 100644 index 0000000000..752ff730a7 --- /dev/null +++ b/queue-5.10/rdma-hns-fix-potential-integer-overflow-in-mhop-hem-.patch @@ -0,0 +1,52 @@ +From 242ebd8a38542a82dea78edcb41005dbeffde34a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 27 Jun 2026 09:59:51 +0000 +Subject: RDMA/hns: Fix potential integer overflow in mhop hem cleanup + +From: Danila Chernetsov + +[ Upstream commit 9f0f2d2121f16d420199a82ac5bbc242269133b3 ] + +In hns_roce_cleanup_mhop_hem_table(), the expression: + + obj = i * buf_chunk_size / table->obj_size; + +is evaluated using 32-bit unsigned arithmetic because +'buf_chunk_size' is u32 and the usual arithmetic conversions convert +'i' to unsigned int. The result is assigned to a u64 variable, but the +multiplication may overflow before the assignment. + +For sufficiently large HEM tables, this produces an incorrect object +index passed to hns_roce_table_mhop_put(). + +Cast 'i' to u64 before the multiplication so that the intermediate +calculation is performed with 64-bit arithmetic. + +Found by Linux Verification Center (linuxtesting.org) with SVACE. + +Fixes: a25d13cbe816 ("RDMA/hns: Add the interfaces to support multi hop addressing for the contexts in hip08") +Link: https://patch.msgid.link/r/20260627095951.51378-1-listdansp@mail.ru +Signed-off-by: Danila Chernetsov +Reviewed-by: Junxian Huang +Signed-off-by: Jason Gunthorpe +Signed-off-by: Sasha Levin +--- + drivers/infiniband/hw/hns/hns_roce_hem.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/infiniband/hw/hns/hns_roce_hem.c b/drivers/infiniband/hw/hns/hns_roce_hem.c +index 570a1bc24fd5a7..f36ea9141c7a1a 100644 +--- a/drivers/infiniband/hw/hns/hns_roce_hem.c ++++ b/drivers/infiniband/hw/hns/hns_roce_hem.c +@@ -896,7 +896,7 @@ static void hns_roce_cleanup_mhop_hem_table(struct hns_roce_dev *hr_dev, + mhop.bt_chunk_size; + + for (i = 0; i < table->num_hem; ++i) { +- obj = i * buf_chunk_size / table->obj_size; ++ obj = (u64)i * buf_chunk_size / table->obj_size; + if (table->hem[i]) + hns_roce_table_mhop_put(hr_dev, table, obj, 0); + } +-- +2.53.0 + diff --git a/queue-5.10/sctp-fix-auth_hmacs-array-size-in-struct-sctp_cookie.patch b/queue-5.10/sctp-fix-auth_hmacs-array-size-in-struct-sctp_cookie.patch new file mode 100644 index 0000000000..6dff375380 --- /dev/null +++ b/queue-5.10/sctp-fix-auth_hmacs-array-size-in-struct-sctp_cookie.patch @@ -0,0 +1,56 @@ +From 76d45000694b09cdeea7c22adbf78e6b59827e30 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 10 Jul 2026 14:12:35 -0400 +Subject: sctp: fix auth_hmacs array size in struct sctp_cookie + +From: Xin Long + +[ Upstream commit e0b5252a59383b77d1b8dbeda00b7184dd95f4d3 ] + +The auth_hmacs array in struct sctp_cookie is supposed to store a complete +SCTP_AUTH_HMAC_ALGO parameter, which consists of a struct sctp_paramhdr +followed by N HMAC identifiers. + +However, the array size was calculated using an extra 2 bytes instead of +sizeof(struct sctp_paramhdr), which is 4 bytes. When four HMAC identifiers +are configured, the HMAC-ALGO parameter stored in the endpoint is larger +than the auth_hmacs buffer in the cookie. + +As a result, sctp_association_init() copies beyond the end of auth_hmacs +when initializing the association, corrupting the adjacent auth_chunks +field. This can lead to an invalid HMAC identifier being accepted and later +cause an out-of-bounds read in sctp_auth_get_hmac(). + +Fix the array size calculation by including the full SCTP parameter header +size. + +Fixes: 1f485649f529 ("[SCTP]: Implement SCTP-AUTH internals") +Reported-by: Yuan Tan +Reported-by: Xin Liu +Reported-by: Zihan Xi +Reported-by: Ren Wei +Signed-off-by: Xin Long +Link: https://patch.msgid.link/634a0de0d5de29532915e6d47c92a0cbc206e03f.1783707155.git.lucien.xin@gmail.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + include/net/sctp/structs.h | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h +index 8d058b50f1386b..85ed2b59ffe71d 100644 +--- a/include/net/sctp/structs.h ++++ b/include/net/sctp/structs.h +@@ -318,7 +318,8 @@ struct sctp_cookie { + + __u8 auth_random[sizeof(struct sctp_paramhdr) + + SCTP_AUTH_RANDOM_LENGTH]; +- __u8 auth_hmacs[SCTP_AUTH_NUM_HMACS * sizeof(__u16) + 2]; ++ __u8 auth_hmacs[sizeof(struct sctp_paramhdr) + ++ SCTP_AUTH_NUM_HMACS * sizeof(__u16)]; + __u8 auth_chunks[sizeof(struct sctp_paramhdr) + SCTP_AUTH_MAX_CHUNKS]; + + /* This is a shim for my peer's INIT packet, followed by +-- +2.53.0 + diff --git a/queue-5.10/series b/queue-5.10/series index f8ba8cc0a3..1bf01b8acb 100644 --- a/queue-5.10/series +++ b/queue-5.10/series @@ -8,3 +8,37 @@ can-isotp-serialize-tx-state-transitions-under-so-rx.patch input-ims-pcu-fix-heap-buffer-overflow-in-ims_pcu_pr.patch input-ims-pcu-fix-logic-error-in-packet-reset.patch kvm-vmx-make-vmread_error_trampoline-uncallable-from.patch +ib-mad-drop-unmatched-rmpp-responses-before-reassemb.patch +mtd-mtdswap-remove-debugfs-stats-file-on-teardown.patch +mtd-nand-mtk-ecc-stop-on-ecc-idle-timeouts.patch +btrfs-remove-crc_check-logic-from-free-space.patch +btrfs-reject-free-space-cache-with-more-entries-than.patch +rdma-hns-fix-potential-integer-overflow-in-mhop-hem-.patch +xfrm-policy-preallocate-inexact-bins-before-xfrm_has.patch +wifi-ipw2100-fix-potential-memory-leak-in-ipw2100_pc.patch +mac80211_hwsim-add-6ghz-channels.patch +wifi-mac80211_hwsim-clamp-virtio-rx-length-before-sk.patch +wifi-libertas-fix-memory-leak-in-helper_firmware_cb.patch +wifi-p54-validate-rx-frame-length-in-p54_rx_eeprom_r.patch +wifi-cfg80211-validate-pmsr-measurement-type-data.patch +wifi-cfg80211-validate-pmsr-ftm-preamble-range.patch +wifi-cfg80211-reject-unsupported-pmsr-ftm-location-r.patch +wifi-mac80211-free-ap_vlan-bc_buf-skbs-outside-irq-l.patch +wifi-brcmfmac-initialize-sdio-data-work-before-clean.patch +wifi-cfg80211-bound-element-id-read-when-checking-no.patch +asoc-meson-aiu-fifo-spdif-soft-reset-the-s-pdif-data.patch +asoc-tas2562-fix-deprecated-shut-down-gpio-always-cl.patch +firmware-arm_scmi-rate-limit-queue-full-warnings-in-.patch +ipv4-fib-free-fib_alias-with-kfree_rcu-on-insert-err.patch +net-iucv-take-a-reference-on-the-socket-found-in-afi.patch +ata-sata_dwc_460ex-enable-sata-interrupts-only-after.patch +ata-sata_dwc_460ex-fix-clear_interrupt_bit-clearing-.patch +ata-sata_dwc_460ex-remove-variable-num_processed.patch +ata-sata_dwc_460ex-fix-infinite-loop-in-ncq-tag-comp.patch +smb-client-handle-overlapping-allocated-ranges-in-fa.patch +drm-i915-gt-use-correct-selftest-config-symbol.patch +can-j1939-fix-lockless-local-destination-check.patch +drm-i915-selftests-fix-gt-pm-sort-comparators.patch +net-sched-act_tunnel_key-defer-dst_release-to-rcu-ca.patch +sctp-fix-auth_hmacs-array-size-in-struct-sctp_cookie.patch +mpls-fix-null-deref-in-mpls_valid_fib_dump_req-on-co.patch diff --git a/queue-5.10/smb-client-handle-overlapping-allocated-ranges-in-fa.patch b/queue-5.10/smb-client-handle-overlapping-allocated-ranges-in-fa.patch new file mode 100644 index 0000000000..f0d71c3d35 --- /dev/null +++ b/queue-5.10/smb-client-handle-overlapping-allocated-ranges-in-fa.patch @@ -0,0 +1,110 @@ +From fd10d0996d7023d5844521f4e7e7f5d14a1c7d86 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 3 Jul 2026 13:32:56 +0800 +Subject: smb/client: handle overlapping allocated ranges in fallocate + +From: Huiwen He + +[ Upstream commit b09ae45d85dc816987a71db9eebc54b0ae288e94 ] + +smb3_simple_fallocate_range() can skip holes when an allocated range +returned by the server starts before the current fallocate offset. The +skipped hole is not zero-filled, but fallocate still returns success. A +later write to that hole may therefore fail with ENOSPC. + +The function queries allocated ranges so that it can preserve existing +contents and write zeroes only into holes. However, the server may return +a range that starts before the current fallocate offset. + +For example, assume the fallocate request is [100, 400) and the only +allocated range returned by the server is [0, 200): + + Request: [100, 400) + Server range: [ 0, 200) allocated + + Correct: + [100, 200) allocated data, skip + [200, 400) hole, zero-fill + + Current: + [100, 300) skipped + [300, 400) zero-filled afterwards + +The current code adds the full server range length, 200, to the current +offset 100 and moves to 300. As a result, the hole in [200, 300) is +skipped without being zero-filled. + +Fix this by advancing only over the part of the allocated range that +overlaps the current fallocate offset. Ignore ranges that end before the +current offset and reject ranges whose end offset overflows. + +This also prevents a malformed range length from causing an out-of-bounds +zero-buffer read. + +Fixes: 966a3cb7c7db ("cifs: improve fallocate emulation") +Signed-off-by: Huiwen He +Reviewed-by: ChenXiaoSong +Signed-off-by: Steve French +Signed-off-by: Sasha Levin +--- + fs/cifs/smb2ops.c | 25 ++++++++++++++++++------- + 1 file changed, 18 insertions(+), 7 deletions(-) + +diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c +index bd4ea48e057613..51f8ea0c890658 100644 +--- a/fs/cifs/smb2ops.c ++++ b/fs/cifs/smb2ops.c +@@ -3553,6 +3553,7 @@ static int smb3_simple_fallocate_range(unsigned int xid, + struct file_allocated_range_buffer in_data, *out_data = NULL, *tmp_data; + u32 out_data_len; + char *buf = NULL; ++ u64 range_start, range_len, range_end; + loff_t l; + int rc; + +@@ -3589,13 +3590,21 @@ static int smb3_simple_fallocate_range(unsigned int xid, + goto out; + } + +- if (off < le64_to_cpu(tmp_data->file_offset)) { ++ range_start = le64_to_cpu(tmp_data->file_offset); ++ range_len = le64_to_cpu(tmp_data->length); ++ if (check_add_overflow(range_start, range_len, &range_end) || ++ range_end > S64_MAX) { ++ rc = -EINVAL; ++ goto out; ++ } ++ ++ if (off < range_start) { + /* + * We are at a hole. Write until the end of the region + * or until the next allocated data, + * whichever comes next. + */ +- l = le64_to_cpu(tmp_data->file_offset) - off; ++ l = range_start - off; + if (len < l) + l = len; + rc = smb3_simple_fallocate_write_range(xid, tcon, +@@ -3612,11 +3621,13 @@ static int smb3_simple_fallocate_range(unsigned int xid, + * until the end of the data or the end of the region + * we are supposed to fallocate, whichever comes first. + */ +- l = le64_to_cpu(tmp_data->length); +- if (len < l) +- l = len; +- off += l; +- len -= l; ++ if (off < range_end) { ++ l = range_end - off; ++ if (len < l) ++ l = len; ++ off += l; ++ len -= l; ++ } + + tmp_data = &tmp_data[1]; + out_data_len -= sizeof(struct file_allocated_range_buffer); +-- +2.53.0 + diff --git a/queue-5.10/wifi-brcmfmac-initialize-sdio-data-work-before-clean.patch b/queue-5.10/wifi-brcmfmac-initialize-sdio-data-work-before-clean.patch new file mode 100644 index 0000000000..25f316697c --- /dev/null +++ b/queue-5.10/wifi-brcmfmac-initialize-sdio-data-work-before-clean.patch @@ -0,0 +1,61 @@ +From 512efeeb06f60e7eee2e71636fe977069bb211a8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 19 Jun 2026 14:44:01 +0800 +Subject: wifi: brcmfmac: initialize SDIO data work before cleanup + +From: Runyu Xiao + +[ Upstream commit 2a665946e0407a05a3f81bd56a08553c446498e0 ] + +brcmf_sdio_probe() stores the newly allocated bus in sdiodev->bus before +allocating the ordered workqueue. If that allocation fails, the function +jumps to fail and calls brcmf_sdio_remove(). + +brcmf_sdio_remove() unconditionally cancels bus->datawork. Initialize the +work item before the first failure path that can reach brcmf_sdio_remove(), +so the cleanup path always observes a valid work object. + +This issue was found by our static analysis tool and then confirmed by +manual review of the probe error path and the remove-time work drain. The +problem pattern is an early setup failure that reaches a cleanup helper +which cancels an embedded work item before its initializer has run. + +A QEMU PoC forced alloc_ordered_workqueue() to fail at the same point in +brcmf_sdio_probe(), before INIT_WORK(&bus->datawork) is reached. The +resulting fail path calls brcmf_sdio_remove(), and DEBUG_OBJECTS reports +the invalid work drain with brcmf_sdio_probe() and brcmf_sdio_remove() in +the stack. + +Fixes: 9982464379e8 ("brcmfmac: make sdio suspend wait for threads to freeze") +Signed-off-by: Runyu Xiao +Acked-by: Arend van Spriel +Link: https://patch.msgid.link/20260619064401.1048976-1-runyu.xiao@seu.edu.cn +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c +index 6ac2132c306478..5338d93e5b2299 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c +@@ -4438,6 +4438,7 @@ struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev) + bus->sdiodev = sdiodev; + sdiodev->bus = bus; + skb_queue_head_init(&bus->glom); ++ INIT_WORK(&bus->datawork, brcmf_sdio_dataworker); + bus->txbound = BRCMF_TXBOUND; + bus->rxbound = BRCMF_RXBOUND; + bus->txminmax = BRCMF_TXMINMAX; +@@ -4451,7 +4452,6 @@ struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev) + goto fail; + } + brcmf_sdiod_freezer_count(sdiodev); +- INIT_WORK(&bus->datawork, brcmf_sdio_dataworker); + bus->brcmf_wq = wq; + + /* attempt to attach to the dongle */ +-- +2.53.0 + diff --git a/queue-5.10/wifi-cfg80211-bound-element-id-read-when-checking-no.patch b/queue-5.10/wifi-cfg80211-bound-element-id-read-when-checking-no.patch new file mode 100644 index 0000000000..f42b6a4b26 --- /dev/null +++ b/queue-5.10/wifi-cfg80211-bound-element-id-read-when-checking-no.patch @@ -0,0 +1,58 @@ +From d945d27ee0b2a1e2c31ae847457fb893c0320559 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 7 Jul 2026 18:48:28 +0900 +Subject: wifi: cfg80211: bound element ID read when checking non-inheritance +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: HE WEI (ギカク) + +[ Upstream commit cb8afea4655ff004fa7feee825d5c79783525383 ] + +cfg80211_is_element_inherited() reads the first data octet of the +candidate element (id = elem->data[0]) to look it up in an extension +non-inheritance list. It does so after testing elem->id, but without +verifying that the element actually has a data octet. A zero-length +extension element (WLAN_EID_EXTENSION with length 0) therefore makes it +read one octet past the end of the element. + +_ieee802_11_parse_elems_full() runs this check for every element of a +frame once a non-inheritance context exists -- e.g. while parsing a +per-STA profile of a Multi-Link element in a (re)association response, +or a non-transmitted BSS profile -- so a crafted frame from an AP can +trigger a one-octet slab-out-of-bounds read during element parsing: + + BUG: KASAN: slab-out-of-bounds in cfg80211_is_element_inherited + Read of size 1 ... in net/wireless/scan.c + +Return early (treat the element as inherited) when an extension element +carries no data, mirroring the existing handling of empty ID lists. + +The bug was found by fuzzing ieee802_11_parse_elems_full() under KASAN. + +Fixes: f7dacfb11475 ("cfg80211: support non-inheritance element") +Signed-off-by: HE WEI (ギカク) +Link: https://patch.msgid.link/20260707094828.16465-1-skyexpoc@gmail.com +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + net/wireless/scan.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/wireless/scan.c b/net/wireless/scan.c +index 2b64bf73cbcf0a..7d0ddc467232a0 100644 +--- a/net/wireless/scan.c ++++ b/net/wireless/scan.c +@@ -240,7 +240,7 @@ bool cfg80211_is_element_inherited(const struct element *elem, + return true; + + if (elem->id == WLAN_EID_EXTENSION) { +- if (!ext_id_len) ++ if (!ext_id_len || !elem->datalen) + return true; + loop_len = ext_id_len; + list = &non_inherit_elem->data[3 + id_len]; +-- +2.53.0 + diff --git a/queue-5.10/wifi-cfg80211-reject-unsupported-pmsr-ftm-location-r.patch b/queue-5.10/wifi-cfg80211-reject-unsupported-pmsr-ftm-location-r.patch new file mode 100644 index 0000000000..16b41ab420 --- /dev/null +++ b/queue-5.10/wifi-cfg80211-reject-unsupported-pmsr-ftm-location-r.patch @@ -0,0 +1,50 @@ +From da8afebc6c9b5272315951354287906a4641669d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 12 Jun 2026 21:37:11 +0800 +Subject: wifi: cfg80211: reject unsupported PMSR FTM location requests + +From: Zhao Li + +[ Upstream commit 69ef6a7ec277f16d216be8da2b3cbe872786c999 ] + +PMSR FTM location request flags are syntactically valid, but they must +be rejected when the device capability does not advertise support for +them. + +Return an error immediately after rejecting unsupported LCI or civic +location request bits so the request cannot reach the driver. + +Fixes: 9bb7e0f24e7e7 ("cfg80211: add peer measurement with FTM initiator API") +Assisted-by: Codex:gpt-5.5 +Assisted-by: Claude:claude-opus-4.8 +Signed-off-by: Zhao Li +Link: https://patch.msgid.link/20260612133710.93544-2-enderaoelyther@gmail.com +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + net/wireless/pmsr.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/net/wireless/pmsr.c b/net/wireless/pmsr.c +index 4e636a07c1e1b4..19a1b256fc0ecf 100644 +--- a/net/wireless/pmsr.c ++++ b/net/wireless/pmsr.c +@@ -116,6 +116,7 @@ static int pmsr_parse_ftm(struct cfg80211_registered_device *rdev, + NL_SET_ERR_MSG_ATTR(info->extack, + tb[NL80211_PMSR_FTM_REQ_ATTR_REQUEST_LCI], + "FTM: LCI request not supported"); ++ return -EOPNOTSUPP; + } + + out->ftm.request_civicloc = +@@ -124,6 +125,7 @@ static int pmsr_parse_ftm(struct cfg80211_registered_device *rdev, + NL_SET_ERR_MSG_ATTR(info->extack, + tb[NL80211_PMSR_FTM_REQ_ATTR_REQUEST_CIVICLOC], + "FTM: civic location request not supported"); ++ return -EOPNOTSUPP; + } + + out->ftm.trigger_based = +-- +2.53.0 + diff --git a/queue-5.10/wifi-cfg80211-validate-pmsr-ftm-preamble-range.patch b/queue-5.10/wifi-cfg80211-validate-pmsr-ftm-preamble-range.patch new file mode 100644 index 0000000000..205b7c38b5 --- /dev/null +++ b/queue-5.10/wifi-cfg80211-validate-pmsr-ftm-preamble-range.patch @@ -0,0 +1,45 @@ +From e72a1cf9f3fc9d0bf9e44b36c99d9b55bc1c7a26 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 12 Jun 2026 21:37:04 +0800 +Subject: wifi: cfg80211: validate PMSR FTM preamble range + +From: Zhao Li + +[ Upstream commit 36230936468f0ba4930e94aef496fc229d4bb951 ] + +PMSR FTM request parsing accepts preamble values outside the +enumerated nl80211 preamble range. + +Reject out-of-range values before using them in the parser capability +bit test using the policy. + +Fixes: 9bb7e0f24e7e7 ("cfg80211: add peer measurement with FTM initiator API") +Assisted-by: Codex:gpt-5.5 +Assisted-by: Claude:claude-opus-4.8 +Signed-off-by: Zhao Li +Link: https://patch.msgid.link/20260612133703.93274-2-enderaoelyther@gmail.com +[drop unnecessary check] +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + net/wireless/nl80211.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c +index 33e2c29fbd3fde..3b2a70b467de9e 100644 +--- a/net/wireless/nl80211.c ++++ b/net/wireless/nl80211.c +@@ -280,7 +280,9 @@ nl80211_ftm_responder_policy[NL80211_FTM_RESP_ATTR_MAX + 1] = { + static const struct nla_policy + nl80211_pmsr_ftm_req_attr_policy[NL80211_PMSR_FTM_REQ_ATTR_MAX + 1] = { + [NL80211_PMSR_FTM_REQ_ATTR_ASAP] = { .type = NLA_FLAG }, +- [NL80211_PMSR_FTM_REQ_ATTR_PREAMBLE] = { .type = NLA_U32 }, ++ [NL80211_PMSR_FTM_REQ_ATTR_PREAMBLE] = ++ NLA_POLICY_RANGE(NLA_U32, NL80211_PREAMBLE_LEGACY, ++ NL80211_PREAMBLE_HE), + [NL80211_PMSR_FTM_REQ_ATTR_NUM_BURSTS_EXP] = + NLA_POLICY_MAX(NLA_U8, 15), + [NL80211_PMSR_FTM_REQ_ATTR_BURST_PERIOD] = { .type = NLA_U16 }, +-- +2.53.0 + diff --git a/queue-5.10/wifi-cfg80211-validate-pmsr-measurement-type-data.patch b/queue-5.10/wifi-cfg80211-validate-pmsr-measurement-type-data.patch new file mode 100644 index 0000000000..e50c316b3f --- /dev/null +++ b/queue-5.10/wifi-cfg80211-validate-pmsr-measurement-type-data.patch @@ -0,0 +1,76 @@ +From 6ea21f13db07299d8d5eefc58e1fdc7b7c7b6834 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 12 Jun 2026 21:36:57 +0800 +Subject: wifi: cfg80211: validate PMSR measurement type data + +From: Zhao Li + +[ Upstream commit 41aa973eb05922848dded26875c55ef982ac1c49 ] + +PMSR request parsing accepts missing or duplicated measurement type +entries in NL80211_PMSR_REQ_ATTR_DATA. + +Track whether one measurement type was already provided, reject a +second one immediately, and return an error if the request data block +contains no measurement type at all. + +Fixes: 9bb7e0f24e7e7 ("cfg80211: add peer measurement with FTM initiator API") +Assisted-by: Codex:gpt-5.5 +Assisted-by: Claude:claude-opus-4.8 +Signed-off-by: Zhao Li +Link: https://patch.msgid.link/20260612133656.92900-2-enderaoelyther@gmail.com +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + net/wireless/pmsr.c | 19 +++++++++++++++++-- + 1 file changed, 17 insertions(+), 2 deletions(-) + +diff --git a/net/wireless/pmsr.c b/net/wireless/pmsr.c +index 7503c7dd71ab5e..4e636a07c1e1b4 100644 +--- a/net/wireless/pmsr.c ++++ b/net/wireless/pmsr.c +@@ -168,6 +168,7 @@ static int pmsr_parse_peer(struct cfg80211_registered_device *rdev, + { + struct nlattr *tb[NL80211_PMSR_PEER_ATTR_MAX + 1]; + struct nlattr *req[NL80211_PMSR_REQ_ATTR_MAX + 1]; ++ bool have_measurement_type = false; + struct nlattr *treq; + int err, rem; + +@@ -220,6 +221,14 @@ static int pmsr_parse_peer(struct cfg80211_registered_device *rdev, + } + + nla_for_each_nested(treq, req[NL80211_PMSR_REQ_ATTR_DATA], rem) { ++ if (have_measurement_type) { ++ NL_SET_ERR_MSG_ATTR(info->extack, treq, ++ "multiple measurement types in request data"); ++ return -EINVAL; ++ } ++ ++ have_measurement_type = true; ++ + switch (nla_type(treq)) { + case NL80211_PMSR_TYPE_FTM: + err = pmsr_parse_ftm(rdev, treq, out, info); +@@ -229,10 +238,16 @@ static int pmsr_parse_peer(struct cfg80211_registered_device *rdev, + "unsupported measurement type"); + err = -EINVAL; + } ++ if (err) ++ return err; + } + +- if (err) +- return err; ++ if (!have_measurement_type) { ++ NL_SET_ERR_MSG_ATTR(info->extack, ++ req[NL80211_PMSR_REQ_ATTR_DATA], ++ "missing measurement type in request data"); ++ return -EINVAL; ++ } + + return 0; + } +-- +2.53.0 + diff --git a/queue-5.10/wifi-ipw2100-fix-potential-memory-leak-in-ipw2100_pc.patch b/queue-5.10/wifi-ipw2100-fix-potential-memory-leak-in-ipw2100_pc.patch new file mode 100644 index 0000000000..9e06ebffa9 --- /dev/null +++ b/queue-5.10/wifi-ipw2100-fix-potential-memory-leak-in-ipw2100_pc.patch @@ -0,0 +1,60 @@ +From 0089396684d1eee1e6b9dfb713667556aa3b9252 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 20 Jun 2026 12:22:39 +0530 +Subject: wifi: ipw2100: fix potential memory leak in ipw2100_pci_init_one() + +From: Abdun Nihaal + +[ Upstream commit 0d388f62031dbabcba0f44bb91b59f10e88cac17 ] + +The memory allocated in the ipw2100_alloc_device() function is not freed +in some of the error paths in ipw2100_pci_init_one(). Fix that by +converting the direct return into a goto to the error path return. + +The error path when pci_enable_device() fails cannot jump to fail, since +at this point priv is not set, so perform error handling inline. + +Fixes: 2c86c275015c ("Add ipw2100 wireless driver.") +Signed-off-by: Abdun Nihaal +Link: https://patch.msgid.link/20260620065242.93798-1-nihaal@cse.iitm.ac.in +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/intel/ipw2x00/ipw2100.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/drivers/net/wireless/intel/ipw2x00/ipw2100.c b/drivers/net/wireless/intel/ipw2x00/ipw2100.c +index 23fbddd0c1f8e0..a46ecfa07ba2b9 100644 +--- a/drivers/net/wireless/intel/ipw2x00/ipw2100.c ++++ b/drivers/net/wireless/intel/ipw2x00/ipw2100.c +@@ -6183,6 +6183,8 @@ static int ipw2100_pci_init_one(struct pci_dev *pci_dev, + if (err) { + printk(KERN_WARNING DRV_NAME + "Error calling pci_enable_device.\n"); ++ free_libipw(dev, 0); ++ pci_iounmap(pci_dev, ioaddr); + return err; + } + +@@ -6195,16 +6197,14 @@ static int ipw2100_pci_init_one(struct pci_dev *pci_dev, + if (err) { + printk(KERN_WARNING DRV_NAME + "Error calling pci_set_dma_mask.\n"); +- pci_disable_device(pci_dev); +- return err; ++ goto fail; + } + + err = pci_request_regions(pci_dev, DRV_NAME); + if (err) { + printk(KERN_WARNING DRV_NAME + "Error calling pci_request_regions.\n"); +- pci_disable_device(pci_dev); +- return err; ++ goto fail; + } + + /* We disable the RETRY_TIMEOUT register (0x41) to keep +-- +2.53.0 + diff --git a/queue-5.10/wifi-libertas-fix-memory-leak-in-helper_firmware_cb.patch b/queue-5.10/wifi-libertas-fix-memory-leak-in-helper_firmware_cb.patch new file mode 100644 index 0000000000..03848b6b87 --- /dev/null +++ b/queue-5.10/wifi-libertas-fix-memory-leak-in-helper_firmware_cb.patch @@ -0,0 +1,50 @@ +From 97762a32a263f0acdc4db5275440f22444d97673 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 24 Jun 2026 16:53:43 +0800 +Subject: wifi: libertas: fix memory leak in helper_firmware_cb() + +From: Dawei Feng + +[ Upstream commit 63c2391deefb31e1b801b7f32bd502ca4808639b ] + +helper_firmware_cb() neglects to free the single-stage firmware image +after a successful async load, leading to a memory leak in the USB +firmware-download path. + +Fix this memory leak by calling release_firmware() immediately after +lbs_fw_loaded() returns. + +The bug was first flagged by an experimental analysis tool we are +developing for kernel memory-management bugs while analyzing +v6.13-rc1. The tool is still under development and is not yet publicly +available. Manual inspection confirms that the bug is still present in +the current wireless tree. + +An x86_64 allyesconfig build showed no new warnings. As we do not have +compatible Libertas USB hardware for exercising this firmware-download +path, no runtime testing was able to be performed. + +Fixes: 1dfba3060fe7 ("libertas: move firmware lifetime handling to firmware.c") +Signed-off-by: Dawei Feng +Link: https://patch.msgid.link/20260624085343.575508-1-dawei.feng@seu.edu.cn +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/marvell/libertas/firmware.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/net/wireless/marvell/libertas/firmware.c b/drivers/net/wireless/marvell/libertas/firmware.c +index f124110944b7e9..9bf7d4c207b9ed 100644 +--- a/drivers/net/wireless/marvell/libertas/firmware.c ++++ b/drivers/net/wireless/marvell/libertas/firmware.c +@@ -78,6 +78,7 @@ static void helper_firmware_cb(const struct firmware *firmware, void *context) + } else { + /* No main firmware needed for this helper --> success! */ + lbs_fw_loaded(priv, 0, firmware, NULL); ++ release_firmware(firmware); + } + } + +-- +2.53.0 + diff --git a/queue-5.10/wifi-mac80211-free-ap_vlan-bc_buf-skbs-outside-irq-l.patch b/queue-5.10/wifi-mac80211-free-ap_vlan-bc_buf-skbs-outside-irq-l.patch new file mode 100644 index 0000000000..e871cbeb87 --- /dev/null +++ b/queue-5.10/wifi-mac80211-free-ap_vlan-bc_buf-skbs-outside-irq-l.patch @@ -0,0 +1,77 @@ +From cc5bad66b2b2a16bf276656aed319a77b3a37f3b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 6 Jul 2026 22:08:41 +0800 +Subject: wifi: mac80211: free AP_VLAN bc_buf SKBs outside IRQ lock + +From: Cen Zhang + +[ Upstream commit f3858d5b1432098c1936e03d6e03dd0e33facf60 ] + +ieee80211_do_stop() removes AP_VLAN packets from the parent AP +ps->bc_buf while holding ps->bc_buf.lock with IRQs disabled. It then +calls ieee80211_free_txskb() before dropping the lock. + +ieee80211_free_txskb() is not just a passive SKB release. For SKBs with +TX status state it can report a dropped frame through cfg80211/nl80211, +and that path can reach netlink tap transmit. This is the same reason +the pending queue cleanup in ieee80211_do_stop() already unlinks SKBs +under the queue lock and frees them after IRQ state is restored. + +The buggy scenario involves two paths, with each column showing the +order within that path: + +AP_VLAN management TX: AP_VLAN stop: +1. attach ACK-status state 1. clear the running state +2. queue a multicast SKB on 2. take ps->bc_buf.lock with IRQs + parent ps->bc_buf disabled + 3. unlink the AP_VLAN SKB + 4. call ieee80211_free_txskb() + +Unlink matching AP_VLAN SKBs from ps->bc_buf under the existing lock, +but move them to a local free queue. Drop the lock and restore IRQ state +before calling ieee80211_free_txskb(). + +WARNING: kernel/softirq.c:430 at __local_bh_enable_ip + +Fixes: 397a7a24ef8c ("mac80211: free ps->bc_buf skbs on vlan device stop") +Assisted-by: Codex:gpt-5.5 +Signed-off-by: Cen Zhang +Link: https://patch.msgid.link/20260706140841.581566-1-zzzccc427@gmail.com +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + net/mac80211/iface.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c +index 644eabaf10e31e..9abec4f929ca0a 100644 +--- a/net/mac80211/iface.c ++++ b/net/mac80211/iface.c +@@ -492,6 +492,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, + WARN_ON(!list_empty(&sdata->u.ap.vlans)); + } else if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) { + /* remove all packets in parent bc_buf pointing to this dev */ ++ __skb_queue_head_init(&freeq); + ps = &sdata->bss->ps; + + spin_lock_irqsave(&ps->bc_buf.lock, flags); +@@ -499,10 +500,15 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, + if (skb->dev == sdata->dev) { + __skb_unlink(skb, &ps->bc_buf); + local->total_ps_buffered--; +- ieee80211_free_txskb(&local->hw, skb); ++ __skb_queue_tail(&freeq, skb); + } + } + spin_unlock_irqrestore(&ps->bc_buf.lock, flags); ++ ++ skb_queue_walk_safe(&freeq, skb, tmp) { ++ __skb_unlink(skb, &freeq); ++ ieee80211_free_txskb(&local->hw, skb); ++ } + } + + if (going_down) +-- +2.53.0 + diff --git a/queue-5.10/wifi-mac80211_hwsim-clamp-virtio-rx-length-before-sk.patch b/queue-5.10/wifi-mac80211_hwsim-clamp-virtio-rx-length-before-sk.patch new file mode 100644 index 0000000000..4ffd9649b1 --- /dev/null +++ b/queue-5.10/wifi-mac80211_hwsim-clamp-virtio-rx-length-before-sk.patch @@ -0,0 +1,46 @@ +From 807fcddcb05fe17336045e90e6d80ae5d9be958f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 20 Jun 2026 21:45:18 -0500 +Subject: wifi: mac80211_hwsim: clamp virtio RX length before skb_put + +From: Bryam Vargas + +[ Upstream commit 10a2b430f8f06ae14b9590b6f6faa6b588ef0654 ] + +hwsim_virtio_rx_work() passes the virtqueue used-ring length reported by +the device straight to skb_put() on a fixed-size receive skb. A backend +reporting a length larger than the skb tailroom drives skb_put() past the +buffer end and hits skb_over_panic() -- a host-triggerable guest panic +(denial of service). + +Clamp the length to the skb's available room before skb_put(). A +conforming device never reports more than the posted buffer size, so valid +frames are unaffected; a truncated over-report then fails the +length/header checks in hwsim_virtio_handle_cmd() and is dropped, so +truncating rather than dropping here cannot be turned into a parsing +problem. + +Fixes: 5d44fe7c9808 ("mac80211_hwsim: add frame transmission support over virtio") +Signed-off-by: Bryam Vargas +Link: https://patch.msgid.link/20260620-b4-disp-474bee37-v1-1-1a4d37f3e2d4@proton.me +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/mac80211_hwsim.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c +index d8b997859de063..02c31f7fcfd13c 100644 +--- a/drivers/net/wireless/mac80211_hwsim.c ++++ b/drivers/net/wireless/mac80211_hwsim.c +@@ -4335,6 +4335,7 @@ static void hwsim_virtio_rx_work(struct work_struct *work) + + skb->data = skb->head; + skb_reset_tail_pointer(skb); ++ len = min(len, skb_end_offset(skb)); + skb_put(skb, len); + hwsim_virtio_handle_cmd(skb); + +-- +2.53.0 + diff --git a/queue-5.10/wifi-p54-validate-rx-frame-length-in-p54_rx_eeprom_r.patch b/queue-5.10/wifi-p54-validate-rx-frame-length-in-p54_rx_eeprom_r.patch new file mode 100644 index 0000000000..a39f4440e2 --- /dev/null +++ b/queue-5.10/wifi-p54-validate-rx-frame-length-in-p54_rx_eeprom_r.patch @@ -0,0 +1,80 @@ +From 0da27e73f307343b5fe2ce88487a25bd239ecdde Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 27 Jun 2026 17:05:10 -0700 +Subject: wifi: p54: validate RX frame length in p54_rx_eeprom_readback() + +From: Xiang Mei + +[ Upstream commit ebd6d37fa94bee929e0b4c9ca19fdf9b1dcf6cea ] + +p54_rx_eeprom_readback() copies the requested EEPROM slice out of a +device-supplied readback frame without checking that the skb actually holds +that many bytes. Commit da1b9a55ff11 ("wifi: p54: prevent buffer-overflow in +p54_rx_eeprom_readback()") closed the destination overflow by copying a +fixed priv->eeprom_slice_size (and rejecting a mismatched advertised len), +but the source side is still unbounded: nothing verifies the frame is long +enough to supply that many bytes. + +A malicious USB device can send a short frame whose advertised len matches +priv->eeprom_slice_size while the payload is truncated. The equality check +passes and memcpy() reads past the end of the skb, leaking adjacent heap: + + BUG: KASAN: slab-out-of-bounds in p54_rx (drivers/net/wireless/intersil/p54/txrx.c:507) + Read of size 1016 at addr ffff88800f077114 by task swapper/0/0 + Call Trace: + + ... + __asan_memcpy (mm/kasan/shadow.c:105) + p54_rx (drivers/net/wireless/intersil/p54/txrx.c:507) + p54u_rx_cb (drivers/net/wireless/intersil/p54/p54usb.c:163) + __usb_hcd_giveback_urb (drivers/usb/core/hcd.c:1657) + dummy_timer (drivers/usb/gadget/udc/dummy_hcd.c:2005) + ... + + + The buggy address belongs to the object at ffff88800f0770c0 + which belongs to the cache skbuff_small_head of size 704 + The buggy address is located 84 bytes inside of + allocated 704-byte region [ffff88800f0770c0, ffff88800f077380) + +Check that the slice fits in the skb before copying. + +Fixes: 7cb770729ba8 ("p54: move eeprom code into common library") +Reported-by: Weiming Shi +Assisted-by: Claude:claude-opus-4-8 +Signed-off-by: Xiang Mei +Acked-by: Christian Lamparter +Link: https://patch.msgid.link/20260628000510.4152481-1-xmei5@asu.edu +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/intersil/p54/txrx.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/drivers/net/wireless/intersil/p54/txrx.c b/drivers/net/wireless/intersil/p54/txrx.c +index 6333b1000f925b..303badbd53d9b0 100644 +--- a/drivers/net/wireless/intersil/p54/txrx.c ++++ b/drivers/net/wireless/intersil/p54/txrx.c +@@ -503,11 +503,19 @@ static void p54_rx_eeprom_readback(struct p54_common *priv, + if (le16_to_cpu(eeprom->v2.len) != priv->eeprom_slice_size) + return; + ++ if (eeprom->v2.data + priv->eeprom_slice_size > ++ skb_tail_pointer(skb)) ++ return; ++ + memcpy(priv->eeprom, eeprom->v2.data, priv->eeprom_slice_size); + } else { + if (le16_to_cpu(eeprom->v1.len) != priv->eeprom_slice_size) + return; + ++ if (eeprom->v1.data + priv->eeprom_slice_size > ++ skb_tail_pointer(skb)) ++ return; ++ + memcpy(priv->eeprom, eeprom->v1.data, priv->eeprom_slice_size); + } + +-- +2.53.0 + diff --git a/queue-5.10/xfrm-policy-preallocate-inexact-bins-before-xfrm_has.patch b/queue-5.10/xfrm-policy-preallocate-inexact-bins-before-xfrm_has.patch new file mode 100644 index 0000000000..2dbe1d376a --- /dev/null +++ b/queue-5.10/xfrm-policy-preallocate-inexact-bins-before-xfrm_has.patch @@ -0,0 +1,75 @@ +From 049bf23bac19b5ecc622a5dfa9adf920086b10fb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 3 Jul 2026 05:19:32 +0000 +Subject: xfrm: policy: preallocate inexact bins before xfrm_hash_rebuild + reinsert + +From: Xiang Mei (Microsoft) + +[ Upstream commit f38f8cce2f7e79775b3db7e8a5eacda04ac908e4 ] + +xfrm_hash_rebuild()'s first loop preallocates the bins/chains the reinsert +loop needs, so the reinsert (after hlist_del_rcu()) cannot allocate or +fail. But its guard is inverted: it skips policies with prefixlen < +threshold and preallocates for the rest. + +prefixlen < threshold is exactly when policy_hash_bysel() returns NULL and +the reinsert takes the allocating xfrm_policy_inexact_insert() path. So the +loop preallocates for the exact policies (which never allocate) and skips +the inexact ones, whose bin/node is then allocated GFP_ATOMIC during +reinsert. On failure the error path only WARN_ONCE()s and continues, +leaving a poisoned bydst node; the next rebuild's hlist_del_rcu() +dereferences LIST_POISON2 and takes a GPF. Reachable under memory pressure, +deterministic via failslab. + +Invert the guard so preallocation covers exactly the reinserted policies; +the reinsert then allocates nothing and cannot fail. + +Crash: + Oops: general protection fault, probably for non-canonical address + 0xfbd59c0000000024: 0000 [#1] SMP KASAN NOPTI + KASAN: maybe wild-memory-access in range [0xdead...] + ... + Workqueue: events xfrm_hash_rebuild + RIP: 0010:xfrm_hash_rebuild+0x5b3/0x1190 + RAX: dead000000000122 (LIST_POISON2 + offset) + ... + Call Trace: + hlist_del_rcu (include/linux/rculist.h:599) + xfrm_hash_rebuild (net/xfrm/xfrm_policy.c:1365) + process_one_work (kernel/workqueue.c:3322) + worker_thread (kernel/workqueue.c:3486) + kthread (kernel/kthread.c:436) + ret_from_fork (arch/x86/kernel/process.c:158) + ret_from_fork_asm (arch/x86/entry/entry_64.S:245) + ... + Kernel panic - not syncing: Fatal exception in interrupt + +Fixes: 24969facd704 ("xfrm: policy: store inexact policies in an rhashtable") +Reported-by: AutonomousCodeSecurity@microsoft.com +Signed-off-by: Xiang Mei (Microsoft) +Reviewed-by: Florian Westphal +Signed-off-by: Steffen Klassert +Signed-off-by: Sasha Levin +--- + net/xfrm/xfrm_policy.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c +index 37c4128e313cb2..26bc0821395507 100644 +--- a/net/xfrm/xfrm_policy.c ++++ b/net/xfrm/xfrm_policy.c +@@ -1292,8 +1292,8 @@ static void xfrm_hash_rebuild(struct work_struct *work) + } + } + +- if (policy->selector.prefixlen_d < dbits || +- policy->selector.prefixlen_s < sbits) ++ if (policy->selector.prefixlen_d >= dbits && ++ policy->selector.prefixlen_s >= sbits) + continue; + + bin = xfrm_policy_inexact_alloc_bin(policy, dir); +-- +2.53.0 + diff --git a/queue-5.15/alsa-usb-audio-skip-dsd-quirk-for-musical-fidelity-m.patch b/queue-5.15/alsa-usb-audio-skip-dsd-quirk-for-musical-fidelity-m.patch new file mode 100644 index 0000000000..50af4559a4 --- /dev/null +++ b/queue-5.15/alsa-usb-audio-skip-dsd-quirk-for-musical-fidelity-m.patch @@ -0,0 +1,47 @@ +From 5d4655fddc5b8b52529a3dc8ca7c683b9159ed12 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 9 Jul 2026 11:56:06 +0200 +Subject: ALSA: usb-audio: Skip DSD quirk for Musical Fidelity M6s DAC + +From: Takashi Iwai + +[ Upstream commit 93b47e66cc6d6c6382d44b44f5e7f6fc3a7b38c3 ] + +Salvador reported that the recent fix for applying the DSD quirk to +Musical Fidelity devices broke for his M6s DAC model (2772:0502). + +Although this is basically a firmware bug, the model in question is +fairly old, and no further firmware update can be expected, so it'd be +better to address in the driver side. + +As an ad hoc workaround, skip the DSD quirk for this device by adding +an empty quirk entry of 2772:0502; this essentially skips the later +DSD quirk entry by the match with the vendor 2772. + +Fixes: da3a7efff64e ("ALSA: usb-audio: Update for native DSD support quirks") +Reported-by: Salvador Blaya +Closes: https://lore.kernel.org/CAOdyq+qFaqCh=tK_wNnA64hv5pQuA1Y09ANxQ=xK8yR-t4mf9Q@mail.gmail.com +Tested-by: Salvador Blaya +Signed-off-by: Takashi Iwai +Link: https://patch.msgid.link/20260709095614.1418838-1-tiwai@suse.de +Signed-off-by: Sasha Levin +--- + sound/usb/quirks.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c +index acfad876362772..9cb0e24004db60 100644 +--- a/sound/usb/quirks.c ++++ b/sound/usb/quirks.c +@@ -1947,6 +1947,8 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = { + QUIRK_FLAG_DSD_RAW), + DEVICE_FLG(0x2708, 0x0002, /* Audient iD14 */ + QUIRK_FLAG_IGNORE_CTL_ERROR), ++ DEVICE_FLG(0x2772, 0x0502, /* Musical Fidelity M6s DAC */ ++ 0), /* for avoiding QUIRK_FLAG_DSD_RAW with vendor match */ + DEVICE_FLG(0x2912, 0x30c8, /* Audioengine D1 */ + QUIRK_FLAG_GET_SAMPLE_RATE), + DEVICE_FLG(0x2b53, 0x0023, /* Fiero SC-01 (firmware v1.0.0 @ 48 kHz) */ +-- +2.53.0 + diff --git a/queue-5.15/asoc-meson-aiu-fifo-spdif-soft-reset-the-s-pdif-data.patch b/queue-5.15/asoc-meson-aiu-fifo-spdif-soft-reset-the-s-pdif-data.patch new file mode 100644 index 0000000000..bcb6730dd2 --- /dev/null +++ b/queue-5.15/asoc-meson-aiu-fifo-spdif-soft-reset-the-s-pdif-data.patch @@ -0,0 +1,64 @@ +From 1de03092214f4067c593daa46beccc2198b117ce Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 27 Jun 2026 13:12:05 +0000 +Subject: ASoC: meson: aiu: fifo-spdif: soft reset the S/PDIF datapath on + start/stop + +From: Christian Hewitt + +[ Upstream commit 6b59c53c8adc2b522327407af5e1793a65b67e4b ] + +The I2S FIFO soft-resets its fast domain on start (AIU_RST_SOFT bit 0 + +AIU_I2S_SYNC read in aiu_fifo_i2s_trigger), mirroring the downstream +vendor driver's audio_out_i2s_enable(). The S/PDIF FIFO has no equivalent: +it only toggles the IEC958 DCU, so a stale datapath FIFO can be replayed, +producing the "machine gun noise" buffer underrun - on start when switching +outputs, and on stop when playback ends. The latter is audible on devices +with an always-on S/PDIF-fed DAC (e.g. the ES7144 on the WeTek Play2). + +The vendor driver resets the IEC958 fast domain (AIU_RST_SOFT bit 2) on +both enable and disable (audio_hw_958_enable), and when reconfiguring +(audio_hw_958_reset clears AIU_958_DCU_FF_CTRL then resets). Do the same: +reset before enabling the DCU on start, and before disabling on stop. + +Fixes: 6ae9ca9ce986bf ("ASoC: meson: aiu: add i2s and spdif support") +Signed-off-by: Christian Hewitt +Reviewed-by: Martin Blumenstingl +Link: https://patch.msgid.link/20260627131205.808800-1-christianshewitt@gmail.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/meson/aiu-fifo-spdif.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/sound/soc/meson/aiu-fifo-spdif.c b/sound/soc/meson/aiu-fifo-spdif.c +index 2fb30f89bf7a2c..515310e8eae79b 100644 +--- a/sound/soc/meson/aiu-fifo-spdif.c ++++ b/sound/soc/meson/aiu-fifo-spdif.c +@@ -24,6 +24,7 @@ + #define AIU_MEM_IEC958_CONTROL_MODE_16BIT BIT(7) + #define AIU_MEM_IEC958_CONTROL_MODE_LINEAR BIT(8) + #define AIU_MEM_IEC958_BUF_CNTL_INIT BIT(0) ++#define AIU_RST_SOFT_958_FAST BIT(2) + + #define AIU_FIFO_SPDIF_BLOCK 8 + +@@ -68,11 +69,15 @@ static int fifo_spdif_trigger(struct snd_pcm_substream *substream, int cmd, + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: ++ snd_soc_component_write(component, AIU_RST_SOFT, ++ AIU_RST_SOFT_958_FAST); + fifo_spdif_dcu_enable(component, true); + break; + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + case SNDRV_PCM_TRIGGER_STOP: ++ snd_soc_component_write(component, AIU_RST_SOFT, ++ AIU_RST_SOFT_958_FAST); + fifo_spdif_dcu_enable(component, false); + break; + default: +-- +2.53.0 + diff --git a/queue-5.15/asoc-tas2562-fix-deprecated-shut-down-gpio-always-cl.patch b/queue-5.15/asoc-tas2562-fix-deprecated-shut-down-gpio-always-cl.patch new file mode 100644 index 0000000000..1f9209eead --- /dev/null +++ b/queue-5.15/asoc-tas2562-fix-deprecated-shut-down-gpio-always-cl.patch @@ -0,0 +1,62 @@ +From 5f06e23a0b4502c5ec24568f34c7335a45a13a9f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 6 Jul 2026 21:01:09 +0530 +Subject: ASoC: tas2562: fix deprecated 'shut-down' GPIO always cleared after + lookup + +From: Uday Khare + +[ Upstream commit 3238c634725afbb2a137fdda762208510828f71d ] + +In tas2562_parse_dt(), the fallback lookup for the deprecated +"shut-down" GPIO property is broken due to a missing pair of braces. + +The code intends to reset sdz_gpio to NULL only when the lookup +returns an error that is not -EPROBE_DEFER (so the driver gracefully +continues without a GPIO). However, without braces the statement: + + tas2562->sdz_gpio = NULL; + +falls outside the IS_ERR() check and is executed unconditionally +for every path through the if block, including a successful GPIO +lookup. + +This means any device using the deprecated 'shut-down' DT property +will always have sdz_gpio == NULL after probe, making the GPIO +completely non-functional. + +Fix this by adding the missing braces to scope the NULL assignment +inside the IS_ERR() branch, matching the pattern already used for +the primary 'shutdown' GPIO lookup above. + +Fixes: f78a97003b8b ("ASoC: tas2562: Update shutdown GPIO property") +Signed-off-by: Uday Khare +Link: https://patch.msgid.link/20260706153109.10953-1-udaykhare77@gmail.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/codecs/tas2562.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/sound/soc/codecs/tas2562.c b/sound/soc/codecs/tas2562.c +index 10302552195e17..8ee40e584c0501 100644 +--- a/sound/soc/codecs/tas2562.c ++++ b/sound/soc/codecs/tas2562.c +@@ -719,11 +719,12 @@ static int tas2562_parse_dt(struct tas2562_data *tas2562) + if (tas2562->sdz_gpio == NULL) { + tas2562->sdz_gpio = devm_gpiod_get_optional(dev, "shut-down", + GPIOD_OUT_HIGH); +- if (IS_ERR(tas2562->sdz_gpio)) ++ if (IS_ERR(tas2562->sdz_gpio)) { + if (PTR_ERR(tas2562->sdz_gpio) == -EPROBE_DEFER) + return -EPROBE_DEFER; + +- tas2562->sdz_gpio = NULL; ++ tas2562->sdz_gpio = NULL; ++ } + } + + if (tas2562->model_id == TAS2110) +-- +2.53.0 + diff --git a/queue-5.15/ata-sata_dwc_460ex-enable-sata-interrupts-only-after.patch b/queue-5.15/ata-sata_dwc_460ex-enable-sata-interrupts-only-after.patch new file mode 100644 index 0000000000..219a826577 --- /dev/null +++ b/queue-5.15/ata-sata_dwc_460ex-enable-sata-interrupts-only-after.patch @@ -0,0 +1,56 @@ +From ab7cc0fbdd35dec88ba1574585aeb21161ba46f1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 12 Jul 2026 14:37:26 -0700 +Subject: ata: sata_dwc_460ex: enable SATA interrupts only after IRQ handler is + registered + +From: Rosen Penev + +[ Upstream commit 4bbc16a353a98023e5ddfca7c1fc0e49971cf4d0 ] + +sata_dwc_enable_interrupts() is called before platform_get_irq() and +ata_host_activate(), leaving the SATA controller's interrupt mask +enabled without a registered handler. If a later step fails (irq +request, phy init, etc.) or if the controller asserts an interrupt +during probe, the irq line may fire with no handler, causing a +spurious interrupt storm. + +Move sata_dwc_enable_interrupts() after ata_host_activate() so that +interrupts are only unmasked once the handler is registered and the +core is fully initialized. + +Fixes: 62936009f35a ("[libata] Add 460EX on-chip SATA driver, sata_dwc_460ex") +Assisted-by: opencode:big-pickle +Signed-off-by: Rosen Penev +Signed-off-by: Damien Le Moal +Signed-off-by: Sasha Levin +--- + drivers/ata/sata_dwc_460ex.c | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c +index 29e2b0dfba3096..dc9d91eacac82e 100644 +--- a/drivers/ata/sata_dwc_460ex.c ++++ b/drivers/ata/sata_dwc_460ex.c +@@ -1256,9 +1256,6 @@ static int sata_dwc_probe(struct platform_device *ofdev) + /* Save dev for later use in dev_xxx() routines */ + hsdev->dev = &ofdev->dev; + +- /* Enable SATA Interrupts */ +- sata_dwc_enable_interrupts(hsdev); +- + /* Get SATA interrupt number */ + irq = irq_of_parse_and_map(np, 0); + if (irq == NO_IRQ) { +@@ -1291,6 +1288,8 @@ static int sata_dwc_probe(struct platform_device *ofdev) + if (err) + dev_err(&ofdev->dev, "failed to activate host"); + ++ /* Enable SATA Interrupts */ ++ sata_dwc_enable_interrupts(hsdev); + return 0; + + error_out: +-- +2.53.0 + diff --git a/queue-5.15/ata-sata_dwc_460ex-fix-clear_interrupt_bit-clearing-.patch b/queue-5.15/ata-sata_dwc_460ex-fix-clear_interrupt_bit-clearing-.patch new file mode 100644 index 0000000000..431eab4c53 --- /dev/null +++ b/queue-5.15/ata-sata_dwc_460ex-fix-clear_interrupt_bit-clearing-.patch @@ -0,0 +1,45 @@ +From 4c93fa8d3cfa9efa6dca830917397729b5f7b8d2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 12 Jul 2026 14:37:27 -0700 +Subject: ata: sata_dwc_460ex: fix clear_interrupt_bit() clearing all pending + interrupts + +From: Rosen Penev + +[ Upstream commit 66c4e310ad71f41e41736d33dd8a1fb5eaaec7f3 ] + +clear_interrupt_bit() ignores the bit argument and performs a +read-write-back of the entire INTPR register. If INTPR uses standard +Write-1-to-Clear semantics, this clears every pending interrupt bit, +not just the intended one. Coalesced interrupts (e.g. DMAT + NEWFP) +would be cleared together, silently losing the second event. + +Write only the specific bit to clear so that other pending interrupts +are preserved. + +Fixes: 62936009f35a ("[libata] Add 460EX on-chip SATA driver, sata_dwc_460ex") +Assisted-by: opencode:big-pickle +Signed-off-by: Rosen Penev +Signed-off-by: Damien Le Moal +Signed-off-by: Sasha Levin +--- + drivers/ata/sata_dwc_460ex.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c +index dc9d91eacac82e..0023b232aeca2f 100644 +--- a/drivers/ata/sata_dwc_460ex.c ++++ b/drivers/ata/sata_dwc_460ex.c +@@ -443,8 +443,7 @@ static void clear_serror(struct ata_port *ap) + + static void clear_interrupt_bit(struct sata_dwc_device *hsdev, u32 bit) + { +- sata_dwc_writel(&hsdev->sata_dwc_regs->intpr, +- sata_dwc_readl(&hsdev->sata_dwc_regs->intpr)); ++ sata_dwc_writel(&hsdev->sata_dwc_regs->intpr, bit); + } + + static u32 qcmd_tag_to_mask(u8 tag) +-- +2.53.0 + diff --git a/queue-5.15/ata-sata_dwc_460ex-fix-infinite-loop-in-ncq-tag-comp.patch b/queue-5.15/ata-sata_dwc_460ex-fix-infinite-loop-in-ncq-tag-comp.patch new file mode 100644 index 0000000000..ac0c4f0759 --- /dev/null +++ b/queue-5.15/ata-sata_dwc_460ex-fix-infinite-loop-in-ncq-tag-comp.patch @@ -0,0 +1,54 @@ +From 5b74bba0f41066ae63323d5bb3103003d2b385c9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 12 Jul 2026 14:37:28 -0700 +Subject: ata: sata_dwc_460ex: fix infinite loop in NCQ tag completion + bit-scanning + +From: Rosen Penev + +[ Upstream commit c2130f6553f4a5cbdc259de069600117a995f197 ] + +The hand-rolled bit-scanning loop in the NCQ completion path has an +infinite loop bug. When tag_mask has only high bits set (e.g. +0x80000000), the inner while loop left-shifts tag_mask until it +overflows to 0. At that point !(0 & 1) is always true and 0 <<= 1 +stays 0, causing an infinite loop in hardirq context with a spinlock +held. + +Replace the open-coded bit-scanning with __ffs() which correctly +finds the least significant set bit and is bounded by the width of +the argument. + +Fixes: 62936009f35a ("[libata] Add 460EX on-chip SATA driver, sata_dwc_460ex") +Assisted-by: opencode:big-pickle +Signed-off-by: Rosen Penev +Signed-off-by: Damien Le Moal +Signed-off-by: Sasha Levin +--- + drivers/ata/sata_dwc_460ex.c | 9 ++------- + 1 file changed, 2 insertions(+), 7 deletions(-) + +diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c +index 98c91c89a3b336..1692c29227a024 100644 +--- a/drivers/ata/sata_dwc_460ex.c ++++ b/drivers/ata/sata_dwc_460ex.c +@@ -655,14 +655,9 @@ static irqreturn_t sata_dwc_isr(int irq, void *dev_instance) + status = ap->ops->sff_check_status(ap); + dev_dbg(ap->dev, "%s ATA status register=0x%x\n", __func__, status); + +- tag = 0; + while (tag_mask) { +- while (!(tag_mask & 0x00000001)) { +- tag++; +- tag_mask <<= 1; +- } +- +- tag_mask &= (~0x00000001); ++ tag = __ffs(tag_mask); ++ tag_mask &= ~(1U << tag); + qc = ata_qc_from_tag(ap, tag); + if (unlikely(!qc)) { + dev_err(ap->dev, "failed to get qc"); +-- +2.53.0 + diff --git a/queue-5.15/ata-sata_dwc_460ex-remove-variable-num_processed.patch b/queue-5.15/ata-sata_dwc_460ex-remove-variable-num_processed.patch new file mode 100644 index 0000000000..a410d80bc5 --- /dev/null +++ b/queue-5.15/ata-sata_dwc_460ex-remove-variable-num_processed.patch @@ -0,0 +1,47 @@ +From 3c90e66701e829e7b45b5de1c631ffefdbf1b089 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 24 Oct 2022 15:17:59 +0100 +Subject: ata: sata_dwc_460ex: remove variable num_processed + +From: Colin Ian King + +[ Upstream commit de58fd3d80f884f7f322a06bfe08465e49b47c5d ] + +Variable num_processed is just being incremented and it's never used +anywhere else. The variable and the increment are redundant so +remove it. + +Signed-off-by: Colin Ian King +Signed-off-by: Damien Le Moal +Stable-dep-of: c2130f6553f4 ("ata: sata_dwc_460ex: fix infinite loop in NCQ tag completion bit-scanning") +Signed-off-by: Sasha Levin +--- + drivers/ata/sata_dwc_460ex.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c +index 0023b232aeca2f..98c91c89a3b336 100644 +--- a/drivers/ata/sata_dwc_460ex.c ++++ b/drivers/ata/sata_dwc_460ex.c +@@ -511,7 +511,7 @@ static irqreturn_t sata_dwc_isr(int irq, void *dev_instance) + struct ata_queued_cmd *qc; + unsigned long flags; + u8 status, tag; +- int handled, num_processed, port = 0; ++ int handled, port = 0; + uint intpr, sactive, sactive2, tag_mask; + struct sata_dwc_device_port *hsdevp; + hsdev->sactive_issued = 0; +@@ -656,9 +656,7 @@ static irqreturn_t sata_dwc_isr(int irq, void *dev_instance) + dev_dbg(ap->dev, "%s ATA status register=0x%x\n", __func__, status); + + tag = 0; +- num_processed = 0; + while (tag_mask) { +- num_processed++; + while (!(tag_mask & 0x00000001)) { + tag++; + tag_mask <<= 1; +-- +2.53.0 + diff --git a/queue-5.15/bluetooth-qca-fix-nvm-tag-length-underflow-in-tlv-pa.patch b/queue-5.15/bluetooth-qca-fix-nvm-tag-length-underflow-in-tlv-pa.patch new file mode 100644 index 0000000000..4d0669e047 --- /dev/null +++ b/queue-5.15/bluetooth-qca-fix-nvm-tag-length-underflow-in-tlv-pa.patch @@ -0,0 +1,68 @@ +From 54a36dafdfb3f7e245d57694bcceca251e39d654 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 4 Jul 2026 16:10:30 -0700 +Subject: Bluetooth: qca: fix NVM tag length underflow in TLV parser + +From: Xiang Mei + +[ Upstream commit c90164ca0f7036942ba088eb7ea8d3f6c2352020 ] + +In the TLV_TYPE_NVM branch of qca_tlv_check_data() the tag loop bound is +"while (idx < length - sizeof(struct tlv_type_nvm))". "length" is a signed +int from the firmware TLV header and sizeof(struct tlv_type_nvm) is a +size_t (12), so "length" is converted to size_t and any firmware-supplied +"length" < 12 makes the subtraction wrap to a huge value. The loop body +then reads a 12-byte struct tlv_type_nvm past the end of the short +vmalloc'd firmware buffer (and the EDL_TAG_ID_* handlers can write past it). + +Rewrite the bound as "idx + sizeof(struct tlv_type_nvm) <= length"; both +operands are non-negative, so it no longer underflows and a "length" too +small for one record correctly skips the loop. + + BUG: KASAN: vmalloc-out-of-bounds in qca_download_firmware.isra.0 (drivers/bluetooth/btqca.c:421) + Read of size 2 at addr ffffc900000e5004 by task kworker/u9:0/52 + Workqueue: hci0 hci_power_on + Call Trace: + ... + kasan_report (mm/kasan/report.c:595) + qca_download_firmware.isra.0 (drivers/bluetooth/btqca.c:421 drivers/bluetooth/btqca.c:617) + qca_uart_setup (drivers/bluetooth/btqca.c:948) + qca_setup (drivers/bluetooth/hci_qca.c:2029) + hci_uart_setup (drivers/bluetooth/hci_ldisc.c:438) + hci_dev_open_sync (net/bluetooth/hci_sync.c:5227) + hci_power_on (net/bluetooth/hci_core.c:920) + process_one_work (kernel/workqueue.c:3322) + worker_thread (kernel/workqueue.c:3486) + kthread (kernel/kthread.c:436) + ret_from_fork (arch/x86/kernel/process.c:158) + ret_from_fork_asm (arch/x86/entry/entry_64.S:245) + +Fixes: 2e4edfa1e2bd ("Bluetooth: qca: add missing firmware sanity checks") +Reported-by: Weiming Shi +Assisted-by: Claude:claude-opus-4-8 +Signed-off-by: Xiang Mei +Reported-by: Weiming Shi +Reviewed-by: Johan Hovold +Acked-by: Bartosz Golaszewski +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + drivers/bluetooth/btqca.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/bluetooth/btqca.c b/drivers/bluetooth/btqca.c +index 25e98ce4a5af98..142d61abb137fd 100644 +--- a/drivers/bluetooth/btqca.c ++++ b/drivers/bluetooth/btqca.c +@@ -352,7 +352,7 @@ static int qca_tlv_check_data(struct hci_dev *hdev, + + idx = 0; + data = tlv->data; +- while (idx < length - sizeof(struct tlv_type_nvm)) { ++ while (idx + sizeof(struct tlv_type_nvm) <= length) { + tlv_nvm = (struct tlv_type_nvm *)(data + idx); + + tag_id = le16_to_cpu(tlv_nvm->tag_id); +-- +2.53.0 + diff --git a/queue-5.15/btrfs-fix-root-leak-if-its-reloc-root-is-unexpected-.patch b/queue-5.15/btrfs-fix-root-leak-if-its-reloc-root-is-unexpected-.patch new file mode 100644 index 0000000000..a499144abc --- /dev/null +++ b/queue-5.15/btrfs-fix-root-leak-if-its-reloc-root-is-unexpected-.patch @@ -0,0 +1,40 @@ +From 737cd72277a7a44f8110808611b4ba0522d5d876 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 11 Jun 2026 15:16:21 +0100 +Subject: btrfs: fix root leak if its reloc root is unexpected in + merge_reloc_roots() + +From: Filipe Manana + +[ Upstream commit ce6050bafb4e33377dc17fcc357736bfc351180c ] + +If we have an unexpected reloc_root for our root, we jump to the out label +but never drop the reference we obtained for root, resulting in a leak. +Add a missing btrfs_put_root() call. + +Fixes: 24213fa46c70 ("btrfs: do proper error handling in merge_reloc_roots") +Reviewed-by: Qu Wenruo +Reviewed-by: Johannes Thumshirn +Signed-off-by: Filipe Manana +Reviewed-by: David Sterba +Signed-off-by: David Sterba +Signed-off-by: Sasha Levin +--- + fs/btrfs/relocation.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c +index e66ec0c23153ea..2c4130c3120175 100644 +--- a/fs/btrfs/relocation.c ++++ b/fs/btrfs/relocation.c +@@ -2047,6 +2047,7 @@ void merge_reloc_roots(struct reloc_control *rc) + * corruption, e.g. bad reloc tree key offset. + */ + ret = -EINVAL; ++ btrfs_put_root(root); + goto out; + } + ret = merge_reloc_root(rc, root); +-- +2.53.0 + diff --git a/queue-5.15/btrfs-reject-free-space-cache-with-more-entries-than.patch b/queue-5.15/btrfs-reject-free-space-cache-with-more-entries-than.patch new file mode 100644 index 0000000000..792f22b367 --- /dev/null +++ b/queue-5.15/btrfs-reject-free-space-cache-with-more-entries-than.patch @@ -0,0 +1,88 @@ +From 86ee5eb18aae835eae7aa9e11aa7c6dc9fd07ee3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 10 Jun 2026 10:29:26 -0700 +Subject: btrfs: reject free space cache with more entries than pages + +From: Xiang Mei + +[ Upstream commit a2d8d5647ed854e38f941741aea45b9eb15a6350 ] + +When loading a v1 free space cache, __load_free_space_cache() takes +num_entries and num_bitmaps straight from the on-disk +btrfs_free_space_header. That header is stored in the tree_root under a key +with type 0, which the tree-checker has no case for, so neither count is +validated before the load trusts it. + +The load loops num_entries times and maps the next page whenever the current +one runs out, going through io_ctl_check_crc() -> io_ctl_map_page(), which +does io_ctl->pages[io_ctl->index++]. But pages[] is allocated in +io_ctl_init() from the cache inode's i_size, not from num_entries: + + num_pages = DIV_ROUND_UP(i_size_read(inode), PAGE_SIZE); + io_ctl->pages = kcalloc(num_pages, sizeof(struct page *), GFP_NOFS); + +So if num_entries claims more records than the pages can hold, io_ctl->index +runs off the end of pages[]. The write side never hits this because +io_ctl_add_entry() and io_ctl_add_bitmap() both stop once +io_ctl->index >= io_ctl->num_pages; the read side just never had the same +check. + +To trigger it, take a clean cache (num_entries = here), set num_entries +in the header to 0x10000, and fix up the leaf checksum so it still passes +the tree-checker. The cache inode has i_size = 65536, so num_pages is 16 and +pages[] is a 16-pointer (kmalloc-128) array. The load now tries to read +65536 entries, io_ctl->index walks up to 16, and pages[16] is read past the +array: + + BUG: KASAN: slab-out-of-bounds in io_ctl_check_crc (fs/btrfs/free-space-cache.c:420 fs/btrfs/free-space-cache.c:565) + Read of size 8 at addr ffff88800c833a80 by task kworker/u8:3/58 + io_ctl_check_crc (fs/btrfs/free-space-cache.c:420 fs/btrfs/free-space-cache.c:565) + __load_free_space_cache (fs/btrfs/free-space-cache.c:655 fs/btrfs/free-space-cache.c:820) + load_free_space_cache (fs/btrfs/free-space-cache.c:1017) + caching_thread (fs/btrfs/block-group.c:880) + btrfs_work_helper (fs/btrfs/async-thread.c:312) + process_one_work + worker_thread + kthread + ret_from_fork + +free-space-cache.c:420 is io_ctl_map_page(), inlined into io_ctl_check_crc() +at line 565, which is why that is the frame KASAN names. The out-of-bounds +slot is then treated as a struct page and handed to crc32c(), so the bad +read turns into a GP fault. + +Add the missing check to io_ctl_check_crc(), which is where both the entry +loop and the bitmap loop end up. When num_entries is too large the load now +fails like any corrupt cache: __load_free_space_cache() drops it and rebuilds +the free space from the extent tree, so a valid cache is never rejected. + +Reported-by: Weiming Shi +Fixes: 5b0e95bf607d ("Btrfs: inline checksums into the disk free space cache") +Link: https://lore.kernel.org/linux-btrfs/CAPpSM+RMPByMCKXvM5QFKToxsyNccfuFLWMdD0mfd0wh2Ja62w@mail.gmail.com/ +Assisted-by: Claude:claude-opus-4-8 +Reviewed-by: Qu Wenruo +Signed-off-by: Xiang Mei +Reviewed-by: David Sterba +Signed-off-by: David Sterba +Signed-off-by: Sasha Levin +--- + fs/btrfs/free-space-cache.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c +index ed8729c990883b..3ffcb6217b530f 100644 +--- a/fs/btrfs/free-space-cache.c ++++ b/fs/btrfs/free-space-cache.c +@@ -528,6 +528,9 @@ static int io_ctl_check_crc(struct btrfs_io_ctl *io_ctl, int index) + u32 crc = ~(u32)0; + unsigned offset = 0; + ++ if (index >= io_ctl->num_pages) ++ return -EIO; ++ + if (index == 0) + offset = sizeof(u32) * io_ctl->num_pages; + +-- +2.53.0 + diff --git a/queue-5.15/can-j1939-fix-lockless-local-destination-check.patch b/queue-5.15/can-j1939-fix-lockless-local-destination-check.patch new file mode 100644 index 0000000000..9be51c52c6 --- /dev/null +++ b/queue-5.15/can-j1939-fix-lockless-local-destination-check.patch @@ -0,0 +1,81 @@ +From f20136e2b53fe2458a4bb9e4c063be6e413b4b84 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 7 May 2026 10:22:26 +0200 +Subject: can: j1939: fix lockless local-destination check + +From: Shuhao Fu + +[ Upstream commit e4e8af62adab2fdcca230006f829407a953070cd ] + +j1939_priv.ents[].nusers is documented as protected by priv->lock, and +its updates already happen under that lock. j1939_can_recv() also reads +it under read_lock_bh(). However, j1939_session_skb_queue() and +j1939_tp_send() still read priv->ents[da].nusers without taking the +lock. + +Those transport-side checks decide whether to set J1939_ECU_LOCAL_DST, so +they can race with j1939_local_ecu_get() and j1939_local_ecu_put() while +userspace is binding or releasing sockets concurrently with TP traffic. +This can misclassify TP/ETP sessions as local or remote and take the wrong +transport path. + +Fix both transport paths by routing the destination-locality check through +a helper that reads ents[].nusers under read_lock_bh(&priv->lock). + +Fixes: 9d71dd0c7009 ("can: add support of SAE J1939 protocol") +Signed-off-by: Shuhao Fu +Tested-by: Oleksij Rempel +Acked-by: Oleksij Rempel +Link: https://patch.msgid.link/20260419140614.GA4041240@chcpu16 +Signed-off-by: Marc Kleine-Budde +Signed-off-by: Sasha Levin +--- + net/can/j1939/transport.c | 18 ++++++++++++++---- + 1 file changed, 14 insertions(+), 4 deletions(-) + +diff --git a/net/can/j1939/transport.c b/net/can/j1939/transport.c +index e17a166a73c422..57d7b14c3949e6 100644 +--- a/net/can/j1939/transport.c ++++ b/net/can/j1939/transport.c +@@ -350,6 +350,18 @@ static void j1939_session_skb_drop_old(struct j1939_session *session) + } + } + ++static bool j1939_address_is_local(struct j1939_priv *priv, u8 addr) ++{ ++ bool local = false; ++ ++ read_lock_bh(&priv->lock); ++ if (j1939_address_is_unicast(addr) && priv->ents[addr].nusers) ++ local = true; ++ read_unlock_bh(&priv->lock); ++ ++ return local; ++} ++ + void j1939_session_skb_queue(struct j1939_session *session, + struct sk_buff *skb) + { +@@ -358,8 +370,7 @@ void j1939_session_skb_queue(struct j1939_session *session, + + j1939_ac_fixup(priv, skb); + +- if (j1939_address_is_unicast(skcb->addr.da) && +- priv->ents[skcb->addr.da].nusers) ++ if (j1939_address_is_local(priv, skcb->addr.da)) + skcb->flags |= J1939_ECU_LOCAL_DST; + + skcb->flags |= J1939_ECU_LOCAL_SRC; +@@ -2021,8 +2032,7 @@ struct j1939_session *j1939_tp_send(struct j1939_priv *priv, + return ERR_PTR(ret); + + /* fix DST flags, it may be used there soon */ +- if (j1939_address_is_unicast(skcb->addr.da) && +- priv->ents[skcb->addr.da].nusers) ++ if (j1939_address_is_local(priv, skcb->addr.da)) + skcb->flags |= J1939_ECU_LOCAL_DST; + + /* src is always local, I'm sending ... */ +-- +2.53.0 + diff --git a/queue-5.15/drm-i915-gt-use-correct-selftest-config-symbol.patch b/queue-5.15/drm-i915-gt-use-correct-selftest-config-symbol.patch new file mode 100644 index 0000000000..cb6bf7ab56 --- /dev/null +++ b/queue-5.15/drm-i915-gt-use-correct-selftest-config-symbol.patch @@ -0,0 +1,50 @@ +From c3458c9bda2521377baa7d28714cfbe2a9fd0047 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 5 Jul 2026 16:02:25 +0800 +Subject: drm/i915/gt: use correct selftest config symbol + +From: Pengpeng Hou + +[ Upstream commit a82f1bb8191aec98a971a2196136016ef70c0880 ] + +intel_engine_user.c checks CONFIG_DRM_I915_SELFTESTS before running +the engine UABI isolation check. Kconfig defines DRM_I915_SELFTEST, +without the trailing "S", and the rest of i915 uses +CONFIG_DRM_I915_SELFTEST. + +Because CONFIG_DRM_I915_SELFTESTS is not backed by any Kconfig symbol, +the IS_ENABLED() test is always false. Use the existing selftest symbol +so the debug/selftest guarded path can be reached when selftests are +enabled. + +This is a source-level fix. It does not claim dynamic hardware +reproduction; the evidence is the Kconfig definition and the inconsistent +guard in intel_engine_user.c. + +Fixes: 750e76b4f9f6 ("drm/i915/gt: Move the [class][inst] lookup for engines onto the GT") +Signed-off-by: Pengpeng Hou +Signed-off-by: Tvrtko Ursulin +Link: https://lore.kernel.org/r/20260705080225.436-1-pengpeng@iscas.ac.cn +(cherry picked from commit 14a2012a490258f3f93857bc4f1b203405964be7) +Signed-off-by: Rodrigo Vivi +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/i915/gt/intel_engine_user.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/i915/gt/intel_engine_user.c b/drivers/gpu/drm/i915/gt/intel_engine_user.c +index 8f8bea08e734d3..04fced8e9d367f 100644 +--- a/drivers/gpu/drm/i915/gt/intel_engine_user.c ++++ b/drivers/gpu/drm/i915/gt/intel_engine_user.c +@@ -235,7 +235,7 @@ void intel_engines_driver_register(struct drm_i915_private *i915) + p = &prev->rb_right; + } + +- if (IS_ENABLED(CONFIG_DRM_I915_SELFTESTS) && ++ if (IS_ENABLED(CONFIG_DRM_I915_SELFTEST) && + IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM)) { + struct intel_engine_cs *engine; + unsigned int isolation; +-- +2.53.0 + diff --git a/queue-5.15/drm-i915-selftests-fix-gt-pm-sort-comparators.patch b/queue-5.15/drm-i915-selftests-fix-gt-pm-sort-comparators.patch new file mode 100644 index 0000000000..ef92b402ac --- /dev/null +++ b/queue-5.15/drm-i915-selftests-fix-gt-pm-sort-comparators.patch @@ -0,0 +1,55 @@ +From 0b9eeff7aebf90212572d62c98b52a06fa5ce60e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 15 Jul 2026 01:04:30 +0300 +Subject: drm/i915/selftests: Fix GT PM sort comparators + +From: Emre Cecanpunar + +[ Upstream commit 612978b83f45bf7018815209db5395d759db6f26 ] + +Compare the sampled clock values instead of their addresses. Comparing +addresses leaves the samples unsorted, preventing the code from discarding +the minimum and maximum samples. + +Fixes: 1a5392479207 ("drm/i915/selftests: Measure CS_TIMESTAMP") +Signed-off-by: Emre Cecanpunar +Signed-off-by: Tvrtko Ursulin +Link: https://lore.kernel.org/r/20260714220430.238433-1-emreleno@gmail.com +(cherry picked from commit 682ea2d28d18bb06f9fc663cb5ab7e80dc0e606a) +Signed-off-by: Rodrigo Vivi +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/i915/gt/selftest_gt_pm.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/drivers/gpu/drm/i915/gt/selftest_gt_pm.c b/drivers/gpu/drm/i915/gt/selftest_gt_pm.c +index b9441217ca3d4d..f8f66beca5340b 100644 +--- a/drivers/gpu/drm/i915/gt/selftest_gt_pm.c ++++ b/drivers/gpu/drm/i915/gt/selftest_gt_pm.c +@@ -15,9 +15,9 @@ static int cmp_u64(const void *A, const void *B) + { + const u64 *a = A, *b = B; + +- if (a < b) ++ if (*a < *b) + return -1; +- else if (a > b) ++ else if (*a > *b) + return 1; + else + return 0; +@@ -27,9 +27,9 @@ static int cmp_u32(const void *A, const void *B) + { + const u32 *a = A, *b = B; + +- if (a < b) ++ if (*a < *b) + return -1; +- else if (a > b) ++ else if (*a > *b) + return 1; + else + return 0; +-- +2.53.0 + diff --git a/queue-5.15/firmware-arm_ffa-fix-null-dereference-in-ffa_partiti.patch b/queue-5.15/firmware-arm_ffa-fix-null-dereference-in-ffa_partiti.patch new file mode 100644 index 0000000000..711a1538a8 --- /dev/null +++ b/queue-5.15/firmware-arm_ffa-fix-null-dereference-in-ffa_partiti.patch @@ -0,0 +1,48 @@ +From bfeb6c11124e01bbdc0c1e491e2f791cae515992 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 17 Jun 2026 16:35:00 -0700 +Subject: firmware: arm_ffa: Fix NULL dereference in ffa_partition_info_get() + +From: Unnathi Chalicheemala + +[ Upstream commit 8ae5f8e4836667fcaffdf2e3c6068b0a8b364dd8 ] + +ffa_partition_info_get() passes uuid_str directly to uuid_parse() +without a NULL check. When a caller passes NULL, uuid_parse() -> +__uuid_parse() -> uuid_is_valid() dereferences the pointer, causing +a kernel panic: + + | Unable to handle kernel NULL pointer dereference at virtual address + | 0000000000000040 + | pc : uuid_parse+0x40/0xac + | lr : ffa_partition_info_get+0x1c/0x94 [arm_ffa] + +Add a NULL guard before uuid_parse() so a NULL argument returns +-ENODEV instead of crashing. Callers are expected to always supply +a valid partition UUID, so NULL is not a supported input. + +Fixes: d0c0bce83122 ("firmware: arm_ffa: Setup in-kernel users of FFA partitions") +Signed-off-by: Unnathi Chalicheemala +Link: https://patch.msgid.link/20260617-ffa_partition_nullptr_fix-v2-1-bc801b4ce34c@oss.qualcomm.com +Signed-off-by: Sudeep Holla +Signed-off-by: Sasha Levin +--- + drivers/firmware/arm_ffa/driver.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/firmware/arm_ffa/driver.c b/drivers/firmware/arm_ffa/driver.c +index 34351f8c4d6f36..2f8c95d9362f44 100644 +--- a/drivers/firmware/arm_ffa/driver.c ++++ b/drivers/firmware/arm_ffa/driver.c +@@ -558,7 +558,7 @@ static int ffa_partition_info_get(const char *uuid_str, + uuid_t uuid; + struct ffa_partition_info *pbuf; + +- if (uuid_parse(uuid_str, &uuid)) { ++ if (!uuid_str || uuid_parse(uuid_str, &uuid)) { + pr_err("invalid uuid (%s)\n", uuid_str); + return -ENODEV; + } +-- +2.53.0 + diff --git a/queue-5.15/firmware-arm_scmi-rate-limit-queue-full-warnings-in-.patch b/queue-5.15/firmware-arm_scmi-rate-limit-queue-full-warnings-in-.patch new file mode 100644 index 0000000000..5847ec4328 --- /dev/null +++ b/queue-5.15/firmware-arm_scmi-rate-limit-queue-full-warnings-in-.patch @@ -0,0 +1,54 @@ +From 6355b173b4f9be30acab6460a6cc6e676fe8a1ae Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 8 Jul 2026 12:53:39 +0530 +Subject: firmware: arm_scmi: Rate-limit queue-full warnings in IRQ context + +From: Pushpendra Singh + +[ Upstream commit a4447c0693830d5ecadd6e755cb7fdc55d86aacc ] + +The scmi_notify() function is called from interrupt context to queue +received notification events onto a per-protocol kfifo. When the kfifo +is full, it logs a warning via dev_warn() for every dropped event. + +Under conditions where the platform sends a burst of SCMI notifications +faster than the deferred worker can drain the queue, this results in a +flood of dev_warn() calls from IRQ context. Each call acquires the +console lock and may execute blocking console writes, causing the CPU +to be held in interrupt context for an extended period and leading to +observable system stalls. + +Fix this by switching to dev_warn_ratelimited() to limit the frequency +of log messages when the notification queue is full. This reduces +console overhead in interrupt context and prevents CPU stalls caused by +excessive logging, while still preserving diagnostic visibility. + +Fixes: bd31b249692e ("firmware: arm_scmi: Add notification dispatch and delivery") +Signed-off-by: Pushpendra Singh +Link: https://patch.msgid.link/20260708072339.3021140-1-pushpendra.singh@oss.qualcomm.com +Signed-off-by: Sudeep Holla +Signed-off-by: Sasha Levin +--- + drivers/firmware/arm_scmi/notify.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/firmware/arm_scmi/notify.c b/drivers/firmware/arm_scmi/notify.c +index 4782b115e6ec51..1bc715fe3968c3 100644 +--- a/drivers/firmware/arm_scmi/notify.c ++++ b/drivers/firmware/arm_scmi/notify.c +@@ -595,9 +595,9 @@ int scmi_notify(const struct scmi_handle *handle, u8 proto_id, u8 evt_id, + return -EINVAL; + } + if (kfifo_avail(&r_evt->proto->equeue.kfifo) < sizeof(eh) + len) { +- dev_warn(handle->dev, +- "queue full, dropping proto_id:%d evt_id:%d ts:%lld\n", +- proto_id, evt_id, ktime_to_ns(ts)); ++ dev_warn_ratelimited(handle->dev, ++ "queue full, dropping proto_id:%d evt_id:%d ts:%lld\n", ++ proto_id, evt_id, ktime_to_ns(ts)); + return -ENOMEM; + } + +-- +2.53.0 + diff --git a/queue-5.15/ib-mad-drop-unmatched-rmpp-responses-before-reassemb.patch b/queue-5.15/ib-mad-drop-unmatched-rmpp-responses-before-reassemb.patch new file mode 100644 index 0000000000..0bf58a087c --- /dev/null +++ b/queue-5.15/ib-mad-drop-unmatched-rmpp-responses-before-reassemb.patch @@ -0,0 +1,90 @@ +From 8609e8db5b61e1fd494bb538c12b0800ba669c98 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 6 Jun 2026 16:01:55 -0400 +Subject: IB/mad: Drop unmatched RMPP responses before reassembly + +From: Michael Bommarito + +[ Upstream commit d2e52d610b9b09694261632340b801a421e0b0c5 ] + +Kernel-handled RMPP receive processing starts reassembly for active +DATA responses before the response is matched to an outstanding send. +The normal match happens later, after ib_process_rmpp_recv_wc() has +either assembled a complete message or consumed the segment. + +That ordering lets an unsolicited response that routes to a kernel +RMPP agent by the high TID bits allocate or extend RMPP receive state +before the full TID and source address are checked against a real +request. A reordered burst can therefore reach the receive-side +insertion path even though the response would not match any send. + +For kernel-handled RMPP DATA responses, require the existing +ib_find_send_mad() match before entering RMPP reassembly. The matcher +already checks the full TID, management class and source address/GID +against the agent wait, backlog and in-flight send lists. If there is +no match, drop the response without creating RMPP state. + +This leaves the RMPP window behavior unchanged and only rejects +responses that have no corresponding request. + +Fixes: fa619a77046b ("[PATCH] IB: Add RMPP implementation") +Assisted-by: Codex:gpt-5-5-xhigh +Signed-off-by: Michael Bommarito +Link: https://patch.msgid.link/3170ff3bc389a930bb1641f2caa394a0b2241579.1780774907.git.michael.bommarito@gmail.com +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + drivers/infiniband/core/mad.c | 30 ++++++++++++++++++++++++++++++ + 1 file changed, 30 insertions(+) + +diff --git a/drivers/infiniband/core/mad.c b/drivers/infiniband/core/mad.c +index 242434c09e8d8f..bddb1c607aff62 100644 +--- a/drivers/infiniband/core/mad.c ++++ b/drivers/infiniband/core/mad.c +@@ -1778,6 +1778,24 @@ void ib_mark_mad_done(struct ib_mad_send_wr_private *mad_send_wr) + &mad_send_wr->mad_agent_priv->done_list); + } + ++static bool is_kernel_rmpp_data_response(struct ib_mad_agent_private *agent, ++ struct ib_mad_recv_wc *mad_recv_wc) ++{ ++ const struct ib_mad_hdr *mad_hdr = &mad_recv_wc->recv_buf.mad->mad_hdr; ++ struct ib_rmpp_mad *rmpp_mad; ++ ++ if (!ib_mad_kernel_rmpp_agent(&agent->agent) || ++ !ib_response_mad(mad_hdr) || ++ !ib_is_mad_class_rmpp(mad_hdr->mgmt_class)) ++ return false; ++ ++ rmpp_mad = (struct ib_rmpp_mad *)mad_recv_wc->recv_buf.mad; ++ ++ return (ib_get_rmpp_flags(&rmpp_mad->rmpp_hdr) & ++ IB_MGMT_RMPP_FLAG_ACTIVE) && ++ rmpp_mad->rmpp_hdr.rmpp_type == IB_MGMT_RMPP_TYPE_DATA; ++} ++ + static void ib_mad_complete_recv(struct ib_mad_agent_private *mad_agent_priv, + struct ib_mad_recv_wc *mad_recv_wc) + { +@@ -1796,6 +1814,18 @@ static void ib_mad_complete_recv(struct ib_mad_agent_private *mad_agent_priv, + } + + list_add(&mad_recv_wc->recv_buf.list, &mad_recv_wc->rmpp_list); ++ if (is_kernel_rmpp_data_response(mad_agent_priv, mad_recv_wc)) { ++ spin_lock_irqsave(&mad_agent_priv->lock, flags); ++ mad_send_wr = ib_find_send_mad(mad_agent_priv, mad_recv_wc); ++ spin_unlock_irqrestore(&mad_agent_priv->lock, flags); ++ ++ if (!mad_send_wr) { ++ ib_free_recv_mad(mad_recv_wc); ++ deref_mad_agent(mad_agent_priv); ++ return; ++ } ++ } ++ + if (ib_mad_kernel_rmpp_agent(&mad_agent_priv->agent)) { + mad_recv_wc = ib_process_rmpp_recv_wc(mad_agent_priv, + mad_recv_wc); +-- +2.53.0 + diff --git a/queue-5.15/ipv4-fib-free-fib_alias-with-kfree_rcu-on-insert-err.patch b/queue-5.15/ipv4-fib-free-fib_alias-with-kfree_rcu-on-insert-err.patch new file mode 100644 index 0000000000..beb79983fb --- /dev/null +++ b/queue-5.15/ipv4-fib-free-fib_alias-with-kfree_rcu-on-insert-err.patch @@ -0,0 +1,67 @@ +From ba1ddc885f55c5e084ae624b6459ecb03a5b08ef Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 4 Jul 2026 10:14:21 -0700 +Subject: ipv4: fib: free fib_alias with kfree_rcu() on insert error path + +From: Weiming Shi + +[ Upstream commit f2f152e94a67bc746afaf05a1b2702c195553112 ] + +fib_table_insert() publishes new_fa into the leaf's fa_list with +fib_insert_alias() before calling the fib entry notifiers. When a +notifier fails, the error path removes new_fa with fib_remove_alias() +(hlist_del_rcu) and frees it right away with kmem_cache_free(). + +fib_table_lookup() walks that list under rcu_read_lock() only, so a +concurrent lookup that already reached new_fa keeps reading it after the +free: + + BUG: KASAN: slab-use-after-free in fib_table_lookup (net/ipv4/fib_trie.c:1601) + Read of size 1 at addr ffff88810676d4eb by task exploit/297 + Call Trace: + fib_table_lookup (net/ipv4/fib_trie.c:1601) + ip_route_output_key_hash_rcu (net/ipv4/route.c:2814) + ip_route_output_key_hash (net/ipv4/route.c:2705) + __ip4_datagram_connect (net/ipv4/datagram.c:49) + udp_connect (net/ipv4/udp.c:2144) + __sys_connect (net/socket.c:2167) + __x64_sys_connect (net/socket.c:2173) + do_syscall_64 + entry_SYSCALL_64_after_hwframe + which belongs to the cache ip_fib_alias of size 56 + +Triggering the error path needs CAP_NET_ADMIN and a registered fib +notifier that can reject a route; a netdevsim device whose IPv4 FIB +resource is exhausted is enough. + +Free new_fa with alias_free_mem_rcu(), as fib_table_delete() already +does for a fib_alias removed from the trie. + +Fixes: a6c76c17df02 ("ipv4: Notify route after insertion to the routing table") +Reported-by: Xiang Mei +Assisted-by: Claude:claude-opus-4-8 +Signed-off-by: Weiming Shi +Reviewed-by: Ido Schimmel +Link: https://patch.msgid.link/20260704171421.1786806-1-bestswngs@gmail.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/ipv4/fib_trie.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c +index 3f43851f87e392..03dac903d96baa 100644 +--- a/net/ipv4/fib_trie.c ++++ b/net/ipv4/fib_trie.c +@@ -1384,7 +1384,7 @@ int fib_table_insert(struct net *net, struct fib_table *tb, + out_remove_new_fa: + fib_remove_alias(t, tp, l, new_fa); + out_free_new_fa: +- kmem_cache_free(fn_alias_kmem, new_fa); ++ alias_free_mem_rcu(new_fa); + out: + fib_release_info(fi); + err: +-- +2.53.0 + diff --git a/queue-5.15/ksmbd-validate-compound-request-size-before-reading-.patch b/queue-5.15/ksmbd-validate-compound-request-size-before-reading-.patch new file mode 100644 index 0000000000..b72d2837b3 --- /dev/null +++ b/queue-5.15/ksmbd-validate-compound-request-size-before-reading-.patch @@ -0,0 +1,69 @@ +From bee2f325e0b26bddb545c15a91a1992093a81237 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 13 Jul 2026 21:55:10 +0000 +Subject: ksmbd: validate compound request size before reading StructureSize2 + +From: Xiang Mei (Microsoft) + +[ Upstream commit 15b38176fd1530372905c602fde51fe89ec8c877 ] + +When ksmbd validates a compound (chained) SMB2 request, +ksmbd_smb2_check_message() reads pdu->StructureSize2 without first +checking that the compound element is large enough to contain it. +StructureSize2 is a 2-byte field at offset 64 +(__SMB2_HEADER_STRUCTURE_SIZE) from the start of each element. + +The compound-walking logic only guarantees that a full 64-byte SMB2 +header is present for the trailing element: when NextCommand is 0, len is +reduced to the number of bytes remaining after next_smb2_rcv_hdr_off. A +remote client can craft a compound request whose last element has exactly +64 bytes, so the 2-byte StructureSize2 read at offset 64 extends one byte +past the receive buffer, producing a slab-out-of-bounds read. + + BUG: KASAN: slab-out-of-bounds in ksmbd_smb2_check_message (fs/smb/server/smb2misc.c:402) + Read of size 2 at addr ffff888012ae31ac by task kworker/0:1/14 + The buggy address is located 172 bytes inside of allocated 173-byte region + Workqueue: ksmbd-io handle_ksmbd_work + Call Trace: + ... + kasan_report (mm/kasan/report.c:595) + ksmbd_smb2_check_message (fs/smb/server/smb2misc.c:402) + handle_ksmbd_work (fs/smb/server/server.c:119) + process_one_work (kernel/workqueue.c:3314) + worker_thread (kernel/workqueue.c:3397) + kthread (kernel/kthread.c:436) + ret_from_fork (arch/x86/kernel/process.c:158) + ret_from_fork_asm (arch/x86/entry/entry_64.S:245) + +Reject any compound element that is too small to hold StructureSize2 +before dereferencing it. + +Fixes: e2f34481b24d ("cifsd: add server-side procedures for SMB3") +Reported-by: AutonomousCodeSecurity@microsoft.com +Signed-off-by: Xiang Mei (Microsoft) +Acked-by: Namjae Jeon +Signed-off-by: Steve French +Signed-off-by: Sasha Levin +--- + fs/ksmbd/smb2misc.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/fs/ksmbd/smb2misc.c b/fs/ksmbd/smb2misc.c +index 9e54ecc9d4adac..8d7368ccda85dc 100644 +--- a/fs/ksmbd/smb2misc.c ++++ b/fs/ksmbd/smb2misc.c +@@ -399,6 +399,11 @@ int ksmbd_smb2_check_message(struct ksmbd_work *work) + return 1; + } + ++ if (len < __SMB2_HEADER_STRUCTURE_SIZE + sizeof(__le16)) { ++ ksmbd_debug(SMB, "Message is too small for StructureSize2\n"); ++ return 1; ++ } ++ + if (smb2_req_struct_sizes[command] != pdu->StructureSize2) { + if (!(command == SMB2_OPLOCK_BREAK_HE && + (le16_to_cpu(pdu->StructureSize2) == OP_BREAK_STRUCT_SIZE_20 || +-- +2.53.0 + diff --git a/queue-5.15/mpls-fix-null-deref-in-mpls_valid_fib_dump_req-on-co.patch b/queue-5.15/mpls-fix-null-deref-in-mpls_valid_fib_dump_req-on-co.patch new file mode 100644 index 0000000000..08c2ab8e42 --- /dev/null +++ b/queue-5.15/mpls-fix-null-deref-in-mpls_valid_fib_dump_req-on-co.patch @@ -0,0 +1,68 @@ +From d0202c13939e1b8854f4881be7e53fe156aad314 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 11 Jul 2026 04:50:00 -0700 +Subject: mpls: fix NULL deref in mpls_valid_fib_dump_req() on CONFIG_INET=n + +From: Weiming Shi + +[ Upstream commit 56d96fededd61192cd7cc8d2b0f36adfd59036c3 ] + +On CONFIG_INET=n builds, mpls_valid_fib_dump_req() walks the parsed +attribute table itself instead of calling ip_valid_fib_dump_req(). The +RTA_OIF arm passes tb[RTA_OIF] to nla_get_u32() without checking it is +present, so an RTM_GETROUTE dump for AF_MPLS with strict checking and no +RTA_OIF hits a NULL dereference. + +RTM_GETROUTE is RTNL_KIND_GET, which rtnetlink_rcv_msg() permits without +CAP_NET_ADMIN, so an unprivileged user can trigger it. + + Oops: general protection fault, probably for non-canonical address + 0xdffffc0000000000: 0000 [#1] SMP KASAN NOPTI + KASAN: null-ptr-deref in range [0x0000000000000000-0x0000000000000007] + RIP: 0010:mpls_valid_fib_dump_req (net/mpls/af_mpls.c:2189) + Call Trace: + mpls_dump_routes (net/mpls/af_mpls.c:2236) + netlink_dump (net/netlink/af_netlink.c:2331) + __netlink_dump_start (net/netlink/af_netlink.c:2446) + rtnetlink_rcv_msg (net/core/rtnetlink.c:7033) + netlink_rcv_skb (net/netlink/af_netlink.c:2556) + netlink_unicast (net/netlink/af_netlink.c:1345) + netlink_sendmsg (net/netlink/af_netlink.c:1900) + __sock_sendmsg (net/socket.c:790) + ____sys_sendmsg (net/socket.c:2684) + ___sys_sendmsg (net/socket.c:2738) + __sys_sendmsg (net/socket.c:2770) + do_syscall_64 (arch/x86/entry/syscall_64.c:94) + entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:121) + +Skip unset attributes, as ip_valid_fib_dump_req() does. + +Fixes: 196cfebf8972 ("net/mpls: Handle kernel side filtering of route dumps") +Assisted-by: Claude:claude-opus-4-8 +Reported-by: Xiang Mei +Signed-off-by: Weiming Shi +Reviewed-by: David Ahern +Link: https://patch.msgid.link/20260711114958.1009619-3-bestswngs@gmail.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/mpls/af_mpls.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/net/mpls/af_mpls.c b/net/mpls/af_mpls.c +index b111778bcc3547..bd84c9ddb006d6 100644 +--- a/net/mpls/af_mpls.c ++++ b/net/mpls/af_mpls.c +@@ -2145,6 +2145,9 @@ static int mpls_valid_fib_dump_req(struct net *net, const struct nlmsghdr *nlh, + int ifindex; + + if (i == RTA_OIF) { ++ if (!tb[i]) ++ continue; ++ + ifindex = nla_get_u32(tb[i]); + filter->dev = __dev_get_by_index(net, ifindex); + if (!filter->dev) +-- +2.53.0 + diff --git a/queue-5.15/mtd-mtdswap-remove-debugfs-stats-file-on-teardown.patch b/queue-5.15/mtd-mtdswap-remove-debugfs-stats-file-on-teardown.patch new file mode 100644 index 0000000000..0f9aae13f1 --- /dev/null +++ b/queue-5.15/mtd-mtdswap-remove-debugfs-stats-file-on-teardown.patch @@ -0,0 +1,57 @@ +From 57f9268989f7968ee9650bd93922ad1504bf6305 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 23 Jun 2026 09:53:17 +0800 +Subject: mtd: mtdswap: remove debugfs stats file on teardown + +From: Pengpeng Hou + +[ Upstream commit 66fb31358108d10245b9e4ef0eef3e7d9747055e ] + +mtdswap_add_debugfs() creates an mtdswap_stats debugfs file under the +per-MTD debugfs directory, but mtdswap_remove_dev() never removes it +before freeing the mtdswap_dev. + +Store the returned dentry and remove it during device teardown before the +driver-private state is freed. + +Fixes: a32159024620 ("mtd: Add mtdswap block driver") +Signed-off-by: Pengpeng Hou +Signed-off-by: Miquel Raynal +Signed-off-by: Sasha Levin +--- + drivers/mtd/mtdswap.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/drivers/mtd/mtdswap.c b/drivers/mtd/mtdswap.c +index 7e309270ddd402..e890b5ec6a72f4 100644 +--- a/drivers/mtd/mtdswap.c ++++ b/drivers/mtd/mtdswap.c +@@ -125,6 +125,7 @@ struct mtdswap_dev { + + char *page_buf; + char *oob_buf; ++ struct dentry *debugfs_stats; + }; + + struct mtdswap_oobdata { +@@ -1263,7 +1264,8 @@ static int mtdswap_add_debugfs(struct mtdswap_dev *d) + if (IS_ERR_OR_NULL(root)) + return -1; + +- debugfs_create_file("mtdswap_stats", S_IRUSR, root, d, &mtdswap_fops); ++ d->debugfs_stats = debugfs_create_file("mtdswap_stats", 0400, root, ++ d, &mtdswap_fops); + + return 0; + } +@@ -1464,6 +1466,7 @@ static void mtdswap_remove_dev(struct mtd_blktrans_dev *dev) + { + struct mtdswap_dev *d = MTDSWAP_MBD_TO_MTDSWAP(dev); + ++ debugfs_remove(d->debugfs_stats); + del_mtd_blktrans_dev(dev); + mtdswap_cleanup(d); + kfree(d); +-- +2.53.0 + diff --git a/queue-5.15/mtd-nand-mtk-ecc-stop-on-ecc-idle-timeouts.patch b/queue-5.15/mtd-nand-mtk-ecc-stop-on-ecc-idle-timeouts.patch new file mode 100644 index 0000000000..8e33303c47 --- /dev/null +++ b/queue-5.15/mtd-nand-mtk-ecc-stop-on-ecc-idle-timeouts.patch @@ -0,0 +1,75 @@ +From 275832697c94c66a4edb50aef2596cf43213442c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 23 Jun 2026 21:57:29 +0800 +Subject: mtd: nand: mtk-ecc: stop on ECC idle timeouts + +From: Pengpeng Hou + +[ Upstream commit 16f7ec8d5dc100eafd2c8e06cd30340a30b104a1 ] + +mtk_ecc_wait_idle() logs when the encoder or decoder does not become +idle, but returns void. Callers can therefore configure a non-idle ECC +engine or read parity bytes after an unconfirmed encoder idle state. + +Return the idle poll result and propagate it from the enable and encode +paths that require the engine to be idle before continuing. + +Fixes: 1d6b1e464950 ("mtd: mediatek: driver for MTK Smart Device") +Signed-off-by: Pengpeng Hou +Signed-off-by: Miquel Raynal +Signed-off-by: Sasha Levin +--- + drivers/mtd/nand/raw/mtk_ecc.c | 16 ++++++++++++---- + 1 file changed, 12 insertions(+), 4 deletions(-) + +diff --git a/drivers/mtd/nand/raw/mtk_ecc.c b/drivers/mtd/nand/raw/mtk_ecc.c +index ec9d1fb07006fc..ec10e942bed2d7 100644 +--- a/drivers/mtd/nand/raw/mtk_ecc.c ++++ b/drivers/mtd/nand/raw/mtk_ecc.c +@@ -116,8 +116,8 @@ static int mt7622_ecc_regs[] = { + [ECC_DECIRQ_STA] = 0x144, + }; + +-static inline void mtk_ecc_wait_idle(struct mtk_ecc *ecc, +- enum mtk_ecc_operation op) ++static inline int mtk_ecc_wait_idle(struct mtk_ecc *ecc, ++ enum mtk_ecc_operation op) + { + struct device *dev = ecc->dev; + u32 val; +@@ -129,6 +129,8 @@ static inline void mtk_ecc_wait_idle(struct mtk_ecc *ecc, + if (ret) + dev_warn(dev, "%s NOT idle\n", + op == ECC_ENCODE ? "encoder" : "decoder"); ++ ++ return ret; + } + + static irqreturn_t mtk_ecc_irq(int irq, void *id) +@@ -302,7 +304,11 @@ int mtk_ecc_enable(struct mtk_ecc *ecc, struct mtk_ecc_config *config) + return ret; + } + +- mtk_ecc_wait_idle(ecc, op); ++ ret = mtk_ecc_wait_idle(ecc, op); ++ if (ret) { ++ mutex_unlock(&ecc->lock); ++ return ret; ++ } + + ret = mtk_ecc_config(ecc, config); + if (ret) { +@@ -402,7 +408,9 @@ int mtk_ecc_encode(struct mtk_ecc *ecc, struct mtk_ecc_config *config, + if (ret) + goto timeout; + +- mtk_ecc_wait_idle(ecc, ECC_ENCODE); ++ ret = mtk_ecc_wait_idle(ecc, ECC_ENCODE); ++ if (ret) ++ goto timeout; + + /* Program ECC bytes to OOB: per sector oob = FDM + ECC + SPARE */ + len = (config->strength * ecc->caps->parity_bits + 7) >> 3; +-- +2.53.0 + diff --git a/queue-5.15/net-iucv-take-a-reference-on-the-socket-found-in-afi.patch b/queue-5.15/net-iucv-take-a-reference-on-the-socket-found-in-afi.patch new file mode 100644 index 0000000000..6e9d20f84c --- /dev/null +++ b/queue-5.15/net-iucv-take-a-reference-on-the-socket-found-in-afi.patch @@ -0,0 +1,55 @@ +From 93d0e59ca9050103039402bf5e813fbea076b1dc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 5 Jul 2026 22:24:36 -0500 +Subject: net/iucv: take a reference on the socket found in afiucv_hs_rcv() + +From: Bryam Vargas + +[ Upstream commit 4fa349156043dc119721d067329714179f501749 ] + +afiucv_hs_rcv() looks up the destination socket under iucv_sk_list.lock, +drops the lock, and then passes the socket to the afiucv_hs_callback_*() +handlers without holding a reference. AF_IUCV sockets are not +RCU-protected and are freed synchronously by iucv_sock_kill() -> +sock_put(), so a concurrent close can free the socket in the window +between read_unlock() and the handler, which then dereferences freed +memory (for example sk->sk_data_ready() in afiucv_hs_callback_syn()). + +Take a reference with sock_hold() while the socket is still on the list +and release it with sock_put() once the handler has run. + +Fixes: 3881ac441f64 ("af_iucv: add HiperSockets transport") +Signed-off-by: Bryam Vargas +Reviewed-by: Hidayath Khan +Link: https://patch.msgid.link/20260705-b4-disp-fc79c0dc-v1-1-d2cdcb57afa9@proton.me +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/iucv/af_iucv.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c +index 3188d719a2e42d..4156e69496b67e 100644 +--- a/net/iucv/af_iucv.c ++++ b/net/iucv/af_iucv.c +@@ -2084,6 +2084,8 @@ static int afiucv_hs_rcv(struct sk_buff *skb, struct net_device *dev, + } + } + } ++ if (sk) ++ sock_hold(sk); + read_unlock(&iucv_sk_list.lock); + if (!iucv) + sk = NULL; +@@ -2133,6 +2135,8 @@ static int afiucv_hs_rcv(struct sk_buff *skb, struct net_device *dev, + kfree_skb(skb); + } + ++ if (sk) ++ sock_put(sk); + return err; + } + +-- +2.53.0 + diff --git a/queue-5.15/net-sched-act_tunnel_key-defer-dst_release-to-rcu-ca.patch b/queue-5.15/net-sched-act_tunnel_key-defer-dst_release-to-rcu-ca.patch new file mode 100644 index 0000000000..63e5109669 --- /dev/null +++ b/queue-5.15/net-sched-act_tunnel_key-defer-dst_release-to-rcu-ca.patch @@ -0,0 +1,176 @@ +From 949963854b3bb1fa957accb9ab9f9be36a544ea1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 11 Jul 2026 11:05:37 -0400 +Subject: net/sched: act_tunnel_key: Defer dst_release to RCU callback + +From: Jamal Hadi Salim + +[ Upstream commit f1f5c8a3955f8fda3f84ed883ac8daa1847e724c ] + +Fix a race-condition use-after-free in tunnel_key_release_params(). + +The function releases the metadata_dst of the old params synchronously +via dst_release() while deferring the params struct free with +kfree_rcu(). A concurrent tunnel_key_act() reader on the datapath may +still hold the old params pointer (under rcu_read_lock_bh) and proceed +to call dst_clone(¶ms->tcft_enc_metadata->dst) after the writer's +dst_release has already pushed the dst's rcuref to RCUREF_DEAD. + +zdi-disclosures@trendmicro.com produced a poc which i (and Victor) verified +that KASAN reports: + +================================================================== +BUG: KASAN: slab-use-after-free in instrument_atomic_read_write include/linux/instrumented.h:112 +BUG: KASAN: slab-use-after-free in atomic_sub_return_release include/linux/atomic/atomic-instrumented.h:326 +BUG: KASAN: slab-use-after-free in __rcuref_put include/linux/rcuref.h:109 +BUG: KASAN: slab-use-after-free in rcuref_put include/linux/rcuref.h:173 +BUG: KASAN: slab-use-after-free in dst_release+0x5b/0x370 net/core/dst.c:168 +Write of size 4 at addr ffff88806158de40 by task poc/9388 + +CPU: 0 UID: 0 PID: 9388 Comm: poc Tainted: G W 7.1.0-rc7 #7 PREEMPT(lazy) +Tainted: [W]=WARN +Hardware name: QEMU Ubuntu 25.10 PC v2 (i440FX + PIIX, + 10.1 machine, 1996), BIOS 1.16.3-debian-1.16.3-2 04/01/2014 +Call Trace: + + __dump_stack lib/dump_stack.c:94 + dump_stack_lvl+0x100/0x190 lib/dump_stack.c:120 + print_address_description mm/kasan/report.c:378 + print_report+0x139/0x4ad mm/kasan/report.c:482 + kasan_report+0xe4/0x1d0 mm/kasan/report.c:595 + check_region_inline mm/kasan/generic.c:186 + kasan_check_range+0x125/0x200 mm/kasan/generic.c:200 + instrument_atomic_read_write include/linux/instrumented.h:112 + atomic_sub_return_release include/linux/atomic/atomic-instrumented.h:326 + __rcuref_put include/linux/rcuref.h:109 + rcuref_put include/linux/rcuref.h:173 + dst_release+0x5b/0x370 net/core/dst.c:168 + refdst_drop include/net/dst.h:272 + skb_dst_drop include/net/dst.h:284 + skb_release_head_state+0x293/0x400 net/core/skbuff.c:1163 + skb_release_all net/core/skbuff.c:1187 +[..] +Allocated by task 9391: + kasan_save_stack+0x30/0x50 mm/kasan/common.c:57 + kasan_save_track+0x14/0x30 mm/kasan/common.c:78 + poison_kmalloc_redzone mm/kasan/common.c:398 + __kasan_kmalloc+0x9a/0xb0 mm/kasan/common.c:415 + kasan_kmalloc include/linux/kasan.h:263 + __do_kmalloc_node mm/slub.c:5296 + __kmalloc_noprof+0x2f1/0x830 mm/slub.c:5308 + kmalloc_noprof include/linux/slab.h:954 + kzalloc_noprof include/linux/slab.h:1188 + offload_action_alloc+0x2f/0x130 net/core/flow_offload.c:35 + tcf_action_offload_add_ex+0x1ba/0x880 net/sched/act_api.c:258 + tcf_action_offload_add net/sched/act_api.c:293 + tcf_action_init+0x66e/0xa20 net/sched/act_api.c:1547 + tcf_action_add+0xf6/0x5d0 net/sched/act_api.c:2101 +[..] +Freed by task 9391: + kasan_save_stack+0x30/0x50 mm/kasan/common.c:57 + kasan_save_track+0x14/0x30 mm/kasan/common.c:78 + kasan_save_free_info+0x3b/0x70 mm/kasan/generic.c:584 + poison_slab_object mm/kasan/common.c:253 + __kasan_slab_free+0x6b/0x90 mm/kasan/common.c:285 + kasan_slab_free include/linux/kasan.h:235 + slab_free_hook mm/slub.c:2689 + slab_free mm/slub.c:6251 + kfree+0x21f/0x6b0 mm/slub.c:6566 + tcf_action_offload_add_ex+0x4ad/0x880 net/sched/act_api.c:284 + tcf_action_offload_add net/sched/act_api.c:293 + tcf_action_init+0x66e/0xa20 net/sched/act_api.c:1547 + tcf_action_add+0xf6/0x5d0 net/sched/act_api.c:2101 + +The buggy address belongs to the object at ffff88806158de00 + which belongs to the cache kmalloc-256 of size 256 +The buggy address is located 64 bytes inside of + freed 256-byte region [ffff88806158de00, ffff88806158df00) + +The buggy address belongs to the physical page: +page: refcount:0 mapcount:0 mapping:0000000000000000 index:0xffff88806158d600 pfn:0x6158c +head: order:1 mapcount:0 entire_mapcount:0 nr_pages_mapped:0 pincount:0 +flags: 0x4fff00000000240(workingset|head|node=1|zone=1|lastcpupid=0x7ff) +page_type: f5(slab) +raw: 04fff00000000240 ffff88801c841b40 ffffea0001856290 ffffea0001856190 +raw: ffff88806158d600 0000000800100009 00000000f5000000 0000000000000000 +head: 04fff00000000240 ffff88801c841b40 ffffea0001856290 ffffea0001856190 +head: ffff88806158d600 0000000800100009 00000000f5000000 0000000000000000 +head: 04fff00000000001 ffffffffffffff81 00000000ffffffff 00000000ffffffff +head: ffffffffffffffff 0000000000000000 00000000ffffffff 0000000000000002 +page dumped because: kasan: bad access detected +page_owner tracks the page as allocated +page last allocated via order 1, migratetype Unmovable, gfp_mask 0xd2820(GFP_ATOMIC|__GFP_NOWARN|__GFP_NORETRY|__GFP_COMP|__GFP_NOMEMALLOC), pid 9391, tgid 9378 (poc), ts 123227323196, free_ts 0 + set_page_owner include/linux/page_owner.h:32 + post_alloc_hook+0xfe/0x140 mm/page_alloc.c:1853 + prep_new_page mm/page_alloc.c:1861 + get_page_from_freelist+0x110c/0x2fc0 mm/page_alloc.c:3941 + __alloc_frozen_pages_noprof+0x263/0x2bc0 mm/page_alloc.c:5221 + alloc_slab_page mm/slub.c:3278 + allocate_slab mm/slub.c:3467 + new_slab+0xa6/0x690 mm/slub.c:3525 + refill_objects+0x271/0x420 mm/slub.c:7272 + refill_sheaf mm/slub.c:2816 + __pcs_replace_empty_main+0x373/0x630 mm/slub.c:4652 + alloc_from_pcs mm/slub.c:4750 + slab_alloc_node mm/slub.c:4884 + __do_kmalloc_node mm/slub.c:5295 + __kmalloc_noprof+0x66d/0x830 mm/slub.c:5308 + kmalloc_noprof include/linux/slab.h:954 + metadata_dst_alloc+0x26/0x90 net/core/dst.c:298 + tun_rx_dst include/net/dst_metadata.h:144 + __ip_tun_set_dst include/net/dst_metadata.h:208 + tunnel_key_init+0xb01/0x1b90 net/sched/act_tunnel_key.c:451 + tcf_action_init_1+0x46b/0x6c0 net/sched/act_api.c:1428 + tcf_action_init+0x448/0xa20 net/sched/act_api.c:1503 + tcf_action_add+0xf6/0x5d0 net/sched/act_api.c:2101 +[..] +================================================================== + +Fix by moving dst_release() into a custom RCU callback that runs +after the grace period, matching the lifetime of the containing +params struct. Readers in the datapath therefore always find a live +rcuref when calling dst_clone(). + +Fixes: 9174c3df1cd18 ("net/sched: act_tunnel_key: fix memory leak in case of action replace") +Reported-by: zdi-disclosures@trendmicro.com +Tested-by: Victor Nogueira +Signed-off-by: Jamal Hadi Salim +Reviewed-by: Davide Caratti +Link: https://patch.msgid.link/20260711150537.7946-1-jhs@mojatatu.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/sched/act_tunnel_key.c | 14 ++++++++++---- + 1 file changed, 10 insertions(+), 4 deletions(-) + +diff --git a/net/sched/act_tunnel_key.c b/net/sched/act_tunnel_key.c +index c79f23367dfb3e..0be95240b939e3 100644 +--- a/net/sched/act_tunnel_key.c ++++ b/net/sched/act_tunnel_key.c +@@ -342,14 +342,20 @@ static const struct nla_policy tunnel_key_policy[TCA_TUNNEL_KEY_MAX + 1] = { + [TCA_TUNNEL_KEY_ENC_TTL] = { .type = NLA_U8 }, + }; + +-static void tunnel_key_release_params(struct tcf_tunnel_key_params *p) ++static void tunnel_key_release_params_rcu(struct rcu_head *head) + { +- if (!p) +- return; ++ struct tcf_tunnel_key_params *p = container_of(head, typeof(*p), rcu); ++ + if (p->tcft_action == TCA_TUNNEL_KEY_ACT_SET) + dst_release(&p->tcft_enc_metadata->dst); ++ kfree(p); ++} + +- kfree_rcu(p, rcu); ++static void tunnel_key_release_params(struct tcf_tunnel_key_params *p) ++{ ++ if (!p) ++ return; ++ call_rcu(&p->rcu, tunnel_key_release_params_rcu); + } + + static int tunnel_key_init(struct net *net, struct nlattr *nla, +-- +2.53.0 + diff --git a/queue-5.15/powerpc-remove-the-last-remnants-of-cputime_t.patch b/queue-5.15/powerpc-remove-the-last-remnants-of-cputime_t.patch new file mode 100644 index 0000000000..94092806e9 --- /dev/null +++ b/queue-5.15/powerpc-remove-the-last-remnants-of-cputime_t.patch @@ -0,0 +1,114 @@ +From 0510cc48135b7bc49bddc8a93b5862bf98dc6035 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Oct 2022 20:56:53 +1000 +Subject: powerpc: remove the last remnants of cputime_t + +From: Nicholas Piggin + +[ Upstream commit f985adaf2ff934ec869b32ca1f7f97e2825e3a49 ] + +cputime_t was a core kernel type, removed by commits +ed5c8c854f2b..b672592f0221. As explained in commit b672592f0221 +("sched/cputime: Remove generic asm headers"), the final cleanup +is for the arch to provide cputime_to_nsec[s](). Commit ade7667a981b +("powerpc: Add cputime_to_nsecs()") did that, but justdidn't remove +the then-unused cputime_to_usecs(), cputime_t type, and associated +remnants. + +Signed-off-by: Nicholas Piggin +Signed-off-by: Michael Ellerman +Link: https://lore.kernel.org/r/20221006105653.115829-1-npiggin@gmail.com +Stable-dep-of: c1c1ffa490fc ("powerpc/vtime: Initialize starttime at boot for native accounting") +Signed-off-by: Sasha Levin +--- + arch/powerpc/include/asm/cputime.h | 17 +---------------- + arch/powerpc/kernel/time.c | 23 ++--------------------- + 2 files changed, 3 insertions(+), 37 deletions(-) + +diff --git a/arch/powerpc/include/asm/cputime.h b/arch/powerpc/include/asm/cputime.h +index 504f7fe6711a32..a23356c05af193 100644 +--- a/arch/powerpc/include/asm/cputime.h ++++ b/arch/powerpc/include/asm/cputime.h +@@ -20,23 +20,8 @@ + #include + #include + +-typedef u64 __nocast cputime_t; +-typedef u64 __nocast cputime64_t; +- +-#define cmpxchg_cputime(ptr, old, new) cmpxchg(ptr, old, new) +- + #ifdef __KERNEL__ +-/* +- * Convert cputime <-> microseconds +- */ +-extern u64 __cputime_usec_factor; +- +-static inline unsigned long cputime_to_usecs(const cputime_t ct) +-{ +- return mulhdu((__force u64) ct, __cputime_usec_factor); +-} +- +-#define cputime_to_nsecs(cputime) tb_to_ns((__force u64)cputime) ++#define cputime_to_nsecs(cputime) tb_to_ns(cputime) + + /* + * PPC64 uses PACA which is task independent for storing accounting data while +diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c +index d3f579f9880173..d0e59f427fd6f1 100644 +--- a/arch/powerpc/kernel/time.c ++++ b/arch/powerpc/kernel/time.c +@@ -123,7 +123,7 @@ unsigned long tb_ticks_per_jiffy; + unsigned long tb_ticks_per_usec = 100; /* sane default */ + EXPORT_SYMBOL(tb_ticks_per_usec); + unsigned long tb_ticks_per_sec; +-EXPORT_SYMBOL(tb_ticks_per_sec); /* for cputime_t conversions */ ++EXPORT_SYMBOL(tb_ticks_per_sec); /* for cputime conversions */ + + DEFINE_SPINLOCK(rtc_lock); + EXPORT_SYMBOL_GPL(rtc_lock); +@@ -143,21 +143,6 @@ EXPORT_SYMBOL_GPL(ppc_tb_freq); + bool tb_invalid; + + #ifdef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE +-/* +- * Factor for converting from cputime_t (timebase ticks) to +- * microseconds. This is stored as 0.64 fixed-point binary fraction. +- */ +-u64 __cputime_usec_factor; +-EXPORT_SYMBOL(__cputime_usec_factor); +- +-static void calc_cputime_factors(void) +-{ +- struct div_result res; +- +- div128_by_32(1000000, 0, tb_ticks_per_sec, &res); +- __cputime_usec_factor = res.result_low; +-} +- + /* + * Read the SPURR on systems that have it, otherwise the PURR, + * or if that doesn't exist return the timebase value passed in. +@@ -444,10 +429,7 @@ void vtime_flush(struct task_struct *tsk) + acct->hardirq_time = 0; + acct->softirq_time = 0; + } +- +-#else /* ! CONFIG_VIRT_CPU_ACCOUNTING_NATIVE */ +-#define calc_cputime_factors() +-#endif ++#endif /* CONFIG_VIRT_CPU_ACCOUNTING_NATIVE */ + + void __no_kcsan __delay(unsigned long loops) + { +@@ -962,7 +944,6 @@ void __init time_init(void) + tb_ticks_per_jiffy = ppc_tb_freq / HZ; + tb_ticks_per_sec = ppc_tb_freq; + tb_ticks_per_usec = ppc_tb_freq / 1000000; +- calc_cputime_factors(); + + /* + * Compute scale factor for sched_clock. +-- +2.53.0 + diff --git a/queue-5.15/powerpc-time-fix-sparse-warnings.patch b/queue-5.15/powerpc-time-fix-sparse-warnings.patch new file mode 100644 index 0000000000..dcefa36361 --- /dev/null +++ b/queue-5.15/powerpc-time-fix-sparse-warnings.patch @@ -0,0 +1,101 @@ +From 338e32d78231b6f6129cd62d06a9adb364ae7c21 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 24 Mar 2021 05:09:39 -0400 +Subject: powerpc/time: Fix sparse warnings + +From: He Ying + +[ Upstream commit ce0091a0e06045e70c526c8735f8b866a85e0a45 ] + +We found these warnings in arch/powerpc/kernel/time.c as follows: + warning: symbol 'decrementer_max' was not declared. Should it be static? + warning: symbol 'rtc_lock' was not declared. Should it be static? + warning: symbol 'dtl_consumer' was not declared. Should it be static? + +Declare 'decrementer_max' in powerpc asm/time.h. + +Include linux/mc146818rtc.h in powerpc kernel/time.c where 'rtc_lock' is +declared. And remove duplicated declaration of 'rtc_lock' in powerpc +platforms/chrp/time.c because it has included linux/mc146818rtc.h. + +Move 'dtl_consumer' definition after "include " because it is +declared there. + +Reported-by: Hulk Robot +Signed-off-by: He Ying +Reviewed-by: Christophe Leroy +Reviewed-by: Alexandre Belloni +Signed-off-by: Christophe Leroy +Signed-off-by: Michael Ellerman +Link: https://lore.kernel.org/r/20210324090939.143477-1-heying24@huawei.com +Stable-dep-of: c1c1ffa490fc ("powerpc/vtime: Initialize starttime at boot for native accounting") +Signed-off-by: Sasha Levin +--- + arch/powerpc/include/asm/time.h | 1 + + arch/powerpc/kernel/time.c | 9 ++++----- + arch/powerpc/platforms/chrp/time.c | 2 -- + 3 files changed, 5 insertions(+), 7 deletions(-) + +diff --git a/arch/powerpc/include/asm/time.h b/arch/powerpc/include/asm/time.h +index 8c2c3dd4ddbac3..d7212a334f7242 100644 +--- a/arch/powerpc/include/asm/time.h ++++ b/arch/powerpc/include/asm/time.h +@@ -22,6 +22,7 @@ extern unsigned long tb_ticks_per_jiffy; + extern unsigned long tb_ticks_per_usec; + extern unsigned long tb_ticks_per_sec; + extern struct clock_event_device decrementer_clockevent; ++extern u64 decrementer_max; + + + extern void generic_calibrate_decr(void); +diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c +index 4406d7a89558bb..d3f579f9880173 100644 +--- a/arch/powerpc/kernel/time.c ++++ b/arch/powerpc/kernel/time.c +@@ -54,8 +54,9 @@ + #include + #include + #include +-#include ++#include + ++#include + #include + #include + #include +@@ -149,10 +150,6 @@ bool tb_invalid; + u64 __cputime_usec_factor; + EXPORT_SYMBOL(__cputime_usec_factor); + +-#ifdef CONFIG_PPC_SPLPAR +-void (*dtl_consumer)(struct dtl_entry *, u64); +-#endif +- + static void calc_cputime_factors(void) + { + struct div_result res; +@@ -178,6 +175,8 @@ static inline unsigned long read_spurr(unsigned long tb) + + #include + ++void (*dtl_consumer)(struct dtl_entry *, u64); ++ + /* + * Scan the dispatch trace log and count up the stolen time. + * Should be called with interrupts disabled. +diff --git a/arch/powerpc/platforms/chrp/time.c b/arch/powerpc/platforms/chrp/time.c +index acde7bbe07164e..b94dfd5090d80f 100644 +--- a/arch/powerpc/platforms/chrp/time.c ++++ b/arch/powerpc/platforms/chrp/time.c +@@ -30,8 +30,6 @@ + + #include + +-extern spinlock_t rtc_lock; +- + #define NVRAM_AS0 0x74 + #define NVRAM_AS1 0x75 + #define NVRAM_DATA 0x77 +-- +2.53.0 + diff --git a/queue-5.15/powerpc-time-prepare-to-stop-elapsing-in-dynticks-id.patch b/queue-5.15/powerpc-time-prepare-to-stop-elapsing-in-dynticks-id.patch new file mode 100644 index 0000000000..e5bf45f728 --- /dev/null +++ b/queue-5.15/powerpc-time-prepare-to-stop-elapsing-in-dynticks-id.patch @@ -0,0 +1,126 @@ +From ecb18ec7a21ea5336f90c27edc5a4c1cb670df3e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 8 May 2026 15:16:37 +0200 +Subject: powerpc/time: Prepare to stop elapsing in dynticks-idle + +From: Frederic Weisbecker + +[ Upstream commit c8ba971cf8567d49eb5f43ee90c4e50424331c18 ] + +Currently the tick subsystem stores the idle cputime accounting in +private fields, allowing cohabitation with architecture idle vtime +accounting. The former is fetched on online CPUs, the latter on offline +CPUs. + +For consolidation purpose, architecture vtime accounting will continue +to account the cputime but will make a break when the idle tick is +stopped. The dyntick cputime accounting will then be relayed by the tick +subsystem so that the idle cputime is still seen advancing coherently +even when the tick isn't there to flush the idle vtime. + +Prepare for that and introduce three new APIs which will be used in +subsequent patches: + + - vtime_dynticks_start() is deemed to be called when idle enters in + dyntick mode. The idle cputime that elapsed so far is accumulated. + + - vtime_dynticks_stop() is deemed to be called when idle exits from + dyntick mode. The vtime entry clocks are fast-forward to current time + so that idle accounting restarts elapsing from now. + + - vtime_reset() is deemed to be called from dynticks idle IRQ entry to + fast-forward the clock to current time so that the IRQ time is still + accounted by vtime while nohz cputime is paused. + +Also accumulated vtime won't be flushed from dyntick-idle ticks to avoid +accounting twice the idle cputime, along with nohz accounting. + +Signed-off-by: Frederic Weisbecker +Signed-off-by: Thomas Gleixner +Tested-by: Shrikanth Hegde +Reviewed-by: Shrikanth Hegde +Link: https://patch.msgid.link/20260508131647.43868-6-frederic@kernel.org +Stable-dep-of: c1c1ffa490fc ("powerpc/vtime: Initialize starttime at boot for native accounting") +Signed-off-by: Sasha Levin +--- + arch/powerpc/kernel/time.c | 41 ++++++++++++++++++++++++++++++++++++++ + include/linux/vtime.h | 6 ++++++ + 2 files changed, 47 insertions(+) + +diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c +index 65235323bee49c..e4ccacdd95435e 100644 +--- a/arch/powerpc/kernel/time.c ++++ b/arch/powerpc/kernel/time.c +@@ -451,6 +451,47 @@ void vtime_task_switch(struct task_struct *prev) + acct->starttime = acct0->starttime; + } + } ++ ++#ifdef CONFIG_NO_HZ_COMMON ++/** ++ * vtime_reset - Fast forward vtime entry clocks ++ * ++ * Called from dynticks idle IRQ entry to fast-forward the clocks to current time ++ * so that the IRQ time is still accounted by vtime while nohz cputime is paused. ++ */ ++void vtime_reset(void) ++{ ++ struct cpu_accounting_data *acct = get_accounting(current); ++ ++ acct->starttime = mftb(); ++#ifdef CONFIG_ARCH_HAS_SCALED_CPUTIME ++ acct->startspurr = read_spurr(acct->starttime); ++#endif ++} ++ ++/** ++ * vtime_dyntick_start - Inform vtime about entry to idle-dynticks ++ * ++ * Called when idle enters in dyntick mode. The idle cputime that elapsed so far ++ * is accumulated and the tick subsystem takes over the idle cputime accounting. ++ */ ++void vtime_dyntick_start(void) ++{ ++ vtime_account_idle(current); ++} ++ ++/** ++ * vtime_dyntick_stop - Inform vtime about exit from idle-dynticks ++ * ++ * Called when idle exits from dyntick mode. The vtime entry clocks are ++ * fast-forward to current time so that idle accounting restarts elapsing from ++ * now. ++ */ ++void vtime_dyntick_stop(void) ++{ ++ vtime_reset(); ++} ++#endif /* CONFIG_NO_HZ_COMMON */ + #endif /* CONFIG_VIRT_CPU_ACCOUNTING_NATIVE */ + + void __no_kcsan __delay(unsigned long loops) +diff --git a/include/linux/vtime.h b/include/linux/vtime.h +index 3684487d01e1c6..7cee518fde3a24 100644 +--- a/include/linux/vtime.h ++++ b/include/linux/vtime.h +@@ -37,11 +37,17 @@ extern void vtime_account_irq(struct task_struct *tsk, unsigned int offset); + extern void vtime_account_softirq(struct task_struct *tsk); + extern void vtime_account_hardirq(struct task_struct *tsk); + extern void vtime_flush(struct task_struct *tsk); ++extern void vtime_reset(void); ++extern void vtime_dyntick_start(void); ++extern void vtime_dyntick_stop(void); + #else /* !CONFIG_VIRT_CPU_ACCOUNTING_NATIVE */ + static inline void vtime_account_irq(struct task_struct *tsk, unsigned int offset) { } + static inline void vtime_account_softirq(struct task_struct *tsk) { } + static inline void vtime_account_hardirq(struct task_struct *tsk) { } + static inline void vtime_flush(struct task_struct *tsk) { } ++static inline void vtime_reset(void) { } ++static inline void vtime_dyntick_start(void) { } ++static inline void vtime_dyntick_stop(void) { } + #endif + + /* +-- +2.53.0 + diff --git a/queue-5.15/powerpc-vtime-initialize-starttime-at-boot-for-nativ.patch b/queue-5.15/powerpc-vtime-initialize-starttime-at-boot-for-nativ.patch new file mode 100644 index 0000000000..977e2e12b3 --- /dev/null +++ b/queue-5.15/powerpc-vtime-initialize-starttime-at-boot-for-nativ.patch @@ -0,0 +1,90 @@ +From 74fed396f9c92154405a3605683356dec043e7d0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 5 Jun 2026 18:13:29 +0530 +Subject: powerpc/vtime: Initialize starttime at boot for native accounting + +From: Shrikanth Hegde + +[ Upstream commit c1c1ffa490fc33591e90852ed0d38804dd20bc36 ] + +It was observed that /proc/stat had very large value for one ore more +CPUs. It was more visible after recent code simplifications around +cpustats. + +System has 240 CPUs. + +cat /proc/uptime; +194.18 46500.55 +cat /proc/stat +cpu 5966 39 837032887 4650070 164 185 100 0 0 0 +cpu0 108 0 837030890 19109 24 4 23 0 0 0 + +Since uptime is 194s, system time of each CPU can't be more than 19400. +Sum of system time of all CPUs can't be more than 19400*240 4656000. +In fact huge value is close to mftb(). Note mftb doesn't reset on powerVM +when the LPAR restart. It only resets when whole system resets. The same +issue exists for kexec too. + +This happens since starttime is not setup at init time. Once it is set +then subsequent vtime_delta will return the right delta. + +Fix it by initializing the starttime during CPU initialization. This +fixes the large times seen. + +cat /proc/uptime; cat /proc/stat +15.78 3694.63 +cpu 6035 35 1347 369479 23 144 49 0 0 0 +cpu0 19 0 38 1508 0 1 14 0 0 0 + +Now, system time is reported as expected. + +Fixes: cf9efce0ce31 ("powerpc: Account time using timebase rather than PURR") +Reviewed-by: Christophe Leroy (CS GROUP) +Suggested-by: Christophe Leroy (CS GROUP) +Signed-off-by: Shrikanth Hegde +Signed-off-by: Madhavan Srinivasan +Link: https://patch.msgid.link/20260605124329.377533-1-sshegde@linux.ibm.com +Signed-off-by: Sasha Levin +--- + arch/powerpc/kernel/time.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c +index e4ccacdd95435e..6dc87b4e2819f4 100644 +--- a/arch/powerpc/kernel/time.c ++++ b/arch/powerpc/kernel/time.c +@@ -452,7 +452,6 @@ void vtime_task_switch(struct task_struct *prev) + } + } + +-#ifdef CONFIG_NO_HZ_COMMON + /** + * vtime_reset - Fast forward vtime entry clocks + * +@@ -469,6 +468,7 @@ void vtime_reset(void) + #endif + } + ++#ifdef CONFIG_NO_HZ_COMMON + /** + * vtime_dyntick_start - Inform vtime about entry to idle-dynticks + * +@@ -973,6 +973,7 @@ static void __init set_decrementer_max(void) + static void __init init_decrementer_clockevent(void) + { + register_decrementer_clockevent(smp_processor_id()); ++ vtime_reset(); + } + + void secondary_cpu_time_init(void) +@@ -988,6 +989,7 @@ void secondary_cpu_time_init(void) + /* FIME: Should make unrelatred change to move snapshot_timebase + * call here ! */ + register_decrementer_clockevent(smp_processor_id()); ++ vtime_reset(); + } + + /* This function is only called on the boot processor */ +-- +2.53.0 + diff --git a/queue-5.15/ppp-defer-channel-free-to-an-rcu-grace-period-to-fix.patch b/queue-5.15/ppp-defer-channel-free-to-an-rcu-grace-period-to-fix.patch new file mode 100644 index 0000000000..0dcc15e2f1 --- /dev/null +++ b/queue-5.15/ppp-defer-channel-free-to-an-rcu-grace-period-to-fix.patch @@ -0,0 +1,104 @@ +From 32e0069237c6a728b25c356321f18f609a0228f4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 6 Jul 2026 11:01:59 +0200 +Subject: ppp: defer channel free to an RCU grace period to fix pppol2tp RX UAF + +From: Norbert Szetei + +[ Upstream commit ec4215683e47424c9c4762fd3c60f552a3119142 ] + +pppol2tp_recv() runs in the L2TP UDP-encap softirq RX path: + + l2tp_udp_encap_recv() -> l2tp_recv_common() -> pppol2tp_recv() + -> ppp_input(&po->chan) + +It runs under rcu_read_lock() holding only an l2tp_session reference and +takes NO reference on the internal PPP channel (struct channel, +chan->ppp) that ppp_input() dereferences. + +The pppox socket is SOCK_RCU_FREE, so 'po' and the embedded ppp_channel +are RCU-safe. But the internal struct channel is a separate allocation +that ppp_release_channel() frees with a plain kfree(): + + close(data socket) -> pppol2tp_release() -> pppox_unbind_sock() + -> ppp_unregister_channel() -> ppp_release_channel() -> kfree(pch) + +For a channel that is bound (PPPIOCGCHAN) but not attached to a ppp unit +(no PPPIOCCONNECT, pch->ppp == NULL) and not bridged, teardown skips +both ppp_disconnect_channel()'s synchronize_net() and +ppp_unbridge_channels()'s synchronize_rcu(), so the kfree() has no grace +period. rcu_read_lock() in pppol2tp_recv() does not protect against a +plain kfree(), so an in-flight ppp_input() on one CPU can dereference +the channel just freed by close() on another CPU. + +The bug is reachable by an unprivileged user. + +Defer the channel free to an RCU callback via call_rcu() so the grace +period fences any in-flight ppp_input(). The disconnect and unbridge +teardown paths already fence with synchronize_net()/synchronize_rcu(); +call_rcu() does the same here without stalling the close() path. + +Fixes: ee40fb2e1eb5 ("l2tp: protect sock pointer of struct pppol2tp_session with RCU") +Assisted-by: Claude:claude-opus-4-8 +Signed-off-by: Norbert Szetei +Reviewed-by: Qingfang Deng +Link: https://patch.msgid.link/E793FCF2-58DE-4387-A983-C7B4BC3158BD@doyensec.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ppp/ppp_generic.c | 18 +++++++++++++++--- + 1 file changed, 15 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c +index 8c28292ed33cf8..4c4dc817bc70c0 100644 +--- a/drivers/net/ppp/ppp_generic.c ++++ b/drivers/net/ppp/ppp_generic.c +@@ -191,6 +191,7 @@ struct channel { + struct list_head clist; /* link in list of channels per unit */ + rwlock_t upl; /* protects `ppp' and 'bridge' */ + struct channel __rcu *bridge; /* "bridged" ppp channel */ ++ struct rcu_head rcu; /* for RCU-deferred free of the channel */ + #ifdef CONFIG_PPP_MULTILINK + u8 avail; /* flag used in multilink stuff */ + u8 had_frag; /* >= 1 fragments have been sent */ +@@ -3554,6 +3555,18 @@ ppp_disconnect_channel(struct channel *pch) + return err; + } + ++/* Purge after the grace period: a late ppp_input() may still queue an ++ * skb on pch->file.rq before the last RCU reader drains. ++ */ ++static void ppp_release_channel_free(struct rcu_head *rcu) ++{ ++ struct channel *pch = container_of(rcu, struct channel, rcu); ++ ++ skb_queue_purge(&pch->file.xq); ++ skb_queue_purge(&pch->file.rq); ++ kfree(pch); ++} ++ + /* + * Free up the resources used by a ppp channel. + */ +@@ -3569,9 +3582,7 @@ static void ppp_destroy_channel(struct channel *pch) + pr_err("ppp: destroying undead channel %p !\n", pch); + return; + } +- skb_queue_purge(&pch->file.xq); +- skb_queue_purge(&pch->file.rq); +- kfree(pch); ++ call_rcu(&pch->rcu, ppp_release_channel_free); + } + + static void __exit ppp_cleanup(void) +@@ -3584,6 +3595,7 @@ static void __exit ppp_cleanup(void) + device_destroy(ppp_class, MKDEV(PPP_MAJOR, 0)); + class_destroy(ppp_class); + unregister_pernet_device(&ppp_net_ops); ++ rcu_barrier(); /* wait for RCU callbacks before module unload */ + } + + /* +-- +2.53.0 + diff --git a/queue-5.15/rdma-hns-fix-potential-integer-overflow-in-mhop-hem-.patch b/queue-5.15/rdma-hns-fix-potential-integer-overflow-in-mhop-hem-.patch new file mode 100644 index 0000000000..95399bfc08 --- /dev/null +++ b/queue-5.15/rdma-hns-fix-potential-integer-overflow-in-mhop-hem-.patch @@ -0,0 +1,52 @@ +From 233be7dc319c9ccfef6f391bac008a3491024cb4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 27 Jun 2026 09:59:51 +0000 +Subject: RDMA/hns: Fix potential integer overflow in mhop hem cleanup + +From: Danila Chernetsov + +[ Upstream commit 9f0f2d2121f16d420199a82ac5bbc242269133b3 ] + +In hns_roce_cleanup_mhop_hem_table(), the expression: + + obj = i * buf_chunk_size / table->obj_size; + +is evaluated using 32-bit unsigned arithmetic because +'buf_chunk_size' is u32 and the usual arithmetic conversions convert +'i' to unsigned int. The result is assigned to a u64 variable, but the +multiplication may overflow before the assignment. + +For sufficiently large HEM tables, this produces an incorrect object +index passed to hns_roce_table_mhop_put(). + +Cast 'i' to u64 before the multiplication so that the intermediate +calculation is performed with 64-bit arithmetic. + +Found by Linux Verification Center (linuxtesting.org) with SVACE. + +Fixes: a25d13cbe816 ("RDMA/hns: Add the interfaces to support multi hop addressing for the contexts in hip08") +Link: https://patch.msgid.link/r/20260627095951.51378-1-listdansp@mail.ru +Signed-off-by: Danila Chernetsov +Reviewed-by: Junxian Huang +Signed-off-by: Jason Gunthorpe +Signed-off-by: Sasha Levin +--- + drivers/infiniband/hw/hns/hns_roce_hem.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/infiniband/hw/hns/hns_roce_hem.c b/drivers/infiniband/hw/hns/hns_roce_hem.c +index 61ae49219e6baa..9649abeadbbf6f 100644 +--- a/drivers/infiniband/hw/hns/hns_roce_hem.c ++++ b/drivers/infiniband/hw/hns/hns_roce_hem.c +@@ -902,7 +902,7 @@ static void hns_roce_cleanup_mhop_hem_table(struct hns_roce_dev *hr_dev, + mhop.bt_chunk_size; + + for (i = 0; i < table->num_hem; ++i) { +- obj = i * buf_chunk_size / table->obj_size; ++ obj = (u64)i * buf_chunk_size / table->obj_size; + if (table->hem[i]) + hns_roce_table_mhop_put(hr_dev, table, obj, 0); + } +-- +2.53.0 + diff --git a/queue-5.15/rdma-irdma-prevent-overflows-in-memory-contiguity-ch.patch b/queue-5.15/rdma-irdma-prevent-overflows-in-memory-contiguity-ch.patch new file mode 100644 index 0000000000..8dac100302 --- /dev/null +++ b/queue-5.15/rdma-irdma-prevent-overflows-in-memory-contiguity-ch.patch @@ -0,0 +1,64 @@ +From 17abe60d3872ed0b8806718bba8a5de6020d247e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 24 Jun 2026 17:48:46 +0300 +Subject: RDMA/irdma: Prevent overflows in memory contiguity checks + +From: Aleksandrova Alyona + +[ Upstream commit 3cda0dfe8c651dcbb9e38977905d3d3b1750c4ab ] + +irdma_check_mem_contiguous() and irdma_check_mr_contiguous() verify that +PBL entries describe physically contiguous memory ranges. + +Both functions calculate byte offsets using 32-bit operands. For example, +with 4 KiB pages, pg_size * pg_idx overflows 32-bit arithmetic when +pg_idx reaches 1048576. In the level-2 check, PBLE_PER_PAGE is 512, so +i * pg_size * PBLE_PER_PAGE overflows when i reaches 2048. + +These values are reachable in the driver. For MRs, palloc->total_cnt +comes from iwmr->page_cnt, which is calculated by +ib_umem_num_dma_blocks(). The MR size is limited by IRDMA_MAX_MR_SIZE, +so a 4 GiB MR with 4 KiB pages can reach page_cnt of 1048576. PBLE +resources do not exclude this value either: for gen3, the limit is based +on avail_sds * MAX_PBLE_PER_SD, and MAX_PBLE_PER_SD is 0x40000, so 4 SDs +are enough for 1048576 PBLEs. + +Cast one operand to u64 before the multiplications so that the offset +calculations are performed in 64-bit arithmetic. + +Found by Linux Verification Center (linuxtesting.org) with SVACE. + +Fixes: b48c24c2d710 ("RDMA/irdma: Implement device supported verb APIs") +Signed-off-by: Aleksandrova Alyona +Link: https://patch.msgid.link/20260624144846.61242-1-aga@itb.spb.ru +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + drivers/infiniband/hw/irdma/verbs.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/infiniband/hw/irdma/verbs.c b/drivers/infiniband/hw/irdma/verbs.c +index e6cf2734c684a8..4c309781b4d6b8 100644 +--- a/drivers/infiniband/hw/irdma/verbs.c ++++ b/drivers/infiniband/hw/irdma/verbs.c +@@ -2256,7 +2256,7 @@ static bool irdma_check_mem_contiguous(u64 *arr, u32 npages, u32 pg_size) + u32 pg_idx; + + for (pg_idx = 0; pg_idx < npages; pg_idx++) { +- if ((*arr + (pg_size * pg_idx)) != arr[pg_idx]) ++ if ((*arr + ((u64)pg_size * pg_idx)) != arr[pg_idx]) + return false; + } + +@@ -2289,7 +2289,7 @@ static bool irdma_check_mr_contiguous(struct irdma_pble_alloc *palloc, + + for (i = 0; i < lvl2->leaf_cnt; i++, leaf++) { + arr = leaf->addr; +- if ((*start_addr + (i * pg_size * PBLE_PER_PAGE)) != *arr) ++ if ((*start_addr + ((u64)i * pg_size * PBLE_PER_PAGE)) != *arr) + return false; + ret = irdma_check_mem_contiguous(arr, leaf->cnt, pg_size); + if (!ret) +-- +2.53.0 + diff --git a/queue-5.15/rdma-siw-only-check-attrs-cap.max_send_wr-in-siw_cre.patch b/queue-5.15/rdma-siw-only-check-attrs-cap.max_send_wr-in-siw_cre.patch new file mode 100644 index 0000000000..fca6855567 --- /dev/null +++ b/queue-5.15/rdma-siw-only-check-attrs-cap.max_send_wr-in-siw_cre.patch @@ -0,0 +1,69 @@ +From 663af707c9cb3c9883b4f0bce771b2ebc37e8291 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 13 Nov 2023 19:57:24 +0800 +Subject: RDMA/siw: Only check attrs->cap.max_send_wr in siw_create_qp + +From: Guoqing Jiang + +[ Upstream commit 788bbf4c2fc6e0c35bae9ed5068f484272539d3e ] + +We can just check max_send_wr here given both max_send_wr and +max_recv_wr are defined as u32 type, and we also need to ensure +num_sqe (derived from max_send_wr) shouldn't be zero. + +Acked-by: Bernard Metzler +Signed-off-by: Guoqing Jiang +Link: https://lore.kernel.org/r/20231113115726.12762-16-guoqing.jiang@linux.dev +Signed-off-by: Leon Romanovsky +Stable-dep-of: bb27fcc67c42 ("RDMA/siw: publish QP after initialization") +Signed-off-by: Sasha Levin +--- + drivers/infiniband/sw/siw/siw_verbs.c | 18 +++++------------- + 1 file changed, 5 insertions(+), 13 deletions(-) + +diff --git a/drivers/infiniband/sw/siw/siw_verbs.c b/drivers/infiniband/sw/siw/siw_verbs.c +index c83701d04c9558..55a1357a636dcd 100644 +--- a/drivers/infiniband/sw/siw/siw_verbs.c ++++ b/drivers/infiniband/sw/siw/siw_verbs.c +@@ -334,11 +334,10 @@ int siw_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attrs, + goto err_atomic; + } + /* +- * NOTE: we allow for zero element SQ and RQ WQE's SGL's +- * but not for a QP unable to hold any WQE (SQ + RQ) ++ * NOTE: we don't allow for a QP unable to hold any SQ WQE + */ +- if (attrs->cap.max_send_wr + attrs->cap.max_recv_wr == 0) { +- siw_dbg(base_dev, "QP must have send or receive queue\n"); ++ if (attrs->cap.max_send_wr == 0) { ++ siw_dbg(base_dev, "QP must have send queue\n"); + rv = -EINVAL; + goto err_atomic; + } +@@ -358,21 +357,14 @@ int siw_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attrs, + if (rv) + goto err_atomic; + +- num_sqe = attrs->cap.max_send_wr; +- num_rqe = attrs->cap.max_recv_wr; + + /* All queue indices are derived from modulo operations + * on a free running 'get' (consumer) and 'put' (producer) + * unsigned counter. Having queue sizes at power of two + * avoids handling counter wrap around. + */ +- if (num_sqe) +- num_sqe = roundup_pow_of_two(num_sqe); +- else { +- /* Zero sized SQ is not supported */ +- rv = -EINVAL; +- goto err_out_xa; +- } ++ num_sqe = roundup_pow_of_two(attrs->cap.max_send_wr); ++ num_rqe = attrs->cap.max_recv_wr; + if (num_rqe) + num_rqe = roundup_pow_of_two(num_rqe); + +-- +2.53.0 + diff --git a/queue-5.15/rdma-siw-publish-qp-after-initialization.patch b/queue-5.15/rdma-siw-publish-qp-after-initialization.patch new file mode 100644 index 0000000000..580220e958 --- /dev/null +++ b/queue-5.15/rdma-siw-publish-qp-after-initialization.patch @@ -0,0 +1,153 @@ +From 66038aeabf4731e4fd31c38c7916001a323b2088 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 30 Jun 2026 14:00:40 +0800 +Subject: RDMA/siw: publish QP after initialization + +From: Ruoyu Wang + +[ Upstream commit bb27fcc67c429d97f785c92c35a6c5adebb05d7f ] + +siw_create_qp() currently calls siw_qp_add() before the queues, CQ +pointers, state, completion, and device list entry are ready. A QPN +lookup can therefore reach a QP that is still being constructed. + +Move siw_qp_add() to the end of siw_create_qp(), after QP +initialization and before adding the QP to the siw device list. + +Fixes: f29dd55b0236 ("rdma/siw: queue pair methods") +Link: https://patch.msgid.link/r/20260630060040.966461-1-ruoyuw560@gmail.com +Suggested-by: Bernard Metzler +Signed-off-by: Ruoyu Wang +Acked-by: Bernard Metzler +Signed-off-by: Jason Gunthorpe +Signed-off-by: Sasha Levin +--- + drivers/infiniband/sw/siw/siw_verbs.c | 44 +++++++++++++++------------ + 1 file changed, 24 insertions(+), 20 deletions(-) + +diff --git a/drivers/infiniband/sw/siw/siw_verbs.c b/drivers/infiniband/sw/siw/siw_verbs.c +index 55a1357a636dcd..817970e3943132 100644 +--- a/drivers/infiniband/sw/siw/siw_verbs.c ++++ b/drivers/infiniband/sw/siw/siw_verbs.c +@@ -300,6 +300,7 @@ int siw_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attrs, + struct siw_ucontext *uctx = + rdma_udata_to_drv_context(udata, struct siw_ucontext, + base_ucontext); ++ struct siw_uresp_create_qp uresp = {}; + unsigned long flags; + int num_sqe, num_rqe, rv = 0; + size_t length; +@@ -353,11 +354,6 @@ int siw_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attrs, + spin_lock_init(&qp->rq_lock); + spin_lock_init(&qp->orq_lock); + +- rv = siw_qp_add(sdev, qp); +- if (rv) +- goto err_atomic; +- +- + /* All queue indices are derived from modulo operations + * on a free running 'get' (consumer) and 'put' (producer) + * unsigned counter. Having queue sizes at power of two +@@ -375,14 +371,14 @@ int siw_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attrs, + + if (qp->sendq == NULL) { + rv = -ENOMEM; +- goto err_out_xa; ++ goto err_out; + } + if (attrs->sq_sig_type != IB_SIGNAL_REQ_WR) { + if (attrs->sq_sig_type == IB_SIGNAL_ALL_WR) + qp->attrs.flags |= SIW_SIGNAL_ALL_WR; + else { + rv = -EINVAL; +- goto err_out_xa; ++ goto err_out; + } + } + qp->pd = pd; +@@ -408,7 +404,7 @@ int siw_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attrs, + + if (qp->recvq == NULL) { + rv = -ENOMEM; +- goto err_out_xa; ++ goto err_out; + } + qp->attrs.rq_size = num_rqe; + } +@@ -423,11 +419,8 @@ int siw_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attrs, + qp->attrs.state = SIW_QP_STATE_IDLE; + + if (udata) { +- struct siw_uresp_create_qp uresp = {}; +- + uresp.num_sqe = num_sqe; + uresp.num_rqe = num_rqe; +- uresp.qp_id = qp_id(qp); + + if (qp->sendq) { + length = num_sqe * sizeof(struct siw_sqe); +@@ -436,7 +429,7 @@ int siw_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attrs, + length, &uresp.sq_key); + if (!qp->sq_entry) { + rv = -ENOMEM; +- goto err_out_xa; ++ goto err_out; + } + } + +@@ -448,9 +441,23 @@ int siw_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attrs, + if (!qp->rq_entry) { + uresp.sq_key = SIW_INVAL_UOBJ_KEY; + rv = -ENOMEM; +- goto err_out_xa; ++ goto err_out; + } + } ++ } ++ qp->tx_cpu = siw_get_tx_cpu(sdev); ++ if (qp->tx_cpu < 0) { ++ rv = -EINVAL; ++ goto err_out; ++ } ++ init_completion(&qp->qp_free); ++ ++ rv = siw_qp_add(sdev, qp); ++ if (rv) ++ goto err_out_tx; ++ ++ if (udata) { ++ uresp.qp_id = qp_id(qp); + + if (udata->outlen < sizeof(uresp)) { + rv = -EINVAL; +@@ -460,22 +467,19 @@ int siw_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attrs, + if (rv) + goto err_out_xa; + } +- qp->tx_cpu = siw_get_tx_cpu(sdev); +- if (qp->tx_cpu < 0) { +- rv = -EINVAL; +- goto err_out_xa; +- } ++ + INIT_LIST_HEAD(&qp->devq); + spin_lock_irqsave(&sdev->lock, flags); + list_add_tail(&qp->devq, &sdev->qp_list); + spin_unlock_irqrestore(&sdev->lock, flags); + +- init_completion(&qp->qp_free); +- + return 0; + + err_out_xa: + xa_erase(&sdev->qp_xa, qp_id(qp)); ++err_out_tx: ++ siw_put_tx_cpu(qp->tx_cpu); ++err_out: + if (uctx) { + rdma_user_mmap_entry_remove(qp->sq_entry); + rdma_user_mmap_entry_remove(qp->rq_entry); +-- +2.53.0 + diff --git a/queue-5.15/sched-vtime-get-rid-of-generic-vtime_task_switch-imp.patch b/queue-5.15/sched-vtime-get-rid-of-generic-vtime_task_switch-imp.patch new file mode 100644 index 0000000000..46aae47b2f --- /dev/null +++ b/queue-5.15/sched-vtime-get-rid-of-generic-vtime_task_switch-imp.patch @@ -0,0 +1,123 @@ +From b23e6d81f99c5f8020c2dc28bb29fcde20622287 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 10 Apr 2024 17:09:45 +0200 +Subject: sched/vtime: Get rid of generic vtime_task_switch() implementation + +From: Alexander Gordeev + +[ Upstream commit 89d6910cc562ab34d1f1c08f3cf0a9700b8bf2c4 ] + +The generic vtime_task_switch() implementation gets built only +if __ARCH_HAS_VTIME_TASK_SWITCH is not defined, but requires an +architecture to implement arch_vtime_task_switch() callback at +the same time, which is confusing. + +Further, arch_vtime_task_switch() is implemented for 32-bit PowerPC +architecture only and vtime_task_switch() generic variant is rather +superfluous. + +Simplify the whole vtime_task_switch() wiring by moving the existing +generic implementation to PowerPC. + +Signed-off-by: Alexander Gordeev +Signed-off-by: Ingo Molnar +Reviewed-by: Frederic Weisbecker +Reviewed-by: Nicholas Piggin +Acked-by: Michael Ellerman +Link: https://lore.kernel.org/r/2cb6e3caada93623f6d4f78ad938ac6cd0e2fda8.1712760275.git.agordeev@linux.ibm.com +Stable-dep-of: c1c1ffa490fc ("powerpc/vtime: Initialize starttime at boot for native accounting") +Signed-off-by: Sasha Levin +--- + arch/powerpc/include/asm/cputime.h | 13 ------------- + arch/powerpc/kernel/time.c | 22 ++++++++++++++++++++++ + kernel/sched/cputime.c | 13 ------------- + 3 files changed, 22 insertions(+), 26 deletions(-) + +diff --git a/arch/powerpc/include/asm/cputime.h b/arch/powerpc/include/asm/cputime.h +index a23356c05af193..2e5cc3abd92df5 100644 +--- a/arch/powerpc/include/asm/cputime.h ++++ b/arch/powerpc/include/asm/cputime.h +@@ -31,23 +31,10 @@ + #ifdef CONFIG_PPC64 + #define get_accounting(tsk) (&get_paca()->accounting) + #define raw_get_accounting(tsk) (&local_paca->accounting) +-static inline void arch_vtime_task_switch(struct task_struct *tsk) { } + + #else + #define get_accounting(tsk) (&task_thread_info(tsk)->accounting) + #define raw_get_accounting(tsk) get_accounting(tsk) +-/* +- * Called from the context switch with interrupts disabled, to charge all +- * accumulated times to the current process, and to prepare accounting on +- * the next process. +- */ +-static inline void arch_vtime_task_switch(struct task_struct *prev) +-{ +- struct cpu_accounting_data *acct = get_accounting(current); +- struct cpu_accounting_data *acct0 = get_accounting(prev); +- +- acct->starttime = acct0->starttime; +-} + #endif + + /* +diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c +index d0e59f427fd6f1..65235323bee49c 100644 +--- a/arch/powerpc/kernel/time.c ++++ b/arch/powerpc/kernel/time.c +@@ -429,6 +429,28 @@ void vtime_flush(struct task_struct *tsk) + acct->hardirq_time = 0; + acct->softirq_time = 0; + } ++ ++/* ++ * Called from the context switch with interrupts disabled, to charge all ++ * accumulated times to the current process, and to prepare accounting on ++ * the next process. ++ */ ++void vtime_task_switch(struct task_struct *prev) ++{ ++ if (is_idle_task(prev)) ++ vtime_account_idle(prev); ++ else ++ vtime_account_kernel(prev); ++ ++ vtime_flush(prev); ++ ++ if (!IS_ENABLED(CONFIG_PPC64)) { ++ struct cpu_accounting_data *acct = get_accounting(current); ++ struct cpu_accounting_data *acct0 = get_accounting(prev); ++ ++ acct->starttime = acct0->starttime; ++ } ++} + #endif /* CONFIG_VIRT_CPU_ACCOUNTING_NATIVE */ + + void __no_kcsan __delay(unsigned long loops) +diff --git a/kernel/sched/cputime.c b/kernel/sched/cputime.c +index e3022598f7b02b..d71c4817996b32 100644 +--- a/kernel/sched/cputime.c ++++ b/kernel/sched/cputime.c +@@ -406,19 +406,6 @@ static inline void irqtime_account_process_tick(struct task_struct *p, int user_ + */ + #ifdef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE + +-# ifndef __ARCH_HAS_VTIME_TASK_SWITCH +-void vtime_task_switch(struct task_struct *prev) +-{ +- if (is_idle_task(prev)) +- vtime_account_idle(prev); +- else +- vtime_account_kernel(prev); +- +- vtime_flush(prev); +- arch_vtime_task_switch(prev); +-} +-# endif +- + void vtime_account_irq(struct task_struct *tsk, unsigned int offset) + { + unsigned int pc = irq_count() - offset; +-- +2.53.0 + diff --git a/queue-5.15/sctp-fix-auth_hmacs-array-size-in-struct-sctp_cookie.patch b/queue-5.15/sctp-fix-auth_hmacs-array-size-in-struct-sctp_cookie.patch new file mode 100644 index 0000000000..7025288134 --- /dev/null +++ b/queue-5.15/sctp-fix-auth_hmacs-array-size-in-struct-sctp_cookie.patch @@ -0,0 +1,56 @@ +From 873d57a6547e4d242cf5f7b1819ba213b6a2bf90 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 10 Jul 2026 14:12:35 -0400 +Subject: sctp: fix auth_hmacs array size in struct sctp_cookie + +From: Xin Long + +[ Upstream commit e0b5252a59383b77d1b8dbeda00b7184dd95f4d3 ] + +The auth_hmacs array in struct sctp_cookie is supposed to store a complete +SCTP_AUTH_HMAC_ALGO parameter, which consists of a struct sctp_paramhdr +followed by N HMAC identifiers. + +However, the array size was calculated using an extra 2 bytes instead of +sizeof(struct sctp_paramhdr), which is 4 bytes. When four HMAC identifiers +are configured, the HMAC-ALGO parameter stored in the endpoint is larger +than the auth_hmacs buffer in the cookie. + +As a result, sctp_association_init() copies beyond the end of auth_hmacs +when initializing the association, corrupting the adjacent auth_chunks +field. This can lead to an invalid HMAC identifier being accepted and later +cause an out-of-bounds read in sctp_auth_get_hmac(). + +Fix the array size calculation by including the full SCTP parameter header +size. + +Fixes: 1f485649f529 ("[SCTP]: Implement SCTP-AUTH internals") +Reported-by: Yuan Tan +Reported-by: Xin Liu +Reported-by: Zihan Xi +Reported-by: Ren Wei +Signed-off-by: Xin Long +Link: https://patch.msgid.link/634a0de0d5de29532915e6d47c92a0cbc206e03f.1783707155.git.lucien.xin@gmail.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + include/net/sctp/structs.h | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h +index b73eadf644b3ec..c9a811a3248fb1 100644 +--- a/include/net/sctp/structs.h ++++ b/include/net/sctp/structs.h +@@ -322,7 +322,8 @@ struct sctp_cookie { + + __u8 auth_random[sizeof(struct sctp_paramhdr) + + SCTP_AUTH_RANDOM_LENGTH]; +- __u8 auth_hmacs[SCTP_AUTH_NUM_HMACS * sizeof(__u16) + 2]; ++ __u8 auth_hmacs[sizeof(struct sctp_paramhdr) + ++ SCTP_AUTH_NUM_HMACS * sizeof(__u16)]; + __u8 auth_chunks[sizeof(struct sctp_paramhdr) + SCTP_AUTH_MAX_CHUNKS]; + + /* This is a shim for my peer's INIT packet, followed by +-- +2.53.0 + diff --git a/queue-5.15/series b/queue-5.15/series index 5cbf8214f8..9dc0182aca 100644 --- a/queue-5.15/series +++ b/queue-5.15/series @@ -9,3 +9,50 @@ dmaengine-sh-rz-dmac-move-interrupt-request-after-ev.patch input-ims-pcu-fix-heap-buffer-overflow-in-ims_pcu_pr.patch input-ims-pcu-fix-logic-error-in-packet-reset.patch kvm-vmx-make-vmread_error_trampoline-uncallable-from.patch +ib-mad-drop-unmatched-rmpp-responses-before-reassemb.patch +mtd-mtdswap-remove-debugfs-stats-file-on-teardown.patch +mtd-nand-mtk-ecc-stop-on-ecc-idle-timeouts.patch +btrfs-reject-free-space-cache-with-more-entries-than.patch +btrfs-fix-root-leak-if-its-reloc-root-is-unexpected-.patch +firmware-arm_ffa-fix-null-dereference-in-ffa_partiti.patch +rdma-hns-fix-potential-integer-overflow-in-mhop-hem-.patch +rdma-siw-only-check-attrs-cap.max_send_wr-in-siw_cre.patch +rdma-siw-publish-qp-after-initialization.patch +rdma-irdma-prevent-overflows-in-memory-contiguity-ch.patch +xfrm-policy-preallocate-inexact-bins-before-xfrm_has.patch +wifi-cfg80211-cancel-sched-scan-results-work-on-unre.patch +wifi-ipw2100-fix-potential-memory-leak-in-ipw2100_pc.patch +wifi-mac80211_hwsim-clamp-virtio-rx-length-before-sk.patch +wifi-libertas-fix-memory-leak-in-helper_firmware_cb.patch +wifi-p54-validate-rx-frame-length-in-p54_rx_eeprom_r.patch +wifi-cfg80211-validate-pmsr-measurement-type-data.patch +wifi-cfg80211-validate-pmsr-ftm-preamble-range.patch +wifi-cfg80211-reject-unsupported-pmsr-ftm-location-r.patch +wifi-mac80211-free-ap_vlan-bc_buf-skbs-outside-irq-l.patch +wifi-brcmfmac-initialize-sdio-data-work-before-clean.patch +wifi-cfg80211-bound-element-id-read-when-checking-no.patch +asoc-meson-aiu-fifo-spdif-soft-reset-the-s-pdif-data.patch +asoc-tas2562-fix-deprecated-shut-down-gpio-always-cl.patch +firmware-arm_scmi-rate-limit-queue-full-warnings-in-.patch +ppp-defer-channel-free-to-an-rcu-grace-period-to-fix.patch +ipv4-fib-free-fib_alias-with-kfree_rcu-on-insert-err.patch +net-iucv-take-a-reference-on-the-socket-found-in-afi.patch +ata-sata_dwc_460ex-enable-sata-interrupts-only-after.patch +ata-sata_dwc_460ex-fix-clear_interrupt_bit-clearing-.patch +ata-sata_dwc_460ex-remove-variable-num_processed.patch +ata-sata_dwc_460ex-fix-infinite-loop-in-ncq-tag-comp.patch +alsa-usb-audio-skip-dsd-quirk-for-musical-fidelity-m.patch +bluetooth-qca-fix-nvm-tag-length-underflow-in-tlv-pa.patch +smb-client-handle-overlapping-allocated-ranges-in-fa.patch +drm-i915-gt-use-correct-selftest-config-symbol.patch +powerpc-time-fix-sparse-warnings.patch +powerpc-remove-the-last-remnants-of-cputime_t.patch +sched-vtime-get-rid-of-generic-vtime_task_switch-imp.patch +powerpc-time-prepare-to-stop-elapsing-in-dynticks-id.patch +powerpc-vtime-initialize-starttime-at-boot-for-nativ.patch +can-j1939-fix-lockless-local-destination-check.patch +ksmbd-validate-compound-request-size-before-reading-.patch +drm-i915-selftests-fix-gt-pm-sort-comparators.patch +net-sched-act_tunnel_key-defer-dst_release-to-rcu-ca.patch +sctp-fix-auth_hmacs-array-size-in-struct-sctp_cookie.patch +mpls-fix-null-deref-in-mpls_valid_fib_dump_req-on-co.patch diff --git a/queue-5.15/smb-client-handle-overlapping-allocated-ranges-in-fa.patch b/queue-5.15/smb-client-handle-overlapping-allocated-ranges-in-fa.patch new file mode 100644 index 0000000000..8169946984 --- /dev/null +++ b/queue-5.15/smb-client-handle-overlapping-allocated-ranges-in-fa.patch @@ -0,0 +1,110 @@ +From 14d6cb9941bffc84054d83d546f32624c1b8fa6e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 3 Jul 2026 13:32:56 +0800 +Subject: smb/client: handle overlapping allocated ranges in fallocate + +From: Huiwen He + +[ Upstream commit b09ae45d85dc816987a71db9eebc54b0ae288e94 ] + +smb3_simple_fallocate_range() can skip holes when an allocated range +returned by the server starts before the current fallocate offset. The +skipped hole is not zero-filled, but fallocate still returns success. A +later write to that hole may therefore fail with ENOSPC. + +The function queries allocated ranges so that it can preserve existing +contents and write zeroes only into holes. However, the server may return +a range that starts before the current fallocate offset. + +For example, assume the fallocate request is [100, 400) and the only +allocated range returned by the server is [0, 200): + + Request: [100, 400) + Server range: [ 0, 200) allocated + + Correct: + [100, 200) allocated data, skip + [200, 400) hole, zero-fill + + Current: + [100, 300) skipped + [300, 400) zero-filled afterwards + +The current code adds the full server range length, 200, to the current +offset 100 and moves to 300. As a result, the hole in [200, 300) is +skipped without being zero-filled. + +Fix this by advancing only over the part of the allocated range that +overlaps the current fallocate offset. Ignore ranges that end before the +current offset and reject ranges whose end offset overflows. + +This also prevents a malformed range length from causing an out-of-bounds +zero-buffer read. + +Fixes: 966a3cb7c7db ("cifs: improve fallocate emulation") +Signed-off-by: Huiwen He +Reviewed-by: ChenXiaoSong +Signed-off-by: Steve French +Signed-off-by: Sasha Levin +--- + fs/cifs/smb2ops.c | 25 ++++++++++++++++++------- + 1 file changed, 18 insertions(+), 7 deletions(-) + +diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c +index 5d80ab4fa08777..3aaa45375d8ba0 100644 +--- a/fs/cifs/smb2ops.c ++++ b/fs/cifs/smb2ops.c +@@ -3721,6 +3721,7 @@ static int smb3_simple_fallocate_range(unsigned int xid, + struct file_allocated_range_buffer in_data, *out_data = NULL, *tmp_data; + u32 out_data_len; + char *buf = NULL; ++ u64 range_start, range_len, range_end; + loff_t l; + int rc; + +@@ -3757,13 +3758,21 @@ static int smb3_simple_fallocate_range(unsigned int xid, + goto out; + } + +- if (off < le64_to_cpu(tmp_data->file_offset)) { ++ range_start = le64_to_cpu(tmp_data->file_offset); ++ range_len = le64_to_cpu(tmp_data->length); ++ if (check_add_overflow(range_start, range_len, &range_end) || ++ range_end > S64_MAX) { ++ rc = -EINVAL; ++ goto out; ++ } ++ ++ if (off < range_start) { + /* + * We are at a hole. Write until the end of the region + * or until the next allocated data, + * whichever comes next. + */ +- l = le64_to_cpu(tmp_data->file_offset) - off; ++ l = range_start - off; + if (len < l) + l = len; + rc = smb3_simple_fallocate_write_range(xid, tcon, +@@ -3780,11 +3789,13 @@ static int smb3_simple_fallocate_range(unsigned int xid, + * until the end of the data or the end of the region + * we are supposed to fallocate, whichever comes first. + */ +- l = le64_to_cpu(tmp_data->length); +- if (len < l) +- l = len; +- off += l; +- len -= l; ++ if (off < range_end) { ++ l = range_end - off; ++ if (len < l) ++ l = len; ++ off += l; ++ len -= l; ++ } + + tmp_data = &tmp_data[1]; + out_data_len -= sizeof(struct file_allocated_range_buffer); +-- +2.53.0 + diff --git a/queue-5.15/wifi-brcmfmac-initialize-sdio-data-work-before-clean.patch b/queue-5.15/wifi-brcmfmac-initialize-sdio-data-work-before-clean.patch new file mode 100644 index 0000000000..5d50a64bfa --- /dev/null +++ b/queue-5.15/wifi-brcmfmac-initialize-sdio-data-work-before-clean.patch @@ -0,0 +1,61 @@ +From 2abf3afa75eae1b385b4064a9cf005349bc8d65a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 19 Jun 2026 14:44:01 +0800 +Subject: wifi: brcmfmac: initialize SDIO data work before cleanup + +From: Runyu Xiao + +[ Upstream commit 2a665946e0407a05a3f81bd56a08553c446498e0 ] + +brcmf_sdio_probe() stores the newly allocated bus in sdiodev->bus before +allocating the ordered workqueue. If that allocation fails, the function +jumps to fail and calls brcmf_sdio_remove(). + +brcmf_sdio_remove() unconditionally cancels bus->datawork. Initialize the +work item before the first failure path that can reach brcmf_sdio_remove(), +so the cleanup path always observes a valid work object. + +This issue was found by our static analysis tool and then confirmed by +manual review of the probe error path and the remove-time work drain. The +problem pattern is an early setup failure that reaches a cleanup helper +which cancels an embedded work item before its initializer has run. + +A QEMU PoC forced alloc_ordered_workqueue() to fail at the same point in +brcmf_sdio_probe(), before INIT_WORK(&bus->datawork) is reached. The +resulting fail path calls brcmf_sdio_remove(), and DEBUG_OBJECTS reports +the invalid work drain with brcmf_sdio_probe() and brcmf_sdio_remove() in +the stack. + +Fixes: 9982464379e8 ("brcmfmac: make sdio suspend wait for threads to freeze") +Signed-off-by: Runyu Xiao +Acked-by: Arend van Spriel +Link: https://patch.msgid.link/20260619064401.1048976-1-runyu.xiao@seu.edu.cn +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c +index 76b2953725c2d0..696f3aa32adcff 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c +@@ -4451,6 +4451,7 @@ struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev) + bus->sdiodev = sdiodev; + sdiodev->bus = bus; + skb_queue_head_init(&bus->glom); ++ INIT_WORK(&bus->datawork, brcmf_sdio_dataworker); + bus->txbound = BRCMF_TXBOUND; + bus->rxbound = BRCMF_RXBOUND; + bus->txminmax = BRCMF_TXMINMAX; +@@ -4464,7 +4465,6 @@ struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev) + goto fail; + } + brcmf_sdiod_freezer_count(sdiodev); +- INIT_WORK(&bus->datawork, brcmf_sdio_dataworker); + bus->brcmf_wq = wq; + + /* attempt to attach to the dongle */ +-- +2.53.0 + diff --git a/queue-5.15/wifi-cfg80211-bound-element-id-read-when-checking-no.patch b/queue-5.15/wifi-cfg80211-bound-element-id-read-when-checking-no.patch new file mode 100644 index 0000000000..5e263c965d --- /dev/null +++ b/queue-5.15/wifi-cfg80211-bound-element-id-read-when-checking-no.patch @@ -0,0 +1,58 @@ +From 9a808e037a032788ff0b1e6acfca1e230f534b10 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 7 Jul 2026 18:48:28 +0900 +Subject: wifi: cfg80211: bound element ID read when checking non-inheritance +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: HE WEI (ギカク) + +[ Upstream commit cb8afea4655ff004fa7feee825d5c79783525383 ] + +cfg80211_is_element_inherited() reads the first data octet of the +candidate element (id = elem->data[0]) to look it up in an extension +non-inheritance list. It does so after testing elem->id, but without +verifying that the element actually has a data octet. A zero-length +extension element (WLAN_EID_EXTENSION with length 0) therefore makes it +read one octet past the end of the element. + +_ieee802_11_parse_elems_full() runs this check for every element of a +frame once a non-inheritance context exists -- e.g. while parsing a +per-STA profile of a Multi-Link element in a (re)association response, +or a non-transmitted BSS profile -- so a crafted frame from an AP can +trigger a one-octet slab-out-of-bounds read during element parsing: + + BUG: KASAN: slab-out-of-bounds in cfg80211_is_element_inherited + Read of size 1 ... in net/wireless/scan.c + +Return early (treat the element as inherited) when an extension element +carries no data, mirroring the existing handling of empty ID lists. + +The bug was found by fuzzing ieee802_11_parse_elems_full() under KASAN. + +Fixes: f7dacfb11475 ("cfg80211: support non-inheritance element") +Signed-off-by: HE WEI (ギカク) +Link: https://patch.msgid.link/20260707094828.16465-1-skyexpoc@gmail.com +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + net/wireless/scan.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/wireless/scan.c b/net/wireless/scan.c +index 1bc2aba69bd732..df9d0431864d39 100644 +--- a/net/wireless/scan.c ++++ b/net/wireless/scan.c +@@ -240,7 +240,7 @@ bool cfg80211_is_element_inherited(const struct element *elem, + return true; + + if (elem->id == WLAN_EID_EXTENSION) { +- if (!ext_id_len) ++ if (!ext_id_len || !elem->datalen) + return true; + loop_len = ext_id_len; + list = &non_inherit_elem->data[3 + id_len]; +-- +2.53.0 + diff --git a/queue-5.15/wifi-cfg80211-cancel-sched-scan-results-work-on-unre.patch b/queue-5.15/wifi-cfg80211-cancel-sched-scan-results-work-on-unre.patch new file mode 100644 index 0000000000..84ccb3da28 --- /dev/null +++ b/queue-5.15/wifi-cfg80211-cancel-sched-scan-results-work-on-unre.patch @@ -0,0 +1,83 @@ +From 3bd85cc9df1d2fdf0eb11e49cd4f298ee56f860d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 20 Jun 2026 00:25:42 +0800 +Subject: wifi: cfg80211: cancel sched scan results work on unregister + +From: Cen Zhang + +[ Upstream commit edf0730be33696a1bd142792830d392129e495cc ] + +cfg80211_sched_scan_results() can queue rdev->sched_scan_res_wk from a +driver result notification while a scheduled scan request is present. The +work callback recovers the containing cfg80211_registered_device and then +locks the wiphy and walks the scheduled-scan request list. + +wiphy_unregister() already makes the wiphy unreachable and drains rdev work +items before cfg80211_dev_free() can release the object, but it does not +drain sched_scan_res_wk. A queued or running result work item can therefore +cross the unregister/free boundary and access freed rdev state. + +The buggy scenario involves two paths, with each column showing the order +within that path: + +scheduled-scan result path: unregister/free path: +1. cfg80211_sched_scan_results() 1. interface teardown stops and + queues rdev->sched_scan_res_wk. removes the scheduled scan request. +2. cfg80211_wq starts the work 2. wiphy_unregister() drains other + item and recovers rdev. rdev work items. +3. The worker locks rdev->wiphy 3. cfg80211_dev_free() destroys and + and walks rdev state. frees rdev. + +Cancel sched_scan_res_wk in wiphy_unregister() alongside the other rdev +work items. cancel_work_sync() removes a pending result notification and +waits for an already running callback, so cfg80211_dev_free() cannot free +rdev while this work item is still active. + +Validation reproduced this kernel report: +BUG: KASAN: use-after-free in cfg80211_sched_scan_results_wk+0x4a6/0x530 +Workqueue: cfg80211 cfg80211_sched_scan_results_wk [cfg80211] +Read of size 8 +Call trace: + dump_stack_lvl+0x66/0xa0 + print_report+0xce/0x630 + cfg80211_sched_scan_results_wk+0x4a6/0x530 + srso_alias_return_thunk+0x5/0xfbef5 + __virt_addr_valid+0x224/0x430 + kasan_report+0xac/0xe0 + lockdep_hardirqs_on_prepare+0xea/0x1a0 + process_one_work+0x8d0/0x18f0 (kernel/workqueue.c:3212) + lock_is_held_type+0x8f/0x100 + worker_thread+0x5ad/0xfd0 + __kthread_parkme+0xc6/0x200 + kthread+0x31e/0x410 + trace_hardirqs_on+0x1a/0x170 + ret_from_fork+0x576/0x810 + __switch_to+0x57e/0xe20 + __switch_to_asm+0x33/0x70 + ret_from_fork_asm+0x1a/0x30 + +Fixes: 807f8a8c3004 ("cfg80211/nl80211: add support for scheduled scans") +Assisted-by: Codex:gpt-5.5 +Signed-off-by: Cen Zhang +Link: https://patch.msgid.link/20260619162542.3878296-1-zzzccc427@gmail.com +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + net/wireless/core.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/net/wireless/core.c b/net/wireless/core.c +index d63480873d0636..3ab7a21a6743d0 100644 +--- a/net/wireless/core.c ++++ b/net/wireless/core.c +@@ -1104,6 +1104,7 @@ void wiphy_unregister(struct wiphy *wiphy) + /* this has nothing to do now but make sure it's gone */ + cancel_work_sync(&rdev->wiphy_work); + ++ cancel_work_sync(&rdev->sched_scan_res_wk); + cancel_work_sync(&rdev->rfkill_block); + cancel_work_sync(&rdev->conn_work); + flush_work(&rdev->event_work); +-- +2.53.0 + diff --git a/queue-5.15/wifi-cfg80211-reject-unsupported-pmsr-ftm-location-r.patch b/queue-5.15/wifi-cfg80211-reject-unsupported-pmsr-ftm-location-r.patch new file mode 100644 index 0000000000..d0ce52dc42 --- /dev/null +++ b/queue-5.15/wifi-cfg80211-reject-unsupported-pmsr-ftm-location-r.patch @@ -0,0 +1,50 @@ +From b31c8cf6e8e60ccbfdd27da287c2a98dc663f0b2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 12 Jun 2026 21:37:11 +0800 +Subject: wifi: cfg80211: reject unsupported PMSR FTM location requests + +From: Zhao Li + +[ Upstream commit 69ef6a7ec277f16d216be8da2b3cbe872786c999 ] + +PMSR FTM location request flags are syntactically valid, but they must +be rejected when the device capability does not advertise support for +them. + +Return an error immediately after rejecting unsupported LCI or civic +location request bits so the request cannot reach the driver. + +Fixes: 9bb7e0f24e7e7 ("cfg80211: add peer measurement with FTM initiator API") +Assisted-by: Codex:gpt-5.5 +Assisted-by: Claude:claude-opus-4.8 +Signed-off-by: Zhao Li +Link: https://patch.msgid.link/20260612133710.93544-2-enderaoelyther@gmail.com +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + net/wireless/pmsr.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/net/wireless/pmsr.c b/net/wireless/pmsr.c +index 5b66a66d05a6ec..9cb8bfb9ba96f8 100644 +--- a/net/wireless/pmsr.c ++++ b/net/wireless/pmsr.c +@@ -116,6 +116,7 @@ static int pmsr_parse_ftm(struct cfg80211_registered_device *rdev, + NL_SET_ERR_MSG_ATTR(info->extack, + tb[NL80211_PMSR_FTM_REQ_ATTR_REQUEST_LCI], + "FTM: LCI request not supported"); ++ return -EOPNOTSUPP; + } + + out->ftm.request_civicloc = +@@ -124,6 +125,7 @@ static int pmsr_parse_ftm(struct cfg80211_registered_device *rdev, + NL_SET_ERR_MSG_ATTR(info->extack, + tb[NL80211_PMSR_FTM_REQ_ATTR_REQUEST_CIVICLOC], + "FTM: civic location request not supported"); ++ return -EOPNOTSUPP; + } + + out->ftm.trigger_based = +-- +2.53.0 + diff --git a/queue-5.15/wifi-cfg80211-validate-pmsr-ftm-preamble-range.patch b/queue-5.15/wifi-cfg80211-validate-pmsr-ftm-preamble-range.patch new file mode 100644 index 0000000000..2d925226c7 --- /dev/null +++ b/queue-5.15/wifi-cfg80211-validate-pmsr-ftm-preamble-range.patch @@ -0,0 +1,45 @@ +From 6e019f0409a2f2079a6591327be191dc56d60983 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 12 Jun 2026 21:37:04 +0800 +Subject: wifi: cfg80211: validate PMSR FTM preamble range + +From: Zhao Li + +[ Upstream commit 36230936468f0ba4930e94aef496fc229d4bb951 ] + +PMSR FTM request parsing accepts preamble values outside the +enumerated nl80211 preamble range. + +Reject out-of-range values before using them in the parser capability +bit test using the policy. + +Fixes: 9bb7e0f24e7e7 ("cfg80211: add peer measurement with FTM initiator API") +Assisted-by: Codex:gpt-5.5 +Assisted-by: Claude:claude-opus-4.8 +Signed-off-by: Zhao Li +Link: https://patch.msgid.link/20260612133703.93274-2-enderaoelyther@gmail.com +[drop unnecessary check] +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + net/wireless/nl80211.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c +index a7f91b584ee0cc..2c74da398cf4ed 100644 +--- a/net/wireless/nl80211.c ++++ b/net/wireless/nl80211.c +@@ -300,7 +300,9 @@ nl80211_ftm_responder_policy[NL80211_FTM_RESP_ATTR_MAX + 1] = { + static const struct nla_policy + nl80211_pmsr_ftm_req_attr_policy[NL80211_PMSR_FTM_REQ_ATTR_MAX + 1] = { + [NL80211_PMSR_FTM_REQ_ATTR_ASAP] = { .type = NLA_FLAG }, +- [NL80211_PMSR_FTM_REQ_ATTR_PREAMBLE] = { .type = NLA_U32 }, ++ [NL80211_PMSR_FTM_REQ_ATTR_PREAMBLE] = ++ NLA_POLICY_RANGE(NLA_U32, NL80211_PREAMBLE_LEGACY, ++ NL80211_PREAMBLE_HE), + [NL80211_PMSR_FTM_REQ_ATTR_NUM_BURSTS_EXP] = + NLA_POLICY_MAX(NLA_U8, 15), + [NL80211_PMSR_FTM_REQ_ATTR_BURST_PERIOD] = { .type = NLA_U16 }, +-- +2.53.0 + diff --git a/queue-5.15/wifi-cfg80211-validate-pmsr-measurement-type-data.patch b/queue-5.15/wifi-cfg80211-validate-pmsr-measurement-type-data.patch new file mode 100644 index 0000000000..cc1849e9ea --- /dev/null +++ b/queue-5.15/wifi-cfg80211-validate-pmsr-measurement-type-data.patch @@ -0,0 +1,76 @@ +From 1c83dc0b203b23e98a0a2c3032bb1e42fffa246f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 12 Jun 2026 21:36:57 +0800 +Subject: wifi: cfg80211: validate PMSR measurement type data + +From: Zhao Li + +[ Upstream commit 41aa973eb05922848dded26875c55ef982ac1c49 ] + +PMSR request parsing accepts missing or duplicated measurement type +entries in NL80211_PMSR_REQ_ATTR_DATA. + +Track whether one measurement type was already provided, reject a +second one immediately, and return an error if the request data block +contains no measurement type at all. + +Fixes: 9bb7e0f24e7e7 ("cfg80211: add peer measurement with FTM initiator API") +Assisted-by: Codex:gpt-5.5 +Assisted-by: Claude:claude-opus-4.8 +Signed-off-by: Zhao Li +Link: https://patch.msgid.link/20260612133656.92900-2-enderaoelyther@gmail.com +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + net/wireless/pmsr.c | 19 +++++++++++++++++-- + 1 file changed, 17 insertions(+), 2 deletions(-) + +diff --git a/net/wireless/pmsr.c b/net/wireless/pmsr.c +index 65fa39275f73f8..5b66a66d05a6ec 100644 +--- a/net/wireless/pmsr.c ++++ b/net/wireless/pmsr.c +@@ -190,6 +190,7 @@ static int pmsr_parse_peer(struct cfg80211_registered_device *rdev, + { + struct nlattr *tb[NL80211_PMSR_PEER_ATTR_MAX + 1]; + struct nlattr *req[NL80211_PMSR_REQ_ATTR_MAX + 1]; ++ bool have_measurement_type = false; + struct nlattr *treq; + int err, rem; + +@@ -242,6 +243,14 @@ static int pmsr_parse_peer(struct cfg80211_registered_device *rdev, + } + + nla_for_each_nested(treq, req[NL80211_PMSR_REQ_ATTR_DATA], rem) { ++ if (have_measurement_type) { ++ NL_SET_ERR_MSG_ATTR(info->extack, treq, ++ "multiple measurement types in request data"); ++ return -EINVAL; ++ } ++ ++ have_measurement_type = true; ++ + switch (nla_type(treq)) { + case NL80211_PMSR_TYPE_FTM: + err = pmsr_parse_ftm(rdev, treq, out, info); +@@ -251,10 +260,16 @@ static int pmsr_parse_peer(struct cfg80211_registered_device *rdev, + "unsupported measurement type"); + err = -EINVAL; + } ++ if (err) ++ return err; + } + +- if (err) +- return err; ++ if (!have_measurement_type) { ++ NL_SET_ERR_MSG_ATTR(info->extack, ++ req[NL80211_PMSR_REQ_ATTR_DATA], ++ "missing measurement type in request data"); ++ return -EINVAL; ++ } + + return 0; + } +-- +2.53.0 + diff --git a/queue-5.15/wifi-ipw2100-fix-potential-memory-leak-in-ipw2100_pc.patch b/queue-5.15/wifi-ipw2100-fix-potential-memory-leak-in-ipw2100_pc.patch new file mode 100644 index 0000000000..5432e11310 --- /dev/null +++ b/queue-5.15/wifi-ipw2100-fix-potential-memory-leak-in-ipw2100_pc.patch @@ -0,0 +1,60 @@ +From 4c4612551ecefbd4d60d77372affcde6f44fd425 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 20 Jun 2026 12:22:39 +0530 +Subject: wifi: ipw2100: fix potential memory leak in ipw2100_pci_init_one() + +From: Abdun Nihaal + +[ Upstream commit 0d388f62031dbabcba0f44bb91b59f10e88cac17 ] + +The memory allocated in the ipw2100_alloc_device() function is not freed +in some of the error paths in ipw2100_pci_init_one(). Fix that by +converting the direct return into a goto to the error path return. + +The error path when pci_enable_device() fails cannot jump to fail, since +at this point priv is not set, so perform error handling inline. + +Fixes: 2c86c275015c ("Add ipw2100 wireless driver.") +Signed-off-by: Abdun Nihaal +Link: https://patch.msgid.link/20260620065242.93798-1-nihaal@cse.iitm.ac.in +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/intel/ipw2x00/ipw2100.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/drivers/net/wireless/intel/ipw2x00/ipw2100.c b/drivers/net/wireless/intel/ipw2x00/ipw2100.c +index 47eb89b773cf7f..c954e6001eab17 100644 +--- a/drivers/net/wireless/intel/ipw2x00/ipw2100.c ++++ b/drivers/net/wireless/intel/ipw2x00/ipw2100.c +@@ -6183,6 +6183,8 @@ static int ipw2100_pci_init_one(struct pci_dev *pci_dev, + if (err) { + printk(KERN_WARNING DRV_NAME + "Error calling pci_enable_device.\n"); ++ free_libipw(dev, 0); ++ pci_iounmap(pci_dev, ioaddr); + return err; + } + +@@ -6195,16 +6197,14 @@ static int ipw2100_pci_init_one(struct pci_dev *pci_dev, + if (err) { + printk(KERN_WARNING DRV_NAME + "Error calling pci_set_dma_mask.\n"); +- pci_disable_device(pci_dev); +- return err; ++ goto fail; + } + + err = pci_request_regions(pci_dev, DRV_NAME); + if (err) { + printk(KERN_WARNING DRV_NAME + "Error calling pci_request_regions.\n"); +- pci_disable_device(pci_dev); +- return err; ++ goto fail; + } + + /* We disable the RETRY_TIMEOUT register (0x41) to keep +-- +2.53.0 + diff --git a/queue-5.15/wifi-libertas-fix-memory-leak-in-helper_firmware_cb.patch b/queue-5.15/wifi-libertas-fix-memory-leak-in-helper_firmware_cb.patch new file mode 100644 index 0000000000..997565ba91 --- /dev/null +++ b/queue-5.15/wifi-libertas-fix-memory-leak-in-helper_firmware_cb.patch @@ -0,0 +1,50 @@ +From d9693b75ea164405d3393706eb60d8ba47b1470c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 24 Jun 2026 16:53:43 +0800 +Subject: wifi: libertas: fix memory leak in helper_firmware_cb() + +From: Dawei Feng + +[ Upstream commit 63c2391deefb31e1b801b7f32bd502ca4808639b ] + +helper_firmware_cb() neglects to free the single-stage firmware image +after a successful async load, leading to a memory leak in the USB +firmware-download path. + +Fix this memory leak by calling release_firmware() immediately after +lbs_fw_loaded() returns. + +The bug was first flagged by an experimental analysis tool we are +developing for kernel memory-management bugs while analyzing +v6.13-rc1. The tool is still under development and is not yet publicly +available. Manual inspection confirms that the bug is still present in +the current wireless tree. + +An x86_64 allyesconfig build showed no new warnings. As we do not have +compatible Libertas USB hardware for exercising this firmware-download +path, no runtime testing was able to be performed. + +Fixes: 1dfba3060fe7 ("libertas: move firmware lifetime handling to firmware.c") +Signed-off-by: Dawei Feng +Link: https://patch.msgid.link/20260624085343.575508-1-dawei.feng@seu.edu.cn +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/marvell/libertas/firmware.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/net/wireless/marvell/libertas/firmware.c b/drivers/net/wireless/marvell/libertas/firmware.c +index f124110944b7e9..9bf7d4c207b9ed 100644 +--- a/drivers/net/wireless/marvell/libertas/firmware.c ++++ b/drivers/net/wireless/marvell/libertas/firmware.c +@@ -78,6 +78,7 @@ static void helper_firmware_cb(const struct firmware *firmware, void *context) + } else { + /* No main firmware needed for this helper --> success! */ + lbs_fw_loaded(priv, 0, firmware, NULL); ++ release_firmware(firmware); + } + } + +-- +2.53.0 + diff --git a/queue-5.15/wifi-mac80211-free-ap_vlan-bc_buf-skbs-outside-irq-l.patch b/queue-5.15/wifi-mac80211-free-ap_vlan-bc_buf-skbs-outside-irq-l.patch new file mode 100644 index 0000000000..214c9acfc1 --- /dev/null +++ b/queue-5.15/wifi-mac80211-free-ap_vlan-bc_buf-skbs-outside-irq-l.patch @@ -0,0 +1,77 @@ +From f993077895d69d0c77420c74581e93c48c6c2775 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 6 Jul 2026 22:08:41 +0800 +Subject: wifi: mac80211: free AP_VLAN bc_buf SKBs outside IRQ lock + +From: Cen Zhang + +[ Upstream commit f3858d5b1432098c1936e03d6e03dd0e33facf60 ] + +ieee80211_do_stop() removes AP_VLAN packets from the parent AP +ps->bc_buf while holding ps->bc_buf.lock with IRQs disabled. It then +calls ieee80211_free_txskb() before dropping the lock. + +ieee80211_free_txskb() is not just a passive SKB release. For SKBs with +TX status state it can report a dropped frame through cfg80211/nl80211, +and that path can reach netlink tap transmit. This is the same reason +the pending queue cleanup in ieee80211_do_stop() already unlinks SKBs +under the queue lock and frees them after IRQ state is restored. + +The buggy scenario involves two paths, with each column showing the +order within that path: + +AP_VLAN management TX: AP_VLAN stop: +1. attach ACK-status state 1. clear the running state +2. queue a multicast SKB on 2. take ps->bc_buf.lock with IRQs + parent ps->bc_buf disabled + 3. unlink the AP_VLAN SKB + 4. call ieee80211_free_txskb() + +Unlink matching AP_VLAN SKBs from ps->bc_buf under the existing lock, +but move them to a local free queue. Drop the lock and restore IRQ state +before calling ieee80211_free_txskb(). + +WARNING: kernel/softirq.c:430 at __local_bh_enable_ip + +Fixes: 397a7a24ef8c ("mac80211: free ps->bc_buf skbs on vlan device stop") +Assisted-by: Codex:gpt-5.5 +Signed-off-by: Cen Zhang +Link: https://patch.msgid.link/20260706140841.581566-1-zzzccc427@gmail.com +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + net/mac80211/iface.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c +index eb7de2d455e1ad..3b2d51df5d9473 100644 +--- a/net/mac80211/iface.c ++++ b/net/mac80211/iface.c +@@ -482,6 +482,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, bool going_do + WARN_ON(!list_empty(&sdata->u.ap.vlans)); + } else if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) { + /* remove all packets in parent bc_buf pointing to this dev */ ++ __skb_queue_head_init(&freeq); + ps = &sdata->bss->ps; + + spin_lock_irqsave(&ps->bc_buf.lock, flags); +@@ -489,10 +490,15 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, bool going_do + if (skb->dev == sdata->dev) { + __skb_unlink(skb, &ps->bc_buf); + local->total_ps_buffered--; +- ieee80211_free_txskb(&local->hw, skb); ++ __skb_queue_tail(&freeq, skb); + } + } + spin_unlock_irqrestore(&ps->bc_buf.lock, flags); ++ ++ skb_queue_walk_safe(&freeq, skb, tmp) { ++ __skb_unlink(skb, &freeq); ++ ieee80211_free_txskb(&local->hw, skb); ++ } + } + + if (going_down) +-- +2.53.0 + diff --git a/queue-5.15/wifi-mac80211_hwsim-clamp-virtio-rx-length-before-sk.patch b/queue-5.15/wifi-mac80211_hwsim-clamp-virtio-rx-length-before-sk.patch new file mode 100644 index 0000000000..a1da89b72e --- /dev/null +++ b/queue-5.15/wifi-mac80211_hwsim-clamp-virtio-rx-length-before-sk.patch @@ -0,0 +1,46 @@ +From 3ab040e7bde6b7db358efab48ebf1f1104143122 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 20 Jun 2026 21:45:18 -0500 +Subject: wifi: mac80211_hwsim: clamp virtio RX length before skb_put + +From: Bryam Vargas + +[ Upstream commit 10a2b430f8f06ae14b9590b6f6faa6b588ef0654 ] + +hwsim_virtio_rx_work() passes the virtqueue used-ring length reported by +the device straight to skb_put() on a fixed-size receive skb. A backend +reporting a length larger than the skb tailroom drives skb_put() past the +buffer end and hits skb_over_panic() -- a host-triggerable guest panic +(denial of service). + +Clamp the length to the skb's available room before skb_put(). A +conforming device never reports more than the posted buffer size, so valid +frames are unaffected; a truncated over-report then fails the +length/header checks in hwsim_virtio_handle_cmd() and is dropped, so +truncating rather than dropping here cannot be turned into a parsing +problem. + +Fixes: 5d44fe7c9808 ("mac80211_hwsim: add frame transmission support over virtio") +Signed-off-by: Bryam Vargas +Link: https://patch.msgid.link/20260620-b4-disp-474bee37-v1-1-1a4d37f3e2d4@proton.me +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/mac80211_hwsim.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c +index ed4d83775fe705..9c102c25a5332f 100644 +--- a/drivers/net/wireless/mac80211_hwsim.c ++++ b/drivers/net/wireless/mac80211_hwsim.c +@@ -4332,6 +4332,7 @@ static void hwsim_virtio_rx_work(struct work_struct *work) + + skb->data = skb->head; + skb_reset_tail_pointer(skb); ++ len = min(len, skb_end_offset(skb)); + skb_put(skb, len); + hwsim_virtio_handle_cmd(skb); + +-- +2.53.0 + diff --git a/queue-5.15/wifi-p54-validate-rx-frame-length-in-p54_rx_eeprom_r.patch b/queue-5.15/wifi-p54-validate-rx-frame-length-in-p54_rx_eeprom_r.patch new file mode 100644 index 0000000000..b90c27339c --- /dev/null +++ b/queue-5.15/wifi-p54-validate-rx-frame-length-in-p54_rx_eeprom_r.patch @@ -0,0 +1,80 @@ +From cdfb04e4cb8d4f3ee5ba0673d02f8ecc18e51ec8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 27 Jun 2026 17:05:10 -0700 +Subject: wifi: p54: validate RX frame length in p54_rx_eeprom_readback() + +From: Xiang Mei + +[ Upstream commit ebd6d37fa94bee929e0b4c9ca19fdf9b1dcf6cea ] + +p54_rx_eeprom_readback() copies the requested EEPROM slice out of a +device-supplied readback frame without checking that the skb actually holds +that many bytes. Commit da1b9a55ff11 ("wifi: p54: prevent buffer-overflow in +p54_rx_eeprom_readback()") closed the destination overflow by copying a +fixed priv->eeprom_slice_size (and rejecting a mismatched advertised len), +but the source side is still unbounded: nothing verifies the frame is long +enough to supply that many bytes. + +A malicious USB device can send a short frame whose advertised len matches +priv->eeprom_slice_size while the payload is truncated. The equality check +passes and memcpy() reads past the end of the skb, leaking adjacent heap: + + BUG: KASAN: slab-out-of-bounds in p54_rx (drivers/net/wireless/intersil/p54/txrx.c:507) + Read of size 1016 at addr ffff88800f077114 by task swapper/0/0 + Call Trace: + + ... + __asan_memcpy (mm/kasan/shadow.c:105) + p54_rx (drivers/net/wireless/intersil/p54/txrx.c:507) + p54u_rx_cb (drivers/net/wireless/intersil/p54/p54usb.c:163) + __usb_hcd_giveback_urb (drivers/usb/core/hcd.c:1657) + dummy_timer (drivers/usb/gadget/udc/dummy_hcd.c:2005) + ... + + + The buggy address belongs to the object at ffff88800f0770c0 + which belongs to the cache skbuff_small_head of size 704 + The buggy address is located 84 bytes inside of + allocated 704-byte region [ffff88800f0770c0, ffff88800f077380) + +Check that the slice fits in the skb before copying. + +Fixes: 7cb770729ba8 ("p54: move eeprom code into common library") +Reported-by: Weiming Shi +Assisted-by: Claude:claude-opus-4-8 +Signed-off-by: Xiang Mei +Acked-by: Christian Lamparter +Link: https://patch.msgid.link/20260628000510.4152481-1-xmei5@asu.edu +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/intersil/p54/txrx.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/drivers/net/wireless/intersil/p54/txrx.c b/drivers/net/wireless/intersil/p54/txrx.c +index 6333b1000f925b..303badbd53d9b0 100644 +--- a/drivers/net/wireless/intersil/p54/txrx.c ++++ b/drivers/net/wireless/intersil/p54/txrx.c +@@ -503,11 +503,19 @@ static void p54_rx_eeprom_readback(struct p54_common *priv, + if (le16_to_cpu(eeprom->v2.len) != priv->eeprom_slice_size) + return; + ++ if (eeprom->v2.data + priv->eeprom_slice_size > ++ skb_tail_pointer(skb)) ++ return; ++ + memcpy(priv->eeprom, eeprom->v2.data, priv->eeprom_slice_size); + } else { + if (le16_to_cpu(eeprom->v1.len) != priv->eeprom_slice_size) + return; + ++ if (eeprom->v1.data + priv->eeprom_slice_size > ++ skb_tail_pointer(skb)) ++ return; ++ + memcpy(priv->eeprom, eeprom->v1.data, priv->eeprom_slice_size); + } + +-- +2.53.0 + diff --git a/queue-5.15/xfrm-policy-preallocate-inexact-bins-before-xfrm_has.patch b/queue-5.15/xfrm-policy-preallocate-inexact-bins-before-xfrm_has.patch new file mode 100644 index 0000000000..3d11d7d66a --- /dev/null +++ b/queue-5.15/xfrm-policy-preallocate-inexact-bins-before-xfrm_has.patch @@ -0,0 +1,75 @@ +From 584504bf4489636953642701178910520a646452 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 3 Jul 2026 05:19:32 +0000 +Subject: xfrm: policy: preallocate inexact bins before xfrm_hash_rebuild + reinsert + +From: Xiang Mei (Microsoft) + +[ Upstream commit f38f8cce2f7e79775b3db7e8a5eacda04ac908e4 ] + +xfrm_hash_rebuild()'s first loop preallocates the bins/chains the reinsert +loop needs, so the reinsert (after hlist_del_rcu()) cannot allocate or +fail. But its guard is inverted: it skips policies with prefixlen < +threshold and preallocates for the rest. + +prefixlen < threshold is exactly when policy_hash_bysel() returns NULL and +the reinsert takes the allocating xfrm_policy_inexact_insert() path. So the +loop preallocates for the exact policies (which never allocate) and skips +the inexact ones, whose bin/node is then allocated GFP_ATOMIC during +reinsert. On failure the error path only WARN_ONCE()s and continues, +leaving a poisoned bydst node; the next rebuild's hlist_del_rcu() +dereferences LIST_POISON2 and takes a GPF. Reachable under memory pressure, +deterministic via failslab. + +Invert the guard so preallocation covers exactly the reinserted policies; +the reinsert then allocates nothing and cannot fail. + +Crash: + Oops: general protection fault, probably for non-canonical address + 0xfbd59c0000000024: 0000 [#1] SMP KASAN NOPTI + KASAN: maybe wild-memory-access in range [0xdead...] + ... + Workqueue: events xfrm_hash_rebuild + RIP: 0010:xfrm_hash_rebuild+0x5b3/0x1190 + RAX: dead000000000122 (LIST_POISON2 + offset) + ... + Call Trace: + hlist_del_rcu (include/linux/rculist.h:599) + xfrm_hash_rebuild (net/xfrm/xfrm_policy.c:1365) + process_one_work (kernel/workqueue.c:3322) + worker_thread (kernel/workqueue.c:3486) + kthread (kernel/kthread.c:436) + ret_from_fork (arch/x86/kernel/process.c:158) + ret_from_fork_asm (arch/x86/entry/entry_64.S:245) + ... + Kernel panic - not syncing: Fatal exception in interrupt + +Fixes: 24969facd704 ("xfrm: policy: store inexact policies in an rhashtable") +Reported-by: AutonomousCodeSecurity@microsoft.com +Signed-off-by: Xiang Mei (Microsoft) +Reviewed-by: Florian Westphal +Signed-off-by: Steffen Klassert +Signed-off-by: Sasha Levin +--- + net/xfrm/xfrm_policy.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c +index cec66c74e1d22a..536b945e1eeb63 100644 +--- a/net/xfrm/xfrm_policy.c ++++ b/net/xfrm/xfrm_policy.c +@@ -1292,8 +1292,8 @@ static void xfrm_hash_rebuild(struct work_struct *work) + } + } + +- if (policy->selector.prefixlen_d < dbits || +- policy->selector.prefixlen_s < sbits) ++ if (policy->selector.prefixlen_d >= dbits && ++ policy->selector.prefixlen_s >= sbits) + continue; + + bin = xfrm_policy_inexact_alloc_bin(policy, dir); +-- +2.53.0 + diff --git a/queue-6.1/alsa-usb-audio-skip-dsd-quirk-for-musical-fidelity-m.patch b/queue-6.1/alsa-usb-audio-skip-dsd-quirk-for-musical-fidelity-m.patch new file mode 100644 index 0000000000..13a49eb7bd --- /dev/null +++ b/queue-6.1/alsa-usb-audio-skip-dsd-quirk-for-musical-fidelity-m.patch @@ -0,0 +1,47 @@ +From 3989e125276729040a74d83c1a4998b5e3905198 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 9 Jul 2026 11:56:06 +0200 +Subject: ALSA: usb-audio: Skip DSD quirk for Musical Fidelity M6s DAC + +From: Takashi Iwai + +[ Upstream commit 93b47e66cc6d6c6382d44b44f5e7f6fc3a7b38c3 ] + +Salvador reported that the recent fix for applying the DSD quirk to +Musical Fidelity devices broke for his M6s DAC model (2772:0502). + +Although this is basically a firmware bug, the model in question is +fairly old, and no further firmware update can be expected, so it'd be +better to address in the driver side. + +As an ad hoc workaround, skip the DSD quirk for this device by adding +an empty quirk entry of 2772:0502; this essentially skips the later +DSD quirk entry by the match with the vendor 2772. + +Fixes: da3a7efff64e ("ALSA: usb-audio: Update for native DSD support quirks") +Reported-by: Salvador Blaya +Closes: https://lore.kernel.org/CAOdyq+qFaqCh=tK_wNnA64hv5pQuA1Y09ANxQ=xK8yR-t4mf9Q@mail.gmail.com +Tested-by: Salvador Blaya +Signed-off-by: Takashi Iwai +Link: https://patch.msgid.link/20260709095614.1418838-1-tiwai@suse.de +Signed-off-by: Sasha Levin +--- + sound/usb/quirks.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c +index 8faf3731e3499d..ece6ae4a21ed9f 100644 +--- a/sound/usb/quirks.c ++++ b/sound/usb/quirks.c +@@ -2261,6 +2261,8 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = { + QUIRK_FLAG_DSD_RAW), + DEVICE_FLG(0x2708, 0x0002, /* Audient iD14 */ + QUIRK_FLAG_IGNORE_CTL_ERROR), ++ DEVICE_FLG(0x2772, 0x0502, /* Musical Fidelity M6s DAC */ ++ 0), /* for avoiding QUIRK_FLAG_DSD_RAW with vendor match */ + DEVICE_FLG(0x2912, 0x30c8, /* Audioengine D1 */ + QUIRK_FLAG_GET_SAMPLE_RATE), + DEVICE_FLG(0x2a70, 0x1881, /* OnePlus Technology (Shenzhen) Co., Ltd. BE02T */ +-- +2.53.0 + diff --git a/queue-6.1/arm64-tegra-fix-cpu-compatible-string-to-cortex-a78a.patch b/queue-6.1/arm64-tegra-fix-cpu-compatible-string-to-cortex-a78a.patch new file mode 100644 index 0000000000..72b1e86c17 --- /dev/null +++ b/queue-6.1/arm64-tegra-fix-cpu-compatible-string-to-cortex-a78a.patch @@ -0,0 +1,144 @@ +From c571cd2e557ae4a5af4e63c2a18600c51359b324 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 21 Jan 2026 16:15:34 +0530 +Subject: arm64: tegra: Fix CPU compatible string to cortex-a78ae on Tegra234 + +From: Sumit Gupta + +[ Upstream commit 0dfa1e960f86e032007882b032c5cc7d14ebe73e ] + +The Tegra234 SoC uses Cortex-A78AE cores, not Cortex-A78. Update the +compatible string for all CPU nodes to match the actual hardware. + +Tegra234 hardware reports: + # head /proc/cpuinfo | egrep 'implementer|part' + CPU implementer : 0x41 + CPU part : 0xd42 + +Which maps to (from arch/arm64/include/asm/cputype.h): + #define ARM_CPU_IMP_ARM 0x41 + #define ARM_CPU_PART_CORTEX_A78AE 0xD42 + +Fixes: a12cf5c339b08 ("arm64: tegra: Describe Tegra234 CPU hierarchy") +Signed-off-by: Sumit Gupta +Signed-off-by: Thierry Reding +Signed-off-by: Sasha Levin +--- + arch/arm64/boot/dts/nvidia/tegra234.dtsi | 24 ++++++++++++------------ + 1 file changed, 12 insertions(+), 12 deletions(-) + +diff --git a/arch/arm64/boot/dts/nvidia/tegra234.dtsi b/arch/arm64/boot/dts/nvidia/tegra234.dtsi +index 94eff4092b3858..482c913915a774 100644 +--- a/arch/arm64/boot/dts/nvidia/tegra234.dtsi ++++ b/arch/arm64/boot/dts/nvidia/tegra234.dtsi +@@ -2659,7 +2659,7 @@ cpus { + #size-cells = <0>; + + cpu0_0: cpu@0 { +- compatible = "arm,cortex-a78"; ++ compatible = "arm,cortex-a78ae"; + device_type = "cpu"; + reg = <0x00000>; + +@@ -2675,7 +2675,7 @@ cpu0_0: cpu@0 { + }; + + cpu0_1: cpu@100 { +- compatible = "arm,cortex-a78"; ++ compatible = "arm,cortex-a78ae"; + device_type = "cpu"; + reg = <0x00100>; + +@@ -2691,7 +2691,7 @@ cpu0_1: cpu@100 { + }; + + cpu0_2: cpu@200 { +- compatible = "arm,cortex-a78"; ++ compatible = "arm,cortex-a78ae"; + device_type = "cpu"; + reg = <0x00200>; + +@@ -2707,7 +2707,7 @@ cpu0_2: cpu@200 { + }; + + cpu0_3: cpu@300 { +- compatible = "arm,cortex-a78"; ++ compatible = "arm,cortex-a78ae"; + device_type = "cpu"; + reg = <0x00300>; + +@@ -2723,7 +2723,7 @@ cpu0_3: cpu@300 { + }; + + cpu1_0: cpu@10000 { +- compatible = "arm,cortex-a78"; ++ compatible = "arm,cortex-a78ae"; + device_type = "cpu"; + reg = <0x10000>; + +@@ -2739,7 +2739,7 @@ cpu1_0: cpu@10000 { + }; + + cpu1_1: cpu@10100 { +- compatible = "arm,cortex-a78"; ++ compatible = "arm,cortex-a78ae"; + device_type = "cpu"; + reg = <0x10100>; + +@@ -2755,7 +2755,7 @@ cpu1_1: cpu@10100 { + }; + + cpu1_2: cpu@10200 { +- compatible = "arm,cortex-a78"; ++ compatible = "arm,cortex-a78ae"; + device_type = "cpu"; + reg = <0x10200>; + +@@ -2771,7 +2771,7 @@ cpu1_2: cpu@10200 { + }; + + cpu1_3: cpu@10300 { +- compatible = "arm,cortex-a78"; ++ compatible = "arm,cortex-a78ae"; + device_type = "cpu"; + reg = <0x10300>; + +@@ -2787,7 +2787,7 @@ cpu1_3: cpu@10300 { + }; + + cpu2_0: cpu@20000 { +- compatible = "arm,cortex-a78"; ++ compatible = "arm,cortex-a78ae"; + device_type = "cpu"; + reg = <0x20000>; + +@@ -2803,7 +2803,7 @@ cpu2_0: cpu@20000 { + }; + + cpu2_1: cpu@20100 { +- compatible = "arm,cortex-a78"; ++ compatible = "arm,cortex-a78ae"; + device_type = "cpu"; + reg = <0x20100>; + +@@ -2819,7 +2819,7 @@ cpu2_1: cpu@20100 { + }; + + cpu2_2: cpu@20200 { +- compatible = "arm,cortex-a78"; ++ compatible = "arm,cortex-a78ae"; + device_type = "cpu"; + reg = <0x20200>; + +@@ -2835,7 +2835,7 @@ cpu2_2: cpu@20200 { + }; + + cpu2_3: cpu@20300 { +- compatible = "arm,cortex-a78"; ++ compatible = "arm,cortex-a78ae"; + device_type = "cpu"; + reg = <0x20300>; + +-- +2.53.0 + diff --git a/queue-6.1/asoc-amd-ps-fix-wrong-acp-version-string-in-pci_requ.patch b/queue-6.1/asoc-amd-ps-fix-wrong-acp-version-string-in-pci_requ.patch new file mode 100644 index 0000000000..7f714b7332 --- /dev/null +++ b/queue-6.1/asoc-amd-ps-fix-wrong-acp-version-string-in-pci_requ.patch @@ -0,0 +1,39 @@ +From 7db6b1576907631e48748371066c37e0ab6fded4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 7 Jul 2026 11:29:37 +0530 +Subject: ASoC: amd: ps: fix wrong ACP version string in pci_request_regions() + +From: Vijendar Mukunda + +[ Upstream commit f7697ecf6eab9d4887dd731038b3dc405c7e755e ] + +The driver handles ACP6.3/7.0/7.1/7.2 platforms but the region was +claimed with the stale name "AMD ACP6.2 audio" left over from the +original ACP6.2 driver. Correct it to "AMD ACP6.3 audio". + +Fixes: 95e43a170bb1 ("ASoC: amd: add Pink Sardine ACP PCI driver") +Signed-off-by: Vijendar Mukunda +Reviewed-by: Mario Limonciello (AMD) +Link: https://patch.msgid.link/20260707060130.2514138-3-Vijendar.Mukunda@amd.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/amd/ps/pci-ps.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/sound/soc/amd/ps/pci-ps.c b/sound/soc/amd/ps/pci-ps.c +index 7c9751a7eedc22..c3bce6ed090d79 100644 +--- a/sound/soc/amd/ps/pci-ps.c ++++ b/sound/soc/amd/ps/pci-ps.c +@@ -163,7 +163,7 @@ static int snd_acp63_probe(struct pci_dev *pci, + return -ENODEV; + } + +- ret = pci_request_regions(pci, "AMD ACP6.2 audio"); ++ ret = pci_request_regions(pci, "AMD ACP6.3 audio"); + if (ret < 0) { + dev_err(&pci->dev, "pci_request_regions failed\n"); + goto disable_pci; +-- +2.53.0 + diff --git a/queue-6.1/asoc-meson-aiu-fifo-spdif-soft-reset-the-s-pdif-data.patch b/queue-6.1/asoc-meson-aiu-fifo-spdif-soft-reset-the-s-pdif-data.patch new file mode 100644 index 0000000000..be9a09f595 --- /dev/null +++ b/queue-6.1/asoc-meson-aiu-fifo-spdif-soft-reset-the-s-pdif-data.patch @@ -0,0 +1,64 @@ +From c7891d128642aa1742780f269437f299970b2a06 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 27 Jun 2026 13:12:05 +0000 +Subject: ASoC: meson: aiu: fifo-spdif: soft reset the S/PDIF datapath on + start/stop + +From: Christian Hewitt + +[ Upstream commit 6b59c53c8adc2b522327407af5e1793a65b67e4b ] + +The I2S FIFO soft-resets its fast domain on start (AIU_RST_SOFT bit 0 + +AIU_I2S_SYNC read in aiu_fifo_i2s_trigger), mirroring the downstream +vendor driver's audio_out_i2s_enable(). The S/PDIF FIFO has no equivalent: +it only toggles the IEC958 DCU, so a stale datapath FIFO can be replayed, +producing the "machine gun noise" buffer underrun - on start when switching +outputs, and on stop when playback ends. The latter is audible on devices +with an always-on S/PDIF-fed DAC (e.g. the ES7144 on the WeTek Play2). + +The vendor driver resets the IEC958 fast domain (AIU_RST_SOFT bit 2) on +both enable and disable (audio_hw_958_enable), and when reconfiguring +(audio_hw_958_reset clears AIU_958_DCU_FF_CTRL then resets). Do the same: +reset before enabling the DCU on start, and before disabling on stop. + +Fixes: 6ae9ca9ce986bf ("ASoC: meson: aiu: add i2s and spdif support") +Signed-off-by: Christian Hewitt +Reviewed-by: Martin Blumenstingl +Link: https://patch.msgid.link/20260627131205.808800-1-christianshewitt@gmail.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/meson/aiu-fifo-spdif.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/sound/soc/meson/aiu-fifo-spdif.c b/sound/soc/meson/aiu-fifo-spdif.c +index 2fb30f89bf7a2c..515310e8eae79b 100644 +--- a/sound/soc/meson/aiu-fifo-spdif.c ++++ b/sound/soc/meson/aiu-fifo-spdif.c +@@ -24,6 +24,7 @@ + #define AIU_MEM_IEC958_CONTROL_MODE_16BIT BIT(7) + #define AIU_MEM_IEC958_CONTROL_MODE_LINEAR BIT(8) + #define AIU_MEM_IEC958_BUF_CNTL_INIT BIT(0) ++#define AIU_RST_SOFT_958_FAST BIT(2) + + #define AIU_FIFO_SPDIF_BLOCK 8 + +@@ -68,11 +69,15 @@ static int fifo_spdif_trigger(struct snd_pcm_substream *substream, int cmd, + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: ++ snd_soc_component_write(component, AIU_RST_SOFT, ++ AIU_RST_SOFT_958_FAST); + fifo_spdif_dcu_enable(component, true); + break; + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + case SNDRV_PCM_TRIGGER_STOP: ++ snd_soc_component_write(component, AIU_RST_SOFT, ++ AIU_RST_SOFT_958_FAST); + fifo_spdif_dcu_enable(component, false); + break; + default: +-- +2.53.0 + diff --git a/queue-6.1/asoc-tas2562-fix-deprecated-shut-down-gpio-always-cl.patch b/queue-6.1/asoc-tas2562-fix-deprecated-shut-down-gpio-always-cl.patch new file mode 100644 index 0000000000..216a234e2e --- /dev/null +++ b/queue-6.1/asoc-tas2562-fix-deprecated-shut-down-gpio-always-cl.patch @@ -0,0 +1,62 @@ +From d604d47177e31a03852c687faa3831f816bb1cff Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 6 Jul 2026 21:01:09 +0530 +Subject: ASoC: tas2562: fix deprecated 'shut-down' GPIO always cleared after + lookup + +From: Uday Khare + +[ Upstream commit 3238c634725afbb2a137fdda762208510828f71d ] + +In tas2562_parse_dt(), the fallback lookup for the deprecated +"shut-down" GPIO property is broken due to a missing pair of braces. + +The code intends to reset sdz_gpio to NULL only when the lookup +returns an error that is not -EPROBE_DEFER (so the driver gracefully +continues without a GPIO). However, without braces the statement: + + tas2562->sdz_gpio = NULL; + +falls outside the IS_ERR() check and is executed unconditionally +for every path through the if block, including a successful GPIO +lookup. + +This means any device using the deprecated 'shut-down' DT property +will always have sdz_gpio == NULL after probe, making the GPIO +completely non-functional. + +Fix this by adding the missing braces to scope the NULL assignment +inside the IS_ERR() branch, matching the pattern already used for +the primary 'shutdown' GPIO lookup above. + +Fixes: f78a97003b8b ("ASoC: tas2562: Update shutdown GPIO property") +Signed-off-by: Uday Khare +Link: https://patch.msgid.link/20260706153109.10953-1-udaykhare77@gmail.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/codecs/tas2562.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/sound/soc/codecs/tas2562.c b/sound/soc/codecs/tas2562.c +index b486d0bd86c991..6d06b95f1c0137 100644 +--- a/sound/soc/codecs/tas2562.c ++++ b/sound/soc/codecs/tas2562.c +@@ -685,11 +685,12 @@ static int tas2562_parse_dt(struct tas2562_data *tas2562) + if (tas2562->sdz_gpio == NULL) { + tas2562->sdz_gpio = devm_gpiod_get_optional(dev, "shut-down", + GPIOD_OUT_HIGH); +- if (IS_ERR(tas2562->sdz_gpio)) ++ if (IS_ERR(tas2562->sdz_gpio)) { + if (PTR_ERR(tas2562->sdz_gpio) == -EPROBE_DEFER) + return -EPROBE_DEFER; + +- tas2562->sdz_gpio = NULL; ++ tas2562->sdz_gpio = NULL; ++ } + } + + if (tas2562->model_id == TAS2110) +-- +2.53.0 + diff --git a/queue-6.1/ata-sata_dwc_460ex-enable-sata-interrupts-only-after.patch b/queue-6.1/ata-sata_dwc_460ex-enable-sata-interrupts-only-after.patch new file mode 100644 index 0000000000..cab86147dd --- /dev/null +++ b/queue-6.1/ata-sata_dwc_460ex-enable-sata-interrupts-only-after.patch @@ -0,0 +1,56 @@ +From 587bcf2ab5794cdf57a1160cade84591c1ea6f94 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 12 Jul 2026 14:37:26 -0700 +Subject: ata: sata_dwc_460ex: enable SATA interrupts only after IRQ handler is + registered + +From: Rosen Penev + +[ Upstream commit 4bbc16a353a98023e5ddfca7c1fc0e49971cf4d0 ] + +sata_dwc_enable_interrupts() is called before platform_get_irq() and +ata_host_activate(), leaving the SATA controller's interrupt mask +enabled without a registered handler. If a later step fails (irq +request, phy init, etc.) or if the controller asserts an interrupt +during probe, the irq line may fire with no handler, causing a +spurious interrupt storm. + +Move sata_dwc_enable_interrupts() after ata_host_activate() so that +interrupts are only unmasked once the handler is registered and the +core is fully initialized. + +Fixes: 62936009f35a ("[libata] Add 460EX on-chip SATA driver, sata_dwc_460ex") +Assisted-by: opencode:big-pickle +Signed-off-by: Rosen Penev +Signed-off-by: Damien Le Moal +Signed-off-by: Sasha Levin +--- + drivers/ata/sata_dwc_460ex.c | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c +index e3263e961045ac..9a4e12a09910a0 100644 +--- a/drivers/ata/sata_dwc_460ex.c ++++ b/drivers/ata/sata_dwc_460ex.c +@@ -1175,9 +1175,6 @@ static int sata_dwc_probe(struct platform_device *ofdev) + /* Save dev for later use in dev_xxx() routines */ + hsdev->dev = dev; + +- /* Enable SATA Interrupts */ +- sata_dwc_enable_interrupts(hsdev); +- + /* Get SATA interrupt number */ + irq = irq_of_parse_and_map(np, 0); + if (irq == NO_IRQ) { +@@ -1210,6 +1207,8 @@ static int sata_dwc_probe(struct platform_device *ofdev) + if (err) + dev_err(dev, "failed to activate host"); + ++ /* Enable SATA Interrupts */ ++ sata_dwc_enable_interrupts(hsdev); + return 0; + + error_out: +-- +2.53.0 + diff --git a/queue-6.1/ata-sata_dwc_460ex-fix-clear_interrupt_bit-clearing-.patch b/queue-6.1/ata-sata_dwc_460ex-fix-clear_interrupt_bit-clearing-.patch new file mode 100644 index 0000000000..bc8ab31216 --- /dev/null +++ b/queue-6.1/ata-sata_dwc_460ex-fix-clear_interrupt_bit-clearing-.patch @@ -0,0 +1,45 @@ +From 48f7628c1fb9d8d3e6b2c5ea9c52750fb5ae15a2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 12 Jul 2026 14:37:27 -0700 +Subject: ata: sata_dwc_460ex: fix clear_interrupt_bit() clearing all pending + interrupts + +From: Rosen Penev + +[ Upstream commit 66c4e310ad71f41e41736d33dd8a1fb5eaaec7f3 ] + +clear_interrupt_bit() ignores the bit argument and performs a +read-write-back of the entire INTPR register. If INTPR uses standard +Write-1-to-Clear semantics, this clears every pending interrupt bit, +not just the intended one. Coalesced interrupts (e.g. DMAT + NEWFP) +would be cleared together, silently losing the second event. + +Write only the specific bit to clear so that other pending interrupts +are preserved. + +Fixes: 62936009f35a ("[libata] Add 460EX on-chip SATA driver, sata_dwc_460ex") +Assisted-by: opencode:big-pickle +Signed-off-by: Rosen Penev +Signed-off-by: Damien Le Moal +Signed-off-by: Sasha Levin +--- + drivers/ata/sata_dwc_460ex.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c +index 9a4e12a09910a0..24bc1b755dc748 100644 +--- a/drivers/ata/sata_dwc_460ex.c ++++ b/drivers/ata/sata_dwc_460ex.c +@@ -403,8 +403,7 @@ static void clear_serror(struct ata_port *ap) + + static void clear_interrupt_bit(struct sata_dwc_device *hsdev, u32 bit) + { +- sata_dwc_writel(&hsdev->sata_dwc_regs->intpr, +- sata_dwc_readl(&hsdev->sata_dwc_regs->intpr)); ++ sata_dwc_writel(&hsdev->sata_dwc_regs->intpr, bit); + } + + static u32 qcmd_tag_to_mask(u8 tag) +-- +2.53.0 + diff --git a/queue-6.1/bluetooth-qca-fix-nvm-tag-length-underflow-in-tlv-pa.patch b/queue-6.1/bluetooth-qca-fix-nvm-tag-length-underflow-in-tlv-pa.patch new file mode 100644 index 0000000000..c969d37c74 --- /dev/null +++ b/queue-6.1/bluetooth-qca-fix-nvm-tag-length-underflow-in-tlv-pa.patch @@ -0,0 +1,68 @@ +From e219400ee3cbc4cdc7987d2fbe4d9d393035a39d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 4 Jul 2026 16:10:30 -0700 +Subject: Bluetooth: qca: fix NVM tag length underflow in TLV parser + +From: Xiang Mei + +[ Upstream commit c90164ca0f7036942ba088eb7ea8d3f6c2352020 ] + +In the TLV_TYPE_NVM branch of qca_tlv_check_data() the tag loop bound is +"while (idx < length - sizeof(struct tlv_type_nvm))". "length" is a signed +int from the firmware TLV header and sizeof(struct tlv_type_nvm) is a +size_t (12), so "length" is converted to size_t and any firmware-supplied +"length" < 12 makes the subtraction wrap to a huge value. The loop body +then reads a 12-byte struct tlv_type_nvm past the end of the short +vmalloc'd firmware buffer (and the EDL_TAG_ID_* handlers can write past it). + +Rewrite the bound as "idx + sizeof(struct tlv_type_nvm) <= length"; both +operands are non-negative, so it no longer underflows and a "length" too +small for one record correctly skips the loop. + + BUG: KASAN: vmalloc-out-of-bounds in qca_download_firmware.isra.0 (drivers/bluetooth/btqca.c:421) + Read of size 2 at addr ffffc900000e5004 by task kworker/u9:0/52 + Workqueue: hci0 hci_power_on + Call Trace: + ... + kasan_report (mm/kasan/report.c:595) + qca_download_firmware.isra.0 (drivers/bluetooth/btqca.c:421 drivers/bluetooth/btqca.c:617) + qca_uart_setup (drivers/bluetooth/btqca.c:948) + qca_setup (drivers/bluetooth/hci_qca.c:2029) + hci_uart_setup (drivers/bluetooth/hci_ldisc.c:438) + hci_dev_open_sync (net/bluetooth/hci_sync.c:5227) + hci_power_on (net/bluetooth/hci_core.c:920) + process_one_work (kernel/workqueue.c:3322) + worker_thread (kernel/workqueue.c:3486) + kthread (kernel/kthread.c:436) + ret_from_fork (arch/x86/kernel/process.c:158) + ret_from_fork_asm (arch/x86/entry/entry_64.S:245) + +Fixes: 2e4edfa1e2bd ("Bluetooth: qca: add missing firmware sanity checks") +Reported-by: Weiming Shi +Assisted-by: Claude:claude-opus-4-8 +Signed-off-by: Xiang Mei +Reported-by: Weiming Shi +Reviewed-by: Johan Hovold +Acked-by: Bartosz Golaszewski +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + drivers/bluetooth/btqca.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/bluetooth/btqca.c b/drivers/bluetooth/btqca.c +index 5b34da23adce7c..09ef7df5c231bf 100644 +--- a/drivers/bluetooth/btqca.c ++++ b/drivers/bluetooth/btqca.c +@@ -430,7 +430,7 @@ static int qca_tlv_check_data(struct hci_dev *hdev, + + idx = 0; + data = tlv->data; +- while (idx < length - sizeof(struct tlv_type_nvm)) { ++ while (idx + sizeof(struct tlv_type_nvm) <= length) { + tlv_nvm = (struct tlv_type_nvm *)(data + idx); + + tag_id = le16_to_cpu(tlv_nvm->tag_id); +-- +2.53.0 + diff --git a/queue-6.1/bpf-sockmap-reject-unhashed-udp-sockets-on-sockmap-u.patch b/queue-6.1/bpf-sockmap-reject-unhashed-udp-sockets-on-sockmap-u.patch new file mode 100644 index 0000000000..ca1b202c42 --- /dev/null +++ b/queue-6.1/bpf-sockmap-reject-unhashed-udp-sockets-on-sockmap-u.patch @@ -0,0 +1,74 @@ +From e9664e5cf4e8179fa9d5b0cc5f2694966c20ac9e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 7 Jul 2026 06:23:57 +0200 +Subject: bpf, sockmap: Reject unhashed UDP sockets on sockmap update + +From: Michal Luczaj + +[ Upstream commit 66efd3368ae10d05e08fbe6425b50fdec7186ac7 ] + +UDP sockets get SOCK_RCU_FREE set when (auto-)bound. This means +sk_is_refcounted(unbound) = true, while sk_is_refcounted(bound) = false. + +Because sockmap accepts unbound UDP sockets, a BPF program can increment a +socket's refcount via lookup. If the socket is subsequently bound, the +transition from unbound to bound causes bpf_sk_release() to skip the +decrement of the refcount, causing a memory leak. + +unreferenced object 0xffff88810bc2eb40 (size 1984): + comm "test_progs", pid 2451, jiffies 4295320596 + hex dump (first 32 bytes): + 7f 00 00 01 7f 00 00 01 d2 04 1b b7 04 d2 00 00 ................ + 02 00 01 40 00 00 00 00 00 00 00 00 00 00 00 00 ...@............ + backtrace (crc bdee079d): + kmem_cache_alloc_noprof+0x557/0x660 + sk_prot_alloc+0x69/0x240 + sk_alloc+0x30/0x460 + inet_create+0x2ce/0xf80 + __sock_create+0x25b/0x5c0 + __sys_socket+0x119/0x1d0 + __x64_sys_socket+0x72/0xd0 + do_syscall_64+0xa1/0x5f0 + entry_SYSCALL_64_after_hwframe+0x76/0x7e + +Instead of special-casing for refcounted sockets, reject unhashed UDP +sockets during sockmap updates, as there is no benefit to supporting those. +This effectively reverts the commit under Fixes, with two exceptions: + +1. sock_map_sk_state_allowed() maintains a fall-through `return true`. +2. In the spirit of commit b8b8315e39ff ("bpf, sockmap: Remove unhash + handler for BPF sockmap usage"), the proto::unhash BPF handler is not + reintroduced. + +Historical note: this issue is related to commit 67312adc96b5 ("bpf: reject +unhashed sockets in bpf_sk_assign"). + +Fixes: 0c48eefae712 ("sock_map: Lift socket state restriction for datagram sockets") +Suggested-by: Kuniyuki Iwashima +Signed-off-by: Michal Luczaj +Reviewed-by: Kuniyuki Iwashima +Reviewed-by: Jakub Sitnicki +Reviewed-by: John Fastabend +Link: https://lore.kernel.org/bpf/20260707-sockmap-lookup-udp-leak-v4-2-f878346f27ab@rbox.co +Signed-off-by: Kumar Kartikeya Dwivedi +Signed-off-by: Sasha Levin +--- + net/core/sock_map.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/net/core/sock_map.c b/net/core/sock_map.c +index f4cca477b0477e..fb10c33acc3fd2 100644 +--- a/net/core/sock_map.c ++++ b/net/core/sock_map.c +@@ -542,6 +542,8 @@ static bool sock_map_sk_state_allowed(const struct sock *sk) + { + if (sk_is_tcp(sk)) + return (1 << sk->sk_state) & (TCPF_ESTABLISHED | TCPF_LISTEN); ++ if (sk_is_udp(sk)) ++ return sk_hashed(sk); + if (sk_is_stream_unix(sk)) + return (1 << sk->sk_state) & TCPF_ESTABLISHED; + return true; +-- +2.53.0 + diff --git a/queue-6.1/btrfs-fix-root-leak-if-its-reloc-root-is-unexpected-.patch b/queue-6.1/btrfs-fix-root-leak-if-its-reloc-root-is-unexpected-.patch new file mode 100644 index 0000000000..43cf69b124 --- /dev/null +++ b/queue-6.1/btrfs-fix-root-leak-if-its-reloc-root-is-unexpected-.patch @@ -0,0 +1,40 @@ +From 7962d2f088268099193e209f504e4f9826943bc5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 11 Jun 2026 15:16:21 +0100 +Subject: btrfs: fix root leak if its reloc root is unexpected in + merge_reloc_roots() + +From: Filipe Manana + +[ Upstream commit ce6050bafb4e33377dc17fcc357736bfc351180c ] + +If we have an unexpected reloc_root for our root, we jump to the out label +but never drop the reference we obtained for root, resulting in a leak. +Add a missing btrfs_put_root() call. + +Fixes: 24213fa46c70 ("btrfs: do proper error handling in merge_reloc_roots") +Reviewed-by: Qu Wenruo +Reviewed-by: Johannes Thumshirn +Signed-off-by: Filipe Manana +Reviewed-by: David Sterba +Signed-off-by: David Sterba +Signed-off-by: Sasha Levin +--- + fs/btrfs/relocation.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c +index 93916c52b50e94..2e66a0672ba7fa 100644 +--- a/fs/btrfs/relocation.c ++++ b/fs/btrfs/relocation.c +@@ -2045,6 +2045,7 @@ void merge_reloc_roots(struct reloc_control *rc) + * corruption, e.g. bad reloc tree key offset. + */ + ret = -EINVAL; ++ btrfs_put_root(root); + goto out; + } + ret = merge_reloc_root(rc, root); +-- +2.53.0 + diff --git a/queue-6.1/btrfs-reject-free-space-cache-with-more-entries-than.patch b/queue-6.1/btrfs-reject-free-space-cache-with-more-entries-than.patch new file mode 100644 index 0000000000..0ba93dd528 --- /dev/null +++ b/queue-6.1/btrfs-reject-free-space-cache-with-more-entries-than.patch @@ -0,0 +1,88 @@ +From 0cf7f7b6a19ecec33e12999d4efa095149bc7c87 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 10 Jun 2026 10:29:26 -0700 +Subject: btrfs: reject free space cache with more entries than pages + +From: Xiang Mei + +[ Upstream commit a2d8d5647ed854e38f941741aea45b9eb15a6350 ] + +When loading a v1 free space cache, __load_free_space_cache() takes +num_entries and num_bitmaps straight from the on-disk +btrfs_free_space_header. That header is stored in the tree_root under a key +with type 0, which the tree-checker has no case for, so neither count is +validated before the load trusts it. + +The load loops num_entries times and maps the next page whenever the current +one runs out, going through io_ctl_check_crc() -> io_ctl_map_page(), which +does io_ctl->pages[io_ctl->index++]. But pages[] is allocated in +io_ctl_init() from the cache inode's i_size, not from num_entries: + + num_pages = DIV_ROUND_UP(i_size_read(inode), PAGE_SIZE); + io_ctl->pages = kcalloc(num_pages, sizeof(struct page *), GFP_NOFS); + +So if num_entries claims more records than the pages can hold, io_ctl->index +runs off the end of pages[]. The write side never hits this because +io_ctl_add_entry() and io_ctl_add_bitmap() both stop once +io_ctl->index >= io_ctl->num_pages; the read side just never had the same +check. + +To trigger it, take a clean cache (num_entries = here), set num_entries +in the header to 0x10000, and fix up the leaf checksum so it still passes +the tree-checker. The cache inode has i_size = 65536, so num_pages is 16 and +pages[] is a 16-pointer (kmalloc-128) array. The load now tries to read +65536 entries, io_ctl->index walks up to 16, and pages[16] is read past the +array: + + BUG: KASAN: slab-out-of-bounds in io_ctl_check_crc (fs/btrfs/free-space-cache.c:420 fs/btrfs/free-space-cache.c:565) + Read of size 8 at addr ffff88800c833a80 by task kworker/u8:3/58 + io_ctl_check_crc (fs/btrfs/free-space-cache.c:420 fs/btrfs/free-space-cache.c:565) + __load_free_space_cache (fs/btrfs/free-space-cache.c:655 fs/btrfs/free-space-cache.c:820) + load_free_space_cache (fs/btrfs/free-space-cache.c:1017) + caching_thread (fs/btrfs/block-group.c:880) + btrfs_work_helper (fs/btrfs/async-thread.c:312) + process_one_work + worker_thread + kthread + ret_from_fork + +free-space-cache.c:420 is io_ctl_map_page(), inlined into io_ctl_check_crc() +at line 565, which is why that is the frame KASAN names. The out-of-bounds +slot is then treated as a struct page and handed to crc32c(), so the bad +read turns into a GP fault. + +Add the missing check to io_ctl_check_crc(), which is where both the entry +loop and the bitmap loop end up. When num_entries is too large the load now +fails like any corrupt cache: __load_free_space_cache() drops it and rebuilds +the free space from the extent tree, so a valid cache is never rejected. + +Reported-by: Weiming Shi +Fixes: 5b0e95bf607d ("Btrfs: inline checksums into the disk free space cache") +Link: https://lore.kernel.org/linux-btrfs/CAPpSM+RMPByMCKXvM5QFKToxsyNccfuFLWMdD0mfd0wh2Ja62w@mail.gmail.com/ +Assisted-by: Claude:claude-opus-4-8 +Reviewed-by: Qu Wenruo +Signed-off-by: Xiang Mei +Reviewed-by: David Sterba +Signed-off-by: David Sterba +Signed-off-by: Sasha Levin +--- + fs/btrfs/free-space-cache.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c +index 9f4dae426037b8..92933cc5596e0f 100644 +--- a/fs/btrfs/free-space-cache.c ++++ b/fs/btrfs/free-space-cache.c +@@ -569,6 +569,9 @@ static int io_ctl_check_crc(struct btrfs_io_ctl *io_ctl, int index) + u32 crc = ~(u32)0; + unsigned offset = 0; + ++ if (index >= io_ctl->num_pages) ++ return -EIO; ++ + if (index == 0) + offset = sizeof(u32) * io_ctl->num_pages; + +-- +2.53.0 + diff --git a/queue-6.1/can-j1939-fix-lockless-local-destination-check.patch b/queue-6.1/can-j1939-fix-lockless-local-destination-check.patch new file mode 100644 index 0000000000..d3cf068d2e --- /dev/null +++ b/queue-6.1/can-j1939-fix-lockless-local-destination-check.patch @@ -0,0 +1,81 @@ +From 14850ce9d691043eab86c76cf646d5fc424e8a0d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 7 May 2026 10:22:26 +0200 +Subject: can: j1939: fix lockless local-destination check + +From: Shuhao Fu + +[ Upstream commit e4e8af62adab2fdcca230006f829407a953070cd ] + +j1939_priv.ents[].nusers is documented as protected by priv->lock, and +its updates already happen under that lock. j1939_can_recv() also reads +it under read_lock_bh(). However, j1939_session_skb_queue() and +j1939_tp_send() still read priv->ents[da].nusers without taking the +lock. + +Those transport-side checks decide whether to set J1939_ECU_LOCAL_DST, so +they can race with j1939_local_ecu_get() and j1939_local_ecu_put() while +userspace is binding or releasing sockets concurrently with TP traffic. +This can misclassify TP/ETP sessions as local or remote and take the wrong +transport path. + +Fix both transport paths by routing the destination-locality check through +a helper that reads ents[].nusers under read_lock_bh(&priv->lock). + +Fixes: 9d71dd0c7009 ("can: add support of SAE J1939 protocol") +Signed-off-by: Shuhao Fu +Tested-by: Oleksij Rempel +Acked-by: Oleksij Rempel +Link: https://patch.msgid.link/20260419140614.GA4041240@chcpu16 +Signed-off-by: Marc Kleine-Budde +Signed-off-by: Sasha Levin +--- + net/can/j1939/transport.c | 18 ++++++++++++++---- + 1 file changed, 14 insertions(+), 4 deletions(-) + +diff --git a/net/can/j1939/transport.c b/net/can/j1939/transport.c +index e17a166a73c422..57d7b14c3949e6 100644 +--- a/net/can/j1939/transport.c ++++ b/net/can/j1939/transport.c +@@ -350,6 +350,18 @@ static void j1939_session_skb_drop_old(struct j1939_session *session) + } + } + ++static bool j1939_address_is_local(struct j1939_priv *priv, u8 addr) ++{ ++ bool local = false; ++ ++ read_lock_bh(&priv->lock); ++ if (j1939_address_is_unicast(addr) && priv->ents[addr].nusers) ++ local = true; ++ read_unlock_bh(&priv->lock); ++ ++ return local; ++} ++ + void j1939_session_skb_queue(struct j1939_session *session, + struct sk_buff *skb) + { +@@ -358,8 +370,7 @@ void j1939_session_skb_queue(struct j1939_session *session, + + j1939_ac_fixup(priv, skb); + +- if (j1939_address_is_unicast(skcb->addr.da) && +- priv->ents[skcb->addr.da].nusers) ++ if (j1939_address_is_local(priv, skcb->addr.da)) + skcb->flags |= J1939_ECU_LOCAL_DST; + + skcb->flags |= J1939_ECU_LOCAL_SRC; +@@ -2021,8 +2032,7 @@ struct j1939_session *j1939_tp_send(struct j1939_priv *priv, + return ERR_PTR(ret); + + /* fix DST flags, it may be used there soon */ +- if (j1939_address_is_unicast(skcb->addr.da) && +- priv->ents[skcb->addr.da].nusers) ++ if (j1939_address_is_local(priv, skcb->addr.da)) + skcb->flags |= J1939_ECU_LOCAL_DST; + + /* src is always local, I'm sending ... */ +-- +2.53.0 + diff --git a/queue-6.1/drm-i915-gt-use-correct-selftest-config-symbol.patch b/queue-6.1/drm-i915-gt-use-correct-selftest-config-symbol.patch new file mode 100644 index 0000000000..22cf3e2ad6 --- /dev/null +++ b/queue-6.1/drm-i915-gt-use-correct-selftest-config-symbol.patch @@ -0,0 +1,50 @@ +From 5695916a7d687c5725754768756b090421429056 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 5 Jul 2026 16:02:25 +0800 +Subject: drm/i915/gt: use correct selftest config symbol + +From: Pengpeng Hou + +[ Upstream commit a82f1bb8191aec98a971a2196136016ef70c0880 ] + +intel_engine_user.c checks CONFIG_DRM_I915_SELFTESTS before running +the engine UABI isolation check. Kconfig defines DRM_I915_SELFTEST, +without the trailing "S", and the rest of i915 uses +CONFIG_DRM_I915_SELFTEST. + +Because CONFIG_DRM_I915_SELFTESTS is not backed by any Kconfig symbol, +the IS_ENABLED() test is always false. Use the existing selftest symbol +so the debug/selftest guarded path can be reached when selftests are +enabled. + +This is a source-level fix. It does not claim dynamic hardware +reproduction; the evidence is the Kconfig definition and the inconsistent +guard in intel_engine_user.c. + +Fixes: 750e76b4f9f6 ("drm/i915/gt: Move the [class][inst] lookup for engines onto the GT") +Signed-off-by: Pengpeng Hou +Signed-off-by: Tvrtko Ursulin +Link: https://lore.kernel.org/r/20260705080225.436-1-pengpeng@iscas.ac.cn +(cherry picked from commit 14a2012a490258f3f93857bc4f1b203405964be7) +Signed-off-by: Rodrigo Vivi +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/i915/gt/intel_engine_user.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/i915/gt/intel_engine_user.c b/drivers/gpu/drm/i915/gt/intel_engine_user.c +index 46a174f8aa0076..9a4309c30f0ea8 100644 +--- a/drivers/gpu/drm/i915/gt/intel_engine_user.c ++++ b/drivers/gpu/drm/i915/gt/intel_engine_user.c +@@ -239,7 +239,7 @@ void intel_engines_driver_register(struct drm_i915_private *i915) + p = &prev->rb_right; + } + +- if (IS_ENABLED(CONFIG_DRM_I915_SELFTESTS) && ++ if (IS_ENABLED(CONFIG_DRM_I915_SELFTEST) && + IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM)) { + struct intel_engine_cs *engine; + unsigned int isolation; +-- +2.53.0 + diff --git a/queue-6.1/drm-i915-selftests-fix-gt-pm-sort-comparators.patch b/queue-6.1/drm-i915-selftests-fix-gt-pm-sort-comparators.patch new file mode 100644 index 0000000000..9428f41b94 --- /dev/null +++ b/queue-6.1/drm-i915-selftests-fix-gt-pm-sort-comparators.patch @@ -0,0 +1,55 @@ +From 75dd696fac1da0e256d60eba88f02aff487a693d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 15 Jul 2026 01:04:30 +0300 +Subject: drm/i915/selftests: Fix GT PM sort comparators + +From: Emre Cecanpunar + +[ Upstream commit 612978b83f45bf7018815209db5395d759db6f26 ] + +Compare the sampled clock values instead of their addresses. Comparing +addresses leaves the samples unsorted, preventing the code from discarding +the minimum and maximum samples. + +Fixes: 1a5392479207 ("drm/i915/selftests: Measure CS_TIMESTAMP") +Signed-off-by: Emre Cecanpunar +Signed-off-by: Tvrtko Ursulin +Link: https://lore.kernel.org/r/20260714220430.238433-1-emreleno@gmail.com +(cherry picked from commit 682ea2d28d18bb06f9fc663cb5ab7e80dc0e606a) +Signed-off-by: Rodrigo Vivi +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/i915/gt/selftest_gt_pm.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/drivers/gpu/drm/i915/gt/selftest_gt_pm.c b/drivers/gpu/drm/i915/gt/selftest_gt_pm.c +index be94f863bdefff..0e237bcf324a83 100644 +--- a/drivers/gpu/drm/i915/gt/selftest_gt_pm.c ++++ b/drivers/gpu/drm/i915/gt/selftest_gt_pm.c +@@ -16,9 +16,9 @@ static int cmp_u64(const void *A, const void *B) + { + const u64 *a = A, *b = B; + +- if (a < b) ++ if (*a < *b) + return -1; +- else if (a > b) ++ else if (*a > *b) + return 1; + else + return 0; +@@ -28,9 +28,9 @@ static int cmp_u32(const void *A, const void *B) + { + const u32 *a = A, *b = B; + +- if (a < b) ++ if (*a < *b) + return -1; +- else if (a > b) ++ else if (*a > *b) + return 1; + else + return 0; +-- +2.53.0 + diff --git a/queue-6.1/firmware-arm_ffa-fix-null-dereference-in-ffa_partiti.patch b/queue-6.1/firmware-arm_ffa-fix-null-dereference-in-ffa_partiti.patch new file mode 100644 index 0000000000..8698ab3894 --- /dev/null +++ b/queue-6.1/firmware-arm_ffa-fix-null-dereference-in-ffa_partiti.patch @@ -0,0 +1,48 @@ +From dbab5f62aa6d73e51bb420dea0194795428286f9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 17 Jun 2026 16:35:00 -0700 +Subject: firmware: arm_ffa: Fix NULL dereference in ffa_partition_info_get() + +From: Unnathi Chalicheemala + +[ Upstream commit 8ae5f8e4836667fcaffdf2e3c6068b0a8b364dd8 ] + +ffa_partition_info_get() passes uuid_str directly to uuid_parse() +without a NULL check. When a caller passes NULL, uuid_parse() -> +__uuid_parse() -> uuid_is_valid() dereferences the pointer, causing +a kernel panic: + + | Unable to handle kernel NULL pointer dereference at virtual address + | 0000000000000040 + | pc : uuid_parse+0x40/0xac + | lr : ffa_partition_info_get+0x1c/0x94 [arm_ffa] + +Add a NULL guard before uuid_parse() so a NULL argument returns +-ENODEV instead of crashing. Callers are expected to always supply +a valid partition UUID, so NULL is not a supported input. + +Fixes: d0c0bce83122 ("firmware: arm_ffa: Setup in-kernel users of FFA partitions") +Signed-off-by: Unnathi Chalicheemala +Link: https://patch.msgid.link/20260617-ffa_partition_nullptr_fix-v2-1-bc801b4ce34c@oss.qualcomm.com +Signed-off-by: Sudeep Holla +Signed-off-by: Sasha Levin +--- + drivers/firmware/arm_ffa/driver.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/firmware/arm_ffa/driver.c b/drivers/firmware/arm_ffa/driver.c +index f7c72fcc9b5e32..67ab5698a14241 100644 +--- a/drivers/firmware/arm_ffa/driver.c ++++ b/drivers/firmware/arm_ffa/driver.c +@@ -655,7 +655,7 @@ static int ffa_partition_info_get(const char *uuid_str, + uuid_t uuid; + struct ffa_partition_info *pbuf; + +- if (uuid_parse(uuid_str, &uuid)) { ++ if (!uuid_str || uuid_parse(uuid_str, &uuid)) { + pr_err("invalid uuid (%s)\n", uuid_str); + return -ENODEV; + } +-- +2.53.0 + diff --git a/queue-6.1/firmware-arm_scmi-rate-limit-queue-full-warnings-in-.patch b/queue-6.1/firmware-arm_scmi-rate-limit-queue-full-warnings-in-.patch new file mode 100644 index 0000000000..3a724a05df --- /dev/null +++ b/queue-6.1/firmware-arm_scmi-rate-limit-queue-full-warnings-in-.patch @@ -0,0 +1,54 @@ +From 78d5e3beb2c0ad758c2a43e339a4d7d5c4f82aa7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 8 Jul 2026 12:53:39 +0530 +Subject: firmware: arm_scmi: Rate-limit queue-full warnings in IRQ context + +From: Pushpendra Singh + +[ Upstream commit a4447c0693830d5ecadd6e755cb7fdc55d86aacc ] + +The scmi_notify() function is called from interrupt context to queue +received notification events onto a per-protocol kfifo. When the kfifo +is full, it logs a warning via dev_warn() for every dropped event. + +Under conditions where the platform sends a burst of SCMI notifications +faster than the deferred worker can drain the queue, this results in a +flood of dev_warn() calls from IRQ context. Each call acquires the +console lock and may execute blocking console writes, causing the CPU +to be held in interrupt context for an extended period and leading to +observable system stalls. + +Fix this by switching to dev_warn_ratelimited() to limit the frequency +of log messages when the notification queue is full. This reduces +console overhead in interrupt context and prevents CPU stalls caused by +excessive logging, while still preserving diagnostic visibility. + +Fixes: bd31b249692e ("firmware: arm_scmi: Add notification dispatch and delivery") +Signed-off-by: Pushpendra Singh +Link: https://patch.msgid.link/20260708072339.3021140-1-pushpendra.singh@oss.qualcomm.com +Signed-off-by: Sudeep Holla +Signed-off-by: Sasha Levin +--- + drivers/firmware/arm_scmi/notify.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/firmware/arm_scmi/notify.c b/drivers/firmware/arm_scmi/notify.c +index 4782b115e6ec51..1bc715fe3968c3 100644 +--- a/drivers/firmware/arm_scmi/notify.c ++++ b/drivers/firmware/arm_scmi/notify.c +@@ -595,9 +595,9 @@ int scmi_notify(const struct scmi_handle *handle, u8 proto_id, u8 evt_id, + return -EINVAL; + } + if (kfifo_avail(&r_evt->proto->equeue.kfifo) < sizeof(eh) + len) { +- dev_warn(handle->dev, +- "queue full, dropping proto_id:%d evt_id:%d ts:%lld\n", +- proto_id, evt_id, ktime_to_ns(ts)); ++ dev_warn_ratelimited(handle->dev, ++ "queue full, dropping proto_id:%d evt_id:%d ts:%lld\n", ++ proto_id, evt_id, ktime_to_ns(ts)); + return -ENOMEM; + } + +-- +2.53.0 + diff --git a/queue-6.1/ib-mad-drop-unmatched-rmpp-responses-before-reassemb.patch b/queue-6.1/ib-mad-drop-unmatched-rmpp-responses-before-reassemb.patch new file mode 100644 index 0000000000..3f42cd7088 --- /dev/null +++ b/queue-6.1/ib-mad-drop-unmatched-rmpp-responses-before-reassemb.patch @@ -0,0 +1,90 @@ +From f591be8217686431d1d4bb63fd1c265a6b632572 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 6 Jun 2026 16:01:55 -0400 +Subject: IB/mad: Drop unmatched RMPP responses before reassembly + +From: Michael Bommarito + +[ Upstream commit d2e52d610b9b09694261632340b801a421e0b0c5 ] + +Kernel-handled RMPP receive processing starts reassembly for active +DATA responses before the response is matched to an outstanding send. +The normal match happens later, after ib_process_rmpp_recv_wc() has +either assembled a complete message or consumed the segment. + +That ordering lets an unsolicited response that routes to a kernel +RMPP agent by the high TID bits allocate or extend RMPP receive state +before the full TID and source address are checked against a real +request. A reordered burst can therefore reach the receive-side +insertion path even though the response would not match any send. + +For kernel-handled RMPP DATA responses, require the existing +ib_find_send_mad() match before entering RMPP reassembly. The matcher +already checks the full TID, management class and source address/GID +against the agent wait, backlog and in-flight send lists. If there is +no match, drop the response without creating RMPP state. + +This leaves the RMPP window behavior unchanged and only rejects +responses that have no corresponding request. + +Fixes: fa619a77046b ("[PATCH] IB: Add RMPP implementation") +Assisted-by: Codex:gpt-5-5-xhigh +Signed-off-by: Michael Bommarito +Link: https://patch.msgid.link/3170ff3bc389a930bb1641f2caa394a0b2241579.1780774907.git.michael.bommarito@gmail.com +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + drivers/infiniband/core/mad.c | 30 ++++++++++++++++++++++++++++++ + 1 file changed, 30 insertions(+) + +diff --git a/drivers/infiniband/core/mad.c b/drivers/infiniband/core/mad.c +index 242434c09e8d8f..bddb1c607aff62 100644 +--- a/drivers/infiniband/core/mad.c ++++ b/drivers/infiniband/core/mad.c +@@ -1778,6 +1778,24 @@ void ib_mark_mad_done(struct ib_mad_send_wr_private *mad_send_wr) + &mad_send_wr->mad_agent_priv->done_list); + } + ++static bool is_kernel_rmpp_data_response(struct ib_mad_agent_private *agent, ++ struct ib_mad_recv_wc *mad_recv_wc) ++{ ++ const struct ib_mad_hdr *mad_hdr = &mad_recv_wc->recv_buf.mad->mad_hdr; ++ struct ib_rmpp_mad *rmpp_mad; ++ ++ if (!ib_mad_kernel_rmpp_agent(&agent->agent) || ++ !ib_response_mad(mad_hdr) || ++ !ib_is_mad_class_rmpp(mad_hdr->mgmt_class)) ++ return false; ++ ++ rmpp_mad = (struct ib_rmpp_mad *)mad_recv_wc->recv_buf.mad; ++ ++ return (ib_get_rmpp_flags(&rmpp_mad->rmpp_hdr) & ++ IB_MGMT_RMPP_FLAG_ACTIVE) && ++ rmpp_mad->rmpp_hdr.rmpp_type == IB_MGMT_RMPP_TYPE_DATA; ++} ++ + static void ib_mad_complete_recv(struct ib_mad_agent_private *mad_agent_priv, + struct ib_mad_recv_wc *mad_recv_wc) + { +@@ -1796,6 +1814,18 @@ static void ib_mad_complete_recv(struct ib_mad_agent_private *mad_agent_priv, + } + + list_add(&mad_recv_wc->recv_buf.list, &mad_recv_wc->rmpp_list); ++ if (is_kernel_rmpp_data_response(mad_agent_priv, mad_recv_wc)) { ++ spin_lock_irqsave(&mad_agent_priv->lock, flags); ++ mad_send_wr = ib_find_send_mad(mad_agent_priv, mad_recv_wc); ++ spin_unlock_irqrestore(&mad_agent_priv->lock, flags); ++ ++ if (!mad_send_wr) { ++ ib_free_recv_mad(mad_recv_wc); ++ deref_mad_agent(mad_agent_priv); ++ return; ++ } ++ } ++ + if (ib_mad_kernel_rmpp_agent(&mad_agent_priv->agent)) { + mad_recv_wc = ib_process_rmpp_recv_wc(mad_agent_priv, + mad_recv_wc); +-- +2.53.0 + diff --git a/queue-6.1/ipv4-fib-free-fib_alias-with-kfree_rcu-on-insert-err.patch b/queue-6.1/ipv4-fib-free-fib_alias-with-kfree_rcu-on-insert-err.patch new file mode 100644 index 0000000000..9ad0267625 --- /dev/null +++ b/queue-6.1/ipv4-fib-free-fib_alias-with-kfree_rcu-on-insert-err.patch @@ -0,0 +1,67 @@ +From 9fa8f1ab21bfa271981598d1e0b4c0afc59ce457 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 4 Jul 2026 10:14:21 -0700 +Subject: ipv4: fib: free fib_alias with kfree_rcu() on insert error path + +From: Weiming Shi + +[ Upstream commit f2f152e94a67bc746afaf05a1b2702c195553112 ] + +fib_table_insert() publishes new_fa into the leaf's fa_list with +fib_insert_alias() before calling the fib entry notifiers. When a +notifier fails, the error path removes new_fa with fib_remove_alias() +(hlist_del_rcu) and frees it right away with kmem_cache_free(). + +fib_table_lookup() walks that list under rcu_read_lock() only, so a +concurrent lookup that already reached new_fa keeps reading it after the +free: + + BUG: KASAN: slab-use-after-free in fib_table_lookup (net/ipv4/fib_trie.c:1601) + Read of size 1 at addr ffff88810676d4eb by task exploit/297 + Call Trace: + fib_table_lookup (net/ipv4/fib_trie.c:1601) + ip_route_output_key_hash_rcu (net/ipv4/route.c:2814) + ip_route_output_key_hash (net/ipv4/route.c:2705) + __ip4_datagram_connect (net/ipv4/datagram.c:49) + udp_connect (net/ipv4/udp.c:2144) + __sys_connect (net/socket.c:2167) + __x64_sys_connect (net/socket.c:2173) + do_syscall_64 + entry_SYSCALL_64_after_hwframe + which belongs to the cache ip_fib_alias of size 56 + +Triggering the error path needs CAP_NET_ADMIN and a registered fib +notifier that can reject a route; a netdevsim device whose IPv4 FIB +resource is exhausted is enough. + +Free new_fa with alias_free_mem_rcu(), as fib_table_delete() already +does for a fib_alias removed from the trie. + +Fixes: a6c76c17df02 ("ipv4: Notify route after insertion to the routing table") +Reported-by: Xiang Mei +Assisted-by: Claude:claude-opus-4-8 +Signed-off-by: Weiming Shi +Reviewed-by: Ido Schimmel +Link: https://patch.msgid.link/20260704171421.1786806-1-bestswngs@gmail.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/ipv4/fib_trie.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c +index c9e1526e749b2b..53e7664eeb0a2a 100644 +--- a/net/ipv4/fib_trie.c ++++ b/net/ipv4/fib_trie.c +@@ -1390,7 +1390,7 @@ int fib_table_insert(struct net *net, struct fib_table *tb, + out_remove_new_fa: + fib_remove_alias(t, tp, l, new_fa); + out_free_new_fa: +- kmem_cache_free(fn_alias_kmem, new_fa); ++ alias_free_mem_rcu(new_fa); + out: + fib_release_info(fi); + err: +-- +2.53.0 + diff --git a/queue-6.1/ksmbd-validate-compound-request-size-before-reading-.patch b/queue-6.1/ksmbd-validate-compound-request-size-before-reading-.patch new file mode 100644 index 0000000000..2cdc03e88e --- /dev/null +++ b/queue-6.1/ksmbd-validate-compound-request-size-before-reading-.patch @@ -0,0 +1,69 @@ +From 456a879be5e489a2ed55ccc2663c285e16913e5d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 13 Jul 2026 21:55:10 +0000 +Subject: ksmbd: validate compound request size before reading StructureSize2 + +From: Xiang Mei (Microsoft) + +[ Upstream commit 15b38176fd1530372905c602fde51fe89ec8c877 ] + +When ksmbd validates a compound (chained) SMB2 request, +ksmbd_smb2_check_message() reads pdu->StructureSize2 without first +checking that the compound element is large enough to contain it. +StructureSize2 is a 2-byte field at offset 64 +(__SMB2_HEADER_STRUCTURE_SIZE) from the start of each element. + +The compound-walking logic only guarantees that a full 64-byte SMB2 +header is present for the trailing element: when NextCommand is 0, len is +reduced to the number of bytes remaining after next_smb2_rcv_hdr_off. A +remote client can craft a compound request whose last element has exactly +64 bytes, so the 2-byte StructureSize2 read at offset 64 extends one byte +past the receive buffer, producing a slab-out-of-bounds read. + + BUG: KASAN: slab-out-of-bounds in ksmbd_smb2_check_message (fs/smb/server/smb2misc.c:402) + Read of size 2 at addr ffff888012ae31ac by task kworker/0:1/14 + The buggy address is located 172 bytes inside of allocated 173-byte region + Workqueue: ksmbd-io handle_ksmbd_work + Call Trace: + ... + kasan_report (mm/kasan/report.c:595) + ksmbd_smb2_check_message (fs/smb/server/smb2misc.c:402) + handle_ksmbd_work (fs/smb/server/server.c:119) + process_one_work (kernel/workqueue.c:3314) + worker_thread (kernel/workqueue.c:3397) + kthread (kernel/kthread.c:436) + ret_from_fork (arch/x86/kernel/process.c:158) + ret_from_fork_asm (arch/x86/entry/entry_64.S:245) + +Reject any compound element that is too small to hold StructureSize2 +before dereferencing it. + +Fixes: e2f34481b24d ("cifsd: add server-side procedures for SMB3") +Reported-by: AutonomousCodeSecurity@microsoft.com +Signed-off-by: Xiang Mei (Microsoft) +Acked-by: Namjae Jeon +Signed-off-by: Steve French +Signed-off-by: Sasha Levin +--- + fs/smb/server/smb2misc.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/fs/smb/server/smb2misc.c b/fs/smb/server/smb2misc.c +index f257e096c8e17f..6a4f1b8a0b13c9 100644 +--- a/fs/smb/server/smb2misc.c ++++ b/fs/smb/server/smb2misc.c +@@ -400,6 +400,11 @@ int ksmbd_smb2_check_message(struct ksmbd_work *work) + return 1; + } + ++ if (len < __SMB2_HEADER_STRUCTURE_SIZE + sizeof(__le16)) { ++ ksmbd_debug(SMB, "Message is too small for StructureSize2\n"); ++ return 1; ++ } ++ + if (smb2_req_struct_sizes[command] != pdu->StructureSize2) { + if (!(command == SMB2_OPLOCK_BREAK_HE && + (le16_to_cpu(pdu->StructureSize2) == OP_BREAK_STRUCT_SIZE_20 || +-- +2.53.0 + diff --git a/queue-6.1/mpls-fix-null-deref-in-mpls_valid_fib_dump_req-on-co.patch b/queue-6.1/mpls-fix-null-deref-in-mpls_valid_fib_dump_req-on-co.patch new file mode 100644 index 0000000000..62da5b945c --- /dev/null +++ b/queue-6.1/mpls-fix-null-deref-in-mpls_valid_fib_dump_req-on-co.patch @@ -0,0 +1,68 @@ +From 6ad06387379fe0b56802bf04e9dc211a9c55a915 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 11 Jul 2026 04:50:00 -0700 +Subject: mpls: fix NULL deref in mpls_valid_fib_dump_req() on CONFIG_INET=n + +From: Weiming Shi + +[ Upstream commit 56d96fededd61192cd7cc8d2b0f36adfd59036c3 ] + +On CONFIG_INET=n builds, mpls_valid_fib_dump_req() walks the parsed +attribute table itself instead of calling ip_valid_fib_dump_req(). The +RTA_OIF arm passes tb[RTA_OIF] to nla_get_u32() without checking it is +present, so an RTM_GETROUTE dump for AF_MPLS with strict checking and no +RTA_OIF hits a NULL dereference. + +RTM_GETROUTE is RTNL_KIND_GET, which rtnetlink_rcv_msg() permits without +CAP_NET_ADMIN, so an unprivileged user can trigger it. + + Oops: general protection fault, probably for non-canonical address + 0xdffffc0000000000: 0000 [#1] SMP KASAN NOPTI + KASAN: null-ptr-deref in range [0x0000000000000000-0x0000000000000007] + RIP: 0010:mpls_valid_fib_dump_req (net/mpls/af_mpls.c:2189) + Call Trace: + mpls_dump_routes (net/mpls/af_mpls.c:2236) + netlink_dump (net/netlink/af_netlink.c:2331) + __netlink_dump_start (net/netlink/af_netlink.c:2446) + rtnetlink_rcv_msg (net/core/rtnetlink.c:7033) + netlink_rcv_skb (net/netlink/af_netlink.c:2556) + netlink_unicast (net/netlink/af_netlink.c:1345) + netlink_sendmsg (net/netlink/af_netlink.c:1900) + __sock_sendmsg (net/socket.c:790) + ____sys_sendmsg (net/socket.c:2684) + ___sys_sendmsg (net/socket.c:2738) + __sys_sendmsg (net/socket.c:2770) + do_syscall_64 (arch/x86/entry/syscall_64.c:94) + entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:121) + +Skip unset attributes, as ip_valid_fib_dump_req() does. + +Fixes: 196cfebf8972 ("net/mpls: Handle kernel side filtering of route dumps") +Assisted-by: Claude:claude-opus-4-8 +Reported-by: Xiang Mei +Signed-off-by: Weiming Shi +Reviewed-by: David Ahern +Link: https://patch.msgid.link/20260711114958.1009619-3-bestswngs@gmail.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/mpls/af_mpls.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/net/mpls/af_mpls.c b/net/mpls/af_mpls.c +index 2d29d230f56989..6369ff87f4b9f3 100644 +--- a/net/mpls/af_mpls.c ++++ b/net/mpls/af_mpls.c +@@ -2139,6 +2139,9 @@ static int mpls_valid_fib_dump_req(struct net *net, const struct nlmsghdr *nlh, + int ifindex; + + if (i == RTA_OIF) { ++ if (!tb[i]) ++ continue; ++ + ifindex = nla_get_u32(tb[i]); + filter->dev = __dev_get_by_index(net, ifindex); + if (!filter->dev) +-- +2.53.0 + diff --git a/queue-6.1/mtd-mtdswap-remove-debugfs-stats-file-on-teardown.patch b/queue-6.1/mtd-mtdswap-remove-debugfs-stats-file-on-teardown.patch new file mode 100644 index 0000000000..9330a28c6d --- /dev/null +++ b/queue-6.1/mtd-mtdswap-remove-debugfs-stats-file-on-teardown.patch @@ -0,0 +1,57 @@ +From 2711b4b006c26710533731de9b5e37f82a533ea4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 23 Jun 2026 09:53:17 +0800 +Subject: mtd: mtdswap: remove debugfs stats file on teardown + +From: Pengpeng Hou + +[ Upstream commit 66fb31358108d10245b9e4ef0eef3e7d9747055e ] + +mtdswap_add_debugfs() creates an mtdswap_stats debugfs file under the +per-MTD debugfs directory, but mtdswap_remove_dev() never removes it +before freeing the mtdswap_dev. + +Store the returned dentry and remove it during device teardown before the +driver-private state is freed. + +Fixes: a32159024620 ("mtd: Add mtdswap block driver") +Signed-off-by: Pengpeng Hou +Signed-off-by: Miquel Raynal +Signed-off-by: Sasha Levin +--- + drivers/mtd/mtdswap.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/drivers/mtd/mtdswap.c b/drivers/mtd/mtdswap.c +index 680366616da240..4d695875ea1b23 100644 +--- a/drivers/mtd/mtdswap.c ++++ b/drivers/mtd/mtdswap.c +@@ -125,6 +125,7 @@ struct mtdswap_dev { + + char *page_buf; + char *oob_buf; ++ struct dentry *debugfs_stats; + }; + + struct mtdswap_oobdata { +@@ -1262,7 +1263,8 @@ static int mtdswap_add_debugfs(struct mtdswap_dev *d) + if (IS_ERR_OR_NULL(root)) + return -1; + +- debugfs_create_file("mtdswap_stats", S_IRUSR, root, d, &mtdswap_fops); ++ d->debugfs_stats = debugfs_create_file("mtdswap_stats", 0400, root, ++ d, &mtdswap_fops); + + return 0; + } +@@ -1463,6 +1465,7 @@ static void mtdswap_remove_dev(struct mtd_blktrans_dev *dev) + { + struct mtdswap_dev *d = MTDSWAP_MBD_TO_MTDSWAP(dev); + ++ debugfs_remove(d->debugfs_stats); + del_mtd_blktrans_dev(dev); + mtdswap_cleanup(d); + kfree(d); +-- +2.53.0 + diff --git a/queue-6.1/mtd-nand-mtk-ecc-stop-on-ecc-idle-timeouts.patch b/queue-6.1/mtd-nand-mtk-ecc-stop-on-ecc-idle-timeouts.patch new file mode 100644 index 0000000000..b2e1a0577e --- /dev/null +++ b/queue-6.1/mtd-nand-mtk-ecc-stop-on-ecc-idle-timeouts.patch @@ -0,0 +1,75 @@ +From f2e91699789b507d1938539caed8e22894a9b3c6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 23 Jun 2026 21:57:29 +0800 +Subject: mtd: nand: mtk-ecc: stop on ECC idle timeouts + +From: Pengpeng Hou + +[ Upstream commit 16f7ec8d5dc100eafd2c8e06cd30340a30b104a1 ] + +mtk_ecc_wait_idle() logs when the encoder or decoder does not become +idle, but returns void. Callers can therefore configure a non-idle ECC +engine or read parity bytes after an unconfirmed encoder idle state. + +Return the idle poll result and propagate it from the enable and encode +paths that require the engine to be idle before continuing. + +Fixes: 1d6b1e464950 ("mtd: mediatek: driver for MTK Smart Device") +Signed-off-by: Pengpeng Hou +Signed-off-by: Miquel Raynal +Signed-off-by: Sasha Levin +--- + drivers/mtd/nand/ecc-mtk.c | 16 ++++++++++++---- + 1 file changed, 12 insertions(+), 4 deletions(-) + +diff --git a/drivers/mtd/nand/ecc-mtk.c b/drivers/mtd/nand/ecc-mtk.c +index 9f9b201fe706a8..e2fb7596f49d71 100644 +--- a/drivers/mtd/nand/ecc-mtk.c ++++ b/drivers/mtd/nand/ecc-mtk.c +@@ -115,8 +115,8 @@ static int mt7622_ecc_regs[] = { + [ECC_DECIRQ_STA] = 0x144, + }; + +-static inline void mtk_ecc_wait_idle(struct mtk_ecc *ecc, +- enum mtk_ecc_operation op) ++static inline int mtk_ecc_wait_idle(struct mtk_ecc *ecc, ++ enum mtk_ecc_operation op) + { + struct device *dev = ecc->dev; + u32 val; +@@ -128,6 +128,8 @@ static inline void mtk_ecc_wait_idle(struct mtk_ecc *ecc, + if (ret) + dev_warn(dev, "%s NOT idle\n", + op == ECC_ENCODE ? "encoder" : "decoder"); ++ ++ return ret; + } + + static irqreturn_t mtk_ecc_irq(int irq, void *id) +@@ -304,7 +306,11 @@ int mtk_ecc_enable(struct mtk_ecc *ecc, struct mtk_ecc_config *config) + return ret; + } + +- mtk_ecc_wait_idle(ecc, op); ++ ret = mtk_ecc_wait_idle(ecc, op); ++ if (ret) { ++ mutex_unlock(&ecc->lock); ++ return ret; ++ } + + ret = mtk_ecc_config(ecc, config); + if (ret) { +@@ -404,7 +410,9 @@ int mtk_ecc_encode(struct mtk_ecc *ecc, struct mtk_ecc_config *config, + if (ret) + goto timeout; + +- mtk_ecc_wait_idle(ecc, ECC_ENCODE); ++ ret = mtk_ecc_wait_idle(ecc, ECC_ENCODE); ++ if (ret) ++ goto timeout; + + /* Program ECC bytes to OOB: per sector oob = FDM + ECC + SPARE */ + len = (config->strength * ecc->caps->parity_bits + 7) >> 3; +-- +2.53.0 + diff --git a/queue-6.1/net-iucv-take-a-reference-on-the-socket-found-in-afi.patch b/queue-6.1/net-iucv-take-a-reference-on-the-socket-found-in-afi.patch new file mode 100644 index 0000000000..1d40b192f8 --- /dev/null +++ b/queue-6.1/net-iucv-take-a-reference-on-the-socket-found-in-afi.patch @@ -0,0 +1,55 @@ +From 46a166e40e824d25c995ffb9f4741043a7d4d3f5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 5 Jul 2026 22:24:36 -0500 +Subject: net/iucv: take a reference on the socket found in afiucv_hs_rcv() + +From: Bryam Vargas + +[ Upstream commit 4fa349156043dc119721d067329714179f501749 ] + +afiucv_hs_rcv() looks up the destination socket under iucv_sk_list.lock, +drops the lock, and then passes the socket to the afiucv_hs_callback_*() +handlers without holding a reference. AF_IUCV sockets are not +RCU-protected and are freed synchronously by iucv_sock_kill() -> +sock_put(), so a concurrent close can free the socket in the window +between read_unlock() and the handler, which then dereferences freed +memory (for example sk->sk_data_ready() in afiucv_hs_callback_syn()). + +Take a reference with sock_hold() while the socket is still on the list +and release it with sock_put() once the handler has run. + +Fixes: 3881ac441f64 ("af_iucv: add HiperSockets transport") +Signed-off-by: Bryam Vargas +Reviewed-by: Hidayath Khan +Link: https://patch.msgid.link/20260705-b4-disp-fc79c0dc-v1-1-d2cdcb57afa9@proton.me +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/iucv/af_iucv.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c +index e9a9bb0dee065a..a7b95590f6c96c 100644 +--- a/net/iucv/af_iucv.c ++++ b/net/iucv/af_iucv.c +@@ -2090,6 +2090,8 @@ static int afiucv_hs_rcv(struct sk_buff *skb, struct net_device *dev, + } + } + } ++ if (sk) ++ sock_hold(sk); + read_unlock(&iucv_sk_list.lock); + if (!iucv) + sk = NULL; +@@ -2139,6 +2141,8 @@ static int afiucv_hs_rcv(struct sk_buff *skb, struct net_device *dev, + kfree_skb(skb); + } + ++ if (sk) ++ sock_put(sk); + return err; + } + +-- +2.53.0 + diff --git a/queue-6.1/net-sched-act_tunnel_key-defer-dst_release-to-rcu-ca.patch b/queue-6.1/net-sched-act_tunnel_key-defer-dst_release-to-rcu-ca.patch new file mode 100644 index 0000000000..4abd161114 --- /dev/null +++ b/queue-6.1/net-sched-act_tunnel_key-defer-dst_release-to-rcu-ca.patch @@ -0,0 +1,176 @@ +From 91e1d03b855dc5b61756e74536c72f7db8b19870 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 11 Jul 2026 11:05:37 -0400 +Subject: net/sched: act_tunnel_key: Defer dst_release to RCU callback + +From: Jamal Hadi Salim + +[ Upstream commit f1f5c8a3955f8fda3f84ed883ac8daa1847e724c ] + +Fix a race-condition use-after-free in tunnel_key_release_params(). + +The function releases the metadata_dst of the old params synchronously +via dst_release() while deferring the params struct free with +kfree_rcu(). A concurrent tunnel_key_act() reader on the datapath may +still hold the old params pointer (under rcu_read_lock_bh) and proceed +to call dst_clone(¶ms->tcft_enc_metadata->dst) after the writer's +dst_release has already pushed the dst's rcuref to RCUREF_DEAD. + +zdi-disclosures@trendmicro.com produced a poc which i (and Victor) verified +that KASAN reports: + +================================================================== +BUG: KASAN: slab-use-after-free in instrument_atomic_read_write include/linux/instrumented.h:112 +BUG: KASAN: slab-use-after-free in atomic_sub_return_release include/linux/atomic/atomic-instrumented.h:326 +BUG: KASAN: slab-use-after-free in __rcuref_put include/linux/rcuref.h:109 +BUG: KASAN: slab-use-after-free in rcuref_put include/linux/rcuref.h:173 +BUG: KASAN: slab-use-after-free in dst_release+0x5b/0x370 net/core/dst.c:168 +Write of size 4 at addr ffff88806158de40 by task poc/9388 + +CPU: 0 UID: 0 PID: 9388 Comm: poc Tainted: G W 7.1.0-rc7 #7 PREEMPT(lazy) +Tainted: [W]=WARN +Hardware name: QEMU Ubuntu 25.10 PC v2 (i440FX + PIIX, + 10.1 machine, 1996), BIOS 1.16.3-debian-1.16.3-2 04/01/2014 +Call Trace: + + __dump_stack lib/dump_stack.c:94 + dump_stack_lvl+0x100/0x190 lib/dump_stack.c:120 + print_address_description mm/kasan/report.c:378 + print_report+0x139/0x4ad mm/kasan/report.c:482 + kasan_report+0xe4/0x1d0 mm/kasan/report.c:595 + check_region_inline mm/kasan/generic.c:186 + kasan_check_range+0x125/0x200 mm/kasan/generic.c:200 + instrument_atomic_read_write include/linux/instrumented.h:112 + atomic_sub_return_release include/linux/atomic/atomic-instrumented.h:326 + __rcuref_put include/linux/rcuref.h:109 + rcuref_put include/linux/rcuref.h:173 + dst_release+0x5b/0x370 net/core/dst.c:168 + refdst_drop include/net/dst.h:272 + skb_dst_drop include/net/dst.h:284 + skb_release_head_state+0x293/0x400 net/core/skbuff.c:1163 + skb_release_all net/core/skbuff.c:1187 +[..] +Allocated by task 9391: + kasan_save_stack+0x30/0x50 mm/kasan/common.c:57 + kasan_save_track+0x14/0x30 mm/kasan/common.c:78 + poison_kmalloc_redzone mm/kasan/common.c:398 + __kasan_kmalloc+0x9a/0xb0 mm/kasan/common.c:415 + kasan_kmalloc include/linux/kasan.h:263 + __do_kmalloc_node mm/slub.c:5296 + __kmalloc_noprof+0x2f1/0x830 mm/slub.c:5308 + kmalloc_noprof include/linux/slab.h:954 + kzalloc_noprof include/linux/slab.h:1188 + offload_action_alloc+0x2f/0x130 net/core/flow_offload.c:35 + tcf_action_offload_add_ex+0x1ba/0x880 net/sched/act_api.c:258 + tcf_action_offload_add net/sched/act_api.c:293 + tcf_action_init+0x66e/0xa20 net/sched/act_api.c:1547 + tcf_action_add+0xf6/0x5d0 net/sched/act_api.c:2101 +[..] +Freed by task 9391: + kasan_save_stack+0x30/0x50 mm/kasan/common.c:57 + kasan_save_track+0x14/0x30 mm/kasan/common.c:78 + kasan_save_free_info+0x3b/0x70 mm/kasan/generic.c:584 + poison_slab_object mm/kasan/common.c:253 + __kasan_slab_free+0x6b/0x90 mm/kasan/common.c:285 + kasan_slab_free include/linux/kasan.h:235 + slab_free_hook mm/slub.c:2689 + slab_free mm/slub.c:6251 + kfree+0x21f/0x6b0 mm/slub.c:6566 + tcf_action_offload_add_ex+0x4ad/0x880 net/sched/act_api.c:284 + tcf_action_offload_add net/sched/act_api.c:293 + tcf_action_init+0x66e/0xa20 net/sched/act_api.c:1547 + tcf_action_add+0xf6/0x5d0 net/sched/act_api.c:2101 + +The buggy address belongs to the object at ffff88806158de00 + which belongs to the cache kmalloc-256 of size 256 +The buggy address is located 64 bytes inside of + freed 256-byte region [ffff88806158de00, ffff88806158df00) + +The buggy address belongs to the physical page: +page: refcount:0 mapcount:0 mapping:0000000000000000 index:0xffff88806158d600 pfn:0x6158c +head: order:1 mapcount:0 entire_mapcount:0 nr_pages_mapped:0 pincount:0 +flags: 0x4fff00000000240(workingset|head|node=1|zone=1|lastcpupid=0x7ff) +page_type: f5(slab) +raw: 04fff00000000240 ffff88801c841b40 ffffea0001856290 ffffea0001856190 +raw: ffff88806158d600 0000000800100009 00000000f5000000 0000000000000000 +head: 04fff00000000240 ffff88801c841b40 ffffea0001856290 ffffea0001856190 +head: ffff88806158d600 0000000800100009 00000000f5000000 0000000000000000 +head: 04fff00000000001 ffffffffffffff81 00000000ffffffff 00000000ffffffff +head: ffffffffffffffff 0000000000000000 00000000ffffffff 0000000000000002 +page dumped because: kasan: bad access detected +page_owner tracks the page as allocated +page last allocated via order 1, migratetype Unmovable, gfp_mask 0xd2820(GFP_ATOMIC|__GFP_NOWARN|__GFP_NORETRY|__GFP_COMP|__GFP_NOMEMALLOC), pid 9391, tgid 9378 (poc), ts 123227323196, free_ts 0 + set_page_owner include/linux/page_owner.h:32 + post_alloc_hook+0xfe/0x140 mm/page_alloc.c:1853 + prep_new_page mm/page_alloc.c:1861 + get_page_from_freelist+0x110c/0x2fc0 mm/page_alloc.c:3941 + __alloc_frozen_pages_noprof+0x263/0x2bc0 mm/page_alloc.c:5221 + alloc_slab_page mm/slub.c:3278 + allocate_slab mm/slub.c:3467 + new_slab+0xa6/0x690 mm/slub.c:3525 + refill_objects+0x271/0x420 mm/slub.c:7272 + refill_sheaf mm/slub.c:2816 + __pcs_replace_empty_main+0x373/0x630 mm/slub.c:4652 + alloc_from_pcs mm/slub.c:4750 + slab_alloc_node mm/slub.c:4884 + __do_kmalloc_node mm/slub.c:5295 + __kmalloc_noprof+0x66d/0x830 mm/slub.c:5308 + kmalloc_noprof include/linux/slab.h:954 + metadata_dst_alloc+0x26/0x90 net/core/dst.c:298 + tun_rx_dst include/net/dst_metadata.h:144 + __ip_tun_set_dst include/net/dst_metadata.h:208 + tunnel_key_init+0xb01/0x1b90 net/sched/act_tunnel_key.c:451 + tcf_action_init_1+0x46b/0x6c0 net/sched/act_api.c:1428 + tcf_action_init+0x448/0xa20 net/sched/act_api.c:1503 + tcf_action_add+0xf6/0x5d0 net/sched/act_api.c:2101 +[..] +================================================================== + +Fix by moving dst_release() into a custom RCU callback that runs +after the grace period, matching the lifetime of the containing +params struct. Readers in the datapath therefore always find a live +rcuref when calling dst_clone(). + +Fixes: 9174c3df1cd18 ("net/sched: act_tunnel_key: fix memory leak in case of action replace") +Reported-by: zdi-disclosures@trendmicro.com +Tested-by: Victor Nogueira +Signed-off-by: Jamal Hadi Salim +Reviewed-by: Davide Caratti +Link: https://patch.msgid.link/20260711150537.7946-1-jhs@mojatatu.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/sched/act_tunnel_key.c | 14 ++++++++++---- + 1 file changed, 10 insertions(+), 4 deletions(-) + +diff --git a/net/sched/act_tunnel_key.c b/net/sched/act_tunnel_key.c +index 55a9dff1cc1e6d..ca4c3776f0f045 100644 +--- a/net/sched/act_tunnel_key.c ++++ b/net/sched/act_tunnel_key.c +@@ -342,14 +342,20 @@ static const struct nla_policy tunnel_key_policy[TCA_TUNNEL_KEY_MAX + 1] = { + [TCA_TUNNEL_KEY_ENC_TTL] = { .type = NLA_U8 }, + }; + +-static void tunnel_key_release_params(struct tcf_tunnel_key_params *p) ++static void tunnel_key_release_params_rcu(struct rcu_head *head) + { +- if (!p) +- return; ++ struct tcf_tunnel_key_params *p = container_of(head, typeof(*p), rcu); ++ + if (p->tcft_action == TCA_TUNNEL_KEY_ACT_SET) + dst_release(&p->tcft_enc_metadata->dst); ++ kfree(p); ++} + +- kfree_rcu(p, rcu); ++static void tunnel_key_release_params(struct tcf_tunnel_key_params *p) ++{ ++ if (!p) ++ return; ++ call_rcu(&p->rcu, tunnel_key_release_params_rcu); + } + + static int tunnel_key_init(struct net *net, struct nlattr *nla, +-- +2.53.0 + diff --git a/queue-6.1/ppp-defer-channel-free-to-an-rcu-grace-period-to-fix.patch b/queue-6.1/ppp-defer-channel-free-to-an-rcu-grace-period-to-fix.patch new file mode 100644 index 0000000000..6184a8c04e --- /dev/null +++ b/queue-6.1/ppp-defer-channel-free-to-an-rcu-grace-period-to-fix.patch @@ -0,0 +1,104 @@ +From b1d0d5b770f9cd32d0abef129762508d37bf94c6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 6 Jul 2026 11:01:59 +0200 +Subject: ppp: defer channel free to an RCU grace period to fix pppol2tp RX UAF + +From: Norbert Szetei + +[ Upstream commit ec4215683e47424c9c4762fd3c60f552a3119142 ] + +pppol2tp_recv() runs in the L2TP UDP-encap softirq RX path: + + l2tp_udp_encap_recv() -> l2tp_recv_common() -> pppol2tp_recv() + -> ppp_input(&po->chan) + +It runs under rcu_read_lock() holding only an l2tp_session reference and +takes NO reference on the internal PPP channel (struct channel, +chan->ppp) that ppp_input() dereferences. + +The pppox socket is SOCK_RCU_FREE, so 'po' and the embedded ppp_channel +are RCU-safe. But the internal struct channel is a separate allocation +that ppp_release_channel() frees with a plain kfree(): + + close(data socket) -> pppol2tp_release() -> pppox_unbind_sock() + -> ppp_unregister_channel() -> ppp_release_channel() -> kfree(pch) + +For a channel that is bound (PPPIOCGCHAN) but not attached to a ppp unit +(no PPPIOCCONNECT, pch->ppp == NULL) and not bridged, teardown skips +both ppp_disconnect_channel()'s synchronize_net() and +ppp_unbridge_channels()'s synchronize_rcu(), so the kfree() has no grace +period. rcu_read_lock() in pppol2tp_recv() does not protect against a +plain kfree(), so an in-flight ppp_input() on one CPU can dereference +the channel just freed by close() on another CPU. + +The bug is reachable by an unprivileged user. + +Defer the channel free to an RCU callback via call_rcu() so the grace +period fences any in-flight ppp_input(). The disconnect and unbridge +teardown paths already fence with synchronize_net()/synchronize_rcu(); +call_rcu() does the same here without stalling the close() path. + +Fixes: ee40fb2e1eb5 ("l2tp: protect sock pointer of struct pppol2tp_session with RCU") +Assisted-by: Claude:claude-opus-4-8 +Signed-off-by: Norbert Szetei +Reviewed-by: Qingfang Deng +Link: https://patch.msgid.link/E793FCF2-58DE-4387-A983-C7B4BC3158BD@doyensec.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ppp/ppp_generic.c | 18 +++++++++++++++--- + 1 file changed, 15 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c +index df72070a3879dd..d3ea1d6da20568 100644 +--- a/drivers/net/ppp/ppp_generic.c ++++ b/drivers/net/ppp/ppp_generic.c +@@ -192,6 +192,7 @@ struct channel { + struct list_head clist; /* link in list of channels per unit */ + rwlock_t upl; /* protects `ppp' and 'bridge' */ + struct channel __rcu *bridge; /* "bridged" ppp channel */ ++ struct rcu_head rcu; /* for RCU-deferred free of the channel */ + #ifdef CONFIG_PPP_MULTILINK + u8 avail; /* flag used in multilink stuff */ + u8 had_frag; /* >= 1 fragments have been sent */ +@@ -3555,6 +3556,18 @@ ppp_disconnect_channel(struct channel *pch) + return err; + } + ++/* Purge after the grace period: a late ppp_input() may still queue an ++ * skb on pch->file.rq before the last RCU reader drains. ++ */ ++static void ppp_release_channel_free(struct rcu_head *rcu) ++{ ++ struct channel *pch = container_of(rcu, struct channel, rcu); ++ ++ skb_queue_purge(&pch->file.xq); ++ skb_queue_purge(&pch->file.rq); ++ kfree(pch); ++} ++ + /* + * Free up the resources used by a ppp channel. + */ +@@ -3570,9 +3583,7 @@ static void ppp_destroy_channel(struct channel *pch) + pr_err("ppp: destroying undead channel %p !\n", pch); + return; + } +- skb_queue_purge(&pch->file.xq); +- skb_queue_purge(&pch->file.rq); +- kfree(pch); ++ call_rcu(&pch->rcu, ppp_release_channel_free); + } + + static void __exit ppp_cleanup(void) +@@ -3585,6 +3596,7 @@ static void __exit ppp_cleanup(void) + device_destroy(ppp_class, MKDEV(PPP_MAJOR, 0)); + class_destroy(ppp_class); + unregister_pernet_device(&ppp_net_ops); ++ rcu_barrier(); /* wait for RCU callbacks before module unload */ + } + + /* +-- +2.53.0 + diff --git a/queue-6.1/rdma-cma-fix-hardware-address-comparison-length-in-n.patch b/queue-6.1/rdma-cma-fix-hardware-address-comparison-length-in-n.patch new file mode 100644 index 0000000000..b6b6e672f0 --- /dev/null +++ b/queue-6.1/rdma-cma-fix-hardware-address-comparison-length-in-n.patch @@ -0,0 +1,43 @@ +From 044993dcf65803fb03313be3fd5084fade67689f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 17 Jun 2026 14:21:05 +0300 +Subject: RDMA/cma: Fix hardware address comparison length in netevent callback + +From: Or Gerlitz + +[ Upstream commit 18313833e2c6de222a4f6c072da759d0d5888528 ] + +The cited commit hardcoded the hardware address comparison len to ETH_ALEN. + +This breaks IPoIB, which uses 20-byte addresses. By truncating the +memcmp, the CMA may incorrectly assume the target address is +unchanged and fails to abort the stalled connection. + +Fix this by replacing ETH_ALEN with the dynamic neigh->dev->addr_len +to correctly evaluate the full address regardless of the link layer. + +Fixes: 925d046e7e52 ("RDMA/core: Add a netevent notifier to cma") +Signed-off-by: Or Gerlitz +Link: https://patch.msgid.link/20260617-fix-cma-ipoib-v1-1-03f869344304@ddn.com +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + drivers/infiniband/core/cma.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c +index b5924919e7f06f..e7827352409026 100644 +--- a/drivers/infiniband/core/cma.c ++++ b/drivers/infiniband/core/cma.c +@@ -5190,7 +5190,7 @@ static int cma_netevent_callback(struct notifier_block *self, + + list_for_each_entry(current_id, &ips_node->id_list, id_list_entry) { + if (!memcmp(current_id->id.route.addr.dev_addr.dst_dev_addr, +- neigh->ha, ETH_ALEN)) ++ neigh->ha, neigh->dev->addr_len)) + continue; + cma_id_get(current_id); + if (!queue_work(cma_wq, ¤t_id->id.net_work)) +-- +2.53.0 + diff --git a/queue-6.1/rdma-erdma-initialize-ret-for-empty-receive-wr-lists.patch b/queue-6.1/rdma-erdma-initialize-ret-for-empty-receive-wr-lists.patch new file mode 100644 index 0000000000..bd05836ac6 --- /dev/null +++ b/queue-6.1/rdma-erdma-initialize-ret-for-empty-receive-wr-lists.patch @@ -0,0 +1,42 @@ +From 7d02a08e730d3b394f5f5bc77711026d8430be2e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 18 Jun 2026 12:17:51 +0800 +Subject: RDMA/erdma: initialize ret for empty receive WR lists + +From: Ruoyu Wang + +[ Upstream commit 2815a277c53e9a84784d6410cd55a9da5b33068d ] + +erdma_post_recv() returns ret after walking the receive work request list. +If the caller passes an empty list, the loop is skipped and ret is not +assigned. + +Initialize ret to 0 so an empty receive work request list returns success +instead of stack data. + +Fixes: 155055771704 ("RDMA/erdma: Add verbs implementation") +Link: https://patch.msgid.link/r/20260618041752.481193-1-ruoyuw560@gmail.com +Signed-off-by: Ruoyu Wang +Reviewed-by: Cheng Xu +Signed-off-by: Jason Gunthorpe +Signed-off-by: Sasha Levin +--- + drivers/infiniband/hw/erdma/erdma_qp.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/infiniband/hw/erdma/erdma_qp.c b/drivers/infiniband/hw/erdma/erdma_qp.c +index e3b0baa703e681..74cb47ab827e14 100644 +--- a/drivers/infiniband/hw/erdma/erdma_qp.c ++++ b/drivers/infiniband/hw/erdma/erdma_qp.c +@@ -537,7 +537,7 @@ int erdma_post_recv(struct ib_qp *ibqp, const struct ib_recv_wr *recv_wr, + const struct ib_recv_wr *wr = recv_wr; + struct erdma_qp *qp = to_eqp(ibqp); + unsigned long flags; +- int ret; ++ int ret = 0; + + spin_lock_irqsave(&qp->lock, flags); + +-- +2.53.0 + diff --git a/queue-6.1/rdma-hns-fix-potential-integer-overflow-in-mhop-hem-.patch b/queue-6.1/rdma-hns-fix-potential-integer-overflow-in-mhop-hem-.patch new file mode 100644 index 0000000000..732fd4d1b0 --- /dev/null +++ b/queue-6.1/rdma-hns-fix-potential-integer-overflow-in-mhop-hem-.patch @@ -0,0 +1,52 @@ +From 3e726fb2a91b1d2b230f65a9201083240297d53a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 27 Jun 2026 09:59:51 +0000 +Subject: RDMA/hns: Fix potential integer overflow in mhop hem cleanup + +From: Danila Chernetsov + +[ Upstream commit 9f0f2d2121f16d420199a82ac5bbc242269133b3 ] + +In hns_roce_cleanup_mhop_hem_table(), the expression: + + obj = i * buf_chunk_size / table->obj_size; + +is evaluated using 32-bit unsigned arithmetic because +'buf_chunk_size' is u32 and the usual arithmetic conversions convert +'i' to unsigned int. The result is assigned to a u64 variable, but the +multiplication may overflow before the assignment. + +For sufficiently large HEM tables, this produces an incorrect object +index passed to hns_roce_table_mhop_put(). + +Cast 'i' to u64 before the multiplication so that the intermediate +calculation is performed with 64-bit arithmetic. + +Found by Linux Verification Center (linuxtesting.org) with SVACE. + +Fixes: a25d13cbe816 ("RDMA/hns: Add the interfaces to support multi hop addressing for the contexts in hip08") +Link: https://patch.msgid.link/r/20260627095951.51378-1-listdansp@mail.ru +Signed-off-by: Danila Chernetsov +Reviewed-by: Junxian Huang +Signed-off-by: Jason Gunthorpe +Signed-off-by: Sasha Levin +--- + drivers/infiniband/hw/hns/hns_roce_hem.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/infiniband/hw/hns/hns_roce_hem.c b/drivers/infiniband/hw/hns/hns_roce_hem.c +index 862acdf59867a9..ce115dbba13020 100644 +--- a/drivers/infiniband/hw/hns/hns_roce_hem.c ++++ b/drivers/infiniband/hw/hns/hns_roce_hem.c +@@ -907,7 +907,7 @@ static void hns_roce_cleanup_mhop_hem_table(struct hns_roce_dev *hr_dev, + mhop.bt_chunk_size; + + for (i = 0; i < table->num_hem; ++i) { +- obj = i * buf_chunk_size / table->obj_size; ++ obj = (u64)i * buf_chunk_size / table->obj_size; + if (table->hem[i]) + hns_roce_table_mhop_put(hr_dev, table, obj, 0); + } +-- +2.53.0 + diff --git a/queue-6.1/rdma-irdma-prevent-overflows-in-memory-contiguity-ch.patch b/queue-6.1/rdma-irdma-prevent-overflows-in-memory-contiguity-ch.patch new file mode 100644 index 0000000000..0d798a44a9 --- /dev/null +++ b/queue-6.1/rdma-irdma-prevent-overflows-in-memory-contiguity-ch.patch @@ -0,0 +1,64 @@ +From a9d480d5b5863b38c8fed8c43dee7096ded18111 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 24 Jun 2026 17:48:46 +0300 +Subject: RDMA/irdma: Prevent overflows in memory contiguity checks + +From: Aleksandrova Alyona + +[ Upstream commit 3cda0dfe8c651dcbb9e38977905d3d3b1750c4ab ] + +irdma_check_mem_contiguous() and irdma_check_mr_contiguous() verify that +PBL entries describe physically contiguous memory ranges. + +Both functions calculate byte offsets using 32-bit operands. For example, +with 4 KiB pages, pg_size * pg_idx overflows 32-bit arithmetic when +pg_idx reaches 1048576. In the level-2 check, PBLE_PER_PAGE is 512, so +i * pg_size * PBLE_PER_PAGE overflows when i reaches 2048. + +These values are reachable in the driver. For MRs, palloc->total_cnt +comes from iwmr->page_cnt, which is calculated by +ib_umem_num_dma_blocks(). The MR size is limited by IRDMA_MAX_MR_SIZE, +so a 4 GiB MR with 4 KiB pages can reach page_cnt of 1048576. PBLE +resources do not exclude this value either: for gen3, the limit is based +on avail_sds * MAX_PBLE_PER_SD, and MAX_PBLE_PER_SD is 0x40000, so 4 SDs +are enough for 1048576 PBLEs. + +Cast one operand to u64 before the multiplications so that the offset +calculations are performed in 64-bit arithmetic. + +Found by Linux Verification Center (linuxtesting.org) with SVACE. + +Fixes: b48c24c2d710 ("RDMA/irdma: Implement device supported verb APIs") +Signed-off-by: Aleksandrova Alyona +Link: https://patch.msgid.link/20260624144846.61242-1-aga@itb.spb.ru +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + drivers/infiniband/hw/irdma/verbs.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/infiniband/hw/irdma/verbs.c b/drivers/infiniband/hw/irdma/verbs.c +index b43ce455050c66..56e3103aa77f91 100644 +--- a/drivers/infiniband/hw/irdma/verbs.c ++++ b/drivers/infiniband/hw/irdma/verbs.c +@@ -2336,7 +2336,7 @@ static bool irdma_check_mem_contiguous(u64 *arr, u32 npages, u32 pg_size) + u32 pg_idx; + + for (pg_idx = 0; pg_idx < npages; pg_idx++) { +- if ((*arr + (pg_size * pg_idx)) != arr[pg_idx]) ++ if ((*arr + ((u64)pg_size * pg_idx)) != arr[pg_idx]) + return false; + } + +@@ -2369,7 +2369,7 @@ static bool irdma_check_mr_contiguous(struct irdma_pble_alloc *palloc, + + for (i = 0; i < lvl2->leaf_cnt; i++, leaf++) { + arr = leaf->addr; +- if ((*start_addr + (i * pg_size * PBLE_PER_PAGE)) != *arr) ++ if ((*start_addr + ((u64)i * pg_size * PBLE_PER_PAGE)) != *arr) + return false; + ret = irdma_check_mem_contiguous(arr, leaf->cnt, pg_size); + if (!ret) +-- +2.53.0 + diff --git a/queue-6.1/rdma-siw-only-check-attrs-cap.max_send_wr-in-siw_cre.patch b/queue-6.1/rdma-siw-only-check-attrs-cap.max_send_wr-in-siw_cre.patch new file mode 100644 index 0000000000..eba8063b7f --- /dev/null +++ b/queue-6.1/rdma-siw-only-check-attrs-cap.max_send_wr-in-siw_cre.patch @@ -0,0 +1,69 @@ +From 1bd7a9e5455269e64b98367828dce3e87beeb1cf Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 13 Nov 2023 19:57:24 +0800 +Subject: RDMA/siw: Only check attrs->cap.max_send_wr in siw_create_qp + +From: Guoqing Jiang + +[ Upstream commit 788bbf4c2fc6e0c35bae9ed5068f484272539d3e ] + +We can just check max_send_wr here given both max_send_wr and +max_recv_wr are defined as u32 type, and we also need to ensure +num_sqe (derived from max_send_wr) shouldn't be zero. + +Acked-by: Bernard Metzler +Signed-off-by: Guoqing Jiang +Link: https://lore.kernel.org/r/20231113115726.12762-16-guoqing.jiang@linux.dev +Signed-off-by: Leon Romanovsky +Stable-dep-of: bb27fcc67c42 ("RDMA/siw: publish QP after initialization") +Signed-off-by: Sasha Levin +--- + drivers/infiniband/sw/siw/siw_verbs.c | 18 +++++------------- + 1 file changed, 5 insertions(+), 13 deletions(-) + +diff --git a/drivers/infiniband/sw/siw/siw_verbs.c b/drivers/infiniband/sw/siw/siw_verbs.c +index dce86f5aee1f76..336702bcbfa9f8 100644 +--- a/drivers/infiniband/sw/siw/siw_verbs.c ++++ b/drivers/infiniband/sw/siw/siw_verbs.c +@@ -336,11 +336,10 @@ int siw_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attrs, + goto err_atomic; + } + /* +- * NOTE: we allow for zero element SQ and RQ WQE's SGL's +- * but not for a QP unable to hold any WQE (SQ + RQ) ++ * NOTE: we don't allow for a QP unable to hold any SQ WQE + */ +- if (attrs->cap.max_send_wr + attrs->cap.max_recv_wr == 0) { +- siw_dbg(base_dev, "QP must have send or receive queue\n"); ++ if (attrs->cap.max_send_wr == 0) { ++ siw_dbg(base_dev, "QP must have send queue\n"); + rv = -EINVAL; + goto err_atomic; + } +@@ -360,21 +359,14 @@ int siw_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attrs, + if (rv) + goto err_atomic; + +- num_sqe = attrs->cap.max_send_wr; +- num_rqe = attrs->cap.max_recv_wr; + + /* All queue indices are derived from modulo operations + * on a free running 'get' (consumer) and 'put' (producer) + * unsigned counter. Having queue sizes at power of two + * avoids handling counter wrap around. + */ +- if (num_sqe) +- num_sqe = roundup_pow_of_two(num_sqe); +- else { +- /* Zero sized SQ is not supported */ +- rv = -EINVAL; +- goto err_out_xa; +- } ++ num_sqe = roundup_pow_of_two(attrs->cap.max_send_wr); ++ num_rqe = attrs->cap.max_recv_wr; + if (num_rqe) + num_rqe = roundup_pow_of_two(num_rqe); + +-- +2.53.0 + diff --git a/queue-6.1/rdma-siw-publish-qp-after-initialization.patch b/queue-6.1/rdma-siw-publish-qp-after-initialization.patch new file mode 100644 index 0000000000..2b43646477 --- /dev/null +++ b/queue-6.1/rdma-siw-publish-qp-after-initialization.patch @@ -0,0 +1,153 @@ +From a1689d35d210d8b9ad7fcc1f55abe68eccde7007 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 30 Jun 2026 14:00:40 +0800 +Subject: RDMA/siw: publish QP after initialization + +From: Ruoyu Wang + +[ Upstream commit bb27fcc67c429d97f785c92c35a6c5adebb05d7f ] + +siw_create_qp() currently calls siw_qp_add() before the queues, CQ +pointers, state, completion, and device list entry are ready. A QPN +lookup can therefore reach a QP that is still being constructed. + +Move siw_qp_add() to the end of siw_create_qp(), after QP +initialization and before adding the QP to the siw device list. + +Fixes: f29dd55b0236 ("rdma/siw: queue pair methods") +Link: https://patch.msgid.link/r/20260630060040.966461-1-ruoyuw560@gmail.com +Suggested-by: Bernard Metzler +Signed-off-by: Ruoyu Wang +Acked-by: Bernard Metzler +Signed-off-by: Jason Gunthorpe +Signed-off-by: Sasha Levin +--- + drivers/infiniband/sw/siw/siw_verbs.c | 44 +++++++++++++++------------ + 1 file changed, 24 insertions(+), 20 deletions(-) + +diff --git a/drivers/infiniband/sw/siw/siw_verbs.c b/drivers/infiniband/sw/siw/siw_verbs.c +index 336702bcbfa9f8..8e89e32435d455 100644 +--- a/drivers/infiniband/sw/siw/siw_verbs.c ++++ b/drivers/infiniband/sw/siw/siw_verbs.c +@@ -302,6 +302,7 @@ int siw_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attrs, + struct siw_ucontext *uctx = + rdma_udata_to_drv_context(udata, struct siw_ucontext, + base_ucontext); ++ struct siw_uresp_create_qp uresp = {}; + unsigned long flags; + int num_sqe, num_rqe, rv = 0; + size_t length; +@@ -355,11 +356,6 @@ int siw_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attrs, + spin_lock_init(&qp->rq_lock); + spin_lock_init(&qp->orq_lock); + +- rv = siw_qp_add(sdev, qp); +- if (rv) +- goto err_atomic; +- +- + /* All queue indices are derived from modulo operations + * on a free running 'get' (consumer) and 'put' (producer) + * unsigned counter. Having queue sizes at power of two +@@ -377,14 +373,14 @@ int siw_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attrs, + + if (qp->sendq == NULL) { + rv = -ENOMEM; +- goto err_out_xa; ++ goto err_out; + } + if (attrs->sq_sig_type != IB_SIGNAL_REQ_WR) { + if (attrs->sq_sig_type == IB_SIGNAL_ALL_WR) + qp->attrs.flags |= SIW_SIGNAL_ALL_WR; + else { + rv = -EINVAL; +- goto err_out_xa; ++ goto err_out; + } + } + qp->pd = pd; +@@ -410,7 +406,7 @@ int siw_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attrs, + + if (qp->recvq == NULL) { + rv = -ENOMEM; +- goto err_out_xa; ++ goto err_out; + } + qp->attrs.rq_size = num_rqe; + } +@@ -425,11 +421,8 @@ int siw_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attrs, + qp->attrs.state = SIW_QP_STATE_IDLE; + + if (udata) { +- struct siw_uresp_create_qp uresp = {}; +- + uresp.num_sqe = num_sqe; + uresp.num_rqe = num_rqe; +- uresp.qp_id = qp_id(qp); + + if (qp->sendq) { + length = num_sqe * sizeof(struct siw_sqe); +@@ -438,7 +431,7 @@ int siw_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attrs, + length, &uresp.sq_key); + if (!qp->sq_entry) { + rv = -ENOMEM; +- goto err_out_xa; ++ goto err_out; + } + } + +@@ -450,9 +443,23 @@ int siw_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attrs, + if (!qp->rq_entry) { + uresp.sq_key = SIW_INVAL_UOBJ_KEY; + rv = -ENOMEM; +- goto err_out_xa; ++ goto err_out; + } + } ++ } ++ qp->tx_cpu = siw_get_tx_cpu(sdev); ++ if (qp->tx_cpu < 0) { ++ rv = -EINVAL; ++ goto err_out; ++ } ++ init_completion(&qp->qp_free); ++ ++ rv = siw_qp_add(sdev, qp); ++ if (rv) ++ goto err_out_tx; ++ ++ if (udata) { ++ uresp.qp_id = qp_id(qp); + + if (udata->outlen < sizeof(uresp)) { + rv = -EINVAL; +@@ -462,22 +469,19 @@ int siw_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attrs, + if (rv) + goto err_out_xa; + } +- qp->tx_cpu = siw_get_tx_cpu(sdev); +- if (qp->tx_cpu < 0) { +- rv = -EINVAL; +- goto err_out_xa; +- } ++ + INIT_LIST_HEAD(&qp->devq); + spin_lock_irqsave(&sdev->lock, flags); + list_add_tail(&qp->devq, &sdev->qp_list); + spin_unlock_irqrestore(&sdev->lock, flags); + +- init_completion(&qp->qp_free); +- + return 0; + + err_out_xa: + xa_erase(&sdev->qp_xa, qp_id(qp)); ++err_out_tx: ++ siw_put_tx_cpu(qp->tx_cpu); ++err_out: + if (uctx) { + rdma_user_mmap_entry_remove(qp->sq_entry); + rdma_user_mmap_entry_remove(qp->rq_entry); +-- +2.53.0 + diff --git a/queue-6.1/sctp-fix-auth_hmacs-array-size-in-struct-sctp_cookie.patch b/queue-6.1/sctp-fix-auth_hmacs-array-size-in-struct-sctp_cookie.patch new file mode 100644 index 0000000000..c64d039d65 --- /dev/null +++ b/queue-6.1/sctp-fix-auth_hmacs-array-size-in-struct-sctp_cookie.patch @@ -0,0 +1,56 @@ +From 939a042eafd2796f6cce6a03c7de44cfd0e8c884 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 10 Jul 2026 14:12:35 -0400 +Subject: sctp: fix auth_hmacs array size in struct sctp_cookie + +From: Xin Long + +[ Upstream commit e0b5252a59383b77d1b8dbeda00b7184dd95f4d3 ] + +The auth_hmacs array in struct sctp_cookie is supposed to store a complete +SCTP_AUTH_HMAC_ALGO parameter, which consists of a struct sctp_paramhdr +followed by N HMAC identifiers. + +However, the array size was calculated using an extra 2 bytes instead of +sizeof(struct sctp_paramhdr), which is 4 bytes. When four HMAC identifiers +are configured, the HMAC-ALGO parameter stored in the endpoint is larger +than the auth_hmacs buffer in the cookie. + +As a result, sctp_association_init() copies beyond the end of auth_hmacs +when initializing the association, corrupting the adjacent auth_chunks +field. This can lead to an invalid HMAC identifier being accepted and later +cause an out-of-bounds read in sctp_auth_get_hmac(). + +Fix the array size calculation by including the full SCTP parameter header +size. + +Fixes: 1f485649f529 ("[SCTP]: Implement SCTP-AUTH internals") +Reported-by: Yuan Tan +Reported-by: Xin Liu +Reported-by: Zihan Xi +Reported-by: Ren Wei +Signed-off-by: Xin Long +Link: https://patch.msgid.link/634a0de0d5de29532915e6d47c92a0cbc206e03f.1783707155.git.lucien.xin@gmail.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + include/net/sctp/structs.h | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h +index 8995914916ca6e..cef44fa66fb36b 100644 +--- a/include/net/sctp/structs.h ++++ b/include/net/sctp/structs.h +@@ -322,7 +322,8 @@ struct sctp_cookie { + + __u8 auth_random[sizeof(struct sctp_paramhdr) + + SCTP_AUTH_RANDOM_LENGTH]; +- __u8 auth_hmacs[SCTP_AUTH_NUM_HMACS * sizeof(__u16) + 2]; ++ __u8 auth_hmacs[sizeof(struct sctp_paramhdr) + ++ SCTP_AUTH_NUM_HMACS * sizeof(__u16)]; + __u8 auth_chunks[sizeof(struct sctp_paramhdr) + SCTP_AUTH_MAX_CHUNKS]; + + /* This is a shim for my peer's INIT packet, followed by +-- +2.53.0 + diff --git a/queue-6.1/selftests-alsa-fix-memory-leak-in-find_controls-erro.patch b/queue-6.1/selftests-alsa-fix-memory-leak-in-find_controls-erro.patch new file mode 100644 index 0000000000..56ff875376 --- /dev/null +++ b/queue-6.1/selftests-alsa-fix-memory-leak-in-find_controls-erro.patch @@ -0,0 +1,41 @@ +From 3329b7a8386457bff6602788d17811a965abb610 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 4 Jul 2026 16:27:36 +0530 +Subject: selftests/alsa: Fix memory leak in find_controls error path + +From: Malaya Kumar Rout + +[ Upstream commit cb89f0c1aed02eb233c4271f76f830b37e222ff6 ] + +In find_controls(), card_data is allocated with malloc() but when +snd_ctl_open_lconf() fails, the code jumps to next_card without +freeing the allocated memory. This results in a memory leak for +each card where snd_ctl_open_lconf() fails. + +Add free(card_data) before goto next_card to ensure proper cleanup +of the allocated memory in the error path. + +Fixes: 5aaf9efffc57 ("kselftest: alsa: Add simplistic test for ALSA mixer controls kselftest") +Signed-off-by: Malaya Kumar Rout +Link: https://patch.msgid.link/20260704105736.94874-1-malayarout91@gmail.com +Signed-off-by: Takashi Iwai +Signed-off-by: Sasha Levin +--- + tools/testing/selftests/alsa/mixer-test.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/tools/testing/selftests/alsa/mixer-test.c b/tools/testing/selftests/alsa/mixer-test.c +index 9ad39db32d1442..960b137789d25e 100644 +--- a/tools/testing/selftests/alsa/mixer-test.c ++++ b/tools/testing/selftests/alsa/mixer-test.c +@@ -130,6 +130,7 @@ static void find_controls(void) + if (err < 0) { + ksft_print_msg("Failed to get hctl for card %d: %s\n", + card, snd_strerror(err)); ++ free(card_data); + goto next_card; + } + +-- +2.53.0 + diff --git a/queue-6.1/series b/queue-6.1/series index e4555fae43..c122029800 100644 --- a/queue-6.1/series +++ b/queue-6.1/series @@ -22,3 +22,52 @@ xprtrdma-clear-receive-side-ownership-pointers-on-re.patch input-ims-pcu-fix-heap-buffer-overflow-in-ims_pcu_pr.patch input-ims-pcu-fix-logic-error-in-packet-reset.patch mm-refactor-mm_access-to-not-return-null.patch +arm64-tegra-fix-cpu-compatible-string-to-cortex-a78a.patch +ib-mad-drop-unmatched-rmpp-responses-before-reassemb.patch +mtd-mtdswap-remove-debugfs-stats-file-on-teardown.patch +mtd-nand-mtk-ecc-stop-on-ecc-idle-timeouts.patch +btrfs-reject-free-space-cache-with-more-entries-than.patch +btrfs-fix-root-leak-if-its-reloc-root-is-unexpected-.patch +firmware-arm_ffa-fix-null-dereference-in-ffa_partiti.patch +rdma-cma-fix-hardware-address-comparison-length-in-n.patch +rdma-erdma-initialize-ret-for-empty-receive-wr-lists.patch +rdma-hns-fix-potential-integer-overflow-in-mhop-hem-.patch +rdma-siw-only-check-attrs-cap.max_send_wr-in-siw_cre.patch +rdma-siw-publish-qp-after-initialization.patch +selftests-alsa-fix-memory-leak-in-find_controls-erro.patch +rdma-irdma-prevent-overflows-in-memory-contiguity-ch.patch +xfrm6-clear-dst.dev-on-error-to-avoid-double-netdev_.patch +xfrm-policy-preallocate-inexact-bins-before-xfrm_has.patch +wifi-cfg80211-cancel-sched-scan-results-work-on-unre.patch +wifi-ipw2100-fix-potential-memory-leak-in-ipw2100_pc.patch +wifi-mac80211_hwsim-clamp-virtio-rx-length-before-sk.patch +wifi-libertas-fix-memory-leak-in-helper_firmware_cb.patch +wifi-p54-validate-rx-frame-length-in-p54_rx_eeprom_r.patch +wifi-nl80211-free-rnr-data-on-mbssid-mismatch.patch +wifi-nl80211-validate-nested-mbssid-ie-blobs.patch +wifi-cfg80211-validate-pmsr-measurement-type-data.patch +wifi-cfg80211-validate-pmsr-ftm-preamble-range.patch +wifi-cfg80211-reject-unsupported-pmsr-ftm-location-r.patch +wifi-mac80211-free-ap_vlan-bc_buf-skbs-outside-irq-l.patch +wifi-brcmfmac-initialize-sdio-data-work-before-clean.patch +wifi-cfg80211-bound-element-id-read-when-checking-no.patch +asoc-meson-aiu-fifo-spdif-soft-reset-the-s-pdif-data.patch +asoc-amd-ps-fix-wrong-acp-version-string-in-pci_requ.patch +asoc-tas2562-fix-deprecated-shut-down-gpio-always-cl.patch +firmware-arm_scmi-rate-limit-queue-full-warnings-in-.patch +ppp-defer-channel-free-to-an-rcu-grace-period-to-fix.patch +ipv4-fib-free-fib_alias-with-kfree_rcu-on-insert-err.patch +net-iucv-take-a-reference-on-the-socket-found-in-afi.patch +ata-sata_dwc_460ex-enable-sata-interrupts-only-after.patch +ata-sata_dwc_460ex-fix-clear_interrupt_bit-clearing-.patch +alsa-usb-audio-skip-dsd-quirk-for-musical-fidelity-m.patch +bluetooth-qca-fix-nvm-tag-length-underflow-in-tlv-pa.patch +smb-client-handle-overlapping-allocated-ranges-in-fa.patch +drm-i915-gt-use-correct-selftest-config-symbol.patch +bpf-sockmap-reject-unhashed-udp-sockets-on-sockmap-u.patch +can-j1939-fix-lockless-local-destination-check.patch +ksmbd-validate-compound-request-size-before-reading-.patch +drm-i915-selftests-fix-gt-pm-sort-comparators.patch +net-sched-act_tunnel_key-defer-dst_release-to-rcu-ca.patch +sctp-fix-auth_hmacs-array-size-in-struct-sctp_cookie.patch +mpls-fix-null-deref-in-mpls_valid_fib_dump_req-on-co.patch diff --git a/queue-6.1/smb-client-handle-overlapping-allocated-ranges-in-fa.patch b/queue-6.1/smb-client-handle-overlapping-allocated-ranges-in-fa.patch new file mode 100644 index 0000000000..f2843ceea8 --- /dev/null +++ b/queue-6.1/smb-client-handle-overlapping-allocated-ranges-in-fa.patch @@ -0,0 +1,110 @@ +From 6555f0932124c812eebe6f76d5d4bf4931a39da5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 3 Jul 2026 13:32:56 +0800 +Subject: smb/client: handle overlapping allocated ranges in fallocate + +From: Huiwen He + +[ Upstream commit b09ae45d85dc816987a71db9eebc54b0ae288e94 ] + +smb3_simple_fallocate_range() can skip holes when an allocated range +returned by the server starts before the current fallocate offset. The +skipped hole is not zero-filled, but fallocate still returns success. A +later write to that hole may therefore fail with ENOSPC. + +The function queries allocated ranges so that it can preserve existing +contents and write zeroes only into holes. However, the server may return +a range that starts before the current fallocate offset. + +For example, assume the fallocate request is [100, 400) and the only +allocated range returned by the server is [0, 200): + + Request: [100, 400) + Server range: [ 0, 200) allocated + + Correct: + [100, 200) allocated data, skip + [200, 400) hole, zero-fill + + Current: + [100, 300) skipped + [300, 400) zero-filled afterwards + +The current code adds the full server range length, 200, to the current +offset 100 and moves to 300. As a result, the hole in [200, 300) is +skipped without being zero-filled. + +Fix this by advancing only over the part of the allocated range that +overlaps the current fallocate offset. Ignore ranges that end before the +current offset and reject ranges whose end offset overflows. + +This also prevents a malformed range length from causing an out-of-bounds +zero-buffer read. + +Fixes: 966a3cb7c7db ("cifs: improve fallocate emulation") +Signed-off-by: Huiwen He +Reviewed-by: ChenXiaoSong +Signed-off-by: Steve French +Signed-off-by: Sasha Levin +--- + fs/smb/client/smb2ops.c | 25 ++++++++++++++++++------- + 1 file changed, 18 insertions(+), 7 deletions(-) + +diff --git a/fs/smb/client/smb2ops.c b/fs/smb/client/smb2ops.c +index a80c5f07fc718c..05b7b02a6b0352 100644 +--- a/fs/smb/client/smb2ops.c ++++ b/fs/smb/client/smb2ops.c +@@ -3655,6 +3655,7 @@ static int smb3_simple_fallocate_range(unsigned int xid, + struct file_allocated_range_buffer in_data, *out_data = NULL, *tmp_data; + u32 out_data_len; + char *buf = NULL; ++ u64 range_start, range_len, range_end; + loff_t l; + int rc; + +@@ -3691,13 +3692,21 @@ static int smb3_simple_fallocate_range(unsigned int xid, + goto out; + } + +- if (off < le64_to_cpu(tmp_data->file_offset)) { ++ range_start = le64_to_cpu(tmp_data->file_offset); ++ range_len = le64_to_cpu(tmp_data->length); ++ if (check_add_overflow(range_start, range_len, &range_end) || ++ range_end > S64_MAX) { ++ rc = -EINVAL; ++ goto out; ++ } ++ ++ if (off < range_start) { + /* + * We are at a hole. Write until the end of the region + * or until the next allocated data, + * whichever comes next. + */ +- l = le64_to_cpu(tmp_data->file_offset) - off; ++ l = range_start - off; + if (len < l) + l = len; + rc = smb3_simple_fallocate_write_range(xid, tcon, +@@ -3714,11 +3723,13 @@ static int smb3_simple_fallocate_range(unsigned int xid, + * until the end of the data or the end of the region + * we are supposed to fallocate, whichever comes first. + */ +- l = le64_to_cpu(tmp_data->length); +- if (len < l) +- l = len; +- off += l; +- len -= l; ++ if (off < range_end) { ++ l = range_end - off; ++ if (len < l) ++ l = len; ++ off += l; ++ len -= l; ++ } + + tmp_data = &tmp_data[1]; + out_data_len -= sizeof(struct file_allocated_range_buffer); +-- +2.53.0 + diff --git a/queue-6.1/wifi-brcmfmac-initialize-sdio-data-work-before-clean.patch b/queue-6.1/wifi-brcmfmac-initialize-sdio-data-work-before-clean.patch new file mode 100644 index 0000000000..6d392dfc2d --- /dev/null +++ b/queue-6.1/wifi-brcmfmac-initialize-sdio-data-work-before-clean.patch @@ -0,0 +1,61 @@ +From adffc2441343cf4fdf3f06698e8f3d4442a69126 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 19 Jun 2026 14:44:01 +0800 +Subject: wifi: brcmfmac: initialize SDIO data work before cleanup + +From: Runyu Xiao + +[ Upstream commit 2a665946e0407a05a3f81bd56a08553c446498e0 ] + +brcmf_sdio_probe() stores the newly allocated bus in sdiodev->bus before +allocating the ordered workqueue. If that allocation fails, the function +jumps to fail and calls brcmf_sdio_remove(). + +brcmf_sdio_remove() unconditionally cancels bus->datawork. Initialize the +work item before the first failure path that can reach brcmf_sdio_remove(), +so the cleanup path always observes a valid work object. + +This issue was found by our static analysis tool and then confirmed by +manual review of the probe error path and the remove-time work drain. The +problem pattern is an early setup failure that reaches a cleanup helper +which cancels an embedded work item before its initializer has run. + +A QEMU PoC forced alloc_ordered_workqueue() to fail at the same point in +brcmf_sdio_probe(), before INIT_WORK(&bus->datawork) is reached. The +resulting fail path calls brcmf_sdio_remove(), and DEBUG_OBJECTS reports +the invalid work drain with brcmf_sdio_probe() and brcmf_sdio_remove() in +the stack. + +Fixes: 9982464379e8 ("brcmfmac: make sdio suspend wait for threads to freeze") +Signed-off-by: Runyu Xiao +Acked-by: Arend van Spriel +Link: https://patch.msgid.link/20260619064401.1048976-1-runyu.xiao@seu.edu.cn +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c +index 5f6c0afe22d49c..fb09d76ea053cb 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c +@@ -4451,6 +4451,7 @@ struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev) + bus->sdiodev = sdiodev; + sdiodev->bus = bus; + skb_queue_head_init(&bus->glom); ++ INIT_WORK(&bus->datawork, brcmf_sdio_dataworker); + bus->txbound = BRCMF_TXBOUND; + bus->rxbound = BRCMF_RXBOUND; + bus->txminmax = BRCMF_TXMINMAX; +@@ -4464,7 +4465,6 @@ struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev) + goto fail; + } + brcmf_sdiod_freezer_count(sdiodev); +- INIT_WORK(&bus->datawork, brcmf_sdio_dataworker); + bus->brcmf_wq = wq; + + /* attempt to attach to the dongle */ +-- +2.53.0 + diff --git a/queue-6.1/wifi-cfg80211-bound-element-id-read-when-checking-no.patch b/queue-6.1/wifi-cfg80211-bound-element-id-read-when-checking-no.patch new file mode 100644 index 0000000000..55bf18cc1e --- /dev/null +++ b/queue-6.1/wifi-cfg80211-bound-element-id-read-when-checking-no.patch @@ -0,0 +1,58 @@ +From 70cff20312ea5aa4a116ec693489b1bab34f0127 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 7 Jul 2026 18:48:28 +0900 +Subject: wifi: cfg80211: bound element ID read when checking non-inheritance +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: HE WEI (ギカク) + +[ Upstream commit cb8afea4655ff004fa7feee825d5c79783525383 ] + +cfg80211_is_element_inherited() reads the first data octet of the +candidate element (id = elem->data[0]) to look it up in an extension +non-inheritance list. It does so after testing elem->id, but without +verifying that the element actually has a data octet. A zero-length +extension element (WLAN_EID_EXTENSION with length 0) therefore makes it +read one octet past the end of the element. + +_ieee802_11_parse_elems_full() runs this check for every element of a +frame once a non-inheritance context exists -- e.g. while parsing a +per-STA profile of a Multi-Link element in a (re)association response, +or a non-transmitted BSS profile -- so a crafted frame from an AP can +trigger a one-octet slab-out-of-bounds read during element parsing: + + BUG: KASAN: slab-out-of-bounds in cfg80211_is_element_inherited + Read of size 1 ... in net/wireless/scan.c + +Return early (treat the element as inherited) when an extension element +carries no data, mirroring the existing handling of empty ID lists. + +The bug was found by fuzzing ieee802_11_parse_elems_full() under KASAN. + +Fixes: f7dacfb11475 ("cfg80211: support non-inheritance element") +Signed-off-by: HE WEI (ギカク) +Link: https://patch.msgid.link/20260707094828.16465-1-skyexpoc@gmail.com +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + net/wireless/scan.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/wireless/scan.c b/net/wireless/scan.c +index ae899e25581d27..1ebe2f3f6f52ac 100644 +--- a/net/wireless/scan.c ++++ b/net/wireless/scan.c +@@ -240,7 +240,7 @@ bool cfg80211_is_element_inherited(const struct element *elem, + return true; + + if (elem->id == WLAN_EID_EXTENSION) { +- if (!ext_id_len) ++ if (!ext_id_len || !elem->datalen) + return true; + loop_len = ext_id_len; + list = &non_inherit_elem->data[3 + id_len]; +-- +2.53.0 + diff --git a/queue-6.1/wifi-cfg80211-cancel-sched-scan-results-work-on-unre.patch b/queue-6.1/wifi-cfg80211-cancel-sched-scan-results-work-on-unre.patch new file mode 100644 index 0000000000..7a8efb1575 --- /dev/null +++ b/queue-6.1/wifi-cfg80211-cancel-sched-scan-results-work-on-unre.patch @@ -0,0 +1,83 @@ +From 1d3f38994513f2458f51a5dee9c23e1b22dd5c66 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 20 Jun 2026 00:25:42 +0800 +Subject: wifi: cfg80211: cancel sched scan results work on unregister + +From: Cen Zhang + +[ Upstream commit edf0730be33696a1bd142792830d392129e495cc ] + +cfg80211_sched_scan_results() can queue rdev->sched_scan_res_wk from a +driver result notification while a scheduled scan request is present. The +work callback recovers the containing cfg80211_registered_device and then +locks the wiphy and walks the scheduled-scan request list. + +wiphy_unregister() already makes the wiphy unreachable and drains rdev work +items before cfg80211_dev_free() can release the object, but it does not +drain sched_scan_res_wk. A queued or running result work item can therefore +cross the unregister/free boundary and access freed rdev state. + +The buggy scenario involves two paths, with each column showing the order +within that path: + +scheduled-scan result path: unregister/free path: +1. cfg80211_sched_scan_results() 1. interface teardown stops and + queues rdev->sched_scan_res_wk. removes the scheduled scan request. +2. cfg80211_wq starts the work 2. wiphy_unregister() drains other + item and recovers rdev. rdev work items. +3. The worker locks rdev->wiphy 3. cfg80211_dev_free() destroys and + and walks rdev state. frees rdev. + +Cancel sched_scan_res_wk in wiphy_unregister() alongside the other rdev +work items. cancel_work_sync() removes a pending result notification and +waits for an already running callback, so cfg80211_dev_free() cannot free +rdev while this work item is still active. + +Validation reproduced this kernel report: +BUG: KASAN: use-after-free in cfg80211_sched_scan_results_wk+0x4a6/0x530 +Workqueue: cfg80211 cfg80211_sched_scan_results_wk [cfg80211] +Read of size 8 +Call trace: + dump_stack_lvl+0x66/0xa0 + print_report+0xce/0x630 + cfg80211_sched_scan_results_wk+0x4a6/0x530 + srso_alias_return_thunk+0x5/0xfbef5 + __virt_addr_valid+0x224/0x430 + kasan_report+0xac/0xe0 + lockdep_hardirqs_on_prepare+0xea/0x1a0 + process_one_work+0x8d0/0x18f0 (kernel/workqueue.c:3212) + lock_is_held_type+0x8f/0x100 + worker_thread+0x5ad/0xfd0 + __kthread_parkme+0xc6/0x200 + kthread+0x31e/0x410 + trace_hardirqs_on+0x1a/0x170 + ret_from_fork+0x576/0x810 + __switch_to+0x57e/0xe20 + __switch_to_asm+0x33/0x70 + ret_from_fork_asm+0x1a/0x30 + +Fixes: 807f8a8c3004 ("cfg80211/nl80211: add support for scheduled scans") +Assisted-by: Codex:gpt-5.5 +Signed-off-by: Cen Zhang +Link: https://patch.msgid.link/20260619162542.3878296-1-zzzccc427@gmail.com +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + net/wireless/core.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/net/wireless/core.c b/net/wireless/core.c +index 2a6a8bdfa72484..6f83ea71b76057 100644 +--- a/net/wireless/core.c ++++ b/net/wireless/core.c +@@ -1125,6 +1125,7 @@ void wiphy_unregister(struct wiphy *wiphy) + /* this has nothing to do now but make sure it's gone */ + cancel_work_sync(&rdev->wiphy_work); + ++ cancel_work_sync(&rdev->sched_scan_res_wk); + cancel_work_sync(&rdev->rfkill_block); + cancel_work_sync(&rdev->conn_work); + flush_work(&rdev->event_work); +-- +2.53.0 + diff --git a/queue-6.1/wifi-cfg80211-reject-unsupported-pmsr-ftm-location-r.patch b/queue-6.1/wifi-cfg80211-reject-unsupported-pmsr-ftm-location-r.patch new file mode 100644 index 0000000000..5849228e2d --- /dev/null +++ b/queue-6.1/wifi-cfg80211-reject-unsupported-pmsr-ftm-location-r.patch @@ -0,0 +1,50 @@ +From 97bb1b16cd1d68b007847946b282f7b9e38fb3fe Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 12 Jun 2026 21:37:11 +0800 +Subject: wifi: cfg80211: reject unsupported PMSR FTM location requests + +From: Zhao Li + +[ Upstream commit 69ef6a7ec277f16d216be8da2b3cbe872786c999 ] + +PMSR FTM location request flags are syntactically valid, but they must +be rejected when the device capability does not advertise support for +them. + +Return an error immediately after rejecting unsupported LCI or civic +location request bits so the request cannot reach the driver. + +Fixes: 9bb7e0f24e7e7 ("cfg80211: add peer measurement with FTM initiator API") +Assisted-by: Codex:gpt-5.5 +Assisted-by: Claude:claude-opus-4.8 +Signed-off-by: Zhao Li +Link: https://patch.msgid.link/20260612133710.93544-2-enderaoelyther@gmail.com +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + net/wireless/pmsr.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/net/wireless/pmsr.c b/net/wireless/pmsr.c +index 647ca369caf994..e3987ba2d40a07 100644 +--- a/net/wireless/pmsr.c ++++ b/net/wireless/pmsr.c +@@ -114,6 +114,7 @@ static int pmsr_parse_ftm(struct cfg80211_registered_device *rdev, + NL_SET_ERR_MSG_ATTR(info->extack, + tb[NL80211_PMSR_FTM_REQ_ATTR_REQUEST_LCI], + "FTM: LCI request not supported"); ++ return -EOPNOTSUPP; + } + + out->ftm.request_civicloc = +@@ -122,6 +123,7 @@ static int pmsr_parse_ftm(struct cfg80211_registered_device *rdev, + NL_SET_ERR_MSG_ATTR(info->extack, + tb[NL80211_PMSR_FTM_REQ_ATTR_REQUEST_CIVICLOC], + "FTM: civic location request not supported"); ++ return -EOPNOTSUPP; + } + + out->ftm.trigger_based = +-- +2.53.0 + diff --git a/queue-6.1/wifi-cfg80211-validate-pmsr-ftm-preamble-range.patch b/queue-6.1/wifi-cfg80211-validate-pmsr-ftm-preamble-range.patch new file mode 100644 index 0000000000..4973fad11a --- /dev/null +++ b/queue-6.1/wifi-cfg80211-validate-pmsr-ftm-preamble-range.patch @@ -0,0 +1,45 @@ +From 3d95fd52be1cc2bdf9298ca61d88bd5d7618f9d3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 12 Jun 2026 21:37:04 +0800 +Subject: wifi: cfg80211: validate PMSR FTM preamble range + +From: Zhao Li + +[ Upstream commit 36230936468f0ba4930e94aef496fc229d4bb951 ] + +PMSR FTM request parsing accepts preamble values outside the +enumerated nl80211 preamble range. + +Reject out-of-range values before using them in the parser capability +bit test using the policy. + +Fixes: 9bb7e0f24e7e7 ("cfg80211: add peer measurement with FTM initiator API") +Assisted-by: Codex:gpt-5.5 +Assisted-by: Claude:claude-opus-4.8 +Signed-off-by: Zhao Li +Link: https://patch.msgid.link/20260612133703.93274-2-enderaoelyther@gmail.com +[drop unnecessary check] +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + net/wireless/nl80211.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c +index dd5bd7826646c2..bb2d19057480b4 100644 +--- a/net/wireless/nl80211.c ++++ b/net/wireless/nl80211.c +@@ -309,7 +309,9 @@ nl80211_ftm_responder_policy[NL80211_FTM_RESP_ATTR_MAX + 1] = { + static const struct nla_policy + nl80211_pmsr_ftm_req_attr_policy[NL80211_PMSR_FTM_REQ_ATTR_MAX + 1] = { + [NL80211_PMSR_FTM_REQ_ATTR_ASAP] = { .type = NLA_FLAG }, +- [NL80211_PMSR_FTM_REQ_ATTR_PREAMBLE] = { .type = NLA_U32 }, ++ [NL80211_PMSR_FTM_REQ_ATTR_PREAMBLE] = ++ NLA_POLICY_RANGE(NLA_U32, NL80211_PREAMBLE_LEGACY, ++ NL80211_PREAMBLE_HE), + [NL80211_PMSR_FTM_REQ_ATTR_NUM_BURSTS_EXP] = + NLA_POLICY_MAX(NLA_U8, 15), + [NL80211_PMSR_FTM_REQ_ATTR_BURST_PERIOD] = { .type = NLA_U16 }, +-- +2.53.0 + diff --git a/queue-6.1/wifi-cfg80211-validate-pmsr-measurement-type-data.patch b/queue-6.1/wifi-cfg80211-validate-pmsr-measurement-type-data.patch new file mode 100644 index 0000000000..40505407ab --- /dev/null +++ b/queue-6.1/wifi-cfg80211-validate-pmsr-measurement-type-data.patch @@ -0,0 +1,76 @@ +From 6490c38b9062432b21c56c9ffb206406dd1aa034 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 12 Jun 2026 21:36:57 +0800 +Subject: wifi: cfg80211: validate PMSR measurement type data + +From: Zhao Li + +[ Upstream commit 41aa973eb05922848dded26875c55ef982ac1c49 ] + +PMSR request parsing accepts missing or duplicated measurement type +entries in NL80211_PMSR_REQ_ATTR_DATA. + +Track whether one measurement type was already provided, reject a +second one immediately, and return an error if the request data block +contains no measurement type at all. + +Fixes: 9bb7e0f24e7e7 ("cfg80211: add peer measurement with FTM initiator API") +Assisted-by: Codex:gpt-5.5 +Assisted-by: Claude:claude-opus-4.8 +Signed-off-by: Zhao Li +Link: https://patch.msgid.link/20260612133656.92900-2-enderaoelyther@gmail.com +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + net/wireless/pmsr.c | 19 +++++++++++++++++-- + 1 file changed, 17 insertions(+), 2 deletions(-) + +diff --git a/net/wireless/pmsr.c b/net/wireless/pmsr.c +index 656464f2de516c..647ca369caf994 100644 +--- a/net/wireless/pmsr.c ++++ b/net/wireless/pmsr.c +@@ -188,6 +188,7 @@ static int pmsr_parse_peer(struct cfg80211_registered_device *rdev, + { + struct nlattr *tb[NL80211_PMSR_PEER_ATTR_MAX + 1]; + struct nlattr *req[NL80211_PMSR_REQ_ATTR_MAX + 1]; ++ bool have_measurement_type = false; + struct nlattr *treq; + int err, rem; + +@@ -240,6 +241,14 @@ static int pmsr_parse_peer(struct cfg80211_registered_device *rdev, + } + + nla_for_each_nested(treq, req[NL80211_PMSR_REQ_ATTR_DATA], rem) { ++ if (have_measurement_type) { ++ NL_SET_ERR_MSG_ATTR(info->extack, treq, ++ "multiple measurement types in request data"); ++ return -EINVAL; ++ } ++ ++ have_measurement_type = true; ++ + switch (nla_type(treq)) { + case NL80211_PMSR_TYPE_FTM: + err = pmsr_parse_ftm(rdev, treq, out, info); +@@ -249,10 +258,16 @@ static int pmsr_parse_peer(struct cfg80211_registered_device *rdev, + "unsupported measurement type"); + err = -EINVAL; + } ++ if (err) ++ return err; + } + +- if (err) +- return err; ++ if (!have_measurement_type) { ++ NL_SET_ERR_MSG_ATTR(info->extack, ++ req[NL80211_PMSR_REQ_ATTR_DATA], ++ "missing measurement type in request data"); ++ return -EINVAL; ++ } + + return 0; + } +-- +2.53.0 + diff --git a/queue-6.1/wifi-ipw2100-fix-potential-memory-leak-in-ipw2100_pc.patch b/queue-6.1/wifi-ipw2100-fix-potential-memory-leak-in-ipw2100_pc.patch new file mode 100644 index 0000000000..6c03bddca8 --- /dev/null +++ b/queue-6.1/wifi-ipw2100-fix-potential-memory-leak-in-ipw2100_pc.patch @@ -0,0 +1,60 @@ +From d7f555b3b02ea989a6d16fdc518828f5fb1eae42 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 20 Jun 2026 12:22:39 +0530 +Subject: wifi: ipw2100: fix potential memory leak in ipw2100_pci_init_one() + +From: Abdun Nihaal + +[ Upstream commit 0d388f62031dbabcba0f44bb91b59f10e88cac17 ] + +The memory allocated in the ipw2100_alloc_device() function is not freed +in some of the error paths in ipw2100_pci_init_one(). Fix that by +converting the direct return into a goto to the error path return. + +The error path when pci_enable_device() fails cannot jump to fail, since +at this point priv is not set, so perform error handling inline. + +Fixes: 2c86c275015c ("Add ipw2100 wireless driver.") +Signed-off-by: Abdun Nihaal +Link: https://patch.msgid.link/20260620065242.93798-1-nihaal@cse.iitm.ac.in +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/intel/ipw2x00/ipw2100.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/drivers/net/wireless/intel/ipw2x00/ipw2100.c b/drivers/net/wireless/intel/ipw2x00/ipw2100.c +index b0f23cf1a621b6..a76e94fcb29558 100644 +--- a/drivers/net/wireless/intel/ipw2x00/ipw2100.c ++++ b/drivers/net/wireless/intel/ipw2x00/ipw2100.c +@@ -6183,6 +6183,8 @@ static int ipw2100_pci_init_one(struct pci_dev *pci_dev, + if (err) { + printk(KERN_WARNING DRV_NAME + "Error calling pci_enable_device.\n"); ++ free_libipw(dev, 0); ++ pci_iounmap(pci_dev, ioaddr); + return err; + } + +@@ -6195,16 +6197,14 @@ static int ipw2100_pci_init_one(struct pci_dev *pci_dev, + if (err) { + printk(KERN_WARNING DRV_NAME + "Error calling pci_set_dma_mask.\n"); +- pci_disable_device(pci_dev); +- return err; ++ goto fail; + } + + err = pci_request_regions(pci_dev, DRV_NAME); + if (err) { + printk(KERN_WARNING DRV_NAME + "Error calling pci_request_regions.\n"); +- pci_disable_device(pci_dev); +- return err; ++ goto fail; + } + + /* We disable the RETRY_TIMEOUT register (0x41) to keep +-- +2.53.0 + diff --git a/queue-6.1/wifi-libertas-fix-memory-leak-in-helper_firmware_cb.patch b/queue-6.1/wifi-libertas-fix-memory-leak-in-helper_firmware_cb.patch new file mode 100644 index 0000000000..0b03b8843b --- /dev/null +++ b/queue-6.1/wifi-libertas-fix-memory-leak-in-helper_firmware_cb.patch @@ -0,0 +1,50 @@ +From 643ae62e5951ff5644acd49afab66f4a44f213e0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 24 Jun 2026 16:53:43 +0800 +Subject: wifi: libertas: fix memory leak in helper_firmware_cb() + +From: Dawei Feng + +[ Upstream commit 63c2391deefb31e1b801b7f32bd502ca4808639b ] + +helper_firmware_cb() neglects to free the single-stage firmware image +after a successful async load, leading to a memory leak in the USB +firmware-download path. + +Fix this memory leak by calling release_firmware() immediately after +lbs_fw_loaded() returns. + +The bug was first flagged by an experimental analysis tool we are +developing for kernel memory-management bugs while analyzing +v6.13-rc1. The tool is still under development and is not yet publicly +available. Manual inspection confirms that the bug is still present in +the current wireless tree. + +An x86_64 allyesconfig build showed no new warnings. As we do not have +compatible Libertas USB hardware for exercising this firmware-download +path, no runtime testing was able to be performed. + +Fixes: 1dfba3060fe7 ("libertas: move firmware lifetime handling to firmware.c") +Signed-off-by: Dawei Feng +Link: https://patch.msgid.link/20260624085343.575508-1-dawei.feng@seu.edu.cn +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/marvell/libertas/firmware.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/net/wireless/marvell/libertas/firmware.c b/drivers/net/wireless/marvell/libertas/firmware.c +index f124110944b7e9..9bf7d4c207b9ed 100644 +--- a/drivers/net/wireless/marvell/libertas/firmware.c ++++ b/drivers/net/wireless/marvell/libertas/firmware.c +@@ -78,6 +78,7 @@ static void helper_firmware_cb(const struct firmware *firmware, void *context) + } else { + /* No main firmware needed for this helper --> success! */ + lbs_fw_loaded(priv, 0, firmware, NULL); ++ release_firmware(firmware); + } + } + +-- +2.53.0 + diff --git a/queue-6.1/wifi-mac80211-free-ap_vlan-bc_buf-skbs-outside-irq-l.patch b/queue-6.1/wifi-mac80211-free-ap_vlan-bc_buf-skbs-outside-irq-l.patch new file mode 100644 index 0000000000..89c57594b2 --- /dev/null +++ b/queue-6.1/wifi-mac80211-free-ap_vlan-bc_buf-skbs-outside-irq-l.patch @@ -0,0 +1,77 @@ +From cc0f1347f0ec57c2e42b3c59aef68b28d7d50286 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 6 Jul 2026 22:08:41 +0800 +Subject: wifi: mac80211: free AP_VLAN bc_buf SKBs outside IRQ lock + +From: Cen Zhang + +[ Upstream commit f3858d5b1432098c1936e03d6e03dd0e33facf60 ] + +ieee80211_do_stop() removes AP_VLAN packets from the parent AP +ps->bc_buf while holding ps->bc_buf.lock with IRQs disabled. It then +calls ieee80211_free_txskb() before dropping the lock. + +ieee80211_free_txskb() is not just a passive SKB release. For SKBs with +TX status state it can report a dropped frame through cfg80211/nl80211, +and that path can reach netlink tap transmit. This is the same reason +the pending queue cleanup in ieee80211_do_stop() already unlinks SKBs +under the queue lock and frees them after IRQ state is restored. + +The buggy scenario involves two paths, with each column showing the +order within that path: + +AP_VLAN management TX: AP_VLAN stop: +1. attach ACK-status state 1. clear the running state +2. queue a multicast SKB on 2. take ps->bc_buf.lock with IRQs + parent ps->bc_buf disabled + 3. unlink the AP_VLAN SKB + 4. call ieee80211_free_txskb() + +Unlink matching AP_VLAN SKBs from ps->bc_buf under the existing lock, +but move them to a local free queue. Drop the lock and restore IRQ state +before calling ieee80211_free_txskb(). + +WARNING: kernel/softirq.c:430 at __local_bh_enable_ip + +Fixes: 397a7a24ef8c ("mac80211: free ps->bc_buf skbs on vlan device stop") +Assisted-by: Codex:gpt-5.5 +Signed-off-by: Cen Zhang +Link: https://patch.msgid.link/20260706140841.581566-1-zzzccc427@gmail.com +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + net/mac80211/iface.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c +index 6818c9d852e8e5..4224a7c244a3d0 100644 +--- a/net/mac80211/iface.c ++++ b/net/mac80211/iface.c +@@ -593,6 +593,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, bool going_do + WARN_ON(!list_empty(&sdata->u.ap.vlans)); + } else if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) { + /* remove all packets in parent bc_buf pointing to this dev */ ++ __skb_queue_head_init(&freeq); + ps = &sdata->bss->ps; + + spin_lock_irqsave(&ps->bc_buf.lock, flags); +@@ -600,10 +601,15 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, bool going_do + if (skb->dev == sdata->dev) { + __skb_unlink(skb, &ps->bc_buf); + local->total_ps_buffered--; +- ieee80211_free_txskb(&local->hw, skb); ++ __skb_queue_tail(&freeq, skb); + } + } + spin_unlock_irqrestore(&ps->bc_buf.lock, flags); ++ ++ skb_queue_walk_safe(&freeq, skb, tmp) { ++ __skb_unlink(skb, &freeq); ++ ieee80211_free_txskb(&local->hw, skb); ++ } + } + + if (going_down) +-- +2.53.0 + diff --git a/queue-6.1/wifi-mac80211_hwsim-clamp-virtio-rx-length-before-sk.patch b/queue-6.1/wifi-mac80211_hwsim-clamp-virtio-rx-length-before-sk.patch new file mode 100644 index 0000000000..8c29e3fa16 --- /dev/null +++ b/queue-6.1/wifi-mac80211_hwsim-clamp-virtio-rx-length-before-sk.patch @@ -0,0 +1,46 @@ +From 4ed9273a0b8a3e54c206b1322ce3e09b48417f4c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 20 Jun 2026 21:45:18 -0500 +Subject: wifi: mac80211_hwsim: clamp virtio RX length before skb_put + +From: Bryam Vargas + +[ Upstream commit 10a2b430f8f06ae14b9590b6f6faa6b588ef0654 ] + +hwsim_virtio_rx_work() passes the virtqueue used-ring length reported by +the device straight to skb_put() on a fixed-size receive skb. A backend +reporting a length larger than the skb tailroom drives skb_put() past the +buffer end and hits skb_over_panic() -- a host-triggerable guest panic +(denial of service). + +Clamp the length to the skb's available room before skb_put(). A +conforming device never reports more than the posted buffer size, so valid +frames are unaffected; a truncated over-report then fails the +length/header checks in hwsim_virtio_handle_cmd() and is dropped, so +truncating rather than dropping here cannot be turned into a parsing +problem. + +Fixes: 5d44fe7c9808 ("mac80211_hwsim: add frame transmission support over virtio") +Signed-off-by: Bryam Vargas +Link: https://patch.msgid.link/20260620-b4-disp-474bee37-v1-1-1a4d37f3e2d4@proton.me +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/mac80211_hwsim.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c +index 316b5f56b6e53f..bb9dabbf1f22c6 100644 +--- a/drivers/net/wireless/mac80211_hwsim.c ++++ b/drivers/net/wireless/mac80211_hwsim.c +@@ -5564,6 +5564,7 @@ static void hwsim_virtio_rx_work(struct work_struct *work) + + skb->data = skb->head; + skb_reset_tail_pointer(skb); ++ len = min(len, skb_end_offset(skb)); + skb_put(skb, len); + hwsim_virtio_handle_cmd(skb); + +-- +2.53.0 + diff --git a/queue-6.1/wifi-nl80211-free-rnr-data-on-mbssid-mismatch.patch b/queue-6.1/wifi-nl80211-free-rnr-data-on-mbssid-mismatch.patch new file mode 100644 index 0000000000..f6c3acba8b --- /dev/null +++ b/queue-6.1/wifi-nl80211-free-rnr-data-on-mbssid-mismatch.patch @@ -0,0 +1,43 @@ +From f0746b366d9985e416be8ab6d91a4319097c03c6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 10 Jun 2026 19:22:09 +0800 +Subject: wifi: nl80211: free RNR data on MBSSID mismatch + +From: Zhao Li + +[ Upstream commit 07a95ec2b54774201fdf4ef7ffb0ca2ab19ed29c ] + +nl80211_parse_beacon() rejects EMA RNR data when there are fewer RNR +entries than MBSSID entries. + +The rejected RNR allocation has not been attached to the beacon data yet, +so free it before returning the error. + +Fixes: dbbb27e183b1 ("cfg80211: support RNR for EMA AP") +Signed-off-by: Zhao Li +Link: https://patch.msgid.link/20260610112208.1308-2-enderaoelyther@gmail.com +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + net/wireless/nl80211.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c +index 36a7b9707eabd2..0146d837b8320e 100644 +--- a/net/wireless/nl80211.c ++++ b/net/wireless/nl80211.c +@@ -5631,8 +5631,10 @@ static int nl80211_parse_beacon(struct cfg80211_registered_device *rdev, + if (IS_ERR(rnr)) + return PTR_ERR(rnr); + +- if (rnr && rnr->cnt < bcn->mbssid_ies->cnt) ++ if (rnr && rnr->cnt < bcn->mbssid_ies->cnt) { ++ kfree(rnr); + return -EINVAL; ++ } + + bcn->rnr_ies = rnr; + } +-- +2.53.0 + diff --git a/queue-6.1/wifi-nl80211-validate-nested-mbssid-ie-blobs.patch b/queue-6.1/wifi-nl80211-validate-nested-mbssid-ie-blobs.patch new file mode 100644 index 0000000000..2a527ed4cc --- /dev/null +++ b/queue-6.1/wifi-nl80211-validate-nested-mbssid-ie-blobs.patch @@ -0,0 +1,67 @@ +From e0b7ac4a2315b11ccf8715313dde4b162edff5b7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 12 Jun 2026 21:18:55 +0800 +Subject: wifi: nl80211: validate nested MBSSID IE blobs + +From: Zhao Li + +[ Upstream commit 7f4b01812323443b55e4c65381c9dc851ff009e3 ] + +Validate each nested NL80211_ATTR_MBSSID_ELEMS entry as a well-formed +information-element stream before storing it for beacon construction. + +RNR parsing already validates each nested blob with validate_ie_attr() +before storing it. Apply the same syntactic IE validation to MBSSID +entries before counting and copying their data and length pointers. + +Fixes: dc1e3cb8da8b ("nl80211: MBSSID and EMA support in AP mode") +Assisted-by: Codex:gpt-5.5 +Assisted-by: Claude:claude-opus-4.8 +Signed-off-by: Zhao Li +Link: https://patch.msgid.link/20260612131854.43575-3-enderaoelyther@gmail.com +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + net/wireless/nl80211.c | 12 ++++++++++-- + 1 file changed, 10 insertions(+), 2 deletions(-) + +diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c +index 0146d837b8320e..dd5bd7826646c2 100644 +--- a/net/wireless/nl80211.c ++++ b/net/wireless/nl80211.c +@@ -5433,7 +5433,8 @@ static int nl80211_parse_mbssid_config(struct wiphy *wiphy, + } + + static struct cfg80211_mbssid_elems * +-nl80211_parse_mbssid_elems(struct wiphy *wiphy, struct nlattr *attrs) ++nl80211_parse_mbssid_elems(struct wiphy *wiphy, struct nlattr *attrs, ++ struct netlink_ext_ack *extack) + { + struct nlattr *nl_elems; + struct cfg80211_mbssid_elems *elems; +@@ -5444,6 +5445,12 @@ nl80211_parse_mbssid_elems(struct wiphy *wiphy, struct nlattr *attrs) + return ERR_PTR(-EINVAL); + + nla_for_each_nested(nl_elems, attrs, rem_elems) { ++ int ret; ++ ++ ret = validate_ie_attr(nl_elems, extack); ++ if (ret) ++ return ERR_PTR(ret); ++ + if (num_elems >= 255) + return ERR_PTR(-EINVAL); + num_elems++; +@@ -5615,7 +5622,8 @@ static int nl80211_parse_beacon(struct cfg80211_registered_device *rdev, + if (attrs[NL80211_ATTR_MBSSID_ELEMS]) { + struct cfg80211_mbssid_elems *mbssid = + nl80211_parse_mbssid_elems(&rdev->wiphy, +- attrs[NL80211_ATTR_MBSSID_ELEMS]); ++ attrs[NL80211_ATTR_MBSSID_ELEMS], ++ extack); + + if (IS_ERR(mbssid)) + return PTR_ERR(mbssid); +-- +2.53.0 + diff --git a/queue-6.1/wifi-p54-validate-rx-frame-length-in-p54_rx_eeprom_r.patch b/queue-6.1/wifi-p54-validate-rx-frame-length-in-p54_rx_eeprom_r.patch new file mode 100644 index 0000000000..072bf45209 --- /dev/null +++ b/queue-6.1/wifi-p54-validate-rx-frame-length-in-p54_rx_eeprom_r.patch @@ -0,0 +1,80 @@ +From 74bcf4e4b0817499115675a21d41e3d1e1d5d537 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 27 Jun 2026 17:05:10 -0700 +Subject: wifi: p54: validate RX frame length in p54_rx_eeprom_readback() + +From: Xiang Mei + +[ Upstream commit ebd6d37fa94bee929e0b4c9ca19fdf9b1dcf6cea ] + +p54_rx_eeprom_readback() copies the requested EEPROM slice out of a +device-supplied readback frame without checking that the skb actually holds +that many bytes. Commit da1b9a55ff11 ("wifi: p54: prevent buffer-overflow in +p54_rx_eeprom_readback()") closed the destination overflow by copying a +fixed priv->eeprom_slice_size (and rejecting a mismatched advertised len), +but the source side is still unbounded: nothing verifies the frame is long +enough to supply that many bytes. + +A malicious USB device can send a short frame whose advertised len matches +priv->eeprom_slice_size while the payload is truncated. The equality check +passes and memcpy() reads past the end of the skb, leaking adjacent heap: + + BUG: KASAN: slab-out-of-bounds in p54_rx (drivers/net/wireless/intersil/p54/txrx.c:507) + Read of size 1016 at addr ffff88800f077114 by task swapper/0/0 + Call Trace: + + ... + __asan_memcpy (mm/kasan/shadow.c:105) + p54_rx (drivers/net/wireless/intersil/p54/txrx.c:507) + p54u_rx_cb (drivers/net/wireless/intersil/p54/p54usb.c:163) + __usb_hcd_giveback_urb (drivers/usb/core/hcd.c:1657) + dummy_timer (drivers/usb/gadget/udc/dummy_hcd.c:2005) + ... + + + The buggy address belongs to the object at ffff88800f0770c0 + which belongs to the cache skbuff_small_head of size 704 + The buggy address is located 84 bytes inside of + allocated 704-byte region [ffff88800f0770c0, ffff88800f077380) + +Check that the slice fits in the skb before copying. + +Fixes: 7cb770729ba8 ("p54: move eeprom code into common library") +Reported-by: Weiming Shi +Assisted-by: Claude:claude-opus-4-8 +Signed-off-by: Xiang Mei +Acked-by: Christian Lamparter +Link: https://patch.msgid.link/20260628000510.4152481-1-xmei5@asu.edu +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/intersil/p54/txrx.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/drivers/net/wireless/intersil/p54/txrx.c b/drivers/net/wireless/intersil/p54/txrx.c +index 2deb1bb54f24bd..dc7bf54e30bba1 100644 +--- a/drivers/net/wireless/intersil/p54/txrx.c ++++ b/drivers/net/wireless/intersil/p54/txrx.c +@@ -499,11 +499,19 @@ static void p54_rx_eeprom_readback(struct p54_common *priv, + if (le16_to_cpu(eeprom->v2.len) != priv->eeprom_slice_size) + return; + ++ if (eeprom->v2.data + priv->eeprom_slice_size > ++ skb_tail_pointer(skb)) ++ return; ++ + memcpy(priv->eeprom, eeprom->v2.data, priv->eeprom_slice_size); + } else { + if (le16_to_cpu(eeprom->v1.len) != priv->eeprom_slice_size) + return; + ++ if (eeprom->v1.data + priv->eeprom_slice_size > ++ skb_tail_pointer(skb)) ++ return; ++ + memcpy(priv->eeprom, eeprom->v1.data, priv->eeprom_slice_size); + } + +-- +2.53.0 + diff --git a/queue-6.1/xfrm-policy-preallocate-inexact-bins-before-xfrm_has.patch b/queue-6.1/xfrm-policy-preallocate-inexact-bins-before-xfrm_has.patch new file mode 100644 index 0000000000..10755dc913 --- /dev/null +++ b/queue-6.1/xfrm-policy-preallocate-inexact-bins-before-xfrm_has.patch @@ -0,0 +1,75 @@ +From 00c0504c77d8a5fa155f301078384e936323355a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 3 Jul 2026 05:19:32 +0000 +Subject: xfrm: policy: preallocate inexact bins before xfrm_hash_rebuild + reinsert + +From: Xiang Mei (Microsoft) + +[ Upstream commit f38f8cce2f7e79775b3db7e8a5eacda04ac908e4 ] + +xfrm_hash_rebuild()'s first loop preallocates the bins/chains the reinsert +loop needs, so the reinsert (after hlist_del_rcu()) cannot allocate or +fail. But its guard is inverted: it skips policies with prefixlen < +threshold and preallocates for the rest. + +prefixlen < threshold is exactly when policy_hash_bysel() returns NULL and +the reinsert takes the allocating xfrm_policy_inexact_insert() path. So the +loop preallocates for the exact policies (which never allocate) and skips +the inexact ones, whose bin/node is then allocated GFP_ATOMIC during +reinsert. On failure the error path only WARN_ONCE()s and continues, +leaving a poisoned bydst node; the next rebuild's hlist_del_rcu() +dereferences LIST_POISON2 and takes a GPF. Reachable under memory pressure, +deterministic via failslab. + +Invert the guard so preallocation covers exactly the reinserted policies; +the reinsert then allocates nothing and cannot fail. + +Crash: + Oops: general protection fault, probably for non-canonical address + 0xfbd59c0000000024: 0000 [#1] SMP KASAN NOPTI + KASAN: maybe wild-memory-access in range [0xdead...] + ... + Workqueue: events xfrm_hash_rebuild + RIP: 0010:xfrm_hash_rebuild+0x5b3/0x1190 + RAX: dead000000000122 (LIST_POISON2 + offset) + ... + Call Trace: + hlist_del_rcu (include/linux/rculist.h:599) + xfrm_hash_rebuild (net/xfrm/xfrm_policy.c:1365) + process_one_work (kernel/workqueue.c:3322) + worker_thread (kernel/workqueue.c:3486) + kthread (kernel/kthread.c:436) + ret_from_fork (arch/x86/kernel/process.c:158) + ret_from_fork_asm (arch/x86/entry/entry_64.S:245) + ... + Kernel panic - not syncing: Fatal exception in interrupt + +Fixes: 24969facd704 ("xfrm: policy: store inexact policies in an rhashtable") +Reported-by: AutonomousCodeSecurity@microsoft.com +Signed-off-by: Xiang Mei (Microsoft) +Reviewed-by: Florian Westphal +Signed-off-by: Steffen Klassert +Signed-off-by: Sasha Levin +--- + net/xfrm/xfrm_policy.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c +index a780fb581388b0..dbaef78f43c215 100644 +--- a/net/xfrm/xfrm_policy.c ++++ b/net/xfrm/xfrm_policy.c +@@ -1295,8 +1295,8 @@ static void xfrm_hash_rebuild(struct work_struct *work) + } + } + +- if (policy->selector.prefixlen_d < dbits || +- policy->selector.prefixlen_s < sbits) ++ if (policy->selector.prefixlen_d >= dbits && ++ policy->selector.prefixlen_s >= sbits) + continue; + + bin = xfrm_policy_inexact_alloc_bin(policy, dir); +-- +2.53.0 + diff --git a/queue-6.1/xfrm6-clear-dst.dev-on-error-to-avoid-double-netdev_.patch b/queue-6.1/xfrm6-clear-dst.dev-on-error-to-avoid-double-netdev_.patch new file mode 100644 index 0000000000..f6887ac24e --- /dev/null +++ b/queue-6.1/xfrm6-clear-dst.dev-on-error-to-avoid-double-netdev_.patch @@ -0,0 +1,60 @@ +From d25d547aff34492c1422a76349f0a9619374f321 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 2 Jul 2026 01:05:16 +0000 +Subject: xfrm6: clear dst.dev on error to avoid double netdev_put in + xfrm6_fill_dst() + +From: Xiang Mei (Microsoft) + +[ Upstream commit 136992de9bb91871084ae52d172610541c76e4d2 ] + +On the error path where in6_dev_get(dev) returns NULL, xfrm6_fill_dst() +releases the device reference with netdev_put() but leaves +xdst->u.dst.dev set. dst_destroy() later calls netdev_put(dst->dev) +again, so the same net_device reference is released twice, underflowing +its refcount (ref_tracker WARNING + "unregister_netdevice: waiting for + to become free"). + +Clear xdst->u.dst.dev after the netdev_put(), the same way the XFRM +device-offload paths xfrm_dev_state_add() and xfrm_dev_policy_add() in +net/xfrm/xfrm_device.c NULL ->dev when releasing the reference on error. + + ref_tracker: reference already released. + ref_tracker: allocated in: + xfrm6_fill_dst (net/ipv6/xfrm6_policy.c:86) + ... + udpv6_sendmsg (net/ipv6/udp.c:1696) + ... + ref_tracker: freed in: + xfrm6_fill_dst (net/ipv6/xfrm6_policy.c:90) + ... + WARNING: lib/ref_tracker.c:322 at ref_tracker_free+0x58b/0x780 + dst_destroy (net/core/dst.c:115) + rcu_core + handle_softirqs + ... + +Fixes: 84c4a9dfbf43 ("xfrm6: release dev before returning error") +Reported-by: AutonomousCodeSecurity@microsoft.com +Signed-off-by: Xiang Mei (Microsoft) +Signed-off-by: Steffen Klassert +Signed-off-by: Sasha Levin +--- + net/ipv6/xfrm6_policy.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c +index c936e083f5d8ab..c945473f6e5fed 100644 +--- a/net/ipv6/xfrm6_policy.c ++++ b/net/ipv6/xfrm6_policy.c +@@ -88,6 +88,7 @@ static int xfrm6_fill_dst(struct xfrm_dst *xdst, struct net_device *dev, + xdst->u.rt6.rt6i_idev = in6_dev_get(dev); + if (!xdst->u.rt6.rt6i_idev) { + netdev_put(dev, &xdst->u.dst.dev_tracker); ++ xdst->u.dst.dev = NULL; + return -ENODEV; + } + +-- +2.53.0 + diff --git a/queue-6.12/accel-ivpu-fix-wrong-register-read-in-lnl-failure-di.patch b/queue-6.12/accel-ivpu-fix-wrong-register-read-in-lnl-failure-di.patch new file mode 100644 index 0000000000..7848a46a9e --- /dev/null +++ b/queue-6.12/accel-ivpu-fix-wrong-register-read-in-lnl-failure-di.patch @@ -0,0 +1,40 @@ +From cd7bbf5a836a48eaa4bcc04d354441d55a439acb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 10 Jul 2026 12:13:31 +0200 +Subject: accel/ivpu: Fix wrong register read in LNL failure diagnostics + +From: Karol Wachowski + +[ Upstream commit e4159045c2704dfe146f0ccb0445d9d074cd6882 ] + +diagnose_failure_lnl() read VPU_HW_BTRS_MTL_INTERRUPT_STAT instead of +VPU_HW_BTRS_LNL_INTERRUPT_STAT, which on LNL and newer parts is a +different register with a different bit layout, so failure diagnostics +decoded the wrong register and reported a bogus error cause. +Read the LNL interrupt status register instead. + +Fixes: 8a27ad81f7d3 ("accel/ivpu: Split IP and buttress code") +Reviewed-by: Andrzej Kacprowski +Signed-off-by: Karol Wachowski +Link: https://patch.msgid.link/20260710101331.1899505-1-karol.wachowski@linux.intel.com +Signed-off-by: Sasha Levin +--- + drivers/accel/ivpu/ivpu_hw_btrs.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/accel/ivpu/ivpu_hw_btrs.c b/drivers/accel/ivpu/ivpu_hw_btrs.c +index 4af1b164d85a73..c9e1922aff5e84 100644 +--- a/drivers/accel/ivpu/ivpu_hw_btrs.c ++++ b/drivers/accel/ivpu/ivpu_hw_btrs.c +@@ -852,7 +852,7 @@ static void diagnose_failure_mtl(struct ivpu_device *vdev) + + static void diagnose_failure_lnl(struct ivpu_device *vdev) + { +- u32 reg = REGB_RD32(VPU_HW_BTRS_MTL_INTERRUPT_STAT) & BTRS_LNL_IRQ_MASK; ++ u32 reg = REGB_RD32(VPU_HW_BTRS_LNL_INTERRUPT_STAT) & BTRS_LNL_IRQ_MASK; + + if (REG_TEST_FLD(VPU_HW_BTRS_LNL_INTERRUPT_STAT, ATS_ERR, reg)) { + ivpu_err(vdev, "ATS_ERR_LOG1 0x%08x ATS_ERR_LOG2 0x%08x\n", +-- +2.53.0 + diff --git a/queue-6.12/alsa-usb-audio-skip-dsd-quirk-for-musical-fidelity-m.patch b/queue-6.12/alsa-usb-audio-skip-dsd-quirk-for-musical-fidelity-m.patch new file mode 100644 index 0000000000..8d472e1343 --- /dev/null +++ b/queue-6.12/alsa-usb-audio-skip-dsd-quirk-for-musical-fidelity-m.patch @@ -0,0 +1,47 @@ +From a9c0ad83b1b23a97b2e9010bd04977a6b72f5d27 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 9 Jul 2026 11:56:06 +0200 +Subject: ALSA: usb-audio: Skip DSD quirk for Musical Fidelity M6s DAC + +From: Takashi Iwai + +[ Upstream commit 93b47e66cc6d6c6382d44b44f5e7f6fc3a7b38c3 ] + +Salvador reported that the recent fix for applying the DSD quirk to +Musical Fidelity devices broke for his M6s DAC model (2772:0502). + +Although this is basically a firmware bug, the model in question is +fairly old, and no further firmware update can be expected, so it'd be +better to address in the driver side. + +As an ad hoc workaround, skip the DSD quirk for this device by adding +an empty quirk entry of 2772:0502; this essentially skips the later +DSD quirk entry by the match with the vendor 2772. + +Fixes: da3a7efff64e ("ALSA: usb-audio: Update for native DSD support quirks") +Reported-by: Salvador Blaya +Closes: https://lore.kernel.org/CAOdyq+qFaqCh=tK_wNnA64hv5pQuA1Y09ANxQ=xK8yR-t4mf9Q@mail.gmail.com +Tested-by: Salvador Blaya +Signed-off-by: Takashi Iwai +Link: https://patch.msgid.link/20260709095614.1418838-1-tiwai@suse.de +Signed-off-by: Sasha Levin +--- + sound/usb/quirks.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c +index 489dd84e20967c..ea2ec3507521ef 100644 +--- a/sound/usb/quirks.c ++++ b/sound/usb/quirks.c +@@ -2369,6 +2369,8 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = { + QUIRK_FLAG_DSD_RAW), + DEVICE_FLG(0x2708, 0x0002, /* Audient iD14 */ + QUIRK_FLAG_IGNORE_CTL_ERROR), ++ DEVICE_FLG(0x2772, 0x0502, /* Musical Fidelity M6s DAC */ ++ 0), /* for avoiding QUIRK_FLAG_DSD_RAW with vendor match */ + DEVICE_FLG(0x2912, 0x30c8, /* Audioengine D1 */ + QUIRK_FLAG_GET_SAMPLE_RATE), + DEVICE_FLG(0x2a70, 0x1881, /* OnePlus Technology (Shenzhen) Co., Ltd. BE02T */ +-- +2.53.0 + diff --git a/queue-6.12/arm64-tegra-fix-cpu-compatible-string-to-cortex-a78a.patch b/queue-6.12/arm64-tegra-fix-cpu-compatible-string-to-cortex-a78a.patch new file mode 100644 index 0000000000..f1a71a80e2 --- /dev/null +++ b/queue-6.12/arm64-tegra-fix-cpu-compatible-string-to-cortex-a78a.patch @@ -0,0 +1,144 @@ +From 39ecbd5d7f99db4d678f5d5a5e25f840bf1a5f56 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 21 Jan 2026 16:15:34 +0530 +Subject: arm64: tegra: Fix CPU compatible string to cortex-a78ae on Tegra234 + +From: Sumit Gupta + +[ Upstream commit 0dfa1e960f86e032007882b032c5cc7d14ebe73e ] + +The Tegra234 SoC uses Cortex-A78AE cores, not Cortex-A78. Update the +compatible string for all CPU nodes to match the actual hardware. + +Tegra234 hardware reports: + # head /proc/cpuinfo | egrep 'implementer|part' + CPU implementer : 0x41 + CPU part : 0xd42 + +Which maps to (from arch/arm64/include/asm/cputype.h): + #define ARM_CPU_IMP_ARM 0x41 + #define ARM_CPU_PART_CORTEX_A78AE 0xD42 + +Fixes: a12cf5c339b08 ("arm64: tegra: Describe Tegra234 CPU hierarchy") +Signed-off-by: Sumit Gupta +Signed-off-by: Thierry Reding +Signed-off-by: Sasha Levin +--- + arch/arm64/boot/dts/nvidia/tegra234.dtsi | 24 ++++++++++++------------ + 1 file changed, 12 insertions(+), 12 deletions(-) + +diff --git a/arch/arm64/boot/dts/nvidia/tegra234.dtsi b/arch/arm64/boot/dts/nvidia/tegra234.dtsi +index 75428e70a69252..c1d2d91975057a 100644 +--- a/arch/arm64/boot/dts/nvidia/tegra234.dtsi ++++ b/arch/arm64/boot/dts/nvidia/tegra234.dtsi +@@ -5262,7 +5262,7 @@ cpus { + #size-cells = <0>; + + cpu0_0: cpu@0 { +- compatible = "arm,cortex-a78"; ++ compatible = "arm,cortex-a78ae"; + device_type = "cpu"; + reg = <0x00000>; + +@@ -5281,7 +5281,7 @@ cpu0_0: cpu@0 { + }; + + cpu0_1: cpu@100 { +- compatible = "arm,cortex-a78"; ++ compatible = "arm,cortex-a78ae"; + device_type = "cpu"; + reg = <0x00100>; + +@@ -5300,7 +5300,7 @@ cpu0_1: cpu@100 { + }; + + cpu0_2: cpu@200 { +- compatible = "arm,cortex-a78"; ++ compatible = "arm,cortex-a78ae"; + device_type = "cpu"; + reg = <0x00200>; + +@@ -5319,7 +5319,7 @@ cpu0_2: cpu@200 { + }; + + cpu0_3: cpu@300 { +- compatible = "arm,cortex-a78"; ++ compatible = "arm,cortex-a78ae"; + device_type = "cpu"; + reg = <0x00300>; + +@@ -5338,7 +5338,7 @@ cpu0_3: cpu@300 { + }; + + cpu1_0: cpu@10000 { +- compatible = "arm,cortex-a78"; ++ compatible = "arm,cortex-a78ae"; + device_type = "cpu"; + reg = <0x10000>; + +@@ -5357,7 +5357,7 @@ cpu1_0: cpu@10000 { + }; + + cpu1_1: cpu@10100 { +- compatible = "arm,cortex-a78"; ++ compatible = "arm,cortex-a78ae"; + device_type = "cpu"; + reg = <0x10100>; + +@@ -5376,7 +5376,7 @@ cpu1_1: cpu@10100 { + }; + + cpu1_2: cpu@10200 { +- compatible = "arm,cortex-a78"; ++ compatible = "arm,cortex-a78ae"; + device_type = "cpu"; + reg = <0x10200>; + +@@ -5395,7 +5395,7 @@ cpu1_2: cpu@10200 { + }; + + cpu1_3: cpu@10300 { +- compatible = "arm,cortex-a78"; ++ compatible = "arm,cortex-a78ae"; + device_type = "cpu"; + reg = <0x10300>; + +@@ -5414,7 +5414,7 @@ cpu1_3: cpu@10300 { + }; + + cpu2_0: cpu@20000 { +- compatible = "arm,cortex-a78"; ++ compatible = "arm,cortex-a78ae"; + device_type = "cpu"; + reg = <0x20000>; + +@@ -5433,7 +5433,7 @@ cpu2_0: cpu@20000 { + }; + + cpu2_1: cpu@20100 { +- compatible = "arm,cortex-a78"; ++ compatible = "arm,cortex-a78ae"; + device_type = "cpu"; + reg = <0x20100>; + +@@ -5452,7 +5452,7 @@ cpu2_1: cpu@20100 { + }; + + cpu2_2: cpu@20200 { +- compatible = "arm,cortex-a78"; ++ compatible = "arm,cortex-a78ae"; + device_type = "cpu"; + reg = <0x20200>; + +@@ -5471,7 +5471,7 @@ cpu2_2: cpu@20200 { + }; + + cpu2_3: cpu@20300 { +- compatible = "arm,cortex-a78"; ++ compatible = "arm,cortex-a78ae"; + device_type = "cpu"; + reg = <0x20300>; + +-- +2.53.0 + diff --git a/queue-6.12/asoc-amd-ps-fix-wrong-acp-version-string-in-pci_requ.patch b/queue-6.12/asoc-amd-ps-fix-wrong-acp-version-string-in-pci_requ.patch new file mode 100644 index 0000000000..b8556e5aa4 --- /dev/null +++ b/queue-6.12/asoc-amd-ps-fix-wrong-acp-version-string-in-pci_requ.patch @@ -0,0 +1,39 @@ +From 52be7cbed75e9e32641ccd9b3581a926655271f7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 7 Jul 2026 11:29:37 +0530 +Subject: ASoC: amd: ps: fix wrong ACP version string in pci_request_regions() + +From: Vijendar Mukunda + +[ Upstream commit f7697ecf6eab9d4887dd731038b3dc405c7e755e ] + +The driver handles ACP6.3/7.0/7.1/7.2 platforms but the region was +claimed with the stale name "AMD ACP6.2 audio" left over from the +original ACP6.2 driver. Correct it to "AMD ACP6.3 audio". + +Fixes: 95e43a170bb1 ("ASoC: amd: add Pink Sardine ACP PCI driver") +Signed-off-by: Vijendar Mukunda +Reviewed-by: Mario Limonciello (AMD) +Link: https://patch.msgid.link/20260707060130.2514138-3-Vijendar.Mukunda@amd.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/amd/ps/pci-ps.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/sound/soc/amd/ps/pci-ps.c b/sound/soc/amd/ps/pci-ps.c +index aec3150ecf5812..eb4b552c942417 100644 +--- a/sound/soc/amd/ps/pci-ps.c ++++ b/sound/soc/amd/ps/pci-ps.c +@@ -570,7 +570,7 @@ static int snd_acp63_probe(struct pci_dev *pci, + return -ENODEV; + } + +- ret = pci_request_regions(pci, "AMD ACP6.2 audio"); ++ ret = pci_request_regions(pci, "AMD ACP6.3 audio"); + if (ret < 0) { + dev_err(&pci->dev, "pci_request_regions failed\n"); + goto disable_pci; +-- +2.53.0 + diff --git a/queue-6.12/asoc-cs42l43-correct-report-for-forced-microphone-ja.patch b/queue-6.12/asoc-cs42l43-correct-report-for-forced-microphone-ja.patch new file mode 100644 index 0000000000..9a684de60d --- /dev/null +++ b/queue-6.12/asoc-cs42l43-correct-report-for-forced-microphone-ja.patch @@ -0,0 +1,45 @@ +From 5f684bf831ebbe226e272d8f6e6060b9089aa23e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 8 Jul 2026 11:34:30 +0100 +Subject: ASoC: cs42l43: Correct report for forced microphone jack + +From: Charles Keepax + +[ Upstream commit f74e6e15485b68b92b2807071e822db6309b7e38 ] + +Currently if the jack is forced to the microphone mode, it will report +as line in. Correct the report to microphone. + +Fixes: fc918cbe874e ("ASoC: cs42l43: Add support for the cs42l43") +Signed-off-by: Charles Keepax +Link: https://patch.msgid.link/20260708103430.1395207-1-ckeepax@opensource.cirrus.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/codecs/cs42l43-jack.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/sound/soc/codecs/cs42l43-jack.c b/sound/soc/codecs/cs42l43-jack.c +index 3a61f222d85fee..57626db1140a2c 100644 +--- a/sound/soc/codecs/cs42l43-jack.c ++++ b/sound/soc/codecs/cs42l43-jack.c +@@ -311,6 +311,7 @@ irqreturn_t cs42l43_bias_detect_clamp(int irq, void *data) + #define CS42L43_JACK_ABSENT 0x0 + + #define CS42L43_JACK_OPTICAL (SND_JACK_MECHANICAL | SND_JACK_AVOUT) ++#define CS42L43_JACK_MICROPHONE (SND_JACK_MECHANICAL | SND_JACK_MICROPHONE) + #define CS42L43_JACK_HEADPHONE (SND_JACK_MECHANICAL | SND_JACK_HEADPHONE) + #define CS42L43_JACK_HEADSET (SND_JACK_MECHANICAL | SND_JACK_HEADSET) + #define CS42L43_JACK_LINEOUT (SND_JACK_MECHANICAL | SND_JACK_LINEOUT) +@@ -879,7 +880,7 @@ static const struct cs42l43_jack_override_mode { + .hsdet_mode = CS42L43_JACK_3_POLE_SWITCHES, + .mic_ctrl = (0x3 << CS42L43_JACK_STEREO_CONFIG_SHIFT) | + CS42L43_HS1_BIAS_EN_MASK | CS42L43_HS2_BIAS_EN_MASK, +- .report = CS42L43_JACK_LINEIN, ++ .report = CS42L43_JACK_MICROPHONE, + }, + [CS42L43_JACK_RAW_OPTICAL] = { + .hsdet_mode = CS42L43_JACK_3_POLE_SWITCHES, +-- +2.53.0 + diff --git a/queue-6.12/asoc-meson-aiu-fifo-spdif-soft-reset-the-s-pdif-data.patch b/queue-6.12/asoc-meson-aiu-fifo-spdif-soft-reset-the-s-pdif-data.patch new file mode 100644 index 0000000000..563f5f5ec3 --- /dev/null +++ b/queue-6.12/asoc-meson-aiu-fifo-spdif-soft-reset-the-s-pdif-data.patch @@ -0,0 +1,64 @@ +From 60ab1f8eb0ba2dfba9aa1158e31c75d4f87f282f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 27 Jun 2026 13:12:05 +0000 +Subject: ASoC: meson: aiu: fifo-spdif: soft reset the S/PDIF datapath on + start/stop + +From: Christian Hewitt + +[ Upstream commit 6b59c53c8adc2b522327407af5e1793a65b67e4b ] + +The I2S FIFO soft-resets its fast domain on start (AIU_RST_SOFT bit 0 + +AIU_I2S_SYNC read in aiu_fifo_i2s_trigger), mirroring the downstream +vendor driver's audio_out_i2s_enable(). The S/PDIF FIFO has no equivalent: +it only toggles the IEC958 DCU, so a stale datapath FIFO can be replayed, +producing the "machine gun noise" buffer underrun - on start when switching +outputs, and on stop when playback ends. The latter is audible on devices +with an always-on S/PDIF-fed DAC (e.g. the ES7144 on the WeTek Play2). + +The vendor driver resets the IEC958 fast domain (AIU_RST_SOFT bit 2) on +both enable and disable (audio_hw_958_enable), and when reconfiguring +(audio_hw_958_reset clears AIU_958_DCU_FF_CTRL then resets). Do the same: +reset before enabling the DCU on start, and before disabling on stop. + +Fixes: 6ae9ca9ce986bf ("ASoC: meson: aiu: add i2s and spdif support") +Signed-off-by: Christian Hewitt +Reviewed-by: Martin Blumenstingl +Link: https://patch.msgid.link/20260627131205.808800-1-christianshewitt@gmail.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/meson/aiu-fifo-spdif.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/sound/soc/meson/aiu-fifo-spdif.c b/sound/soc/meson/aiu-fifo-spdif.c +index e0e00ec026dcc4..a9861c5d663745 100644 +--- a/sound/soc/meson/aiu-fifo-spdif.c ++++ b/sound/soc/meson/aiu-fifo-spdif.c +@@ -24,6 +24,7 @@ + #define AIU_MEM_IEC958_CONTROL_MODE_16BIT BIT(7) + #define AIU_MEM_IEC958_CONTROL_MODE_LINEAR BIT(8) + #define AIU_MEM_IEC958_BUF_CNTL_INIT BIT(0) ++#define AIU_RST_SOFT_958_FAST BIT(2) + + #define AIU_FIFO_SPDIF_BLOCK 8 + +@@ -68,11 +69,15 @@ static int fifo_spdif_trigger(struct snd_pcm_substream *substream, int cmd, + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: ++ snd_soc_component_write(component, AIU_RST_SOFT, ++ AIU_RST_SOFT_958_FAST); + fifo_spdif_dcu_enable(component, true); + break; + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + case SNDRV_PCM_TRIGGER_STOP: ++ snd_soc_component_write(component, AIU_RST_SOFT, ++ AIU_RST_SOFT_958_FAST); + fifo_spdif_dcu_enable(component, false); + break; + default: +-- +2.53.0 + diff --git a/queue-6.12/asoc-tas2562-fix-deprecated-shut-down-gpio-always-cl.patch b/queue-6.12/asoc-tas2562-fix-deprecated-shut-down-gpio-always-cl.patch new file mode 100644 index 0000000000..521148dfce --- /dev/null +++ b/queue-6.12/asoc-tas2562-fix-deprecated-shut-down-gpio-always-cl.patch @@ -0,0 +1,62 @@ +From 64de8558d3e36ee254d71bf4e3c5f4fa1a0d34f2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 6 Jul 2026 21:01:09 +0530 +Subject: ASoC: tas2562: fix deprecated 'shut-down' GPIO always cleared after + lookup + +From: Uday Khare + +[ Upstream commit 3238c634725afbb2a137fdda762208510828f71d ] + +In tas2562_parse_dt(), the fallback lookup for the deprecated +"shut-down" GPIO property is broken due to a missing pair of braces. + +The code intends to reset sdz_gpio to NULL only when the lookup +returns an error that is not -EPROBE_DEFER (so the driver gracefully +continues without a GPIO). However, without braces the statement: + + tas2562->sdz_gpio = NULL; + +falls outside the IS_ERR() check and is executed unconditionally +for every path through the if block, including a successful GPIO +lookup. + +This means any device using the deprecated 'shut-down' DT property +will always have sdz_gpio == NULL after probe, making the GPIO +completely non-functional. + +Fix this by adding the missing braces to scope the NULL assignment +inside the IS_ERR() branch, matching the pattern already used for +the primary 'shutdown' GPIO lookup above. + +Fixes: f78a97003b8b ("ASoC: tas2562: Update shutdown GPIO property") +Signed-off-by: Uday Khare +Link: https://patch.msgid.link/20260706153109.10953-1-udaykhare77@gmail.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/codecs/tas2562.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/sound/soc/codecs/tas2562.c b/sound/soc/codecs/tas2562.c +index 54561ae598b87a..7daa9e9e0f60e9 100644 +--- a/sound/soc/codecs/tas2562.c ++++ b/sound/soc/codecs/tas2562.c +@@ -683,11 +683,12 @@ static int tas2562_parse_dt(struct tas2562_data *tas2562) + if (tas2562->sdz_gpio == NULL) { + tas2562->sdz_gpio = devm_gpiod_get_optional(dev, "shut-down", + GPIOD_OUT_HIGH); +- if (IS_ERR(tas2562->sdz_gpio)) ++ if (IS_ERR(tas2562->sdz_gpio)) { + if (PTR_ERR(tas2562->sdz_gpio) == -EPROBE_DEFER) + return -EPROBE_DEFER; + +- tas2562->sdz_gpio = NULL; ++ tas2562->sdz_gpio = NULL; ++ } + } + + if (tas2562->model_id == TAS2110) +-- +2.53.0 + diff --git a/queue-6.12/ata-sata_dwc_460ex-enable-sata-interrupts-only-after.patch b/queue-6.12/ata-sata_dwc_460ex-enable-sata-interrupts-only-after.patch new file mode 100644 index 0000000000..90493a986a --- /dev/null +++ b/queue-6.12/ata-sata_dwc_460ex-enable-sata-interrupts-only-after.patch @@ -0,0 +1,56 @@ +From 43053a1833506811431d3d59f8d22e01aeebb963 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 12 Jul 2026 14:37:26 -0700 +Subject: ata: sata_dwc_460ex: enable SATA interrupts only after IRQ handler is + registered + +From: Rosen Penev + +[ Upstream commit 4bbc16a353a98023e5ddfca7c1fc0e49971cf4d0 ] + +sata_dwc_enable_interrupts() is called before platform_get_irq() and +ata_host_activate(), leaving the SATA controller's interrupt mask +enabled without a registered handler. If a later step fails (irq +request, phy init, etc.) or if the controller asserts an interrupt +during probe, the irq line may fire with no handler, causing a +spurious interrupt storm. + +Move sata_dwc_enable_interrupts() after ata_host_activate() so that +interrupts are only unmasked once the handler is registered and the +core is fully initialized. + +Fixes: 62936009f35a ("[libata] Add 460EX on-chip SATA driver, sata_dwc_460ex") +Assisted-by: opencode:big-pickle +Signed-off-by: Rosen Penev +Signed-off-by: Damien Le Moal +Signed-off-by: Sasha Levin +--- + drivers/ata/sata_dwc_460ex.c | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c +index 52f5168e4db542..16c1deef389d10 100644 +--- a/drivers/ata/sata_dwc_460ex.c ++++ b/drivers/ata/sata_dwc_460ex.c +@@ -1168,9 +1168,6 @@ static int sata_dwc_probe(struct platform_device *ofdev) + /* Save dev for later use in dev_xxx() routines */ + hsdev->dev = dev; + +- /* Enable SATA Interrupts */ +- sata_dwc_enable_interrupts(hsdev); +- + /* Get SATA interrupt number */ + irq = irq_of_parse_and_map(np, 0); + if (!irq) { +@@ -1203,6 +1200,8 @@ static int sata_dwc_probe(struct platform_device *ofdev) + if (err) + dev_err(dev, "failed to activate host"); + ++ /* Enable SATA Interrupts */ ++ sata_dwc_enable_interrupts(hsdev); + return 0; + + error_out: +-- +2.53.0 + diff --git a/queue-6.12/ata-sata_dwc_460ex-fix-clear_interrupt_bit-clearing-.patch b/queue-6.12/ata-sata_dwc_460ex-fix-clear_interrupt_bit-clearing-.patch new file mode 100644 index 0000000000..5ba112e43b --- /dev/null +++ b/queue-6.12/ata-sata_dwc_460ex-fix-clear_interrupt_bit-clearing-.patch @@ -0,0 +1,45 @@ +From acc8e21011d89c6b212f0688fed3471c374c2c5e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 12 Jul 2026 14:37:27 -0700 +Subject: ata: sata_dwc_460ex: fix clear_interrupt_bit() clearing all pending + interrupts + +From: Rosen Penev + +[ Upstream commit 66c4e310ad71f41e41736d33dd8a1fb5eaaec7f3 ] + +clear_interrupt_bit() ignores the bit argument and performs a +read-write-back of the entire INTPR register. If INTPR uses standard +Write-1-to-Clear semantics, this clears every pending interrupt bit, +not just the intended one. Coalesced interrupts (e.g. DMAT + NEWFP) +would be cleared together, silently losing the second event. + +Write only the specific bit to clear so that other pending interrupts +are preserved. + +Fixes: 62936009f35a ("[libata] Add 460EX on-chip SATA driver, sata_dwc_460ex") +Assisted-by: opencode:big-pickle +Signed-off-by: Rosen Penev +Signed-off-by: Damien Le Moal +Signed-off-by: Sasha Levin +--- + drivers/ata/sata_dwc_460ex.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c +index 97b934fa116e26..74514608a7fada 100644 +--- a/drivers/ata/sata_dwc_460ex.c ++++ b/drivers/ata/sata_dwc_460ex.c +@@ -394,8 +394,7 @@ static void clear_serror(struct ata_port *ap) + + static void clear_interrupt_bit(struct sata_dwc_device *hsdev, u32 bit) + { +- sata_dwc_writel(&hsdev->sata_dwc_regs->intpr, +- sata_dwc_readl(&hsdev->sata_dwc_regs->intpr)); ++ sata_dwc_writel(&hsdev->sata_dwc_regs->intpr, bit); + } + + static u32 qcmd_tag_to_mask(u8 tag) +-- +2.53.0 + diff --git a/queue-6.12/ata-sata_dwc_460ex-fix-infinite-loop-in-ncq-tag-comp.patch b/queue-6.12/ata-sata_dwc_460ex-fix-infinite-loop-in-ncq-tag-comp.patch new file mode 100644 index 0000000000..a4ec906c03 --- /dev/null +++ b/queue-6.12/ata-sata_dwc_460ex-fix-infinite-loop-in-ncq-tag-comp.patch @@ -0,0 +1,54 @@ +From 77debf89ac3b127571ef8451d556024660b9c7ae Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 12 Jul 2026 14:37:28 -0700 +Subject: ata: sata_dwc_460ex: fix infinite loop in NCQ tag completion + bit-scanning + +From: Rosen Penev + +[ Upstream commit c2130f6553f4a5cbdc259de069600117a995f197 ] + +The hand-rolled bit-scanning loop in the NCQ completion path has an +infinite loop bug. When tag_mask has only high bits set (e.g. +0x80000000), the inner while loop left-shifts tag_mask until it +overflows to 0. At that point !(0 & 1) is always true and 0 <<= 1 +stays 0, causing an infinite loop in hardirq context with a spinlock +held. + +Replace the open-coded bit-scanning with __ffs() which correctly +finds the least significant set bit and is bounded by the width of +the argument. + +Fixes: 62936009f35a ("[libata] Add 460EX on-chip SATA driver, sata_dwc_460ex") +Assisted-by: opencode:big-pickle +Signed-off-by: Rosen Penev +Signed-off-by: Damien Le Moal +Signed-off-by: Sasha Levin +--- + drivers/ata/sata_dwc_460ex.c | 9 ++------- + 1 file changed, 2 insertions(+), 7 deletions(-) + +diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c +index 74514608a7fada..66db8dd8ec2670 100644 +--- a/drivers/ata/sata_dwc_460ex.c ++++ b/drivers/ata/sata_dwc_460ex.c +@@ -607,14 +607,9 @@ static irqreturn_t sata_dwc_isr(int irq, void *dev_instance) + status = ap->ops->sff_check_status(ap); + dev_dbg(ap->dev, "%s ATA status register=0x%x\n", __func__, status); + +- tag = 0; + while (tag_mask) { +- while (!(tag_mask & 0x00000001)) { +- tag++; +- tag_mask <<= 1; +- } +- +- tag_mask &= (~0x00000001); ++ tag = __ffs(tag_mask); ++ tag_mask &= ~(1U << tag); + qc = ata_qc_from_tag(ap, tag); + if (unlikely(!qc)) { + dev_err(ap->dev, "failed to get qc"); +-- +2.53.0 + diff --git a/queue-6.12/ata-sata_dwc_460ex-use-platform_get_irq.patch b/queue-6.12/ata-sata_dwc_460ex-use-platform_get_irq.patch new file mode 100644 index 0000000000..c5f03572e2 --- /dev/null +++ b/queue-6.12/ata-sata_dwc_460ex-use-platform_get_irq.patch @@ -0,0 +1,92 @@ +From 50c3a563916660318ff7c185dd625e8d627577bd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 12 Jul 2026 14:37:25 -0700 +Subject: ata: sata_dwc_460ex: use platform_get_irq() + +From: Rosen Penev + +[ Upstream commit a4af122106f73ea510bb35a9ea1dedd980fc0db7 ] + +Replace irq_of_parse_and_map() with platform_get_irq() in both +sata_dwc_dma_init_old() and sata_dwc_probe(). This is the preferred +way to obtain IRQs for platform devices and provides better error +reporting. Remove the now-unnecessary #include . + +irq_of_parse_and_map() requires irq_dispose_mapping(), which is missing. + +Also fix unused variable when CONFIG_SATA_DWC_OLD_DMA is disabled. + +Fixes: 62936009f35a ("[libata] Add 460EX on-chip SATA driver, sata_dwc_460ex") +Assisted-by: opencode:big-pickle +Signed-off-by: Rosen Penev +Signed-off-by: Damien Le Moal +Signed-off-by: Sasha Levin +--- + drivers/ata/sata_dwc_460ex.c | 21 +++++++-------------- + 1 file changed, 7 insertions(+), 14 deletions(-) + +diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c +index 16c1deef389d10..97b934fa116e26 100644 +--- a/drivers/ata/sata_dwc_460ex.c ++++ b/drivers/ata/sata_dwc_460ex.c +@@ -19,7 +19,6 @@ + #include + #include + #include +-#include + #include + #include + #include +@@ -226,7 +225,6 @@ static int sata_dwc_dma_init_old(struct platform_device *pdev, + struct sata_dwc_device *hsdev) + { + struct device *dev = &pdev->dev; +- struct device_node *np = dev->of_node; + + hsdev->dma = devm_kzalloc(dev, sizeof(*hsdev->dma), GFP_KERNEL); + if (!hsdev->dma) +@@ -236,11 +234,9 @@ static int sata_dwc_dma_init_old(struct platform_device *pdev, + hsdev->dma->id = pdev->id; + + /* Get SATA DMA interrupt number */ +- hsdev->dma->irq = irq_of_parse_and_map(np, 1); +- if (!hsdev->dma->irq) { +- dev_err(dev, "no SATA DMA irq\n"); +- return -ENODEV; +- } ++ hsdev->dma->irq = platform_get_irq(pdev, 1); ++ if (hsdev->dma->irq < 0) ++ return hsdev->dma->irq; + + /* Get physical SATA DMA register base address */ + hsdev->dma->regs = devm_platform_ioremap_resource(pdev, 1); +@@ -1125,7 +1121,6 @@ static const struct ata_port_info sata_dwc_port_info[] = { + static int sata_dwc_probe(struct platform_device *ofdev) + { + struct device *dev = &ofdev->dev; +- struct device_node *np = dev->of_node; + struct sata_dwc_device *hsdev; + u32 idr, versionr; + char *ver = (char *)&versionr; +@@ -1169,14 +1164,12 @@ static int sata_dwc_probe(struct platform_device *ofdev) + hsdev->dev = dev; + + /* Get SATA interrupt number */ +- irq = irq_of_parse_and_map(np, 0); +- if (!irq) { +- dev_err(dev, "no SATA DMA irq\n"); +- return -ENODEV; +- } ++ irq = platform_get_irq(ofdev, 0); ++ if (irq < 0) ++ return irq; + + #ifdef CONFIG_SATA_DWC_OLD_DMA +- if (!of_property_present(np, "dmas")) { ++ if (!of_property_present(dev->of_node, "dmas")) { + err = sata_dwc_dma_init_old(ofdev, hsdev); + if (err) + return err; +-- +2.53.0 + diff --git a/queue-6.12/bluetooth-hci_qca-clear-memdump-state-on-invalid-dum.patch b/queue-6.12/bluetooth-hci_qca-clear-memdump-state-on-invalid-dum.patch new file mode 100644 index 0000000000..9406ebd434 --- /dev/null +++ b/queue-6.12/bluetooth-hci_qca-clear-memdump-state-on-invalid-dum.patch @@ -0,0 +1,55 @@ +From 545986a12260a23b3cad84197f0836544479a002 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 9 Jul 2026 14:22:50 +0800 +Subject: Bluetooth: hci_qca: Clear memdump state on invalid dump size + +From: Ruoyu Wang + +[ Upstream commit bf587a10c33e5571a299742e45bc18960b9912e7 ] + +qca_controller_memdump() allocates qca->qca_memdump before processing +the first dump packet. For a sequence-zero packet it then disables IBS, +marks memdump collection active, and reads the advertised dump size. + +If the controller reports a zero dump size, the error path frees the +local qca_memdump object and returns without clearing qca->qca_memdump +or undoing the collection state. A later memdump work item initializes +its local pointer from qca->qca_memdump and skips allocation when that +pointer is non-NULL, so it can operate on freed memory. The stale +collection and IBS-disabled flags can also leave waiters or later +transmit handling blocked behind an aborted dump. + +Clear the saved pointer and memdump state before returning from the +invalid-size path, matching the cleanup used when hci_devcd_init() fails. + +A static analysis checker reported the stale memdump state, and manual +source review confirmed the invalid-size failure path. + +Fixes: 06d3fdfcdf5c ("Bluetooth: hci_qca: Add qcom devcoredump support") +Signed-off-by: Ruoyu Wang +Reviewed-by: Paul Menzel +Reviewed-by: Zijun Hu +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + drivers/bluetooth/hci_qca.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c +index de9fd0e77d398a..524fc638ceb49f 100644 +--- a/drivers/bluetooth/hci_qca.c ++++ b/drivers/bluetooth/hci_qca.c +@@ -1070,6 +1070,10 @@ static void qca_controller_memdump(struct work_struct *work) + if (!(qca_memdump->ram_dump_size)) { + bt_dev_err(hu->hdev, "Rx invalid memdump size"); + kfree(qca_memdump); ++ qca->qca_memdump = NULL; ++ qca->memdump_state = QCA_MEMDUMP_COLLECTED; ++ clear_and_wake_up_bit(QCA_MEMDUMP_COLLECTION, &qca->flags); ++ clear_bit(QCA_IBS_DISABLED, &qca->flags); + kfree_skb(skb); + mutex_unlock(&qca->hci_memdump_lock); + return; +-- +2.53.0 + diff --git a/queue-6.12/bluetooth-mgmt-fix-locking-in-unpair_device-disconne.patch b/queue-6.12/bluetooth-mgmt-fix-locking-in-unpair_device-disconne.patch new file mode 100644 index 0000000000..1fe2d5f697 --- /dev/null +++ b/queue-6.12/bluetooth-mgmt-fix-locking-in-unpair_device-disconne.patch @@ -0,0 +1,88 @@ +From 3fa8e2956a995627ee6585806f324345cdf2ca9a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 10 Jul 2026 11:23:41 +0300 +Subject: Bluetooth: mgmt: fix locking in unpair_device/disconnect_sync + +From: Pauli Virtanen + +[ Upstream commit 16cd66443957e4ad42155c6fec401012f600c6f8 ] + +Dereferencing RCU-protected pointers outside critical sections is +invalid and may lead to UAF. + +Take hdev->lock for hci_conn lookup and hci_abort_conn(). Don't use RCU +to ensure the conn is fully initialized at this point. + +Fixes: 227a0cdf4a028 ("Bluetooth: MGMT: Fix not generating command complete for MGMT_OP_DISCONNECT") +Signed-off-by: Pauli Virtanen +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/mgmt.c | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + +diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c +index 0c09cb5a78e028..a5945cfd71c5a5 100644 +--- a/net/bluetooth/mgmt.c ++++ b/net/bluetooth/mgmt.c +@@ -3012,6 +3012,8 @@ static int unpair_device_sync(struct hci_dev *hdev, void *data) + struct mgmt_cp_unpair_device *cp = cmd->param; + struct hci_conn *conn; + ++ hci_dev_lock(hdev); ++ + if (cp->addr.type == BDADDR_BREDR) + conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, + &cp->addr.bdaddr); +@@ -3019,6 +3021,11 @@ static int unpair_device_sync(struct hci_dev *hdev, void *data) + conn = hci_conn_hash_lookup_le(hdev, &cp->addr.bdaddr, + le_addr_type(cp->addr.type)); + ++ if (conn) ++ hci_conn_get(conn); ++ ++ hci_dev_unlock(hdev); ++ + if (!conn) + return 0; + +@@ -3026,6 +3033,7 @@ static int unpair_device_sync(struct hci_dev *hdev, void *data) + * will clean up the connection no matter the error. + */ + hci_abort_conn(conn, HCI_ERROR_REMOTE_USER_TERM); ++ hci_conn_put(conn); + + return 0; + } +@@ -3173,6 +3181,8 @@ static int disconnect_sync(struct hci_dev *hdev, void *data) + struct mgmt_cp_disconnect *cp = cmd->param; + struct hci_conn *conn; + ++ hci_dev_lock(hdev); ++ + if (cp->addr.type == BDADDR_BREDR) + conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, + &cp->addr.bdaddr); +@@ -3180,6 +3190,11 @@ static int disconnect_sync(struct hci_dev *hdev, void *data) + conn = hci_conn_hash_lookup_le(hdev, &cp->addr.bdaddr, + le_addr_type(cp->addr.type)); + ++ if (conn) ++ hci_conn_get(conn); ++ ++ hci_dev_unlock(hdev); ++ + if (!conn) + return -ENOTCONN; + +@@ -3187,6 +3202,7 @@ static int disconnect_sync(struct hci_dev *hdev, void *data) + * will clean up the connection no matter the error. + */ + hci_abort_conn(conn, HCI_ERROR_REMOTE_USER_TERM); ++ hci_conn_put(conn); + + return 0; + } +-- +2.53.0 + diff --git a/queue-6.12/bluetooth-mgmt-hold-reference-for-hci_conn-in-mgmt_p.patch b/queue-6.12/bluetooth-mgmt-hold-reference-for-hci_conn-in-mgmt_p.patch new file mode 100644 index 0000000000..ec154683fd --- /dev/null +++ b/queue-6.12/bluetooth-mgmt-hold-reference-for-hci_conn-in-mgmt_p.patch @@ -0,0 +1,107 @@ +From 1f0d466074d8206483ef9fbece1db984e181cdea Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 10 Jul 2026 11:23:42 +0300 +Subject: Bluetooth: mgmt: hold reference for hci_conn in mgmt_pending_cmds + +From: Pauli Virtanen + +[ Upstream commit da55f570191d5d72f10c607a7043b947eb05ea46 ] + +Dereferencing RCU-protected pointers outside critical sections is +invalid and may lead to UAF. Use of hci_conn in hci_sync callbacks also +needs to hold refcount to avoid UAF. + +Take appropriate locks for hci_conn lookups, and take refcount for +hci_conn pointers stored in mgmt_pending_cmd so that the pointer stays +valid. + +When accessing conn->state, ensure hdev->lock is held to avoid data +race. + +Fixes: 7b445e220db9 ("Bluetooth: MGMT: Fix holding hci_conn reference while command is queued") +Signed-off-by: Pauli Virtanen +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/mgmt.c | 26 ++++++++++++++++++++++---- + 1 file changed, 22 insertions(+), 4 deletions(-) + +diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c +index a5945cfd71c5a5..f472ce8fb978bd 100644 +--- a/net/bluetooth/mgmt.c ++++ b/net/bluetooth/mgmt.c +@@ -7425,6 +7425,9 @@ static void get_conn_info_complete(struct hci_dev *hdev, void *data, int err) + rp.max_tx_power = HCI_TX_POWER_INVALID; + } + ++ if (conn) ++ hci_conn_put(conn); ++ + mgmt_cmd_complete(cmd->sk, cmd->hdev->id, MGMT_OP_GET_CONN_INFO, status, + &rp, sizeof(rp)); + +@@ -7439,6 +7442,8 @@ static int get_conn_info_sync(struct hci_dev *hdev, void *data) + int err; + __le16 handle; + ++ hci_dev_lock(hdev); ++ + /* Make sure we are still connected */ + if (cp->addr.type == BDADDR_BREDR) + conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, +@@ -7446,12 +7451,16 @@ static int get_conn_info_sync(struct hci_dev *hdev, void *data) + else + conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr); + +- if (!conn || conn->state != BT_CONNECTED) ++ if (!conn || conn->state != BT_CONNECTED) { ++ hci_dev_unlock(hdev); + return MGMT_STATUS_NOT_CONNECTED; ++ } + +- cmd->user_data = conn; ++ cmd->user_data = hci_conn_get(conn); + handle = cpu_to_le16(conn->handle); + ++ hci_dev_unlock(hdev); ++ + /* Refresh RSSI each time */ + err = hci_read_rssi_sync(hdev, handle); + +@@ -7585,6 +7594,9 @@ static void get_clock_info_complete(struct hci_dev *hdev, void *data, int err) + } + + complete: ++ if (conn) ++ hci_conn_put(conn); ++ + mgmt_cmd_complete(cmd->sk, cmd->hdev->id, cmd->opcode, status, &rp, + sizeof(rp)); + +@@ -7601,15 +7613,21 @@ static int get_clock_info_sync(struct hci_dev *hdev, void *data) + memset(&hci_cp, 0, sizeof(hci_cp)); + hci_read_clock_sync(hdev, &hci_cp); + ++ hci_dev_lock(hdev); ++ + /* Make sure connection still exists */ + conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->addr.bdaddr); +- if (!conn || conn->state != BT_CONNECTED) ++ if (!conn || conn->state != BT_CONNECTED) { ++ hci_dev_unlock(hdev); + return MGMT_STATUS_NOT_CONNECTED; ++ } + +- cmd->user_data = conn; ++ cmd->user_data = hci_conn_get(conn); + hci_cp.handle = cpu_to_le16(conn->handle); + hci_cp.which = 0x01; /* Piconet clock */ + ++ hci_dev_unlock(hdev); ++ + return hci_read_clock_sync(hdev, &hci_cp); + } + +-- +2.53.0 + diff --git a/queue-6.12/bluetooth-mgmt-revalidate-load_conn_param-queued-upd.patch b/queue-6.12/bluetooth-mgmt-revalidate-load_conn_param-queued-upd.patch new file mode 100644 index 0000000000..39146fad2c --- /dev/null +++ b/queue-6.12/bluetooth-mgmt-revalidate-load_conn_param-queued-upd.patch @@ -0,0 +1,131 @@ +From 13806c208f009734f7c7271a9fe0d7f95554cf40 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 7 Jul 2026 12:15:18 +0800 +Subject: Bluetooth: MGMT: revalidate LOAD_CONN_PARAM queued update + +From: Cen Zhang + +[ Upstream commit 2bf282f8f715f5d05d6f4c49ffb3bd241c5e667e ] + +MGMT_OP_LOAD_CONN_PARAM queues conn_update_sync() when a single parameter +update changes an existing LE central connection. The queued work currently +stores a borrowed hci_conn_params entry from hdev->le_conn_params. A later +LOAD_CONN_PARAM request can clear disabled parameters and free that entry +before hci_cmd_sync_work() runs the queued callback. + +Do not keep the borrowed hci_conn_params pointer in queued work. Queue the +hci_conn instead and hold a reference until the queued callback completes. +When the work runs, revalidate that the connection is still present, look +up the current hci_conn_params entry, and cancel the update if userspace +removed that entry while the work was pending. + +Copy the interval values from the current params entry under hdev->lock, +then drop the lock and keep using hci_le_conn_update_sync() to issue the +update. + +Validation reproduced this kernel report: +BUG: KASAN: slab-use-after-free in conn_update_sync+0x2a/0xf0 [bluetooth] +Read of size 1 at addr ffff88810c697126 by task kworker/u17:0/377 +Workqueue: hci0 hci_cmd_sync_work [bluetooth] + +Call Trace: + + dump_stack_lvl+0x66/0xa0 + print_report+0xce/0x5f0 + kasan_report+0xe0/0x110 + conn_update_sync+0x2a/0xf0 [bluetooth] + hci_cmd_sync_work+0x187/0x210 [bluetooth] + process_one_work+0x4fd/0xbc0 + worker_thread+0x2d8/0x570 + kthread+0x1ad/0x1f0 + ret_from_fork+0x3c9/0x540 + ret_from_fork_asm+0x1a/0x30 + +Allocated by task 466: + hci_conn_params_add+0xa6/0x240 [bluetooth] + load_conn_param+0x4e1/0x850 [bluetooth] + hci_sock_sendmsg+0x96b/0xf80 [bluetooth] + +Freed by task 474: + kfree+0x313/0x590 + hci_conn_params_clear_disabled+0x9b/0xc0 [bluetooth] + load_conn_param+0x4bf/0x850 [bluetooth] + hci_sock_sendmsg+0x96b/0xf80 [bluetooth] + +Fixes: 0ece498c27d8c ("Bluetooth: MGMT: Make MGMT_OP_LOAD_CONN_PARAM update existing connection") +Suggested-by: Luiz Augusto von Dentz +Assisted-by: Codex:gpt-5.5 +Signed-off-by: Cen Zhang +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/mgmt.c | 44 +++++++++++++++++++++++++++++++++++--------- + 1 file changed, 35 insertions(+), 9 deletions(-) + +diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c +index 6280fcfcdd0c6a..0c09cb5a78e028 100644 +--- a/net/bluetooth/mgmt.c ++++ b/net/bluetooth/mgmt.c +@@ -8024,14 +8024,36 @@ static int remove_device(struct sock *sk, struct hci_dev *hdev, + + static int conn_update_sync(struct hci_dev *hdev, void *data) + { +- struct hci_conn_params *params = data; +- struct hci_conn *conn; ++ struct hci_conn *conn = data; ++ struct hci_conn_params *params; ++ struct hci_conn_params local = {}; + +- conn = hci_conn_hash_lookup_le(hdev, ¶ms->addr, params->addr_type); +- if (!conn) +- return -ECANCELED; ++ hci_dev_lock(hdev); ++ ++ if (!hci_conn_valid(hdev, conn) || conn->role != HCI_ROLE_MASTER) ++ goto cancel; ++ ++ params = hci_conn_params_lookup(hdev, &conn->dst, conn->dst_type); ++ if (!params) ++ goto cancel; ++ ++ local.conn_min_interval = params->conn_min_interval; ++ local.conn_max_interval = params->conn_max_interval; ++ local.conn_latency = params->conn_latency; ++ local.supervision_timeout = params->supervision_timeout; + +- return hci_le_conn_update_sync(hdev, conn, params); ++ hci_dev_unlock(hdev); ++ ++ return hci_le_conn_update_sync(hdev, conn, &local); ++ ++cancel: ++ hci_dev_unlock(hdev); ++ return -ECANCELED; ++} ++ ++static void conn_update_sync_destroy(struct hci_dev *hdev, void *data, int err) ++{ ++ hci_conn_put(data); + } + + static int load_conn_param(struct sock *sk, struct hci_dev *hdev, void *data, +@@ -8141,9 +8163,13 @@ static int load_conn_param(struct sock *sk, struct hci_dev *hdev, void *data, + (conn->le_conn_min_interval != min || + conn->le_conn_max_interval != max || + conn->le_conn_latency != latency || +- conn->le_supv_timeout != timeout)) +- hci_cmd_sync_queue(hdev, conn_update_sync, +- hci_param, NULL); ++ conn->le_supv_timeout != timeout)) { ++ hci_conn_get(conn); ++ if (hci_cmd_sync_queue(hdev, conn_update_sync, ++ conn, ++ conn_update_sync_destroy) < 0) ++ hci_conn_put(conn); ++ } + } + } + +-- +2.53.0 + diff --git a/queue-6.12/bluetooth-qca-fix-nvm-tag-length-underflow-in-tlv-pa.patch b/queue-6.12/bluetooth-qca-fix-nvm-tag-length-underflow-in-tlv-pa.patch new file mode 100644 index 0000000000..2bcdc9b024 --- /dev/null +++ b/queue-6.12/bluetooth-qca-fix-nvm-tag-length-underflow-in-tlv-pa.patch @@ -0,0 +1,68 @@ +From 20bbffc2d1ff1546ffd400d10e6e8f40548d2991 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 4 Jul 2026 16:10:30 -0700 +Subject: Bluetooth: qca: fix NVM tag length underflow in TLV parser + +From: Xiang Mei + +[ Upstream commit c90164ca0f7036942ba088eb7ea8d3f6c2352020 ] + +In the TLV_TYPE_NVM branch of qca_tlv_check_data() the tag loop bound is +"while (idx < length - sizeof(struct tlv_type_nvm))". "length" is a signed +int from the firmware TLV header and sizeof(struct tlv_type_nvm) is a +size_t (12), so "length" is converted to size_t and any firmware-supplied +"length" < 12 makes the subtraction wrap to a huge value. The loop body +then reads a 12-byte struct tlv_type_nvm past the end of the short +vmalloc'd firmware buffer (and the EDL_TAG_ID_* handlers can write past it). + +Rewrite the bound as "idx + sizeof(struct tlv_type_nvm) <= length"; both +operands are non-negative, so it no longer underflows and a "length" too +small for one record correctly skips the loop. + + BUG: KASAN: vmalloc-out-of-bounds in qca_download_firmware.isra.0 (drivers/bluetooth/btqca.c:421) + Read of size 2 at addr ffffc900000e5004 by task kworker/u9:0/52 + Workqueue: hci0 hci_power_on + Call Trace: + ... + kasan_report (mm/kasan/report.c:595) + qca_download_firmware.isra.0 (drivers/bluetooth/btqca.c:421 drivers/bluetooth/btqca.c:617) + qca_uart_setup (drivers/bluetooth/btqca.c:948) + qca_setup (drivers/bluetooth/hci_qca.c:2029) + hci_uart_setup (drivers/bluetooth/hci_ldisc.c:438) + hci_dev_open_sync (net/bluetooth/hci_sync.c:5227) + hci_power_on (net/bluetooth/hci_core.c:920) + process_one_work (kernel/workqueue.c:3322) + worker_thread (kernel/workqueue.c:3486) + kthread (kernel/kthread.c:436) + ret_from_fork (arch/x86/kernel/process.c:158) + ret_from_fork_asm (arch/x86/entry/entry_64.S:245) + +Fixes: 2e4edfa1e2bd ("Bluetooth: qca: add missing firmware sanity checks") +Reported-by: Weiming Shi +Assisted-by: Claude:claude-opus-4-8 +Signed-off-by: Xiang Mei +Reported-by: Weiming Shi +Reviewed-by: Johan Hovold +Acked-by: Bartosz Golaszewski +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + drivers/bluetooth/btqca.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/bluetooth/btqca.c b/drivers/bluetooth/btqca.c +index 372427747cd649..083a599eec74db 100644 +--- a/drivers/bluetooth/btqca.c ++++ b/drivers/bluetooth/btqca.c +@@ -413,7 +413,7 @@ static int qca_tlv_check_data(struct hci_dev *hdev, + + idx = 0; + data = tlv->data; +- while (idx < length - sizeof(struct tlv_type_nvm)) { ++ while (idx + sizeof(struct tlv_type_nvm) <= length) { + tlv_nvm = (struct tlv_type_nvm *)(data + idx); + + tag_id = le16_to_cpu(tlv_nvm->tag_id); +-- +2.53.0 + diff --git a/queue-6.12/bpf-sockmap-reject-unhashed-udp-sockets-on-sockmap-u.patch b/queue-6.12/bpf-sockmap-reject-unhashed-udp-sockets-on-sockmap-u.patch new file mode 100644 index 0000000000..3144633bad --- /dev/null +++ b/queue-6.12/bpf-sockmap-reject-unhashed-udp-sockets-on-sockmap-u.patch @@ -0,0 +1,74 @@ +From 3455fb2d4c77b92b72b831ec98f8fbd299a4b252 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 7 Jul 2026 06:23:57 +0200 +Subject: bpf, sockmap: Reject unhashed UDP sockets on sockmap update + +From: Michal Luczaj + +[ Upstream commit 66efd3368ae10d05e08fbe6425b50fdec7186ac7 ] + +UDP sockets get SOCK_RCU_FREE set when (auto-)bound. This means +sk_is_refcounted(unbound) = true, while sk_is_refcounted(bound) = false. + +Because sockmap accepts unbound UDP sockets, a BPF program can increment a +socket's refcount via lookup. If the socket is subsequently bound, the +transition from unbound to bound causes bpf_sk_release() to skip the +decrement of the refcount, causing a memory leak. + +unreferenced object 0xffff88810bc2eb40 (size 1984): + comm "test_progs", pid 2451, jiffies 4295320596 + hex dump (first 32 bytes): + 7f 00 00 01 7f 00 00 01 d2 04 1b b7 04 d2 00 00 ................ + 02 00 01 40 00 00 00 00 00 00 00 00 00 00 00 00 ...@............ + backtrace (crc bdee079d): + kmem_cache_alloc_noprof+0x557/0x660 + sk_prot_alloc+0x69/0x240 + sk_alloc+0x30/0x460 + inet_create+0x2ce/0xf80 + __sock_create+0x25b/0x5c0 + __sys_socket+0x119/0x1d0 + __x64_sys_socket+0x72/0xd0 + do_syscall_64+0xa1/0x5f0 + entry_SYSCALL_64_after_hwframe+0x76/0x7e + +Instead of special-casing for refcounted sockets, reject unhashed UDP +sockets during sockmap updates, as there is no benefit to supporting those. +This effectively reverts the commit under Fixes, with two exceptions: + +1. sock_map_sk_state_allowed() maintains a fall-through `return true`. +2. In the spirit of commit b8b8315e39ff ("bpf, sockmap: Remove unhash + handler for BPF sockmap usage"), the proto::unhash BPF handler is not + reintroduced. + +Historical note: this issue is related to commit 67312adc96b5 ("bpf: reject +unhashed sockets in bpf_sk_assign"). + +Fixes: 0c48eefae712 ("sock_map: Lift socket state restriction for datagram sockets") +Suggested-by: Kuniyuki Iwashima +Signed-off-by: Michal Luczaj +Reviewed-by: Kuniyuki Iwashima +Reviewed-by: Jakub Sitnicki +Reviewed-by: John Fastabend +Link: https://lore.kernel.org/bpf/20260707-sockmap-lookup-udp-leak-v4-2-f878346f27ab@rbox.co +Signed-off-by: Kumar Kartikeya Dwivedi +Signed-off-by: Sasha Levin +--- + net/core/sock_map.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/net/core/sock_map.c b/net/core/sock_map.c +index 82a14f131d00c6..6440ce16fc6214 100644 +--- a/net/core/sock_map.c ++++ b/net/core/sock_map.c +@@ -542,6 +542,8 @@ static bool sock_map_sk_state_allowed(const struct sock *sk) + { + if (sk_is_tcp(sk)) + return (1 << sk->sk_state) & (TCPF_ESTABLISHED | TCPF_LISTEN); ++ if (sk_is_udp(sk)) ++ return sk_hashed(sk); + if (sk_is_stream_unix(sk)) + return (1 << sk->sk_state) & TCPF_ESTABLISHED; + if (sk_is_vsock(sk) && +-- +2.53.0 + diff --git a/queue-6.12/btrfs-fix-root-leak-if-its-reloc-root-is-unexpected-.patch b/queue-6.12/btrfs-fix-root-leak-if-its-reloc-root-is-unexpected-.patch new file mode 100644 index 0000000000..4d33baedc0 --- /dev/null +++ b/queue-6.12/btrfs-fix-root-leak-if-its-reloc-root-is-unexpected-.patch @@ -0,0 +1,40 @@ +From 2e7001078bfd090f024c8555205b99f2fbe1e430 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 11 Jun 2026 15:16:21 +0100 +Subject: btrfs: fix root leak if its reloc root is unexpected in + merge_reloc_roots() + +From: Filipe Manana + +[ Upstream commit ce6050bafb4e33377dc17fcc357736bfc351180c ] + +If we have an unexpected reloc_root for our root, we jump to the out label +but never drop the reference we obtained for root, resulting in a leak. +Add a missing btrfs_put_root() call. + +Fixes: 24213fa46c70 ("btrfs: do proper error handling in merge_reloc_roots") +Reviewed-by: Qu Wenruo +Reviewed-by: Johannes Thumshirn +Signed-off-by: Filipe Manana +Reviewed-by: David Sterba +Signed-off-by: David Sterba +Signed-off-by: Sasha Levin +--- + fs/btrfs/relocation.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c +index 43e8c331168e94..d2a1323e8b1034 100644 +--- a/fs/btrfs/relocation.c ++++ b/fs/btrfs/relocation.c +@@ -1956,6 +1956,7 @@ void merge_reloc_roots(struct reloc_control *rc) + * corruption, e.g. bad reloc tree key offset. + */ + ret = -EINVAL; ++ btrfs_put_root(root); + goto out; + } + ret = merge_reloc_root(rc, root); +-- +2.53.0 + diff --git a/queue-6.12/btrfs-reject-free-space-cache-with-more-entries-than.patch b/queue-6.12/btrfs-reject-free-space-cache-with-more-entries-than.patch new file mode 100644 index 0000000000..3f53cd1e40 --- /dev/null +++ b/queue-6.12/btrfs-reject-free-space-cache-with-more-entries-than.patch @@ -0,0 +1,88 @@ +From da1ecd3bb3658a3edb5ddf72acd7c475c8adcc16 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 10 Jun 2026 10:29:26 -0700 +Subject: btrfs: reject free space cache with more entries than pages + +From: Xiang Mei + +[ Upstream commit a2d8d5647ed854e38f941741aea45b9eb15a6350 ] + +When loading a v1 free space cache, __load_free_space_cache() takes +num_entries and num_bitmaps straight from the on-disk +btrfs_free_space_header. That header is stored in the tree_root under a key +with type 0, which the tree-checker has no case for, so neither count is +validated before the load trusts it. + +The load loops num_entries times and maps the next page whenever the current +one runs out, going through io_ctl_check_crc() -> io_ctl_map_page(), which +does io_ctl->pages[io_ctl->index++]. But pages[] is allocated in +io_ctl_init() from the cache inode's i_size, not from num_entries: + + num_pages = DIV_ROUND_UP(i_size_read(inode), PAGE_SIZE); + io_ctl->pages = kcalloc(num_pages, sizeof(struct page *), GFP_NOFS); + +So if num_entries claims more records than the pages can hold, io_ctl->index +runs off the end of pages[]. The write side never hits this because +io_ctl_add_entry() and io_ctl_add_bitmap() both stop once +io_ctl->index >= io_ctl->num_pages; the read side just never had the same +check. + +To trigger it, take a clean cache (num_entries = here), set num_entries +in the header to 0x10000, and fix up the leaf checksum so it still passes +the tree-checker. The cache inode has i_size = 65536, so num_pages is 16 and +pages[] is a 16-pointer (kmalloc-128) array. The load now tries to read +65536 entries, io_ctl->index walks up to 16, and pages[16] is read past the +array: + + BUG: KASAN: slab-out-of-bounds in io_ctl_check_crc (fs/btrfs/free-space-cache.c:420 fs/btrfs/free-space-cache.c:565) + Read of size 8 at addr ffff88800c833a80 by task kworker/u8:3/58 + io_ctl_check_crc (fs/btrfs/free-space-cache.c:420 fs/btrfs/free-space-cache.c:565) + __load_free_space_cache (fs/btrfs/free-space-cache.c:655 fs/btrfs/free-space-cache.c:820) + load_free_space_cache (fs/btrfs/free-space-cache.c:1017) + caching_thread (fs/btrfs/block-group.c:880) + btrfs_work_helper (fs/btrfs/async-thread.c:312) + process_one_work + worker_thread + kthread + ret_from_fork + +free-space-cache.c:420 is io_ctl_map_page(), inlined into io_ctl_check_crc() +at line 565, which is why that is the frame KASAN names. The out-of-bounds +slot is then treated as a struct page and handed to crc32c(), so the bad +read turns into a GP fault. + +Add the missing check to io_ctl_check_crc(), which is where both the entry +loop and the bitmap loop end up. When num_entries is too large the load now +fails like any corrupt cache: __load_free_space_cache() drops it and rebuilds +the free space from the extent tree, so a valid cache is never rejected. + +Reported-by: Weiming Shi +Fixes: 5b0e95bf607d ("Btrfs: inline checksums into the disk free space cache") +Link: https://lore.kernel.org/linux-btrfs/CAPpSM+RMPByMCKXvM5QFKToxsyNccfuFLWMdD0mfd0wh2Ja62w@mail.gmail.com/ +Assisted-by: Claude:claude-opus-4-8 +Reviewed-by: Qu Wenruo +Signed-off-by: Xiang Mei +Reviewed-by: David Sterba +Signed-off-by: David Sterba +Signed-off-by: Sasha Levin +--- + fs/btrfs/free-space-cache.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c +index f4bcb25306606a..01588dd3c7028f 100644 +--- a/fs/btrfs/free-space-cache.c ++++ b/fs/btrfs/free-space-cache.c +@@ -556,6 +556,9 @@ static int io_ctl_check_crc(struct btrfs_io_ctl *io_ctl, int index) + u32 crc = ~(u32)0; + unsigned offset = 0; + ++ if (index >= io_ctl->num_pages) ++ return -EIO; ++ + if (index == 0) + offset = sizeof(u32) * io_ctl->num_pages; + +-- +2.53.0 + diff --git a/queue-6.12/can-j1939-fix-lockless-local-destination-check.patch b/queue-6.12/can-j1939-fix-lockless-local-destination-check.patch new file mode 100644 index 0000000000..2f9f40dfe7 --- /dev/null +++ b/queue-6.12/can-j1939-fix-lockless-local-destination-check.patch @@ -0,0 +1,81 @@ +From c934e6698c7c28c97b55d181aaf5c5bf4de26771 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 7 May 2026 10:22:26 +0200 +Subject: can: j1939: fix lockless local-destination check + +From: Shuhao Fu + +[ Upstream commit e4e8af62adab2fdcca230006f829407a953070cd ] + +j1939_priv.ents[].nusers is documented as protected by priv->lock, and +its updates already happen under that lock. j1939_can_recv() also reads +it under read_lock_bh(). However, j1939_session_skb_queue() and +j1939_tp_send() still read priv->ents[da].nusers without taking the +lock. + +Those transport-side checks decide whether to set J1939_ECU_LOCAL_DST, so +they can race with j1939_local_ecu_get() and j1939_local_ecu_put() while +userspace is binding or releasing sockets concurrently with TP traffic. +This can misclassify TP/ETP sessions as local or remote and take the wrong +transport path. + +Fix both transport paths by routing the destination-locality check through +a helper that reads ents[].nusers under read_lock_bh(&priv->lock). + +Fixes: 9d71dd0c7009 ("can: add support of SAE J1939 protocol") +Signed-off-by: Shuhao Fu +Tested-by: Oleksij Rempel +Acked-by: Oleksij Rempel +Link: https://patch.msgid.link/20260419140614.GA4041240@chcpu16 +Signed-off-by: Marc Kleine-Budde +Signed-off-by: Sasha Levin +--- + net/can/j1939/transport.c | 18 ++++++++++++++---- + 1 file changed, 14 insertions(+), 4 deletions(-) + +diff --git a/net/can/j1939/transport.c b/net/can/j1939/transport.c +index 6c37562a50f72e..d8dada03b3cd12 100644 +--- a/net/can/j1939/transport.c ++++ b/net/can/j1939/transport.c +@@ -350,6 +350,18 @@ static void j1939_session_skb_drop_old(struct j1939_session *session) + } + } + ++static bool j1939_address_is_local(struct j1939_priv *priv, u8 addr) ++{ ++ bool local = false; ++ ++ read_lock_bh(&priv->lock); ++ if (j1939_address_is_unicast(addr) && priv->ents[addr].nusers) ++ local = true; ++ read_unlock_bh(&priv->lock); ++ ++ return local; ++} ++ + void j1939_session_skb_queue(struct j1939_session *session, + struct sk_buff *skb) + { +@@ -358,8 +370,7 @@ void j1939_session_skb_queue(struct j1939_session *session, + + j1939_ac_fixup(priv, skb); + +- if (j1939_address_is_unicast(skcb->addr.da) && +- priv->ents[skcb->addr.da].nusers) ++ if (j1939_address_is_local(priv, skcb->addr.da)) + skcb->flags |= J1939_ECU_LOCAL_DST; + + skcb->flags |= J1939_ECU_LOCAL_SRC; +@@ -2021,8 +2032,7 @@ struct j1939_session *j1939_tp_send(struct j1939_priv *priv, + return ERR_PTR(ret); + + /* fix DST flags, it may be used there soon */ +- if (j1939_address_is_unicast(skcb->addr.da) && +- priv->ents[skcb->addr.da].nusers) ++ if (j1939_address_is_local(priv, skcb->addr.da)) + skcb->flags |= J1939_ECU_LOCAL_DST; + + /* src is always local, I'm sending ... */ +-- +2.53.0 + diff --git a/queue-6.12/cpufreq-make-cpufreq_update_pressure-fall-back-to-cp.patch b/queue-6.12/cpufreq-make-cpufreq_update_pressure-fall-back-to-cp.patch new file mode 100644 index 0000000000..d1b9d62ecf --- /dev/null +++ b/queue-6.12/cpufreq-make-cpufreq_update_pressure-fall-back-to-cp.patch @@ -0,0 +1,55 @@ +From 5ca9a66f6d8f168faa05f7182b3ec8f4151f8180 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 7 Jul 2026 19:25:39 +0200 +Subject: cpufreq: Make cpufreq_update_pressure() fall back to cpuinfo.max_freq + +From: Rafael J. Wysocki + +[ Upstream commit d2d5c129d07ea8eb91cd8a8633b5774116c4d171 ] + +If arch_scale_freq_ref() is not defined for a given arch (like x86, for +example), cpufreq_update_pressure() will always set cpufreq_pressure to +zero for all CPUs in the system, which is generally problematic on +systems with asymmetric capacity [1]. + +However, in the absence of arch_scale_freq_ref(), it is reasonable +to assume that cpuinfo.max_freq is the maximum sustainable frequency +for the given cpufreq policy. Moreover, there are cases in which +arch_scale_freq_ref() would need to be defined to return essentially +the cpuinfo.max_freq value anyway (for example, intel_pstate on +hybrid platforms). + +For the above reasons, update cpufreq_update_pressure() to fall back to +using cpuinfo.max_freq as the reference frequency if zero is returned by +arch_scale_freq_ref(). + +Fixes: 75d659317bb1 ("cpufreq: Add a cpufreq pressure feedback for the scheduler") +Link: https://lore.kernel.org/lkml/CAKfTPtBuRLfYNnR4w--cFZYZy-R8gaPEgVwCcaMmbCcJ2H-muQ@mail.gmail.com/ [1] +Signed-off-by: Rafael J. Wysocki +Acked-by: Viresh Kumar +Reviewed-by: Zhongqiu Han +Tested-by: Ricardo Neri # cluster scheduling +Acked-by: Vincent Guittot +Link: https://patch.msgid.link/5086499.GXAFRqVoOG@rafael.j.wysocki +Signed-off-by: Sasha Levin +--- + drivers/cpufreq/cpufreq.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c +index 17df96564ad6f2..2c86539eb4bc38 100644 +--- a/drivers/cpufreq/cpufreq.c ++++ b/drivers/cpufreq/cpufreq.c +@@ -2601,6 +2601,9 @@ static void cpufreq_update_pressure(struct cpufreq_policy *policy) + + cpu = cpumask_first(policy->related_cpus); + max_freq = arch_scale_freq_ref(cpu); ++ if (!max_freq) ++ max_freq = policy->cpuinfo.max_freq; ++ + capped_freq = policy->max; + + /* +-- +2.53.0 + diff --git a/queue-6.12/drm-i915-gt-use-correct-selftest-config-symbol.patch b/queue-6.12/drm-i915-gt-use-correct-selftest-config-symbol.patch new file mode 100644 index 0000000000..fc81bf634f --- /dev/null +++ b/queue-6.12/drm-i915-gt-use-correct-selftest-config-symbol.patch @@ -0,0 +1,50 @@ +From ad458b4d0569c558ff5817dc6f9e2c017f4db094 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 5 Jul 2026 16:02:25 +0800 +Subject: drm/i915/gt: use correct selftest config symbol + +From: Pengpeng Hou + +[ Upstream commit a82f1bb8191aec98a971a2196136016ef70c0880 ] + +intel_engine_user.c checks CONFIG_DRM_I915_SELFTESTS before running +the engine UABI isolation check. Kconfig defines DRM_I915_SELFTEST, +without the trailing "S", and the rest of i915 uses +CONFIG_DRM_I915_SELFTEST. + +Because CONFIG_DRM_I915_SELFTESTS is not backed by any Kconfig symbol, +the IS_ENABLED() test is always false. Use the existing selftest symbol +so the debug/selftest guarded path can be reached when selftests are +enabled. + +This is a source-level fix. It does not claim dynamic hardware +reproduction; the evidence is the Kconfig definition and the inconsistent +guard in intel_engine_user.c. + +Fixes: 750e76b4f9f6 ("drm/i915/gt: Move the [class][inst] lookup for engines onto the GT") +Signed-off-by: Pengpeng Hou +Signed-off-by: Tvrtko Ursulin +Link: https://lore.kernel.org/r/20260705080225.436-1-pengpeng@iscas.ac.cn +(cherry picked from commit 14a2012a490258f3f93857bc4f1b203405964be7) +Signed-off-by: Rodrigo Vivi +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/i915/gt/intel_engine_user.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/i915/gt/intel_engine_user.c b/drivers/gpu/drm/i915/gt/intel_engine_user.c +index 833987015b8bbc..ed42b9d05a07d5 100644 +--- a/drivers/gpu/drm/i915/gt/intel_engine_user.c ++++ b/drivers/gpu/drm/i915/gt/intel_engine_user.c +@@ -257,7 +257,7 @@ void intel_engines_driver_register(struct drm_i915_private *i915) + p = &prev->rb_right; + } + +- if (IS_ENABLED(CONFIG_DRM_I915_SELFTESTS) && ++ if (IS_ENABLED(CONFIG_DRM_I915_SELFTEST) && + IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM)) { + struct intel_engine_cs *engine; + unsigned int isolation; +-- +2.53.0 + diff --git a/queue-6.12/drm-i915-selftests-fix-gt-pm-sort-comparators.patch b/queue-6.12/drm-i915-selftests-fix-gt-pm-sort-comparators.patch new file mode 100644 index 0000000000..0130754535 --- /dev/null +++ b/queue-6.12/drm-i915-selftests-fix-gt-pm-sort-comparators.patch @@ -0,0 +1,55 @@ +From c87f07f9bbae55bf5ae7835576982d9884b6de76 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 15 Jul 2026 01:04:30 +0300 +Subject: drm/i915/selftests: Fix GT PM sort comparators + +From: Emre Cecanpunar + +[ Upstream commit 612978b83f45bf7018815209db5395d759db6f26 ] + +Compare the sampled clock values instead of their addresses. Comparing +addresses leaves the samples unsorted, preventing the code from discarding +the minimum and maximum samples. + +Fixes: 1a5392479207 ("drm/i915/selftests: Measure CS_TIMESTAMP") +Signed-off-by: Emre Cecanpunar +Signed-off-by: Tvrtko Ursulin +Link: https://lore.kernel.org/r/20260714220430.238433-1-emreleno@gmail.com +(cherry picked from commit 682ea2d28d18bb06f9fc663cb5ab7e80dc0e606a) +Signed-off-by: Rodrigo Vivi +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/i915/gt/selftest_gt_pm.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/drivers/gpu/drm/i915/gt/selftest_gt_pm.c b/drivers/gpu/drm/i915/gt/selftest_gt_pm.c +index 33351deeea4f0b..07eaf71955c447 100644 +--- a/drivers/gpu/drm/i915/gt/selftest_gt_pm.c ++++ b/drivers/gpu/drm/i915/gt/selftest_gt_pm.c +@@ -16,9 +16,9 @@ static int cmp_u64(const void *A, const void *B) + { + const u64 *a = A, *b = B; + +- if (a < b) ++ if (*a < *b) + return -1; +- else if (a > b) ++ else if (*a > *b) + return 1; + else + return 0; +@@ -28,9 +28,9 @@ static int cmp_u32(const void *A, const void *B) + { + const u32 *a = A, *b = B; + +- if (a < b) ++ if (*a < *b) + return -1; +- else if (a > b) ++ else if (*a > *b) + return 1; + else + return 0; +-- +2.53.0 + diff --git a/queue-6.12/drm-xe-wopcm-fix-wopcm-size-for-lnl.patch b/queue-6.12/drm-xe-wopcm-fix-wopcm-size-for-lnl.patch new file mode 100644 index 0000000000..aefae12c04 --- /dev/null +++ b/queue-6.12/drm-xe-wopcm-fix-wopcm-size-for-lnl.patch @@ -0,0 +1,71 @@ +From 038a9aa9829cd78d4e0bb131d5167a6d5d540263 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 13 Jul 2026 15:17:59 -0700 +Subject: drm/xe/wopcm: fix WOPCM size for LNL+ +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Daniele Ceraolo Spurio + +[ Upstream commit ad87e2476b3b246580f407afc8ffa91d621bc849 ] + +Starting on LNL the WOPCM size is 8MB instead of 4, so we need to avoid +using the [0, 8MB) range of the GGTT as that can be unaccessible from +the microcontrollers. + +Note that the proper long-term fix here is to read the WOPCM size from +the HW, but that is a more serious rework that would be difficult to +backport, so we can do that as a follow-up. + +Fixes: 9c57bc08652a ("drm/xe/lnl: Drop force_probe requirement") +Signed-off-by: Daniele Ceraolo Spurio +Cc: Rodrigo Vivi +Cc: Shuicheng Lin +Cc: Matt Roper +Reviewed-by: Shuicheng Lin +Link: https://patch.msgid.link/20260713221758.3285744-2-daniele.ceraolospurio@intel.com +(cherry picked from commit 3033b0b24ed0e2f5e56bdd4d9c183417c365a45b) +Signed-off-by: Thomas Hellström +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/xe/xe_wopcm.c | 15 ++++++++++----- + 1 file changed, 10 insertions(+), 5 deletions(-) + +diff --git a/drivers/gpu/drm/xe/xe_wopcm.c b/drivers/gpu/drm/xe/xe_wopcm.c +index d3a99157e52338..b7de817cce8870 100644 +--- a/drivers/gpu/drm/xe/xe_wopcm.c ++++ b/drivers/gpu/drm/xe/xe_wopcm.c +@@ -47,9 +47,9 @@ + */ + + /* Default WOPCM size is 2MB from Gen11, 1MB on previous platforms */ +-/* FIXME: Larger size require for 2 tile PVC, do a proper probe sooner or later */ ++/* FIXME: Larger size require for some platforms, do a proper probe sooner or later */ + #define DGFX_WOPCM_SIZE SZ_4M +-/* FIXME: Larger size require for MTL, do a proper probe sooner or later */ ++#define LNL_WOPCM_SIZE SZ_8M + #define MTL_WOPCM_SIZE SZ_4M + #define WOPCM_SIZE SZ_2M + +@@ -179,9 +179,14 @@ static int __wopcm_init_regs(struct xe_device *xe, struct xe_gt *gt, + + u32 xe_wopcm_size(struct xe_device *xe) + { +- return IS_DGFX(xe) ? DGFX_WOPCM_SIZE : +- xe->info.platform == XE_METEORLAKE ? MTL_WOPCM_SIZE : +- WOPCM_SIZE; ++ if (xe->info.platform >= XE_LUNARLAKE) ++ return LNL_WOPCM_SIZE; ++ else if (IS_DGFX(xe)) ++ return DGFX_WOPCM_SIZE; ++ else if (xe->info.platform == XE_METEORLAKE) ++ return MTL_WOPCM_SIZE; ++ else ++ return WOPCM_SIZE; + } + + /** +-- +2.53.0 + diff --git a/queue-6.12/firmware-arm_ffa-fix-null-dereference-in-ffa_partiti.patch b/queue-6.12/firmware-arm_ffa-fix-null-dereference-in-ffa_partiti.patch new file mode 100644 index 0000000000..4fae47fa53 --- /dev/null +++ b/queue-6.12/firmware-arm_ffa-fix-null-dereference-in-ffa_partiti.patch @@ -0,0 +1,48 @@ +From 6538923b68474dcb45c4a0bc487c3da7417408bb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 17 Jun 2026 16:35:00 -0700 +Subject: firmware: arm_ffa: Fix NULL dereference in ffa_partition_info_get() + +From: Unnathi Chalicheemala + +[ Upstream commit 8ae5f8e4836667fcaffdf2e3c6068b0a8b364dd8 ] + +ffa_partition_info_get() passes uuid_str directly to uuid_parse() +without a NULL check. When a caller passes NULL, uuid_parse() -> +__uuid_parse() -> uuid_is_valid() dereferences the pointer, causing +a kernel panic: + + | Unable to handle kernel NULL pointer dereference at virtual address + | 0000000000000040 + | pc : uuid_parse+0x40/0xac + | lr : ffa_partition_info_get+0x1c/0x94 [arm_ffa] + +Add a NULL guard before uuid_parse() so a NULL argument returns +-ENODEV instead of crashing. Callers are expected to always supply +a valid partition UUID, so NULL is not a supported input. + +Fixes: d0c0bce83122 ("firmware: arm_ffa: Setup in-kernel users of FFA partitions") +Signed-off-by: Unnathi Chalicheemala +Link: https://patch.msgid.link/20260617-ffa_partition_nullptr_fix-v2-1-bc801b4ce34c@oss.qualcomm.com +Signed-off-by: Sudeep Holla +Signed-off-by: Sasha Levin +--- + drivers/firmware/arm_ffa/driver.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/firmware/arm_ffa/driver.c b/drivers/firmware/arm_ffa/driver.c +index 67fc9e46001b77..62222c9cfc3e6d 100644 +--- a/drivers/firmware/arm_ffa/driver.c ++++ b/drivers/firmware/arm_ffa/driver.c +@@ -1029,7 +1029,7 @@ static int ffa_partition_info_get(const char *uuid_str, + uuid_t uuid; + struct ffa_partition_info *pbuf; + +- if (uuid_parse(uuid_str, &uuid)) { ++ if (!uuid_str || uuid_parse(uuid_str, &uuid)) { + pr_err("invalid uuid (%s)\n", uuid_str); + return -ENODEV; + } +-- +2.53.0 + diff --git a/queue-6.12/firmware-arm_ffa-respect-firmware-advertised-rx-tx-b.patch b/queue-6.12/firmware-arm_ffa-respect-firmware-advertised-rx-tx-b.patch new file mode 100644 index 0000000000..bd4ef0f114 --- /dev/null +++ b/queue-6.12/firmware-arm_ffa-respect-firmware-advertised-rx-tx-b.patch @@ -0,0 +1,118 @@ +From 25daa9a4975add00456e21e1cd85ad83517a137f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 2 Jun 2026 21:54:06 +0000 +Subject: firmware: arm_ffa: Respect firmware advertised RX/TX buffer size + limits + +From: Seth Forshee + +[ Upstream commit 53716a4d745f1dac7aff33f3d1494b701eb2f888 ] + +FFA_FEATURES reports the minimum size and alignment boundary required +for RXTX_MAP. In FF-A v1.2 and later it can also report a maximum buffer +size, with zero meaning that no maximum is enforced. + +The driver only used the minimum value and then rounded it up to PAGE_SIZE +before invoking RXTX_MAP after commit 83210251fd70 ("firmware: arm_ffa: +Use the correct buffer size during RXTX_MAP"). On systems where PAGE_SIZE +is larger than the advertised minimum, this can exceed a non-zero maximum +reported by firmware. Older implementations do not advertise a maximum and +may also reject the rounded-up size. + +Decode the maximum size and clamp the page-aligned minimum to it when it +is present. If no maximum is advertised and RXTX_MAP rejects the rounded +size with INVALID_PARAMETERS, retry with the advertised minimum size. +Record drv_info->rxtx_bufsz only after RXTX_MAP succeeds so it reflects +the size registered with firmware. + +While there, also update RXTX_MAP_MIN_BUFSZ() to use FIELD_GET() for +consistency. + +Fixes: 83210251fd70 ("firmware: arm_ffa: Use the correct buffer size during RXTX_MAP") +Suggested-by: Sudeep Holla +Signed-off-by: Seth Forshee +Link: https://patch.msgid.link/20260602-b4-ffa-rxtx-map-fixes-v2-1-7cb06508da84@nvidia.com +(sudeep.holla: Minor rewording subject and commit message) +Signed-off-by: Sudeep Holla +Signed-off-by: Sasha Levin +--- + drivers/firmware/arm_ffa/driver.c | 27 ++++++++++++++++++++------- + 1 file changed, 20 insertions(+), 7 deletions(-) + +diff --git a/drivers/firmware/arm_ffa/driver.c b/drivers/firmware/arm_ffa/driver.c +index 3b221ba990aa1e..67fc9e46001b77 100644 +--- a/drivers/firmware/arm_ffa/driver.c ++++ b/drivers/firmware/arm_ffa/driver.c +@@ -32,6 +32,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -55,7 +56,9 @@ + (FIELD_PREP(SENDER_ID_MASK, (s)) | FIELD_PREP(RECEIVER_ID_MASK, (r))) + + #define RXTX_MAP_MIN_BUFSZ_MASK GENMASK(1, 0) +-#define RXTX_MAP_MIN_BUFSZ(x) ((x) & RXTX_MAP_MIN_BUFSZ_MASK) ++#define RXTX_MAP_MAX_BUFSZ_MASK GENMASK(31, 16) ++#define RXTX_MAP_MIN_BUFSZ(x) (FIELD_GET(RXTX_MAP_MIN_BUFSZ_MASK, (x))) ++#define RXTX_MAP_MAX_BUFSZ(x) (FIELD_GET(RXTX_MAP_MAX_BUFSZ_MASK, (x))) + + #define FFA_MAX_NOTIFICATIONS 64 + +@@ -1855,7 +1858,7 @@ static int __init ffa_init(void) + { + int ret; + u32 buf_sz; +- size_t rxtx_bufsz = SZ_4K; ++ size_t rxtx_min_bufsz = SZ_4K, rxtx_max_bufsz = 0, rxtx_bufsz; + + ret = ffa_transport_init(&invoke_ffa_fn); + if (ret) +@@ -1878,15 +1881,18 @@ static int __init ffa_init(void) + ret = ffa_features(FFA_FN_NATIVE(RXTX_MAP), 0, &buf_sz, NULL); + if (!ret) { + if (RXTX_MAP_MIN_BUFSZ(buf_sz) == 1) +- rxtx_bufsz = SZ_64K; ++ rxtx_min_bufsz = SZ_64K; + else if (RXTX_MAP_MIN_BUFSZ(buf_sz) == 2) +- rxtx_bufsz = SZ_16K; ++ rxtx_min_bufsz = SZ_16K; + else +- rxtx_bufsz = SZ_4K; ++ rxtx_min_bufsz = SZ_4K; ++ ++ rxtx_max_bufsz = RXTX_MAP_MAX_BUFSZ(buf_sz) * SZ_4K; ++ if (rxtx_max_bufsz != 0 && rxtx_max_bufsz < rxtx_min_bufsz) ++ rxtx_max_bufsz = rxtx_min_bufsz; + } + +- rxtx_bufsz = PAGE_ALIGN(rxtx_bufsz); +- drv_info->rxtx_bufsz = rxtx_bufsz; ++ rxtx_bufsz = min_not_zero(PAGE_ALIGN(rxtx_min_bufsz), rxtx_max_bufsz); + drv_info->rx_buffer = alloc_pages_exact(rxtx_bufsz, GFP_KERNEL); + if (!drv_info->rx_buffer) { + ret = -ENOMEM; +@@ -1902,10 +1908,17 @@ static int __init ffa_init(void) + ret = ffa_rxtx_map(virt_to_phys(drv_info->tx_buffer), + virt_to_phys(drv_info->rx_buffer), + rxtx_bufsz / FFA_PAGE_SIZE); ++ if (ret == -EINVAL && !rxtx_max_bufsz && rxtx_min_bufsz < rxtx_bufsz) { ++ rxtx_bufsz = rxtx_min_bufsz; ++ ret = ffa_rxtx_map(virt_to_phys(drv_info->tx_buffer), ++ virt_to_phys(drv_info->rx_buffer), ++ rxtx_bufsz / FFA_PAGE_SIZE); ++ } + if (ret) { + pr_err("failed to register FFA RxTx buffers\n"); + goto free_pages; + } ++ drv_info->rxtx_bufsz = rxtx_bufsz; + + mutex_init(&drv_info->rx_lock); + mutex_init(&drv_info->tx_lock); +-- +2.53.0 + diff --git a/queue-6.12/firmware-arm_scmi-rate-limit-queue-full-warnings-in-.patch b/queue-6.12/firmware-arm_scmi-rate-limit-queue-full-warnings-in-.patch new file mode 100644 index 0000000000..4681be87f0 --- /dev/null +++ b/queue-6.12/firmware-arm_scmi-rate-limit-queue-full-warnings-in-.patch @@ -0,0 +1,54 @@ +From 5b0782b88de5c075214f488c29e8afaf68367d9f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 8 Jul 2026 12:53:39 +0530 +Subject: firmware: arm_scmi: Rate-limit queue-full warnings in IRQ context + +From: Pushpendra Singh + +[ Upstream commit a4447c0693830d5ecadd6e755cb7fdc55d86aacc ] + +The scmi_notify() function is called from interrupt context to queue +received notification events onto a per-protocol kfifo. When the kfifo +is full, it logs a warning via dev_warn() for every dropped event. + +Under conditions where the platform sends a burst of SCMI notifications +faster than the deferred worker can drain the queue, this results in a +flood of dev_warn() calls from IRQ context. Each call acquires the +console lock and may execute blocking console writes, causing the CPU +to be held in interrupt context for an extended period and leading to +observable system stalls. + +Fix this by switching to dev_warn_ratelimited() to limit the frequency +of log messages when the notification queue is full. This reduces +console overhead in interrupt context and prevents CPU stalls caused by +excessive logging, while still preserving diagnostic visibility. + +Fixes: bd31b249692e ("firmware: arm_scmi: Add notification dispatch and delivery") +Signed-off-by: Pushpendra Singh +Link: https://patch.msgid.link/20260708072339.3021140-1-pushpendra.singh@oss.qualcomm.com +Signed-off-by: Sudeep Holla +Signed-off-by: Sasha Levin +--- + drivers/firmware/arm_scmi/notify.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/firmware/arm_scmi/notify.c b/drivers/firmware/arm_scmi/notify.c +index e160ecb22948fc..f042fb8a050265 100644 +--- a/drivers/firmware/arm_scmi/notify.c ++++ b/drivers/firmware/arm_scmi/notify.c +@@ -596,9 +596,9 @@ int scmi_notify(const struct scmi_handle *handle, u8 proto_id, u8 evt_id, + return -EINVAL; + } + if (kfifo_avail(&r_evt->proto->equeue.kfifo) < sizeof(eh) + len) { +- dev_warn(handle->dev, +- "queue full, dropping proto_id:%d evt_id:%d ts:%lld\n", +- proto_id, evt_id, ktime_to_ns(ts)); ++ dev_warn_ratelimited(handle->dev, ++ "queue full, dropping proto_id:%d evt_id:%d ts:%lld\n", ++ proto_id, evt_id, ktime_to_ns(ts)); + return -ENOMEM; + } + +-- +2.53.0 + diff --git a/queue-6.12/ib-mad-drop-unmatched-rmpp-responses-before-reassemb.patch b/queue-6.12/ib-mad-drop-unmatched-rmpp-responses-before-reassemb.patch new file mode 100644 index 0000000000..8336b695a8 --- /dev/null +++ b/queue-6.12/ib-mad-drop-unmatched-rmpp-responses-before-reassemb.patch @@ -0,0 +1,90 @@ +From 0d9ad6c0da2e7e3bcc03b58964a5ae5785b3e3b8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 6 Jun 2026 16:01:55 -0400 +Subject: IB/mad: Drop unmatched RMPP responses before reassembly + +From: Michael Bommarito + +[ Upstream commit d2e52d610b9b09694261632340b801a421e0b0c5 ] + +Kernel-handled RMPP receive processing starts reassembly for active +DATA responses before the response is matched to an outstanding send. +The normal match happens later, after ib_process_rmpp_recv_wc() has +either assembled a complete message or consumed the segment. + +That ordering lets an unsolicited response that routes to a kernel +RMPP agent by the high TID bits allocate or extend RMPP receive state +before the full TID and source address are checked against a real +request. A reordered burst can therefore reach the receive-side +insertion path even though the response would not match any send. + +For kernel-handled RMPP DATA responses, require the existing +ib_find_send_mad() match before entering RMPP reassembly. The matcher +already checks the full TID, management class and source address/GID +against the agent wait, backlog and in-flight send lists. If there is +no match, drop the response without creating RMPP state. + +This leaves the RMPP window behavior unchanged and only rejects +responses that have no corresponding request. + +Fixes: fa619a77046b ("[PATCH] IB: Add RMPP implementation") +Assisted-by: Codex:gpt-5-5-xhigh +Signed-off-by: Michael Bommarito +Link: https://patch.msgid.link/3170ff3bc389a930bb1641f2caa394a0b2241579.1780774907.git.michael.bommarito@gmail.com +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + drivers/infiniband/core/mad.c | 30 ++++++++++++++++++++++++++++++ + 1 file changed, 30 insertions(+) + +diff --git a/drivers/infiniband/core/mad.c b/drivers/infiniband/core/mad.c +index 73f3a0b9a54b5f..96c1fd8039fb59 100644 +--- a/drivers/infiniband/core/mad.c ++++ b/drivers/infiniband/core/mad.c +@@ -1778,6 +1778,24 @@ void ib_mark_mad_done(struct ib_mad_send_wr_private *mad_send_wr) + &mad_send_wr->mad_agent_priv->done_list); + } + ++static bool is_kernel_rmpp_data_response(struct ib_mad_agent_private *agent, ++ struct ib_mad_recv_wc *mad_recv_wc) ++{ ++ const struct ib_mad_hdr *mad_hdr = &mad_recv_wc->recv_buf.mad->mad_hdr; ++ struct ib_rmpp_mad *rmpp_mad; ++ ++ if (!ib_mad_kernel_rmpp_agent(&agent->agent) || ++ !ib_response_mad(mad_hdr) || ++ !ib_is_mad_class_rmpp(mad_hdr->mgmt_class)) ++ return false; ++ ++ rmpp_mad = (struct ib_rmpp_mad *)mad_recv_wc->recv_buf.mad; ++ ++ return (ib_get_rmpp_flags(&rmpp_mad->rmpp_hdr) & ++ IB_MGMT_RMPP_FLAG_ACTIVE) && ++ rmpp_mad->rmpp_hdr.rmpp_type == IB_MGMT_RMPP_TYPE_DATA; ++} ++ + static void ib_mad_complete_recv(struct ib_mad_agent_private *mad_agent_priv, + struct ib_mad_recv_wc *mad_recv_wc) + { +@@ -1796,6 +1814,18 @@ static void ib_mad_complete_recv(struct ib_mad_agent_private *mad_agent_priv, + } + + list_add(&mad_recv_wc->recv_buf.list, &mad_recv_wc->rmpp_list); ++ if (is_kernel_rmpp_data_response(mad_agent_priv, mad_recv_wc)) { ++ spin_lock_irqsave(&mad_agent_priv->lock, flags); ++ mad_send_wr = ib_find_send_mad(mad_agent_priv, mad_recv_wc); ++ spin_unlock_irqrestore(&mad_agent_priv->lock, flags); ++ ++ if (!mad_send_wr) { ++ ib_free_recv_mad(mad_recv_wc); ++ deref_mad_agent(mad_agent_priv); ++ return; ++ } ++ } ++ + if (ib_mad_kernel_rmpp_agent(&mad_agent_priv->agent)) { + mad_recv_wc = ib_process_rmpp_recv_wc(mad_agent_priv, + mad_recv_wc); +-- +2.53.0 + diff --git a/queue-6.12/ipv4-fib-free-fib_alias-with-kfree_rcu-on-insert-err.patch b/queue-6.12/ipv4-fib-free-fib_alias-with-kfree_rcu-on-insert-err.patch new file mode 100644 index 0000000000..afed429a88 --- /dev/null +++ b/queue-6.12/ipv4-fib-free-fib_alias-with-kfree_rcu-on-insert-err.patch @@ -0,0 +1,67 @@ +From bce11750e000ea0e0ad0cdec12975b73b3de1441 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 4 Jul 2026 10:14:21 -0700 +Subject: ipv4: fib: free fib_alias with kfree_rcu() on insert error path + +From: Weiming Shi + +[ Upstream commit f2f152e94a67bc746afaf05a1b2702c195553112 ] + +fib_table_insert() publishes new_fa into the leaf's fa_list with +fib_insert_alias() before calling the fib entry notifiers. When a +notifier fails, the error path removes new_fa with fib_remove_alias() +(hlist_del_rcu) and frees it right away with kmem_cache_free(). + +fib_table_lookup() walks that list under rcu_read_lock() only, so a +concurrent lookup that already reached new_fa keeps reading it after the +free: + + BUG: KASAN: slab-use-after-free in fib_table_lookup (net/ipv4/fib_trie.c:1601) + Read of size 1 at addr ffff88810676d4eb by task exploit/297 + Call Trace: + fib_table_lookup (net/ipv4/fib_trie.c:1601) + ip_route_output_key_hash_rcu (net/ipv4/route.c:2814) + ip_route_output_key_hash (net/ipv4/route.c:2705) + __ip4_datagram_connect (net/ipv4/datagram.c:49) + udp_connect (net/ipv4/udp.c:2144) + __sys_connect (net/socket.c:2167) + __x64_sys_connect (net/socket.c:2173) + do_syscall_64 + entry_SYSCALL_64_after_hwframe + which belongs to the cache ip_fib_alias of size 56 + +Triggering the error path needs CAP_NET_ADMIN and a registered fib +notifier that can reject a route; a netdevsim device whose IPv4 FIB +resource is exhausted is enough. + +Free new_fa with alias_free_mem_rcu(), as fib_table_delete() already +does for a fib_alias removed from the trie. + +Fixes: a6c76c17df02 ("ipv4: Notify route after insertion to the routing table") +Reported-by: Xiang Mei +Assisted-by: Claude:claude-opus-4-8 +Signed-off-by: Weiming Shi +Reviewed-by: Ido Schimmel +Link: https://patch.msgid.link/20260704171421.1786806-1-bestswngs@gmail.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/ipv4/fib_trie.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c +index ee47b67a087034..3d2df1d435ae10 100644 +--- a/net/ipv4/fib_trie.c ++++ b/net/ipv4/fib_trie.c +@@ -1391,7 +1391,7 @@ int fib_table_insert(struct net *net, struct fib_table *tb, + out_remove_new_fa: + fib_remove_alias(t, tp, l, new_fa); + out_free_new_fa: +- kmem_cache_free(fn_alias_kmem, new_fa); ++ alias_free_mem_rcu(new_fa); + out: + fib_release_info(fi); + err: +-- +2.53.0 + diff --git a/queue-6.12/ksmbd-pin-conn-during-async-oplock-break-notificatio.patch b/queue-6.12/ksmbd-pin-conn-during-async-oplock-break-notificatio.patch new file mode 100644 index 0000000000..6fec72e8a7 --- /dev/null +++ b/queue-6.12/ksmbd-pin-conn-during-async-oplock-break-notificatio.patch @@ -0,0 +1,75 @@ +From 9c36eb6c60a6eb7b6a6983611dd20d030a422de7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 9 Jul 2026 22:49:55 +0800 +Subject: ksmbd: pin conn during async oplock break notification + +From: Qihang + +[ Upstream commit aa5d8f3f96aa11a4a54ce993c11ce8af11c546f9 ] + +smb2_oplock_break_noti() and smb2_lease_break_noti() store a ksmbd_conn +pointer in an async ksmbd_work and then queue that work on ksmbd-io. The +work only increments conn->r_count, which prevents teardown from passing +the pending-request wait after the increment, but it does not pin the +struct ksmbd_conn object. + +If connection teardown races with an oplock break notification, the last +conn reference can be dropped before the queued worker finishes. The +worker then uses the freed conn in ksmbd_conn_write() and +ksmbd_conn_r_count_dec(). + +Take a real conn reference when publishing the conn pointer to the async +work item, and drop it after the notification work has decremented +r_count. Apply the same lifetime rule to lease break notification, which +uses the same work->conn pattern. + +Fixes: 3aa660c05924 ("ksmbd: prevent connection release during oplock break notification") +Signed-off-by: Qihang +Acked-by: Namjae Jeon +Signed-off-by: Steve French +Signed-off-by: Sasha Levin +--- + fs/smb/server/oplock.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/fs/smb/server/oplock.c b/fs/smb/server/oplock.c +index a019c4496ae433..ff0dbf3f8cbf49 100644 +--- a/fs/smb/server/oplock.c ++++ b/fs/smb/server/oplock.c +@@ -705,6 +705,7 @@ static void __smb2_oplock_break_noti(struct work_struct *wk) + out: + ksmbd_free_work_struct(work); + ksmbd_conn_r_count_dec(conn); ++ ksmbd_conn_put(conn); + } + + /** +@@ -740,7 +741,7 @@ static int smb2_oplock_break_noti(struct oplock_info *opinfo) + br_info->open_trunc = opinfo->open_trunc; + + work->request_buf = (char *)br_info; +- work->conn = conn; ++ work->conn = ksmbd_conn_get(conn); + work->sess = opinfo->sess; + + ksmbd_conn_r_count_inc(conn); +@@ -814,6 +815,7 @@ static void __smb2_lease_break_noti(struct work_struct *wk) + out: + ksmbd_free_work_struct(work); + ksmbd_conn_r_count_dec(conn); ++ ksmbd_conn_put(conn); + } + + /** +@@ -853,7 +855,7 @@ static int smb2_lease_break_noti(struct oplock_info *opinfo) + memcpy(br_info->lease_key, lease->lease_key, SMB2_LEASE_KEY_SIZE); + + work->request_buf = (char *)br_info; +- work->conn = conn; ++ work->conn = ksmbd_conn_get(conn); + work->sess = opinfo->sess; + + ksmbd_conn_r_count_inc(conn); +-- +2.53.0 + diff --git a/queue-6.12/ksmbd-validate-compound-request-size-before-reading-.patch b/queue-6.12/ksmbd-validate-compound-request-size-before-reading-.patch new file mode 100644 index 0000000000..ad7dcb1858 --- /dev/null +++ b/queue-6.12/ksmbd-validate-compound-request-size-before-reading-.patch @@ -0,0 +1,69 @@ +From 4d62b9f8c29cb59f220168314107d634a98617b9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 13 Jul 2026 21:55:10 +0000 +Subject: ksmbd: validate compound request size before reading StructureSize2 + +From: Xiang Mei (Microsoft) + +[ Upstream commit 15b38176fd1530372905c602fde51fe89ec8c877 ] + +When ksmbd validates a compound (chained) SMB2 request, +ksmbd_smb2_check_message() reads pdu->StructureSize2 without first +checking that the compound element is large enough to contain it. +StructureSize2 is a 2-byte field at offset 64 +(__SMB2_HEADER_STRUCTURE_SIZE) from the start of each element. + +The compound-walking logic only guarantees that a full 64-byte SMB2 +header is present for the trailing element: when NextCommand is 0, len is +reduced to the number of bytes remaining after next_smb2_rcv_hdr_off. A +remote client can craft a compound request whose last element has exactly +64 bytes, so the 2-byte StructureSize2 read at offset 64 extends one byte +past the receive buffer, producing a slab-out-of-bounds read. + + BUG: KASAN: slab-out-of-bounds in ksmbd_smb2_check_message (fs/smb/server/smb2misc.c:402) + Read of size 2 at addr ffff888012ae31ac by task kworker/0:1/14 + The buggy address is located 172 bytes inside of allocated 173-byte region + Workqueue: ksmbd-io handle_ksmbd_work + Call Trace: + ... + kasan_report (mm/kasan/report.c:595) + ksmbd_smb2_check_message (fs/smb/server/smb2misc.c:402) + handle_ksmbd_work (fs/smb/server/server.c:119) + process_one_work (kernel/workqueue.c:3314) + worker_thread (kernel/workqueue.c:3397) + kthread (kernel/kthread.c:436) + ret_from_fork (arch/x86/kernel/process.c:158) + ret_from_fork_asm (arch/x86/entry/entry_64.S:245) + +Reject any compound element that is too small to hold StructureSize2 +before dereferencing it. + +Fixes: e2f34481b24d ("cifsd: add server-side procedures for SMB3") +Reported-by: AutonomousCodeSecurity@microsoft.com +Signed-off-by: Xiang Mei (Microsoft) +Acked-by: Namjae Jeon +Signed-off-by: Steve French +Signed-off-by: Sasha Levin +--- + fs/smb/server/smb2misc.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/fs/smb/server/smb2misc.c b/fs/smb/server/smb2misc.c +index ae501024665e1f..6317edbfe4fa43 100644 +--- a/fs/smb/server/smb2misc.c ++++ b/fs/smb/server/smb2misc.c +@@ -400,6 +400,11 @@ int ksmbd_smb2_check_message(struct ksmbd_work *work) + return 1; + } + ++ if (len < __SMB2_HEADER_STRUCTURE_SIZE + sizeof(__le16)) { ++ ksmbd_debug(SMB, "Message is too small for StructureSize2\n"); ++ return 1; ++ } ++ + if (smb2_req_struct_sizes[command] != pdu->StructureSize2) { + if (!(command == SMB2_OPLOCK_BREAK_HE && + (le16_to_cpu(pdu->StructureSize2) == OP_BREAK_STRUCT_SIZE_20 || +-- +2.53.0 + diff --git a/queue-6.12/mpls-fix-null-deref-in-mpls_valid_fib_dump_req-on-co.patch b/queue-6.12/mpls-fix-null-deref-in-mpls_valid_fib_dump_req-on-co.patch new file mode 100644 index 0000000000..1e2a964aef --- /dev/null +++ b/queue-6.12/mpls-fix-null-deref-in-mpls_valid_fib_dump_req-on-co.patch @@ -0,0 +1,68 @@ +From 34162525ce69d234ee3796e6f5c3642c6fb7449f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 11 Jul 2026 04:50:00 -0700 +Subject: mpls: fix NULL deref in mpls_valid_fib_dump_req() on CONFIG_INET=n + +From: Weiming Shi + +[ Upstream commit 56d96fededd61192cd7cc8d2b0f36adfd59036c3 ] + +On CONFIG_INET=n builds, mpls_valid_fib_dump_req() walks the parsed +attribute table itself instead of calling ip_valid_fib_dump_req(). The +RTA_OIF arm passes tb[RTA_OIF] to nla_get_u32() without checking it is +present, so an RTM_GETROUTE dump for AF_MPLS with strict checking and no +RTA_OIF hits a NULL dereference. + +RTM_GETROUTE is RTNL_KIND_GET, which rtnetlink_rcv_msg() permits without +CAP_NET_ADMIN, so an unprivileged user can trigger it. + + Oops: general protection fault, probably for non-canonical address + 0xdffffc0000000000: 0000 [#1] SMP KASAN NOPTI + KASAN: null-ptr-deref in range [0x0000000000000000-0x0000000000000007] + RIP: 0010:mpls_valid_fib_dump_req (net/mpls/af_mpls.c:2189) + Call Trace: + mpls_dump_routes (net/mpls/af_mpls.c:2236) + netlink_dump (net/netlink/af_netlink.c:2331) + __netlink_dump_start (net/netlink/af_netlink.c:2446) + rtnetlink_rcv_msg (net/core/rtnetlink.c:7033) + netlink_rcv_skb (net/netlink/af_netlink.c:2556) + netlink_unicast (net/netlink/af_netlink.c:1345) + netlink_sendmsg (net/netlink/af_netlink.c:1900) + __sock_sendmsg (net/socket.c:790) + ____sys_sendmsg (net/socket.c:2684) + ___sys_sendmsg (net/socket.c:2738) + __sys_sendmsg (net/socket.c:2770) + do_syscall_64 (arch/x86/entry/syscall_64.c:94) + entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:121) + +Skip unset attributes, as ip_valid_fib_dump_req() does. + +Fixes: 196cfebf8972 ("net/mpls: Handle kernel side filtering of route dumps") +Assisted-by: Claude:claude-opus-4-8 +Reported-by: Xiang Mei +Signed-off-by: Weiming Shi +Reviewed-by: David Ahern +Link: https://patch.msgid.link/20260711114958.1009619-3-bestswngs@gmail.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/mpls/af_mpls.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/net/mpls/af_mpls.c b/net/mpls/af_mpls.c +index 719dabb76ea218..98816e51e01a49 100644 +--- a/net/mpls/af_mpls.c ++++ b/net/mpls/af_mpls.c +@@ -2123,6 +2123,9 @@ static int mpls_valid_fib_dump_req(struct net *net, const struct nlmsghdr *nlh, + int ifindex; + + if (i == RTA_OIF) { ++ if (!tb[i]) ++ continue; ++ + ifindex = nla_get_u32(tb[i]); + filter->dev = __dev_get_by_index(net, ifindex); + if (!filter->dev) +-- +2.53.0 + diff --git a/queue-6.12/mtd-fix-double-free-and-warn_on-in-add_mtd_device-er.patch b/queue-6.12/mtd-fix-double-free-and-warn_on-in-add_mtd_device-er.patch new file mode 100644 index 0000000000..dbe48e53f2 --- /dev/null +++ b/queue-6.12/mtd-fix-double-free-and-warn_on-in-add_mtd_device-er.patch @@ -0,0 +1,102 @@ +From da75999363fe2e95f603290ccd5ecc6496d264f3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 1 Jul 2026 20:10:42 +0800 +Subject: mtd: fix double free and WARN_ON in add_mtd_device() error paths + +From: Xue Lei + +[ Upstream commit 9d4af746af8ce27eefc2338b2feaa1e01f28b6c3 ] + +When device_register() or mtd_nvmem_add() fails inside +add_mtd_device() for a partition, the error handling triggers +mtd_release() via put_device() or device_unregister(). mtd_release() +calls release_mtd_partition() which frees the mtd_info structure. +However, callers such as mtd_add_partition() and add_mtd_partitions() +also call free_partition() in their error paths, resulting in a double +free. + +Additionally, release_mtd_partition() hits WARN_ON(!list_empty( +&mtd->part.node)) because the partition node is still linked in the +parent's partitions list when the release callback fires from the +add_mtd_device() error path. + +Fix this by overriding dev->type and dev->release before put_device() +in the error paths, so that device_release() invokes a no-op function +instead of mtd_release(). For the mtd_nvmem_add() failure case, +device_unregister() is replaced with device_del() to separate the +device removal from the final kobject reference drop, allowing the +override to take effect before put_device() is called. + +The callers' error paths (list_del + free_partition) remain the sole +owners of mtd_info lifetime on add_mtd_device() failure, which is the +expected contract. + +The normal partition teardown path is not affected: del_mtd_device() +goes through kref_put() -> mtd_device_release() -> device_unregister() +with dev->type still set to &mtd_devtype, so mtd_release() -> +release_mtd_partition() continues to work correctly for the regular +removal case. + +Reported-by: syzbot+e9c76b56dc05023b8117@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=e9c76b56dc05023b8117 +Fixes: 19bfa9ebebb5 ("mtd: use refcount to prevent corruption") +Signed-off-by: Xue Lei +Signed-off-by: Miquel Raynal +Signed-off-by: Sasha Levin +--- + drivers/mtd/mtdcore.c | 23 +++++++++++++++++++---- + 1 file changed, 19 insertions(+), 4 deletions(-) + +diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c +index 724f917f91bac0..0c8e8eb5f0f3d8 100644 +--- a/drivers/mtd/mtdcore.c ++++ b/drivers/mtd/mtdcore.c +@@ -104,6 +104,15 @@ static void mtd_release(struct device *dev) + device_destroy(&mtd_class, index + 1); + } + ++/* ++ * No-op device release used in add_mtd_device() error paths. ++ * Prevents mtd_release() from being called via device_release(), ++ * which would free the mtd_info that the caller still manages. ++ */ ++static void mtd_dev_release_nop(struct device *dev) ++{ ++} ++ + static void mtd_device_release(struct kref *kref) + { + struct mtd_info *mtd = container_of(kref, struct mtd_info, refcnt); +@@ -746,10 +755,8 @@ int add_mtd_device(struct mtd_info *mtd) + mtd_check_of_node(mtd); + of_node_get(mtd_get_of_node(mtd)); + error = device_register(&mtd->dev); +- if (error) { +- put_device(&mtd->dev); ++ if (error) + goto fail_added; +- } + + /* Add the nvmem provider */ + error = mtd_nvmem_add(mtd); +@@ -787,8 +794,16 @@ int add_mtd_device(struct mtd_info *mtd) + return 0; + + fail_nvmem_add: +- device_unregister(&mtd->dev); ++ device_del(&mtd->dev); + fail_added: ++ /* ++ * Clear type and set nop release to prevent mtd_release() -> ++ * release_mtd_partition() -> free_partition() from freeing mtd. ++ * The caller handles cleanup on failure. ++ */ ++ mtd->dev.type = NULL; ++ mtd->dev.release = mtd_dev_release_nop; ++ put_device(&mtd->dev); + of_node_put(mtd_get_of_node(mtd)); + idr_remove(&mtd_idr, i); + fail_locked: +-- +2.53.0 + diff --git a/queue-6.12/mtd-mtdswap-remove-debugfs-stats-file-on-teardown.patch b/queue-6.12/mtd-mtdswap-remove-debugfs-stats-file-on-teardown.patch new file mode 100644 index 0000000000..6763860b8f --- /dev/null +++ b/queue-6.12/mtd-mtdswap-remove-debugfs-stats-file-on-teardown.patch @@ -0,0 +1,57 @@ +From ed3080bc69294bbce6bfc8af627048f630af214d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 23 Jun 2026 09:53:17 +0800 +Subject: mtd: mtdswap: remove debugfs stats file on teardown + +From: Pengpeng Hou + +[ Upstream commit 66fb31358108d10245b9e4ef0eef3e7d9747055e ] + +mtdswap_add_debugfs() creates an mtdswap_stats debugfs file under the +per-MTD debugfs directory, but mtdswap_remove_dev() never removes it +before freeing the mtdswap_dev. + +Store the returned dentry and remove it during device teardown before the +driver-private state is freed. + +Fixes: a32159024620 ("mtd: Add mtdswap block driver") +Signed-off-by: Pengpeng Hou +Signed-off-by: Miquel Raynal +Signed-off-by: Sasha Levin +--- + drivers/mtd/mtdswap.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/drivers/mtd/mtdswap.c b/drivers/mtd/mtdswap.c +index 680366616da240..4d695875ea1b23 100644 +--- a/drivers/mtd/mtdswap.c ++++ b/drivers/mtd/mtdswap.c +@@ -125,6 +125,7 @@ struct mtdswap_dev { + + char *page_buf; + char *oob_buf; ++ struct dentry *debugfs_stats; + }; + + struct mtdswap_oobdata { +@@ -1262,7 +1263,8 @@ static int mtdswap_add_debugfs(struct mtdswap_dev *d) + if (IS_ERR_OR_NULL(root)) + return -1; + +- debugfs_create_file("mtdswap_stats", S_IRUSR, root, d, &mtdswap_fops); ++ d->debugfs_stats = debugfs_create_file("mtdswap_stats", 0400, root, ++ d, &mtdswap_fops); + + return 0; + } +@@ -1463,6 +1465,7 @@ static void mtdswap_remove_dev(struct mtd_blktrans_dev *dev) + { + struct mtdswap_dev *d = MTDSWAP_MBD_TO_MTDSWAP(dev); + ++ debugfs_remove(d->debugfs_stats); + del_mtd_blktrans_dev(dev); + mtdswap_cleanup(d); + kfree(d); +-- +2.53.0 + diff --git a/queue-6.12/mtd-nand-mtk-ecc-stop-on-ecc-idle-timeouts.patch b/queue-6.12/mtd-nand-mtk-ecc-stop-on-ecc-idle-timeouts.patch new file mode 100644 index 0000000000..4923658ff5 --- /dev/null +++ b/queue-6.12/mtd-nand-mtk-ecc-stop-on-ecc-idle-timeouts.patch @@ -0,0 +1,75 @@ +From da5387a962fc05cf7917829686a320be06ddf820 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 23 Jun 2026 21:57:29 +0800 +Subject: mtd: nand: mtk-ecc: stop on ECC idle timeouts + +From: Pengpeng Hou + +[ Upstream commit 16f7ec8d5dc100eafd2c8e06cd30340a30b104a1 ] + +mtk_ecc_wait_idle() logs when the encoder or decoder does not become +idle, but returns void. Callers can therefore configure a non-idle ECC +engine or read parity bytes after an unconfirmed encoder idle state. + +Return the idle poll result and propagate it from the enable and encode +paths that require the engine to be idle before continuing. + +Fixes: 1d6b1e464950 ("mtd: mediatek: driver for MTK Smart Device") +Signed-off-by: Pengpeng Hou +Signed-off-by: Miquel Raynal +Signed-off-by: Sasha Levin +--- + drivers/mtd/nand/ecc-mtk.c | 16 ++++++++++++---- + 1 file changed, 12 insertions(+), 4 deletions(-) + +diff --git a/drivers/mtd/nand/ecc-mtk.c b/drivers/mtd/nand/ecc-mtk.c +index c75bb8b80cc1e1..96703f0a418ea2 100644 +--- a/drivers/mtd/nand/ecc-mtk.c ++++ b/drivers/mtd/nand/ecc-mtk.c +@@ -123,8 +123,8 @@ static int mt7622_ecc_regs[] = { + [ECC_DECIRQ_STA] = 0x144, + }; + +-static inline void mtk_ecc_wait_idle(struct mtk_ecc *ecc, +- enum mtk_ecc_operation op) ++static inline int mtk_ecc_wait_idle(struct mtk_ecc *ecc, ++ enum mtk_ecc_operation op) + { + struct device *dev = ecc->dev; + u32 val; +@@ -136,6 +136,8 @@ static inline void mtk_ecc_wait_idle(struct mtk_ecc *ecc, + if (ret) + dev_warn(dev, "%s NOT idle\n", + op == ECC_ENCODE ? "encoder" : "decoder"); ++ ++ return ret; + } + + static irqreturn_t mtk_ecc_irq(int irq, void *id) +@@ -312,7 +314,11 @@ int mtk_ecc_enable(struct mtk_ecc *ecc, struct mtk_ecc_config *config) + return ret; + } + +- mtk_ecc_wait_idle(ecc, op); ++ ret = mtk_ecc_wait_idle(ecc, op); ++ if (ret) { ++ mutex_unlock(&ecc->lock); ++ return ret; ++ } + + ret = mtk_ecc_config(ecc, config); + if (ret) { +@@ -412,7 +418,9 @@ int mtk_ecc_encode(struct mtk_ecc *ecc, struct mtk_ecc_config *config, + if (ret) + goto timeout; + +- mtk_ecc_wait_idle(ecc, ECC_ENCODE); ++ ret = mtk_ecc_wait_idle(ecc, ECC_ENCODE); ++ if (ret) ++ goto timeout; + + /* Program ECC bytes to OOB: per sector oob = FDM + ECC + SPARE */ + len = (config->strength * ecc->caps->parity_bits + 7) >> 3; +-- +2.53.0 + diff --git a/queue-6.12/net-iucv-take-a-reference-on-the-socket-found-in-afi.patch b/queue-6.12/net-iucv-take-a-reference-on-the-socket-found-in-afi.patch new file mode 100644 index 0000000000..1b3026e3aa --- /dev/null +++ b/queue-6.12/net-iucv-take-a-reference-on-the-socket-found-in-afi.patch @@ -0,0 +1,55 @@ +From 16aff95c28bfcce92e63281557927df71ddd2e0a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 5 Jul 2026 22:24:36 -0500 +Subject: net/iucv: take a reference on the socket found in afiucv_hs_rcv() + +From: Bryam Vargas + +[ Upstream commit 4fa349156043dc119721d067329714179f501749 ] + +afiucv_hs_rcv() looks up the destination socket under iucv_sk_list.lock, +drops the lock, and then passes the socket to the afiucv_hs_callback_*() +handlers without holding a reference. AF_IUCV sockets are not +RCU-protected and are freed synchronously by iucv_sock_kill() -> +sock_put(), so a concurrent close can free the socket in the window +between read_unlock() and the handler, which then dereferences freed +memory (for example sk->sk_data_ready() in afiucv_hs_callback_syn()). + +Take a reference with sock_hold() while the socket is still on the list +and release it with sock_put() once the handler has run. + +Fixes: 3881ac441f64 ("af_iucv: add HiperSockets transport") +Signed-off-by: Bryam Vargas +Reviewed-by: Hidayath Khan +Link: https://patch.msgid.link/20260705-b4-disp-fc79c0dc-v1-1-d2cdcb57afa9@proton.me +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/iucv/af_iucv.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c +index 1a0b41fcea8131..bb54e23397e8c6 100644 +--- a/net/iucv/af_iucv.c ++++ b/net/iucv/af_iucv.c +@@ -2088,6 +2088,8 @@ static int afiucv_hs_rcv(struct sk_buff *skb, struct net_device *dev, + } + } + } ++ if (sk) ++ sock_hold(sk); + read_unlock(&iucv_sk_list.lock); + if (!iucv) + sk = NULL; +@@ -2137,6 +2139,8 @@ static int afiucv_hs_rcv(struct sk_buff *skb, struct net_device *dev, + kfree_skb(skb); + } + ++ if (sk) ++ sock_put(sk); + return err; + } + +-- +2.53.0 + diff --git a/queue-6.12/net-sched-act_tunnel_key-defer-dst_release-to-rcu-ca.patch b/queue-6.12/net-sched-act_tunnel_key-defer-dst_release-to-rcu-ca.patch new file mode 100644 index 0000000000..01e334f43d --- /dev/null +++ b/queue-6.12/net-sched-act_tunnel_key-defer-dst_release-to-rcu-ca.patch @@ -0,0 +1,176 @@ +From 67cc5990b6e42c1dae8a7e1f74c0454f2300cc24 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 11 Jul 2026 11:05:37 -0400 +Subject: net/sched: act_tunnel_key: Defer dst_release to RCU callback + +From: Jamal Hadi Salim + +[ Upstream commit f1f5c8a3955f8fda3f84ed883ac8daa1847e724c ] + +Fix a race-condition use-after-free in tunnel_key_release_params(). + +The function releases the metadata_dst of the old params synchronously +via dst_release() while deferring the params struct free with +kfree_rcu(). A concurrent tunnel_key_act() reader on the datapath may +still hold the old params pointer (under rcu_read_lock_bh) and proceed +to call dst_clone(¶ms->tcft_enc_metadata->dst) after the writer's +dst_release has already pushed the dst's rcuref to RCUREF_DEAD. + +zdi-disclosures@trendmicro.com produced a poc which i (and Victor) verified +that KASAN reports: + +================================================================== +BUG: KASAN: slab-use-after-free in instrument_atomic_read_write include/linux/instrumented.h:112 +BUG: KASAN: slab-use-after-free in atomic_sub_return_release include/linux/atomic/atomic-instrumented.h:326 +BUG: KASAN: slab-use-after-free in __rcuref_put include/linux/rcuref.h:109 +BUG: KASAN: slab-use-after-free in rcuref_put include/linux/rcuref.h:173 +BUG: KASAN: slab-use-after-free in dst_release+0x5b/0x370 net/core/dst.c:168 +Write of size 4 at addr ffff88806158de40 by task poc/9388 + +CPU: 0 UID: 0 PID: 9388 Comm: poc Tainted: G W 7.1.0-rc7 #7 PREEMPT(lazy) +Tainted: [W]=WARN +Hardware name: QEMU Ubuntu 25.10 PC v2 (i440FX + PIIX, + 10.1 machine, 1996), BIOS 1.16.3-debian-1.16.3-2 04/01/2014 +Call Trace: + + __dump_stack lib/dump_stack.c:94 + dump_stack_lvl+0x100/0x190 lib/dump_stack.c:120 + print_address_description mm/kasan/report.c:378 + print_report+0x139/0x4ad mm/kasan/report.c:482 + kasan_report+0xe4/0x1d0 mm/kasan/report.c:595 + check_region_inline mm/kasan/generic.c:186 + kasan_check_range+0x125/0x200 mm/kasan/generic.c:200 + instrument_atomic_read_write include/linux/instrumented.h:112 + atomic_sub_return_release include/linux/atomic/atomic-instrumented.h:326 + __rcuref_put include/linux/rcuref.h:109 + rcuref_put include/linux/rcuref.h:173 + dst_release+0x5b/0x370 net/core/dst.c:168 + refdst_drop include/net/dst.h:272 + skb_dst_drop include/net/dst.h:284 + skb_release_head_state+0x293/0x400 net/core/skbuff.c:1163 + skb_release_all net/core/skbuff.c:1187 +[..] +Allocated by task 9391: + kasan_save_stack+0x30/0x50 mm/kasan/common.c:57 + kasan_save_track+0x14/0x30 mm/kasan/common.c:78 + poison_kmalloc_redzone mm/kasan/common.c:398 + __kasan_kmalloc+0x9a/0xb0 mm/kasan/common.c:415 + kasan_kmalloc include/linux/kasan.h:263 + __do_kmalloc_node mm/slub.c:5296 + __kmalloc_noprof+0x2f1/0x830 mm/slub.c:5308 + kmalloc_noprof include/linux/slab.h:954 + kzalloc_noprof include/linux/slab.h:1188 + offload_action_alloc+0x2f/0x130 net/core/flow_offload.c:35 + tcf_action_offload_add_ex+0x1ba/0x880 net/sched/act_api.c:258 + tcf_action_offload_add net/sched/act_api.c:293 + tcf_action_init+0x66e/0xa20 net/sched/act_api.c:1547 + tcf_action_add+0xf6/0x5d0 net/sched/act_api.c:2101 +[..] +Freed by task 9391: + kasan_save_stack+0x30/0x50 mm/kasan/common.c:57 + kasan_save_track+0x14/0x30 mm/kasan/common.c:78 + kasan_save_free_info+0x3b/0x70 mm/kasan/generic.c:584 + poison_slab_object mm/kasan/common.c:253 + __kasan_slab_free+0x6b/0x90 mm/kasan/common.c:285 + kasan_slab_free include/linux/kasan.h:235 + slab_free_hook mm/slub.c:2689 + slab_free mm/slub.c:6251 + kfree+0x21f/0x6b0 mm/slub.c:6566 + tcf_action_offload_add_ex+0x4ad/0x880 net/sched/act_api.c:284 + tcf_action_offload_add net/sched/act_api.c:293 + tcf_action_init+0x66e/0xa20 net/sched/act_api.c:1547 + tcf_action_add+0xf6/0x5d0 net/sched/act_api.c:2101 + +The buggy address belongs to the object at ffff88806158de00 + which belongs to the cache kmalloc-256 of size 256 +The buggy address is located 64 bytes inside of + freed 256-byte region [ffff88806158de00, ffff88806158df00) + +The buggy address belongs to the physical page: +page: refcount:0 mapcount:0 mapping:0000000000000000 index:0xffff88806158d600 pfn:0x6158c +head: order:1 mapcount:0 entire_mapcount:0 nr_pages_mapped:0 pincount:0 +flags: 0x4fff00000000240(workingset|head|node=1|zone=1|lastcpupid=0x7ff) +page_type: f5(slab) +raw: 04fff00000000240 ffff88801c841b40 ffffea0001856290 ffffea0001856190 +raw: ffff88806158d600 0000000800100009 00000000f5000000 0000000000000000 +head: 04fff00000000240 ffff88801c841b40 ffffea0001856290 ffffea0001856190 +head: ffff88806158d600 0000000800100009 00000000f5000000 0000000000000000 +head: 04fff00000000001 ffffffffffffff81 00000000ffffffff 00000000ffffffff +head: ffffffffffffffff 0000000000000000 00000000ffffffff 0000000000000002 +page dumped because: kasan: bad access detected +page_owner tracks the page as allocated +page last allocated via order 1, migratetype Unmovable, gfp_mask 0xd2820(GFP_ATOMIC|__GFP_NOWARN|__GFP_NORETRY|__GFP_COMP|__GFP_NOMEMALLOC), pid 9391, tgid 9378 (poc), ts 123227323196, free_ts 0 + set_page_owner include/linux/page_owner.h:32 + post_alloc_hook+0xfe/0x140 mm/page_alloc.c:1853 + prep_new_page mm/page_alloc.c:1861 + get_page_from_freelist+0x110c/0x2fc0 mm/page_alloc.c:3941 + __alloc_frozen_pages_noprof+0x263/0x2bc0 mm/page_alloc.c:5221 + alloc_slab_page mm/slub.c:3278 + allocate_slab mm/slub.c:3467 + new_slab+0xa6/0x690 mm/slub.c:3525 + refill_objects+0x271/0x420 mm/slub.c:7272 + refill_sheaf mm/slub.c:2816 + __pcs_replace_empty_main+0x373/0x630 mm/slub.c:4652 + alloc_from_pcs mm/slub.c:4750 + slab_alloc_node mm/slub.c:4884 + __do_kmalloc_node mm/slub.c:5295 + __kmalloc_noprof+0x66d/0x830 mm/slub.c:5308 + kmalloc_noprof include/linux/slab.h:954 + metadata_dst_alloc+0x26/0x90 net/core/dst.c:298 + tun_rx_dst include/net/dst_metadata.h:144 + __ip_tun_set_dst include/net/dst_metadata.h:208 + tunnel_key_init+0xb01/0x1b90 net/sched/act_tunnel_key.c:451 + tcf_action_init_1+0x46b/0x6c0 net/sched/act_api.c:1428 + tcf_action_init+0x448/0xa20 net/sched/act_api.c:1503 + tcf_action_add+0xf6/0x5d0 net/sched/act_api.c:2101 +[..] +================================================================== + +Fix by moving dst_release() into a custom RCU callback that runs +after the grace period, matching the lifetime of the containing +params struct. Readers in the datapath therefore always find a live +rcuref when calling dst_clone(). + +Fixes: 9174c3df1cd18 ("net/sched: act_tunnel_key: fix memory leak in case of action replace") +Reported-by: zdi-disclosures@trendmicro.com +Tested-by: Victor Nogueira +Signed-off-by: Jamal Hadi Salim +Reviewed-by: Davide Caratti +Link: https://patch.msgid.link/20260711150537.7946-1-jhs@mojatatu.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/sched/act_tunnel_key.c | 14 ++++++++++---- + 1 file changed, 10 insertions(+), 4 deletions(-) + +diff --git a/net/sched/act_tunnel_key.c b/net/sched/act_tunnel_key.c +index e296714803dc02..74e9b5ea76a555 100644 +--- a/net/sched/act_tunnel_key.c ++++ b/net/sched/act_tunnel_key.c +@@ -344,14 +344,20 @@ static const struct nla_policy tunnel_key_policy[TCA_TUNNEL_KEY_MAX + 1] = { + [TCA_TUNNEL_KEY_ENC_TTL] = { .type = NLA_U8 }, + }; + +-static void tunnel_key_release_params(struct tcf_tunnel_key_params *p) ++static void tunnel_key_release_params_rcu(struct rcu_head *head) + { +- if (!p) +- return; ++ struct tcf_tunnel_key_params *p = container_of(head, typeof(*p), rcu); ++ + if (p->tcft_action == TCA_TUNNEL_KEY_ACT_SET) + dst_release(&p->tcft_enc_metadata->dst); ++ kfree(p); ++} + +- kfree_rcu(p, rcu); ++static void tunnel_key_release_params(struct tcf_tunnel_key_params *p) ++{ ++ if (!p) ++ return; ++ call_rcu(&p->rcu, tunnel_key_release_params_rcu); + } + + static int tunnel_key_init(struct net *net, struct nlattr *nla, +-- +2.53.0 + diff --git a/queue-6.12/powerpc-85xx-add-fsl-ifc-to-common-device-ids.patch b/queue-6.12/powerpc-85xx-add-fsl-ifc-to-common-device-ids.patch new file mode 100644 index 0000000000..bbafbc488e --- /dev/null +++ b/queue-6.12/powerpc-85xx-add-fsl-ifc-to-common-device-ids.patch @@ -0,0 +1,41 @@ +From 99cd76b3e8d6a351ab289ebb81902dbd26e9aba1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 3 Jun 2026 21:33:09 -0700 +Subject: powerpc/85xx: Add fsl,ifc to common device ids + +From: Rosen Penev + +[ Upstream commit 25957f7c3dac3265332d766b71233e3622f17e14 ] + +Add fsl,ifc to mpc85xx_common_ids so that of_platform_bus_probe +creates a platform device for the IFC node even without 'simple-bus' +in its compatible property. On P1010 and similar platforms the IFC +node is a direct child of the root, so it must be explicitly matched +to be populated. + +Fixes: 0bf51cc9e9e5 ("powerpc: dts: mpc85xx: remove "simple-bus" compatible from ifc node") +Assisted-by: opencode:big-pickle +Signed-off-by: Rosen Penev +Signed-off-by: Madhavan Srinivasan +Link: https://patch.msgid.link/20260604043309.91280-1-rosenp@gmail.com +Signed-off-by: Sasha Levin +--- + arch/powerpc/platforms/85xx/common.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/arch/powerpc/platforms/85xx/common.c b/arch/powerpc/platforms/85xx/common.c +index 757811155587db..c11deb2f50ed45 100644 +--- a/arch/powerpc/platforms/85xx/common.c ++++ b/arch/powerpc/platforms/85xx/common.c +@@ -42,6 +42,8 @@ static const struct of_device_id mpc85xx_common_ids[] __initconst = { + { .compatible = "fsl,qoriq-pcie-v2.3", }, + { .compatible = "fsl,qoriq-pcie-v2.2", }, + { .compatible = "fsl,fman", }, ++ /* IFC NAND and NOR controllers */ ++ { .compatible = "fsl,ifc", }, + {}, + }; + +-- +2.53.0 + diff --git a/queue-6.12/powerpc-time-prepare-to-stop-elapsing-in-dynticks-id.patch b/queue-6.12/powerpc-time-prepare-to-stop-elapsing-in-dynticks-id.patch new file mode 100644 index 0000000000..9c578f76da --- /dev/null +++ b/queue-6.12/powerpc-time-prepare-to-stop-elapsing-in-dynticks-id.patch @@ -0,0 +1,126 @@ +From bc67335d172b49f378ea40624c4a7f715da419de Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 8 May 2026 15:16:37 +0200 +Subject: powerpc/time: Prepare to stop elapsing in dynticks-idle + +From: Frederic Weisbecker + +[ Upstream commit c8ba971cf8567d49eb5f43ee90c4e50424331c18 ] + +Currently the tick subsystem stores the idle cputime accounting in +private fields, allowing cohabitation with architecture idle vtime +accounting. The former is fetched on online CPUs, the latter on offline +CPUs. + +For consolidation purpose, architecture vtime accounting will continue +to account the cputime but will make a break when the idle tick is +stopped. The dyntick cputime accounting will then be relayed by the tick +subsystem so that the idle cputime is still seen advancing coherently +even when the tick isn't there to flush the idle vtime. + +Prepare for that and introduce three new APIs which will be used in +subsequent patches: + + - vtime_dynticks_start() is deemed to be called when idle enters in + dyntick mode. The idle cputime that elapsed so far is accumulated. + + - vtime_dynticks_stop() is deemed to be called when idle exits from + dyntick mode. The vtime entry clocks are fast-forward to current time + so that idle accounting restarts elapsing from now. + + - vtime_reset() is deemed to be called from dynticks idle IRQ entry to + fast-forward the clock to current time so that the IRQ time is still + accounted by vtime while nohz cputime is paused. + +Also accumulated vtime won't be flushed from dyntick-idle ticks to avoid +accounting twice the idle cputime, along with nohz accounting. + +Signed-off-by: Frederic Weisbecker +Signed-off-by: Thomas Gleixner +Tested-by: Shrikanth Hegde +Reviewed-by: Shrikanth Hegde +Link: https://patch.msgid.link/20260508131647.43868-6-frederic@kernel.org +Stable-dep-of: c1c1ffa490fc ("powerpc/vtime: Initialize starttime at boot for native accounting") +Signed-off-by: Sasha Levin +--- + arch/powerpc/kernel/time.c | 41 ++++++++++++++++++++++++++++++++++++++ + include/linux/vtime.h | 6 ++++++ + 2 files changed, 47 insertions(+) + +diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c +index ce7f91172ec2b6..c8beb00e6a27c6 100644 +--- a/arch/powerpc/kernel/time.c ++++ b/arch/powerpc/kernel/time.c +@@ -376,6 +376,47 @@ void vtime_task_switch(struct task_struct *prev) + acct->starttime = acct0->starttime; + } + } ++ ++#ifdef CONFIG_NO_HZ_COMMON ++/** ++ * vtime_reset - Fast forward vtime entry clocks ++ * ++ * Called from dynticks idle IRQ entry to fast-forward the clocks to current time ++ * so that the IRQ time is still accounted by vtime while nohz cputime is paused. ++ */ ++void vtime_reset(void) ++{ ++ struct cpu_accounting_data *acct = get_accounting(current); ++ ++ acct->starttime = mftb(); ++#ifdef CONFIG_ARCH_HAS_SCALED_CPUTIME ++ acct->startspurr = read_spurr(acct->starttime); ++#endif ++} ++ ++/** ++ * vtime_dyntick_start - Inform vtime about entry to idle-dynticks ++ * ++ * Called when idle enters in dyntick mode. The idle cputime that elapsed so far ++ * is accumulated and the tick subsystem takes over the idle cputime accounting. ++ */ ++void vtime_dyntick_start(void) ++{ ++ vtime_account_idle(current); ++} ++ ++/** ++ * vtime_dyntick_stop - Inform vtime about exit from idle-dynticks ++ * ++ * Called when idle exits from dyntick mode. The vtime entry clocks are ++ * fast-forward to current time so that idle accounting restarts elapsing from ++ * now. ++ */ ++void vtime_dyntick_stop(void) ++{ ++ vtime_reset(); ++} ++#endif /* CONFIG_NO_HZ_COMMON */ + #endif /* CONFIG_VIRT_CPU_ACCOUNTING_NATIVE */ + + void __no_kcsan __delay(unsigned long loops) +diff --git a/include/linux/vtime.h b/include/linux/vtime.h +index 29dd5b91dd7d66..3fc04b849e4e30 100644 +--- a/include/linux/vtime.h ++++ b/include/linux/vtime.h +@@ -32,11 +32,17 @@ extern void vtime_account_irq(struct task_struct *tsk, unsigned int offset); + extern void vtime_account_softirq(struct task_struct *tsk); + extern void vtime_account_hardirq(struct task_struct *tsk); + extern void vtime_flush(struct task_struct *tsk); ++extern void vtime_reset(void); ++extern void vtime_dyntick_start(void); ++extern void vtime_dyntick_stop(void); + #else /* !CONFIG_VIRT_CPU_ACCOUNTING_NATIVE */ + static inline void vtime_account_irq(struct task_struct *tsk, unsigned int offset) { } + static inline void vtime_account_softirq(struct task_struct *tsk) { } + static inline void vtime_account_hardirq(struct task_struct *tsk) { } + static inline void vtime_flush(struct task_struct *tsk) { } ++static inline void vtime_reset(void) { } ++static inline void vtime_dyntick_start(void) { } ++static inline void vtime_dyntick_stop(void) { } + #endif + + /* +-- +2.53.0 + diff --git a/queue-6.12/powerpc-vtime-initialize-starttime-at-boot-for-nativ.patch b/queue-6.12/powerpc-vtime-initialize-starttime-at-boot-for-nativ.patch new file mode 100644 index 0000000000..5b2fc73c5e --- /dev/null +++ b/queue-6.12/powerpc-vtime-initialize-starttime-at-boot-for-nativ.patch @@ -0,0 +1,90 @@ +From 5bbe93ca196fa142272229eb8166e346b4ac3a10 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 5 Jun 2026 18:13:29 +0530 +Subject: powerpc/vtime: Initialize starttime at boot for native accounting + +From: Shrikanth Hegde + +[ Upstream commit c1c1ffa490fc33591e90852ed0d38804dd20bc36 ] + +It was observed that /proc/stat had very large value for one ore more +CPUs. It was more visible after recent code simplifications around +cpustats. + +System has 240 CPUs. + +cat /proc/uptime; +194.18 46500.55 +cat /proc/stat +cpu 5966 39 837032887 4650070 164 185 100 0 0 0 +cpu0 108 0 837030890 19109 24 4 23 0 0 0 + +Since uptime is 194s, system time of each CPU can't be more than 19400. +Sum of system time of all CPUs can't be more than 19400*240 4656000. +In fact huge value is close to mftb(). Note mftb doesn't reset on powerVM +when the LPAR restart. It only resets when whole system resets. The same +issue exists for kexec too. + +This happens since starttime is not setup at init time. Once it is set +then subsequent vtime_delta will return the right delta. + +Fix it by initializing the starttime during CPU initialization. This +fixes the large times seen. + +cat /proc/uptime; cat /proc/stat +15.78 3694.63 +cpu 6035 35 1347 369479 23 144 49 0 0 0 +cpu0 19 0 38 1508 0 1 14 0 0 0 + +Now, system time is reported as expected. + +Fixes: cf9efce0ce31 ("powerpc: Account time using timebase rather than PURR") +Reviewed-by: Christophe Leroy (CS GROUP) +Suggested-by: Christophe Leroy (CS GROUP) +Signed-off-by: Shrikanth Hegde +Signed-off-by: Madhavan Srinivasan +Link: https://patch.msgid.link/20260605124329.377533-1-sshegde@linux.ibm.com +Signed-off-by: Sasha Levin +--- + arch/powerpc/kernel/time.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c +index c8beb00e6a27c6..c69c0f23f5212a 100644 +--- a/arch/powerpc/kernel/time.c ++++ b/arch/powerpc/kernel/time.c +@@ -377,7 +377,6 @@ void vtime_task_switch(struct task_struct *prev) + } + } + +-#ifdef CONFIG_NO_HZ_COMMON + /** + * vtime_reset - Fast forward vtime entry clocks + * +@@ -394,6 +393,7 @@ void vtime_reset(void) + #endif + } + ++#ifdef CONFIG_NO_HZ_COMMON + /** + * vtime_dyntick_start - Inform vtime about entry to idle-dynticks + * +@@ -927,6 +927,7 @@ static void __init set_decrementer_max(void) + static void __init init_decrementer_clockevent(void) + { + register_decrementer_clockevent(smp_processor_id()); ++ vtime_reset(); + } + + void secondary_cpu_time_init(void) +@@ -942,6 +943,7 @@ void secondary_cpu_time_init(void) + /* FIME: Should make unrelated change to move snapshot_timebase + * call here ! */ + register_decrementer_clockevent(smp_processor_id()); ++ vtime_reset(); + } + + /* This function is only called on the boot processor */ +-- +2.53.0 + diff --git a/queue-6.12/ppp-defer-channel-free-to-an-rcu-grace-period-to-fix.patch b/queue-6.12/ppp-defer-channel-free-to-an-rcu-grace-period-to-fix.patch new file mode 100644 index 0000000000..a414a1da71 --- /dev/null +++ b/queue-6.12/ppp-defer-channel-free-to-an-rcu-grace-period-to-fix.patch @@ -0,0 +1,104 @@ +From dfd5c0865567cf7ec80277635d848d98f07a6caf Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 6 Jul 2026 11:01:59 +0200 +Subject: ppp: defer channel free to an RCU grace period to fix pppol2tp RX UAF + +From: Norbert Szetei + +[ Upstream commit ec4215683e47424c9c4762fd3c60f552a3119142 ] + +pppol2tp_recv() runs in the L2TP UDP-encap softirq RX path: + + l2tp_udp_encap_recv() -> l2tp_recv_common() -> pppol2tp_recv() + -> ppp_input(&po->chan) + +It runs under rcu_read_lock() holding only an l2tp_session reference and +takes NO reference on the internal PPP channel (struct channel, +chan->ppp) that ppp_input() dereferences. + +The pppox socket is SOCK_RCU_FREE, so 'po' and the embedded ppp_channel +are RCU-safe. But the internal struct channel is a separate allocation +that ppp_release_channel() frees with a plain kfree(): + + close(data socket) -> pppol2tp_release() -> pppox_unbind_sock() + -> ppp_unregister_channel() -> ppp_release_channel() -> kfree(pch) + +For a channel that is bound (PPPIOCGCHAN) but not attached to a ppp unit +(no PPPIOCCONNECT, pch->ppp == NULL) and not bridged, teardown skips +both ppp_disconnect_channel()'s synchronize_net() and +ppp_unbridge_channels()'s synchronize_rcu(), so the kfree() has no grace +period. rcu_read_lock() in pppol2tp_recv() does not protect against a +plain kfree(), so an in-flight ppp_input() on one CPU can dereference +the channel just freed by close() on another CPU. + +The bug is reachable by an unprivileged user. + +Defer the channel free to an RCU callback via call_rcu() so the grace +period fences any in-flight ppp_input(). The disconnect and unbridge +teardown paths already fence with synchronize_net()/synchronize_rcu(); +call_rcu() does the same here without stalling the close() path. + +Fixes: ee40fb2e1eb5 ("l2tp: protect sock pointer of struct pppol2tp_session with RCU") +Assisted-by: Claude:claude-opus-4-8 +Signed-off-by: Norbert Szetei +Reviewed-by: Qingfang Deng +Link: https://patch.msgid.link/E793FCF2-58DE-4387-A983-C7B4BC3158BD@doyensec.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ppp/ppp_generic.c | 18 +++++++++++++++--- + 1 file changed, 15 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c +index c70994c6a265e3..9f787adef3eb38 100644 +--- a/drivers/net/ppp/ppp_generic.c ++++ b/drivers/net/ppp/ppp_generic.c +@@ -192,6 +192,7 @@ struct channel { + struct list_head clist; /* link in list of channels per unit */ + rwlock_t upl; /* protects `ppp' and 'bridge' */ + struct channel __rcu *bridge; /* "bridged" ppp channel */ ++ struct rcu_head rcu; /* for RCU-deferred free of the channel */ + #ifdef CONFIG_PPP_MULTILINK + u8 avail; /* flag used in multilink stuff */ + u8 had_frag; /* >= 1 fragments have been sent */ +@@ -3555,6 +3556,18 @@ ppp_disconnect_channel(struct channel *pch) + return err; + } + ++/* Purge after the grace period: a late ppp_input() may still queue an ++ * skb on pch->file.rq before the last RCU reader drains. ++ */ ++static void ppp_release_channel_free(struct rcu_head *rcu) ++{ ++ struct channel *pch = container_of(rcu, struct channel, rcu); ++ ++ skb_queue_purge(&pch->file.xq); ++ skb_queue_purge(&pch->file.rq); ++ kfree(pch); ++} ++ + /* + * Free up the resources used by a ppp channel. + */ +@@ -3570,9 +3583,7 @@ static void ppp_destroy_channel(struct channel *pch) + pr_err("ppp: destroying undead channel %p !\n", pch); + return; + } +- skb_queue_purge(&pch->file.xq); +- skb_queue_purge(&pch->file.rq); +- kfree(pch); ++ call_rcu(&pch->rcu, ppp_release_channel_free); + } + + static void __exit ppp_cleanup(void) +@@ -3585,6 +3596,7 @@ static void __exit ppp_cleanup(void) + device_destroy(&ppp_class, MKDEV(PPP_MAJOR, 0)); + class_unregister(&ppp_class); + unregister_pernet_device(&ppp_net_ops); ++ rcu_barrier(); /* wait for RCU callbacks before module unload */ + } + + /* +-- +2.53.0 + diff --git a/queue-6.12/rdma-cma-fix-hardware-address-comparison-length-in-n.patch b/queue-6.12/rdma-cma-fix-hardware-address-comparison-length-in-n.patch new file mode 100644 index 0000000000..e63495fc7f --- /dev/null +++ b/queue-6.12/rdma-cma-fix-hardware-address-comparison-length-in-n.patch @@ -0,0 +1,43 @@ +From a4d5bde1224f9e1263b18e6dae0d4abf908ce845 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 17 Jun 2026 14:21:05 +0300 +Subject: RDMA/cma: Fix hardware address comparison length in netevent callback + +From: Or Gerlitz + +[ Upstream commit 18313833e2c6de222a4f6c072da759d0d5888528 ] + +The cited commit hardcoded the hardware address comparison len to ETH_ALEN. + +This breaks IPoIB, which uses 20-byte addresses. By truncating the +memcmp, the CMA may incorrectly assume the target address is +unchanged and fails to abort the stalled connection. + +Fix this by replacing ETH_ALEN with the dynamic neigh->dev->addr_len +to correctly evaluate the full address regardless of the link layer. + +Fixes: 925d046e7e52 ("RDMA/core: Add a netevent notifier to cma") +Signed-off-by: Or Gerlitz +Link: https://patch.msgid.link/20260617-fix-cma-ipoib-v1-1-03f869344304@ddn.com +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + drivers/infiniband/core/cma.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c +index 52d70eeb0c52ec..a225eae78d3e58 100644 +--- a/drivers/infiniband/core/cma.c ++++ b/drivers/infiniband/core/cma.c +@@ -5231,7 +5231,7 @@ static int cma_netevent_callback(struct notifier_block *self, + + list_for_each_entry(current_id, &ips_node->id_list, id_list_entry) { + if (!memcmp(current_id->id.route.addr.dev_addr.dst_dev_addr, +- neigh->ha, ETH_ALEN)) ++ neigh->ha, neigh->dev->addr_len)) + continue; + cma_id_get(current_id); + if (!queue_work(cma_wq, ¤t_id->id.net_work)) +-- +2.53.0 + diff --git a/queue-6.12/rdma-erdma-initialize-ret-for-empty-receive-wr-lists.patch b/queue-6.12/rdma-erdma-initialize-ret-for-empty-receive-wr-lists.patch new file mode 100644 index 0000000000..9e6a6e7cf5 --- /dev/null +++ b/queue-6.12/rdma-erdma-initialize-ret-for-empty-receive-wr-lists.patch @@ -0,0 +1,42 @@ +From 0d5b0bd4b766029cb385997e9dc4f631537b9728 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 18 Jun 2026 12:17:51 +0800 +Subject: RDMA/erdma: initialize ret for empty receive WR lists + +From: Ruoyu Wang + +[ Upstream commit 2815a277c53e9a84784d6410cd55a9da5b33068d ] + +erdma_post_recv() returns ret after walking the receive work request list. +If the caller passes an empty list, the loop is skipped and ret is not +assigned. + +Initialize ret to 0 so an empty receive work request list returns success +instead of stack data. + +Fixes: 155055771704 ("RDMA/erdma: Add verbs implementation") +Link: https://patch.msgid.link/r/20260618041752.481193-1-ruoyuw560@gmail.com +Signed-off-by: Ruoyu Wang +Reviewed-by: Cheng Xu +Signed-off-by: Jason Gunthorpe +Signed-off-by: Sasha Levin +--- + drivers/infiniband/hw/erdma/erdma_qp.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/infiniband/hw/erdma/erdma_qp.c b/drivers/infiniband/hw/erdma/erdma_qp.c +index 4d1f9114cd97c5..4dfab0c49e5192 100644 +--- a/drivers/infiniband/hw/erdma/erdma_qp.c ++++ b/drivers/infiniband/hw/erdma/erdma_qp.c +@@ -573,7 +573,7 @@ int erdma_post_recv(struct ib_qp *ibqp, const struct ib_recv_wr *recv_wr, + const struct ib_recv_wr *wr = recv_wr; + struct erdma_qp *qp = to_eqp(ibqp); + unsigned long flags; +- int ret; ++ int ret = 0; + + spin_lock_irqsave(&qp->lock, flags); + +-- +2.53.0 + diff --git a/queue-6.12/rdma-hns-fix-potential-integer-overflow-in-mhop-hem-.patch b/queue-6.12/rdma-hns-fix-potential-integer-overflow-in-mhop-hem-.patch new file mode 100644 index 0000000000..af851de178 --- /dev/null +++ b/queue-6.12/rdma-hns-fix-potential-integer-overflow-in-mhop-hem-.patch @@ -0,0 +1,52 @@ +From 531dbf51e2ed6f22a6bafbb97ef0bd715198230f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 27 Jun 2026 09:59:51 +0000 +Subject: RDMA/hns: Fix potential integer overflow in mhop hem cleanup + +From: Danila Chernetsov + +[ Upstream commit 9f0f2d2121f16d420199a82ac5bbc242269133b3 ] + +In hns_roce_cleanup_mhop_hem_table(), the expression: + + obj = i * buf_chunk_size / table->obj_size; + +is evaluated using 32-bit unsigned arithmetic because +'buf_chunk_size' is u32 and the usual arithmetic conversions convert +'i' to unsigned int. The result is assigned to a u64 variable, but the +multiplication may overflow before the assignment. + +For sufficiently large HEM tables, this produces an incorrect object +index passed to hns_roce_table_mhop_put(). + +Cast 'i' to u64 before the multiplication so that the intermediate +calculation is performed with 64-bit arithmetic. + +Found by Linux Verification Center (linuxtesting.org) with SVACE. + +Fixes: a25d13cbe816 ("RDMA/hns: Add the interfaces to support multi hop addressing for the contexts in hip08") +Link: https://patch.msgid.link/r/20260627095951.51378-1-listdansp@mail.ru +Signed-off-by: Danila Chernetsov +Reviewed-by: Junxian Huang +Signed-off-by: Jason Gunthorpe +Signed-off-by: Sasha Levin +--- + drivers/infiniband/hw/hns/hns_roce_hem.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/infiniband/hw/hns/hns_roce_hem.c b/drivers/infiniband/hw/hns/hns_roce_hem.c +index 1680d0ac071ed1..ae7a3939124f23 100644 +--- a/drivers/infiniband/hw/hns/hns_roce_hem.c ++++ b/drivers/infiniband/hw/hns/hns_roce_hem.c +@@ -842,7 +842,7 @@ static void hns_roce_cleanup_mhop_hem_table(struct hns_roce_dev *hr_dev, + mhop.bt_chunk_size; + + for (i = 0; i < table->num_hem; ++i) { +- obj = i * buf_chunk_size / table->obj_size; ++ obj = (u64)i * buf_chunk_size / table->obj_size; + if (table->hem[i]) + hns_roce_table_mhop_put(hr_dev, table, obj, 0); + } +-- +2.53.0 + diff --git a/queue-6.12/rdma-irdma-prevent-overflows-in-memory-contiguity-ch.patch b/queue-6.12/rdma-irdma-prevent-overflows-in-memory-contiguity-ch.patch new file mode 100644 index 0000000000..fa6385d400 --- /dev/null +++ b/queue-6.12/rdma-irdma-prevent-overflows-in-memory-contiguity-ch.patch @@ -0,0 +1,64 @@ +From 422063da335107369283cdf5941aac671ea5411f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 24 Jun 2026 17:48:46 +0300 +Subject: RDMA/irdma: Prevent overflows in memory contiguity checks + +From: Aleksandrova Alyona + +[ Upstream commit 3cda0dfe8c651dcbb9e38977905d3d3b1750c4ab ] + +irdma_check_mem_contiguous() and irdma_check_mr_contiguous() verify that +PBL entries describe physically contiguous memory ranges. + +Both functions calculate byte offsets using 32-bit operands. For example, +with 4 KiB pages, pg_size * pg_idx overflows 32-bit arithmetic when +pg_idx reaches 1048576. In the level-2 check, PBLE_PER_PAGE is 512, so +i * pg_size * PBLE_PER_PAGE overflows when i reaches 2048. + +These values are reachable in the driver. For MRs, palloc->total_cnt +comes from iwmr->page_cnt, which is calculated by +ib_umem_num_dma_blocks(). The MR size is limited by IRDMA_MAX_MR_SIZE, +so a 4 GiB MR with 4 KiB pages can reach page_cnt of 1048576. PBLE +resources do not exclude this value either: for gen3, the limit is based +on avail_sds * MAX_PBLE_PER_SD, and MAX_PBLE_PER_SD is 0x40000, so 4 SDs +are enough for 1048576 PBLEs. + +Cast one operand to u64 before the multiplications so that the offset +calculations are performed in 64-bit arithmetic. + +Found by Linux Verification Center (linuxtesting.org) with SVACE. + +Fixes: b48c24c2d710 ("RDMA/irdma: Implement device supported verb APIs") +Signed-off-by: Aleksandrova Alyona +Link: https://patch.msgid.link/20260624144846.61242-1-aga@itb.spb.ru +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + drivers/infiniband/hw/irdma/verbs.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/infiniband/hw/irdma/verbs.c b/drivers/infiniband/hw/irdma/verbs.c +index 255c6d21756ba4..d8e101fc74ff73 100644 +--- a/drivers/infiniband/hw/irdma/verbs.c ++++ b/drivers/infiniband/hw/irdma/verbs.c +@@ -2367,7 +2367,7 @@ static bool irdma_check_mem_contiguous(u64 *arr, u32 npages, u32 pg_size) + u32 pg_idx; + + for (pg_idx = 0; pg_idx < npages; pg_idx++) { +- if ((*arr + (pg_size * pg_idx)) != arr[pg_idx]) ++ if ((*arr + ((u64)pg_size * pg_idx)) != arr[pg_idx]) + return false; + } + +@@ -2400,7 +2400,7 @@ static bool irdma_check_mr_contiguous(struct irdma_pble_alloc *palloc, + + for (i = 0; i < lvl2->leaf_cnt; i++, leaf++) { + arr = leaf->addr; +- if ((*start_addr + (i * pg_size * PBLE_PER_PAGE)) != *arr) ++ if ((*start_addr + ((u64)i * pg_size * PBLE_PER_PAGE)) != *arr) + return false; + ret = irdma_check_mem_contiguous(arr, leaf->cnt, pg_size); + if (!ret) +-- +2.53.0 + diff --git a/queue-6.12/rdma-irdma-prevent-rereg_mr-for-non-mem-regions.patch b/queue-6.12/rdma-irdma-prevent-rereg_mr-for-non-mem-regions.patch new file mode 100644 index 0000000000..bab08b66ce --- /dev/null +++ b/queue-6.12/rdma-irdma-prevent-rereg_mr-for-non-mem-regions.patch @@ -0,0 +1,51 @@ +From 0e5b4b0e7d77ce89e7ace8cceb8ee9c6a4c964a8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 17 Jun 2026 14:19:36 +0000 +Subject: RDMA/irdma: Prevent rereg_mr for non-mem regions + +From: Jacob Moroni + +[ Upstream commit a846aecb931b4d65d5eafa92a0623545af46d4f2 ] + +When a QP/CQ/SRQ is created, a two step process is used +where the buffer is allocated in userspace and explicitly +registered with the normal reg_mr mechanism prior to creating +the actual QP/CQ/SRQ object. + +These special registrations are indicated via an ABI field +so the driver knows that they do not have a valid mkey and +to skip the actual CQP command submission. + +Since these are real MR objects from the core's perspective, +it is possible for a user application to invoke rereg_mr on them +and cause a real CQP op to be emitted with the zero-initialized +mkey value of 0. + +Fix this by preventing rereg_mr on these special regions. + +Fixes: 5ac388db27c4 ("RDMA/irdma: Add support to re-register a memory region") +Signed-off-by: Jacob Moroni +Reviewed-by: David Hu +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + drivers/infiniband/hw/irdma/verbs.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/infiniband/hw/irdma/verbs.c b/drivers/infiniband/hw/irdma/verbs.c +index 92b56338819ef8..255c6d21756ba4 100644 +--- a/drivers/infiniband/hw/irdma/verbs.c ++++ b/drivers/infiniband/hw/irdma/verbs.c +@@ -3252,6 +3252,9 @@ static struct ib_mr *irdma_rereg_user_mr(struct ib_mr *ib_mr, int flags, + if (flags & ~(IB_MR_REREG_TRANS | IB_MR_REREG_PD | IB_MR_REREG_ACCESS)) + return ERR_PTR(-EOPNOTSUPP); + ++ if (iwmr->type != IRDMA_MEMREG_TYPE_MEM) ++ return ERR_PTR(-EINVAL); ++ + ret = ib_umem_check_rereg(iwmr->region, flags, new_access); + if (ret) + return ERR_PTR(ret); +-- +2.53.0 + diff --git a/queue-6.12/rdma-siw-publish-qp-after-initialization.patch b/queue-6.12/rdma-siw-publish-qp-after-initialization.patch new file mode 100644 index 0000000000..6ec0ae1360 --- /dev/null +++ b/queue-6.12/rdma-siw-publish-qp-after-initialization.patch @@ -0,0 +1,153 @@ +From d5e9c1b8f83ca3801cb14af397549581eaafd4bc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 30 Jun 2026 14:00:40 +0800 +Subject: RDMA/siw: publish QP after initialization + +From: Ruoyu Wang + +[ Upstream commit bb27fcc67c429d97f785c92c35a6c5adebb05d7f ] + +siw_create_qp() currently calls siw_qp_add() before the queues, CQ +pointers, state, completion, and device list entry are ready. A QPN +lookup can therefore reach a QP that is still being constructed. + +Move siw_qp_add() to the end of siw_create_qp(), after QP +initialization and before adding the QP to the siw device list. + +Fixes: f29dd55b0236 ("rdma/siw: queue pair methods") +Link: https://patch.msgid.link/r/20260630060040.966461-1-ruoyuw560@gmail.com +Suggested-by: Bernard Metzler +Signed-off-by: Ruoyu Wang +Acked-by: Bernard Metzler +Signed-off-by: Jason Gunthorpe +Signed-off-by: Sasha Levin +--- + drivers/infiniband/sw/siw/siw_verbs.c | 44 +++++++++++++++------------ + 1 file changed, 24 insertions(+), 20 deletions(-) + +diff --git a/drivers/infiniband/sw/siw/siw_verbs.c b/drivers/infiniband/sw/siw/siw_verbs.c +index d0c0cde09f1186..8ecff632ab6f3d 100644 +--- a/drivers/infiniband/sw/siw/siw_verbs.c ++++ b/drivers/infiniband/sw/siw/siw_verbs.c +@@ -317,6 +317,7 @@ int siw_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attrs, + struct siw_ucontext *uctx = + rdma_udata_to_drv_context(udata, struct siw_ucontext, + base_ucontext); ++ struct siw_uresp_create_qp uresp = {}; + unsigned long flags; + int num_sqe, num_rqe, rv = 0; + size_t length; +@@ -370,11 +371,6 @@ int siw_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attrs, + spin_lock_init(&qp->rq_lock); + spin_lock_init(&qp->orq_lock); + +- rv = siw_qp_add(sdev, qp); +- if (rv) +- goto err_atomic; +- +- + /* All queue indices are derived from modulo operations + * on a free running 'get' (consumer) and 'put' (producer) + * unsigned counter. Having queue sizes at power of two +@@ -392,14 +388,14 @@ int siw_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attrs, + + if (qp->sendq == NULL) { + rv = -ENOMEM; +- goto err_out_xa; ++ goto err_out; + } + if (attrs->sq_sig_type != IB_SIGNAL_REQ_WR) { + if (attrs->sq_sig_type == IB_SIGNAL_ALL_WR) + qp->attrs.flags |= SIW_SIGNAL_ALL_WR; + else { + rv = -EINVAL; +- goto err_out_xa; ++ goto err_out; + } + } + qp->pd = pd; +@@ -425,7 +421,7 @@ int siw_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attrs, + + if (qp->recvq == NULL) { + rv = -ENOMEM; +- goto err_out_xa; ++ goto err_out; + } + qp->attrs.rq_size = num_rqe; + } +@@ -440,11 +436,8 @@ int siw_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attrs, + qp->attrs.state = SIW_QP_STATE_IDLE; + + if (udata) { +- struct siw_uresp_create_qp uresp = {}; +- + uresp.num_sqe = num_sqe; + uresp.num_rqe = num_rqe; +- uresp.qp_id = qp_id(qp); + + if (qp->sendq) { + length = num_sqe * sizeof(struct siw_sqe); +@@ -453,7 +446,7 @@ int siw_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attrs, + length, &uresp.sq_key); + if (!qp->sq_entry) { + rv = -ENOMEM; +- goto err_out_xa; ++ goto err_out; + } + } + +@@ -465,9 +458,23 @@ int siw_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attrs, + if (!qp->rq_entry) { + uresp.sq_key = SIW_INVAL_UOBJ_KEY; + rv = -ENOMEM; +- goto err_out_xa; ++ goto err_out; + } + } ++ } ++ qp->tx_cpu = siw_get_tx_cpu(sdev); ++ if (qp->tx_cpu < 0) { ++ rv = -EINVAL; ++ goto err_out; ++ } ++ init_completion(&qp->qp_free); ++ ++ rv = siw_qp_add(sdev, qp); ++ if (rv) ++ goto err_out_tx; ++ ++ if (udata) { ++ uresp.qp_id = qp_id(qp); + + if (udata->outlen < sizeof(uresp)) { + rv = -EINVAL; +@@ -477,22 +484,19 @@ int siw_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attrs, + if (rv) + goto err_out_xa; + } +- qp->tx_cpu = siw_get_tx_cpu(sdev); +- if (qp->tx_cpu < 0) { +- rv = -EINVAL; +- goto err_out_xa; +- } ++ + INIT_LIST_HEAD(&qp->devq); + spin_lock_irqsave(&sdev->lock, flags); + list_add_tail(&qp->devq, &sdev->qp_list); + spin_unlock_irqrestore(&sdev->lock, flags); + +- init_completion(&qp->qp_free); +- + return 0; + + err_out_xa: + xa_erase(&sdev->qp_xa, qp_id(qp)); ++err_out_tx: ++ siw_put_tx_cpu(qp->tx_cpu); ++err_out: + if (uctx) { + rdma_user_mmap_entry_remove(qp->sq_entry); + rdma_user_mmap_entry_remove(qp->rq_entry); +-- +2.53.0 + diff --git a/queue-6.12/rdma-umem-add-pinned-revocable-dmabuf-import-interfa.patch b/queue-6.12/rdma-umem-add-pinned-revocable-dmabuf-import-interfa.patch new file mode 100644 index 0000000000..487f86a2a6 --- /dev/null +++ b/queue-6.12/rdma-umem-add-pinned-revocable-dmabuf-import-interfa.patch @@ -0,0 +1,167 @@ +From e35a6d16e9bbf2a5f83633126b83eb48547cac61 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 5 Mar 2026 17:08:24 +0000 +Subject: RDMA/umem: Add pinned revocable dmabuf import interface + +From: Jacob Moroni + +[ Upstream commit ff85a2ebacbdaec9f28c4660c991295ace93cd1c ] + +Added an interface for importing a pinned but revocable dmabuf. +This interface can be used by drivers that are capable of revocation +so that they can import dmabufs from exporters that may require it, +such as VFIO. + +This interface implements a two step process, where drivers will first +call ib_umem_dmabuf_get_pinned_revocable_and_lock() which will pin and +map the dmabuf (and provide a functional move_notify/invalidate_mappings +callback), but will return with the lock still held so that the +driver can then populate the callback via +ib_umem_dmabuf_set_revoke_locked() without races from concurrent +revocations. This scheme also allows for easier integration with drivers +that may not have actually allocated their internal MR objects at the time +of the get_pinned_revocable* call. + +Signed-off-by: Jacob Moroni +Link: https://patch.msgid.link/20260305170826.3803155-4-jmoroni@google.com +Signed-off-by: Leon Romanovsky +Stable-dep-of: a846aecb931b ("RDMA/irdma: Prevent rereg_mr for non-mem regions") +Signed-off-by: Sasha Levin +--- + drivers/infiniband/core/umem_dmabuf.c | 61 +++++++++++++++++++++++++++ + include/rdma/ib_umem.h | 19 +++++++++ + 2 files changed, 80 insertions(+) + +diff --git a/drivers/infiniband/core/umem_dmabuf.c b/drivers/infiniband/core/umem_dmabuf.c +index f16491bd5f2b11..1206993e2e3e83 100644 +--- a/drivers/infiniband/core/umem_dmabuf.c ++++ b/drivers/infiniband/core/umem_dmabuf.c +@@ -206,6 +206,10 @@ static void ib_umem_dmabuf_revoke_locked(struct dma_buf_attachment *attach) + + if (umem_dmabuf->revoked) + return; ++ ++ if (umem_dmabuf->pinned_revoke) ++ umem_dmabuf->pinned_revoke(umem_dmabuf->private); ++ + ib_umem_dmabuf_unmap_pages(umem_dmabuf); + if (umem_dmabuf->pinned) { + dma_buf_unpin(umem_dmabuf->attach); +@@ -214,6 +218,11 @@ static void ib_umem_dmabuf_revoke_locked(struct dma_buf_attachment *attach) + umem_dmabuf->revoked = 1; + } + ++static struct dma_buf_attach_ops ib_umem_dmabuf_attach_pinned_revocable_ops = { ++ .allow_peer2peer = true, ++ .move_notify = ib_umem_dmabuf_revoke_locked, ++}; ++ + static struct ib_umem_dmabuf * + ib_umem_dmabuf_get_pinned_and_lock(struct ib_device *device, + struct device *dma_device, +@@ -266,6 +275,58 @@ ib_umem_dmabuf_get_pinned_with_dma_device(struct ib_device *device, + } + EXPORT_SYMBOL(ib_umem_dmabuf_get_pinned_with_dma_device); + ++/** ++ * ib_umem_dmabuf_get_pinned_revocable_and_lock - Map & pin a revocable dmabuf ++ * @device: IB device. ++ * @offset: Start offset. ++ * @size: Length. ++ * @fd: dmabuf fd. ++ * @access: Access flags. ++ * ++ * Obtains a umem from a dmabuf for drivers/devices that can support revocation. ++ * ++ * Returns with dma_resv_lock held upon success. The driver must set the revoke ++ * callback prior to unlock by calling ib_umem_dmabuf_set_revoke_locked(). ++ * ++ * When a revocation occurs, the revoke callback will be called. The driver must ++ * ensure that the region is no longer accessed when the callback returns. Any ++ * subsequent access attempts should also probably cause an AE for MRs. ++ * ++ * If the umem is used for an MR, the driver must ensure that the key remains in ++ * use such that it cannot be obtained by a new region until this region is ++ * fully deregistered (i.e., ibv_dereg_mr). If a driver needs to serialize with ++ * revoke calls, it can use dma_resv_lock. ++ * ++ * If successful, then the revoke callback may be called at any time and will ++ * also be called automatically upon ib_umem_release (serialized). The revoke ++ * callback will be called one time at most. ++ * ++ * Return: A pointer to ib_umem_dmabuf on success, or an ERR_PTR on failure. ++ */ ++struct ib_umem_dmabuf * ++ib_umem_dmabuf_get_pinned_revocable_and_lock(struct ib_device *device, ++ unsigned long offset, size_t size, ++ int fd, int access) ++{ ++ const struct dma_buf_attach_ops *ops = ++ &ib_umem_dmabuf_attach_pinned_revocable_ops; ++ ++ return ib_umem_dmabuf_get_pinned_and_lock(device, device->dma_device, ++ offset, size, fd, access, ++ ops); ++} ++EXPORT_SYMBOL(ib_umem_dmabuf_get_pinned_revocable_and_lock); ++ ++void ib_umem_dmabuf_set_revoke_locked(struct ib_umem_dmabuf *umem_dmabuf, ++ void (*revoke)(void *priv), void *priv) ++{ ++ dma_resv_assert_held(umem_dmabuf->attach->dmabuf->resv); ++ ++ umem_dmabuf->pinned_revoke = revoke; ++ umem_dmabuf->private = priv; ++} ++EXPORT_SYMBOL(ib_umem_dmabuf_set_revoke_locked); ++ + struct ib_umem_dmabuf *ib_umem_dmabuf_get_pinned(struct ib_device *device, + unsigned long offset, + size_t size, int fd, +diff --git a/include/rdma/ib_umem.h b/include/rdma/ib_umem.h +index 694f7e0876af81..4c5329b504d0cb 100644 +--- a/include/rdma/ib_umem.h ++++ b/include/rdma/ib_umem.h +@@ -36,6 +36,7 @@ struct ib_umem_dmabuf { + struct scatterlist *last_sg; + unsigned long first_sg_offset; + unsigned long last_sg_trim; ++ void (*pinned_revoke)(void *priv); + void *private; + u8 pinned : 1; + u8 revoked : 1; +@@ -124,6 +125,12 @@ struct ib_umem_dmabuf *ib_umem_dmabuf_get_pinned(struct ib_device *device, + size_t size, int fd, + int access); + struct ib_umem_dmabuf * ++ib_umem_dmabuf_get_pinned_revocable_and_lock(struct ib_device *device, ++ unsigned long offset, size_t size, ++ int fd, int access); ++void ib_umem_dmabuf_set_revoke_locked(struct ib_umem_dmabuf *umem_dmabuf, ++ void (*revoke)(void *priv), void *priv); ++struct ib_umem_dmabuf * + ib_umem_dmabuf_get_pinned_with_dma_device(struct ib_device *device, + struct device *dma_device, + unsigned long offset, size_t size, +@@ -180,6 +187,18 @@ ib_umem_dmabuf_get_pinned(struct ib_device *device, unsigned long offset, + return ERR_PTR(-EOPNOTSUPP); + } + ++static inline struct ib_umem_dmabuf * ++ib_umem_dmabuf_get_pinned_revocable_and_lock(struct ib_device *device, ++ unsigned long offset, size_t size, ++ int fd, int access) ++{ ++ return ERR_PTR(-EOPNOTSUPP); ++} ++ ++static inline void ++ib_umem_dmabuf_set_revoke_locked(struct ib_umem_dmabuf *umem_dmabuf, ++ void (*revoke)(void *priv), void *priv) {} ++ + static inline struct ib_umem_dmabuf * + ib_umem_dmabuf_get_pinned_with_dma_device(struct ib_device *device, + struct device *dma_device, +-- +2.53.0 + diff --git a/queue-6.12/riscv-hwprobe-avoid-uninitialized-read-in-hwprobe_ge.patch b/queue-6.12/riscv-hwprobe-avoid-uninitialized-read-in-hwprobe_ge.patch new file mode 100644 index 0000000000..dff76ace07 --- /dev/null +++ b/queue-6.12/riscv-hwprobe-avoid-uninitialized-read-in-hwprobe_ge.patch @@ -0,0 +1,41 @@ +From f998c0296582ff7f15b9646dc0f791450de7741c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 13 Jul 2026 17:30:56 -0700 +Subject: riscv: hwprobe: Avoid uninitialized read in hwprobe_get_cpus() + +From: Mark Harris + +[ Upstream commit 5caae1deee89a6582c761d5dcd4b924b744426cc ] + +When cpusetsize < cpumask_size(), hwprobe_get_cpus() did not fully +initialize its copy of the cpu mask, which could cause non-deterministic +results from the riscv_hwprobe syscall on a system with more than 8 CPUs +when the supplied cpu mask is empty. Address this by fully initializing +the cpu mask. + +Fixes: e178bf146e4b ("RISC-V: hwprobe: Introduce which-cpus flag") +Signed-off-by: Mark Harris +Reviewed-by: Nam Cao +Reviewed-by: Michael Ellerman +Link: https://patch.msgid.link/20260714003056.73707-1-mark.hsj@gmail.com +Signed-off-by: Paul Walmsley +Signed-off-by: Sasha Levin +--- + arch/riscv/kernel/sys_hwprobe.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/arch/riscv/kernel/sys_hwprobe.c b/arch/riscv/kernel/sys_hwprobe.c +index fc62548888c587..d273080bec34d8 100644 +--- a/arch/riscv/kernel/sys_hwprobe.c ++++ b/arch/riscv/kernel/sys_hwprobe.c +@@ -336,6 +336,7 @@ static int hwprobe_get_cpus(struct riscv_hwprobe __user *pairs, + if (cpusetsize > cpumask_size()) + cpusetsize = cpumask_size(); + ++ cpumask_clear(&cpus); + ret = copy_from_user(&cpus, cpus_user, cpusetsize); + if (ret) + return -EFAULT; +-- +2.53.0 + diff --git a/queue-6.12/s390-checksum-fix-csum_partial-without-vector-facili.patch b/queue-6.12/s390-checksum-fix-csum_partial-without-vector-facili.patch new file mode 100644 index 0000000000..a4f772a726 --- /dev/null +++ b/queue-6.12/s390-checksum-fix-csum_partial-without-vector-facili.patch @@ -0,0 +1,41 @@ +From f3f1dced11fa36b35f852be47b10715556bc1ec0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 8 Jul 2026 12:02:14 +0200 +Subject: s390/checksum: Fix csum_partial() without vector facility + +From: Vasily Gorbik + +[ Upstream commit 4bb06b60d982355e22647b3d12d6619419f8c1fa ] + +Currently csum_partial() calls csum_copy() with copy=false and dst=NULL. +On machines without the vector facility, csum_copy() falls back to +cksm(dst, ...), causing the checksum to be calculated from address zero +instead of the source buffer. + +The VX implementation already checksums data loaded from src. Make the +fallback do the same by passing src to cksm(). + +Fixes: dcd3e1de9d17 ("s390/checksum: provide csum_partial_copy_nocheck()") +Reviewed-by: Heiko Carstens +Signed-off-by: Vasily Gorbik +Signed-off-by: Sasha Levin +--- + arch/s390/lib/csum-partial.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/s390/lib/csum-partial.c b/arch/s390/lib/csum-partial.c +index 458abd9bac7025..9d74ceff136c54 100644 +--- a/arch/s390/lib/csum-partial.c ++++ b/arch/s390/lib/csum-partial.c +@@ -23,7 +23,7 @@ static __always_inline __wsum csum_copy(void *dst, const void *src, int len, __w + if (!cpu_has_vx()) { + if (copy) + memcpy(dst, src, len); +- return cksm(dst, len, sum); ++ return cksm(src, len, sum); + } + kernel_fpu_begin(&vxstate, KERNEL_VXR_V16V23); + fpu_vlvgf(16, (__force u32)sum, 1); +-- +2.53.0 + diff --git a/queue-6.12/scsi-core-wake-eh-reliably-when-using-scsi_schedule_.patch b/queue-6.12/scsi-core-wake-eh-reliably-when-using-scsi_schedule_.patch new file mode 100644 index 0000000000..c9c2f2cc8f --- /dev/null +++ b/queue-6.12/scsi-core-wake-eh-reliably-when-using-scsi_schedule_.patch @@ -0,0 +1,123 @@ +From 65589fc197720ae32b3049459c74d3a460ffd54e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 15 Jun 2026 13:46:30 -0400 +Subject: scsi: core: wake eh reliably when using scsi_schedule_eh + +From: David Jeffery + +[ Upstream commit dccf3b1798b70f94e958b3d00b83010399e6fb05 ] + +Drivers which use the scsi_schedule_eh function to run the error handler +currently risk the error handler thread never waking once all commands are +timed out or inactive. There is no enforced memory order between setting +the host into error recovery state and counting busy commands. This can +result in a race with scsi_dec_host_busy where neither CPU sees both +conditions of all commands inactive and the host error state to request +waking the error handler. + +To fix this, run the scsi_schedule_eh's scsi_eh_wakeup from a new work item +which will use rcu to ensure scsi_schedule_eh's call to scsi_host_busy will +occur after the error state is globally visible and will be seen by any +current scsi_dec_host_busy callers. + +Fixes: 6eb045e092ef ("scsi: core: avoid host-wide host_busy counter for scsi_mq") +Signed-off-by: David Jeffery +Link: https://patch.msgid.link/20260615174630.11492-1-djeffery@redhat.com +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +--- + drivers/scsi/hosts.c | 2 ++ + drivers/scsi/scsi_error.c | 22 +++++++++++++++++++++- + drivers/scsi/scsi_priv.h | 1 + + include/scsi/scsi_host.h | 3 +++ + 4 files changed, 27 insertions(+), 1 deletion(-) + +diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c +index 5cf13d019a15e9..e617b98ce84cf2 100644 +--- a/drivers/scsi/hosts.c ++++ b/drivers/scsi/hosts.c +@@ -343,6 +343,7 @@ static void scsi_host_dev_release(struct device *dev) + /* Wait for functions invoked through call_rcu(&scmd->rcu, ...) */ + rcu_barrier(); + ++ cancel_work_sync(&shost->eh_work); + if (shost->tmf_work_q) + destroy_workqueue(shost->tmf_work_q); + if (shost->ehandler) +@@ -408,6 +409,7 @@ struct Scsi_Host *scsi_host_alloc(const struct scsi_host_template *sht, int priv + INIT_LIST_HEAD(&shost->starved_list); + init_waitqueue_head(&shost->host_wait); + mutex_init(&shost->scan_mutex); ++ INIT_WORK(&shost->eh_work, scsi_rcu_eh_wakeup); + + index = ida_alloc(&host_index_ida, GFP_KERNEL); + if (index < 0) { +diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c +index 9a89a94784cd0c..03fadefa1cee8e 100644 +--- a/drivers/scsi/scsi_error.c ++++ b/drivers/scsi/scsi_error.c +@@ -73,6 +73,26 @@ void scsi_eh_wakeup(struct Scsi_Host *shost, unsigned int busy) + } + } + ++void scsi_rcu_eh_wakeup(struct work_struct *work) ++{ ++ struct Scsi_Host *shost = container_of(work, struct Scsi_Host, eh_work); ++ unsigned long flags; ++ unsigned int busy; ++ ++ /* ++ * Ensure any running scsi_dec_host_busy has completed its rcu section ++ * so changes to host state and host_eh_scheduled are visible to all ++ * future calls of scsi_dec_host_busy ++ */ ++ synchronize_rcu(); ++ ++ busy = scsi_host_busy(shost); ++ ++ spin_lock_irqsave(shost->host_lock, flags); ++ scsi_eh_wakeup(shost, busy); ++ spin_unlock_irqrestore(shost->host_lock, flags); ++} ++ + /** + * scsi_schedule_eh - schedule EH for SCSI host + * @shost: SCSI host to invoke error handling on. +@@ -88,7 +108,7 @@ void scsi_schedule_eh(struct Scsi_Host *shost) + if (scsi_host_set_state(shost, SHOST_RECOVERY) == 0 || + scsi_host_set_state(shost, SHOST_CANCEL_RECOVERY) == 0) { + shost->host_eh_scheduled++; +- scsi_eh_wakeup(shost, scsi_host_busy(shost)); ++ queue_work(shost->tmf_work_q, &shost->eh_work); + } + + spin_unlock_irqrestore(shost->host_lock, flags); +diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h +index 9fc397a9ce7a4f..7238d53883be76 100644 +--- a/drivers/scsi/scsi_priv.h ++++ b/drivers/scsi/scsi_priv.h +@@ -93,6 +93,7 @@ extern enum blk_eh_timer_return scsi_timeout(struct request *req); + extern int scsi_error_handler(void *host); + extern enum scsi_disposition scsi_decide_disposition(struct scsi_cmnd *cmd); + extern void scsi_eh_wakeup(struct Scsi_Host *shost, unsigned int busy); ++extern void scsi_rcu_eh_wakeup(struct work_struct *work); + extern void scsi_eh_scmd_add(struct scsi_cmnd *); + void scsi_eh_ready_devs(struct Scsi_Host *shost, + struct list_head *work_q, +diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h +index 2b4ab0369ffbe9..990747f803feff 100644 +--- a/include/scsi/scsi_host.h ++++ b/include/scsi/scsi_host.h +@@ -718,6 +718,9 @@ struct Scsi_Host { + */ + struct device *dma_dev; + ++ /* Used for an rcu-synchronizing eh wakeup */ ++ struct work_struct eh_work; ++ + /* Delay for runtime autosuspend */ + int rpm_autosuspend_delay; + +-- +2.53.0 + diff --git a/queue-6.12/sctp-fix-auth_hmacs-array-size-in-struct-sctp_cookie.patch b/queue-6.12/sctp-fix-auth_hmacs-array-size-in-struct-sctp_cookie.patch new file mode 100644 index 0000000000..f584dcbf29 --- /dev/null +++ b/queue-6.12/sctp-fix-auth_hmacs-array-size-in-struct-sctp_cookie.patch @@ -0,0 +1,56 @@ +From 7099f6185576902bb93608616b93977cad205668 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 10 Jul 2026 14:12:35 -0400 +Subject: sctp: fix auth_hmacs array size in struct sctp_cookie + +From: Xin Long + +[ Upstream commit e0b5252a59383b77d1b8dbeda00b7184dd95f4d3 ] + +The auth_hmacs array in struct sctp_cookie is supposed to store a complete +SCTP_AUTH_HMAC_ALGO parameter, which consists of a struct sctp_paramhdr +followed by N HMAC identifiers. + +However, the array size was calculated using an extra 2 bytes instead of +sizeof(struct sctp_paramhdr), which is 4 bytes. When four HMAC identifiers +are configured, the HMAC-ALGO parameter stored in the endpoint is larger +than the auth_hmacs buffer in the cookie. + +As a result, sctp_association_init() copies beyond the end of auth_hmacs +when initializing the association, corrupting the adjacent auth_chunks +field. This can lead to an invalid HMAC identifier being accepted and later +cause an out-of-bounds read in sctp_auth_get_hmac(). + +Fix the array size calculation by including the full SCTP parameter header +size. + +Fixes: 1f485649f529 ("[SCTP]: Implement SCTP-AUTH internals") +Reported-by: Yuan Tan +Reported-by: Xin Liu +Reported-by: Zihan Xi +Reported-by: Ren Wei +Signed-off-by: Xin Long +Link: https://patch.msgid.link/634a0de0d5de29532915e6d47c92a0cbc206e03f.1783707155.git.lucien.xin@gmail.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + include/net/sctp/structs.h | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h +index dcd288fa1bb6fb..d20c28c3105664 100644 +--- a/include/net/sctp/structs.h ++++ b/include/net/sctp/structs.h +@@ -319,7 +319,8 @@ struct sctp_cookie { + + __u8 auth_random[sizeof(struct sctp_paramhdr) + + SCTP_AUTH_RANDOM_LENGTH]; +- __u8 auth_hmacs[SCTP_AUTH_NUM_HMACS * sizeof(__u16) + 2]; ++ __u8 auth_hmacs[sizeof(struct sctp_paramhdr) + ++ SCTP_AUTH_NUM_HMACS * sizeof(__u16)]; + __u8 auth_chunks[sizeof(struct sctp_paramhdr) + SCTP_AUTH_MAX_CHUNKS]; + + /* This is a shim for my peer's INIT packet, followed by +-- +2.53.0 + diff --git a/queue-6.12/selftests-alsa-fix-memory-leak-in-find_controls-erro.patch b/queue-6.12/selftests-alsa-fix-memory-leak-in-find_controls-erro.patch new file mode 100644 index 0000000000..ea9ebc015e --- /dev/null +++ b/queue-6.12/selftests-alsa-fix-memory-leak-in-find_controls-erro.patch @@ -0,0 +1,41 @@ +From b1fb19de8fb01ead98d1810c76471e95f7b76e48 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 4 Jul 2026 16:27:36 +0530 +Subject: selftests/alsa: Fix memory leak in find_controls error path + +From: Malaya Kumar Rout + +[ Upstream commit cb89f0c1aed02eb233c4271f76f830b37e222ff6 ] + +In find_controls(), card_data is allocated with malloc() but when +snd_ctl_open_lconf() fails, the code jumps to next_card without +freeing the allocated memory. This results in a memory leak for +each card where snd_ctl_open_lconf() fails. + +Add free(card_data) before goto next_card to ensure proper cleanup +of the allocated memory in the error path. + +Fixes: 5aaf9efffc57 ("kselftest: alsa: Add simplistic test for ALSA mixer controls kselftest") +Signed-off-by: Malaya Kumar Rout +Link: https://patch.msgid.link/20260704105736.94874-1-malayarout91@gmail.com +Signed-off-by: Takashi Iwai +Signed-off-by: Sasha Levin +--- + tools/testing/selftests/alsa/mixer-test.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/tools/testing/selftests/alsa/mixer-test.c b/tools/testing/selftests/alsa/mixer-test.c +index 2a4b2662035efc..2964f02ffd9d3c 100644 +--- a/tools/testing/selftests/alsa/mixer-test.c ++++ b/tools/testing/selftests/alsa/mixer-test.c +@@ -84,6 +84,7 @@ static void find_controls(void) + if (err < 0) { + ksft_print_msg("Failed to get hctl for card %d: %s\n", + card, snd_strerror(err)); ++ free(card_data); + goto next_card; + } + +-- +2.53.0 + diff --git a/queue-6.12/series b/queue-6.12/series index 385379a618..8222f6e232 100644 --- a/queue-6.12/series +++ b/queue-6.12/series @@ -35,3 +35,80 @@ input-ims-pcu-fix-logic-error-in-packet-reset.patch soc-qcom-ice-allow-explicit-votes-on-iface-clock-for.patch mm-refactor-mm_access-to-not-return-null.patch posix-cpu-timers-prevent-uaf-caused-by-non-leader-ex.patch +arm64-tegra-fix-cpu-compatible-string-to-cortex-a78a.patch +firmware-arm_ffa-respect-firmware-advertised-rx-tx-b.patch +ib-mad-drop-unmatched-rmpp-responses-before-reassemb.patch +mtd-mtdswap-remove-debugfs-stats-file-on-teardown.patch +mtd-nand-mtk-ecc-stop-on-ecc-idle-timeouts.patch +btrfs-reject-free-space-cache-with-more-entries-than.patch +btrfs-fix-root-leak-if-its-reloc-root-is-unexpected-.patch +firmware-arm_ffa-fix-null-dereference-in-ffa_partiti.patch +rdma-cma-fix-hardware-address-comparison-length-in-n.patch +rdma-umem-add-pinned-revocable-dmabuf-import-interfa.patch +rdma-irdma-prevent-rereg_mr-for-non-mem-regions.patch +rdma-erdma-initialize-ret-for-empty-receive-wr-lists.patch +rdma-hns-fix-potential-integer-overflow-in-mhop-hem-.patch +rdma-siw-publish-qp-after-initialization.patch +mtd-fix-double-free-and-warn_on-in-add_mtd_device-er.patch +selftests-alsa-fix-memory-leak-in-find_controls-erro.patch +rdma-irdma-prevent-overflows-in-memory-contiguity-ch.patch +xfrm6-clear-dst.dev-on-error-to-avoid-double-netdev_.patch +xfrm-policy-preallocate-inexact-bins-before-xfrm_has.patch +wifi-cfg80211-cancel-sched-scan-results-work-on-unre.patch +wifi-ipw2100-fix-potential-memory-leak-in-ipw2100_pc.patch +wifi-mac80211_hwsim-clamp-virtio-rx-length-before-sk.patch +wifi-mac80211-fix-unsol_bcast_probe_resp-double-free.patch +wifi-mac80211-fix-fils_discovery-double-free-on-allo.patch +wifi-libertas-fix-memory-leak-in-helper_firmware_cb.patch +wifi-p54-validate-rx-frame-length-in-p54_rx_eeprom_r.patch +wifi-cfg80211-pass-net_device-to-.set_monitor_channe.patch +wifi-cfg80211-define-and-use-wiphy-guard.patch +wifi-cfg80211-convert-pmsr_free_wk-to-wiphy_work-to-.patch +wifi-nl80211-free-rnr-data-on-mbssid-mismatch.patch +wifi-cfg80211-derive-s1g-beacon-tsf-from-s1g-fields.patch +wifi-nl80211-validate-nested-mbssid-ie-blobs.patch +wifi-cfg80211-validate-pmsr-measurement-type-data.patch +wifi-cfg80211-validate-pmsr-ftm-preamble-range.patch +wifi-cfg80211-reject-unsupported-pmsr-ftm-location-r.patch +wifi-mac80211-free-ap_vlan-bc_buf-skbs-outside-irq-l.patch +wifi-brcmfmac-initialize-sdio-data-work-before-clean.patch +wifi-cfg80211-bound-element-id-read-when-checking-no.patch +asoc-meson-aiu-fifo-spdif-soft-reset-the-s-pdif-data.patch +asoc-amd-ps-fix-wrong-acp-version-string-in-pci_requ.patch +asoc-cs42l43-correct-report-for-forced-microphone-ja.patch +asoc-tas2562-fix-deprecated-shut-down-gpio-always-cl.patch +firmware-arm_scmi-rate-limit-queue-full-warnings-in-.patch +cpufreq-make-cpufreq_update_pressure-fall-back-to-cp.patch +ppp-defer-channel-free-to-an-rcu-grace-period-to-fix.patch +ipv4-fib-free-fib_alias-with-kfree_rcu-on-insert-err.patch +net-iucv-take-a-reference-on-the-socket-found-in-afi.patch +udmabuf-ensure-to-perform-cache-synchronisation-in-b.patch +scsi-core-wake-eh-reliably-when-using-scsi_schedule_.patch +ata-sata_dwc_460ex-enable-sata-interrupts-only-after.patch +ata-sata_dwc_460ex-use-platform_get_irq.patch +ata-sata_dwc_460ex-fix-clear_interrupt_bit-clearing-.patch +ata-sata_dwc_460ex-fix-infinite-loop-in-ncq-tag-comp.patch +accel-ivpu-fix-wrong-register-read-in-lnl-failure-di.patch +alsa-usb-audio-skip-dsd-quirk-for-musical-fidelity-m.patch +bluetooth-qca-fix-nvm-tag-length-underflow-in-tlv-pa.patch +bluetooth-mgmt-revalidate-load_conn_param-queued-upd.patch +bluetooth-mgmt-fix-locking-in-unpair_device-disconne.patch +bluetooth-mgmt-hold-reference-for-hci_conn-in-mgmt_p.patch +bluetooth-hci_qca-clear-memdump-state-on-invalid-dum.patch +smb-client-handle-overlapping-allocated-ranges-in-fa.patch +drm-i915-gt-use-correct-selftest-config-symbol.patch +powerpc-85xx-add-fsl-ifc-to-common-device-ids.patch +powerpc-time-prepare-to-stop-elapsing-in-dynticks-id.patch +powerpc-vtime-initialize-starttime-at-boot-for-nativ.patch +bpf-sockmap-reject-unhashed-udp-sockets-on-sockmap-u.patch +s390-checksum-fix-csum_partial-without-vector-facili.patch +riscv-hwprobe-avoid-uninitialized-read-in-hwprobe_ge.patch +can-j1939-fix-lockless-local-destination-check.patch +drm-xe-wopcm-fix-wopcm-size-for-lnl.patch +smb-move-some-duplicate-definitions-to-common-cifsgl.patch +ksmbd-pin-conn-during-async-oplock-break-notificatio.patch +ksmbd-validate-compound-request-size-before-reading-.patch +drm-i915-selftests-fix-gt-pm-sort-comparators.patch +net-sched-act_tunnel_key-defer-dst_release-to-rcu-ca.patch +sctp-fix-auth_hmacs-array-size-in-struct-sctp_cookie.patch +mpls-fix-null-deref-in-mpls_valid_fib_dump_req-on-co.patch diff --git a/queue-6.12/smb-client-handle-overlapping-allocated-ranges-in-fa.patch b/queue-6.12/smb-client-handle-overlapping-allocated-ranges-in-fa.patch new file mode 100644 index 0000000000..c6fc3521f8 --- /dev/null +++ b/queue-6.12/smb-client-handle-overlapping-allocated-ranges-in-fa.patch @@ -0,0 +1,110 @@ +From 201cb945100d190bc06a815237799c43e2dbdfe7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 3 Jul 2026 13:32:56 +0800 +Subject: smb/client: handle overlapping allocated ranges in fallocate + +From: Huiwen He + +[ Upstream commit b09ae45d85dc816987a71db9eebc54b0ae288e94 ] + +smb3_simple_fallocate_range() can skip holes when an allocated range +returned by the server starts before the current fallocate offset. The +skipped hole is not zero-filled, but fallocate still returns success. A +later write to that hole may therefore fail with ENOSPC. + +The function queries allocated ranges so that it can preserve existing +contents and write zeroes only into holes. However, the server may return +a range that starts before the current fallocate offset. + +For example, assume the fallocate request is [100, 400) and the only +allocated range returned by the server is [0, 200): + + Request: [100, 400) + Server range: [ 0, 200) allocated + + Correct: + [100, 200) allocated data, skip + [200, 400) hole, zero-fill + + Current: + [100, 300) skipped + [300, 400) zero-filled afterwards + +The current code adds the full server range length, 200, to the current +offset 100 and moves to 300. As a result, the hole in [200, 300) is +skipped without being zero-filled. + +Fix this by advancing only over the part of the allocated range that +overlaps the current fallocate offset. Ignore ranges that end before the +current offset and reject ranges whose end offset overflows. + +This also prevents a malformed range length from causing an out-of-bounds +zero-buffer read. + +Fixes: 966a3cb7c7db ("cifs: improve fallocate emulation") +Signed-off-by: Huiwen He +Reviewed-by: ChenXiaoSong +Signed-off-by: Steve French +Signed-off-by: Sasha Levin +--- + fs/smb/client/smb2ops.c | 25 ++++++++++++++++++------- + 1 file changed, 18 insertions(+), 7 deletions(-) + +diff --git a/fs/smb/client/smb2ops.c b/fs/smb/client/smb2ops.c +index f63361bc1641d5..61309fead04e57 100644 +--- a/fs/smb/client/smb2ops.c ++++ b/fs/smb/client/smb2ops.c +@@ -3482,6 +3482,7 @@ static int smb3_simple_fallocate_range(unsigned int xid, + struct file_allocated_range_buffer in_data, *out_data = NULL, *tmp_data; + u32 out_data_len; + char *buf = NULL; ++ u64 range_start, range_len, range_end; + loff_t l; + int rc; + +@@ -3518,13 +3519,21 @@ static int smb3_simple_fallocate_range(unsigned int xid, + goto out; + } + +- if (off < le64_to_cpu(tmp_data->file_offset)) { ++ range_start = le64_to_cpu(tmp_data->file_offset); ++ range_len = le64_to_cpu(tmp_data->length); ++ if (check_add_overflow(range_start, range_len, &range_end) || ++ range_end > S64_MAX) { ++ rc = -EINVAL; ++ goto out; ++ } ++ ++ if (off < range_start) { + /* + * We are at a hole. Write until the end of the region + * or until the next allocated data, + * whichever comes next. + */ +- l = le64_to_cpu(tmp_data->file_offset) - off; ++ l = range_start - off; + if (len < l) + l = len; + rc = smb3_simple_fallocate_write_range(xid, tcon, +@@ -3541,11 +3550,13 @@ static int smb3_simple_fallocate_range(unsigned int xid, + * until the end of the data or the end of the region + * we are supposed to fallocate, whichever comes first. + */ +- l = le64_to_cpu(tmp_data->length); +- if (len < l) +- l = len; +- off += l; +- len -= l; ++ if (off < range_end) { ++ l = range_end - off; ++ if (len < l) ++ l = len; ++ off += l; ++ len -= l; ++ } + + tmp_data = &tmp_data[1]; + out_data_len -= sizeof(struct file_allocated_range_buffer); +-- +2.53.0 + diff --git a/queue-6.12/smb-move-some-duplicate-definitions-to-common-cifsgl.patch b/queue-6.12/smb-move-some-duplicate-definitions-to-common-cifsgl.patch new file mode 100644 index 0000000000..b1ab26018c --- /dev/null +++ b/queue-6.12/smb-move-some-duplicate-definitions-to-common-cifsgl.patch @@ -0,0 +1,168 @@ +From 6b9ce022a6417b074c455489d898b487f971ec38 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 13 Oct 2025 00:17:30 +0800 +Subject: smb: move some duplicate definitions to common/cifsglob.h + +From: ZhangGuoDong + +[ Upstream commit d877470b59910b5c50383d634dda3782386bba51 ] + +In order to maintain the code more easily, move duplicate definitions to +new common header file. + +Co-developed-by: ChenXiaoSong +Signed-off-by: ChenXiaoSong +Signed-off-by: ZhangGuoDong +Signed-off-by: Steve French +Stable-dep-of: aa5d8f3f96aa ("ksmbd: pin conn during async oplock break notification") +Signed-off-by: Sasha Levin +--- + fs/smb/client/cifsglob.h | 19 +------------------ + fs/smb/common/cifsglob.h | 30 ++++++++++++++++++++++++++++++ + fs/smb/server/smb_common.h | 14 +------------- + 3 files changed, 32 insertions(+), 31 deletions(-) + create mode 100644 fs/smb/common/cifsglob.h + +diff --git a/fs/smb/client/cifsglob.h b/fs/smb/client/cifsglob.h +index dcfadbc20723f0..c054ee44269416 100644 +--- a/fs/smb/client/cifsglob.h ++++ b/fs/smb/client/cifsglob.h +@@ -25,6 +25,7 @@ + #include "cifsacl.h" + #include + #include ++#include "../common/cifsglob.h" + #include "../common/smb2pdu.h" + #include "smb2pdu.h" + #include +@@ -669,12 +670,6 @@ get_rfc1002_length(void *buf) + return be32_to_cpu(*((__be32 *)buf)) & 0xffffff; + } + +-static inline void +-inc_rfc1001_len(void *buf, int count) +-{ +- be32_add_cpu((__be32 *)buf, count); +-} +- + struct TCP_Server_Info { + struct list_head tcp_ses_list; + struct list_head smb_ses_list; +@@ -986,8 +981,6 @@ compare_mid(__u16 mid, const struct smb_hdr *smb) + #define CIFS_MAX_RFC1002_WSIZE ((1<<17) - 1 - sizeof(WRITE_REQ) + 4) + #define CIFS_MAX_RFC1002_RSIZE ((1<<17) - 1 - sizeof(READ_RSP) + 4) + +-#define CIFS_DEFAULT_IOSIZE (1024 * 1024) +- + /* + * Windows only supports a max of 60kb reads and 65535 byte writes. Default to + * those values when posix extensions aren't in force. In actuality here, we +@@ -2094,30 +2087,20 @@ extern mempool_t cifs_io_request_pool; + extern mempool_t cifs_io_subrequest_pool; + + /* Operations for different SMB versions */ +-#define SMB1_VERSION_STRING "1.0" +-#define SMB20_VERSION_STRING "2.0" + #ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY + extern struct smb_version_operations smb1_operations; + extern struct smb_version_values smb1_values; + extern struct smb_version_operations smb20_operations; + extern struct smb_version_values smb20_values; + #endif /* CIFS_ALLOW_INSECURE_LEGACY */ +-#define SMB21_VERSION_STRING "2.1" + extern struct smb_version_operations smb21_operations; + extern struct smb_version_values smb21_values; +-#define SMBDEFAULT_VERSION_STRING "default" + extern struct smb_version_values smbdefault_values; +-#define SMB3ANY_VERSION_STRING "3" + extern struct smb_version_values smb3any_values; +-#define SMB30_VERSION_STRING "3.0" + extern struct smb_version_operations smb30_operations; + extern struct smb_version_values smb30_values; +-#define SMB302_VERSION_STRING "3.02" +-#define ALT_SMB302_VERSION_STRING "3.0.2" + /*extern struct smb_version_operations smb302_operations;*/ /* not needed yet */ + extern struct smb_version_values smb302_values; +-#define SMB311_VERSION_STRING "3.1.1" +-#define ALT_SMB311_VERSION_STRING "3.11" + extern struct smb_version_operations smb311_operations; + extern struct smb_version_values smb311_values; + +diff --git a/fs/smb/common/cifsglob.h b/fs/smb/common/cifsglob.h +new file mode 100644 +index 00000000000000..00fd215e3eb547 +--- /dev/null ++++ b/fs/smb/common/cifsglob.h +@@ -0,0 +1,30 @@ ++/* SPDX-License-Identifier: LGPL-2.1 */ ++/* ++ * ++ * Copyright (C) International Business Machines Corp., 2002,2008 ++ * Author(s): Steve French (sfrench@us.ibm.com) ++ * Jeremy Allison (jra@samba.org) ++ * ++ */ ++#ifndef _COMMON_CIFS_GLOB_H ++#define _COMMON_CIFS_GLOB_H ++ ++static inline void inc_rfc1001_len(void *buf, int count) ++{ ++ be32_add_cpu((__be32 *)buf, count); ++} ++ ++#define SMB1_VERSION_STRING "1.0" ++#define SMB20_VERSION_STRING "2.0" ++#define SMB21_VERSION_STRING "2.1" ++#define SMBDEFAULT_VERSION_STRING "default" ++#define SMB3ANY_VERSION_STRING "3" ++#define SMB30_VERSION_STRING "3.0" ++#define SMB302_VERSION_STRING "3.02" ++#define ALT_SMB302_VERSION_STRING "3.0.2" ++#define SMB311_VERSION_STRING "3.1.1" ++#define ALT_SMB311_VERSION_STRING "3.11" ++ ++#define CIFS_DEFAULT_IOSIZE (1024 * 1024) ++ ++#endif /* _COMMON_CIFS_GLOB_H */ +diff --git a/fs/smb/server/smb_common.h b/fs/smb/server/smb_common.h +index a3d8a905b07e07..a353e187dfd7ad 100644 +--- a/fs/smb/server/smb_common.h ++++ b/fs/smb/server/smb_common.h +@@ -10,6 +10,7 @@ + + #include "glob.h" + #include "nterr.h" ++#include "../common/cifsglob.h" + #include "../common/smb2pdu.h" + #include "smb2pdu.h" + +@@ -26,16 +27,8 @@ + #define SMB311_PROT 6 + #define BAD_PROT 0xFFFF + +-#define SMB1_VERSION_STRING "1.0" +-#define SMB20_VERSION_STRING "2.0" +-#define SMB21_VERSION_STRING "2.1" +-#define SMB30_VERSION_STRING "3.0" +-#define SMB302_VERSION_STRING "3.02" +-#define SMB311_VERSION_STRING "3.1.1" +- + #define SMB_ECHO_INTERVAL (60 * HZ) + +-#define CIFS_DEFAULT_IOSIZE (64 * 1024) + #define MAX_CIFS_SMALL_BUFFER_SIZE 448 /* big enough for most */ + + #define MAX_STREAM_PROT_LEN 0x00FFFFFF +@@ -462,9 +455,4 @@ static inline unsigned int get_rfc1002_len(void *buf) + { + return be32_to_cpu(*((__be32 *)buf)) & 0xffffff; + } +- +-static inline void inc_rfc1001_len(void *buf, int count) +-{ +- be32_add_cpu((__be32 *)buf, count); +-} + #endif /* __SMB_COMMON_H__ */ +-- +2.53.0 + diff --git a/queue-6.12/udmabuf-ensure-to-perform-cache-synchronisation-in-b.patch b/queue-6.12/udmabuf-ensure-to-perform-cache-synchronisation-in-b.patch new file mode 100644 index 0000000000..943e17ca92 --- /dev/null +++ b/queue-6.12/udmabuf-ensure-to-perform-cache-synchronisation-in-b.patch @@ -0,0 +1,68 @@ +From b2236dba4de5fe82fca7b297be9da43657b6a1be Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 27 Jun 2026 12:57:25 +0200 +Subject: udmabuf: Ensure to perform cache synchronisation in + begin_cpu_udmabuf() + +From: Robert Mader + +[ Upstream commit 1d0e25c1ddf2063c499264fb2ba0fa6a3e4f8a00 ] + +The message of commit 504e2b4ab97a ("dma-buf/udmabuf: skip redundant cpu sync to +fix cacheline EEXIST warning") says: + +> The CPU sync at map/unmap time is also redundant for udmabuf: +> begin_cpu_udmabuf() and end_cpu_udmabuf() already perform explicit +> cache synchronization via dma_sync_sgtable_for_cpu/device() when CPU +> access is requested through the dma-buf interface. + +This, however, does not apply to the first time begin_cpu_udmabuf() is +called on an udmabuf, in which case the implementation previously relied on +get_sg_table() to perform the cache synchronisation. + +Ensure to call dma_sync_sgtable_for_cpu() in that case as well. + +Fixes: 504e2b4ab97a ("dma-buf/udmabuf: skip redundant cpu sync to fix cacheline EEXIST warning") +Signed-off-by: Robert Mader +Reviewed-by: Mikhail Gavrilov +Signed-off-by: Vivek Kasireddy +Link: https://patch.msgid.link/20260627105725.9083-1-robert.mader@collabora.com +Signed-off-by: Sasha Levin +--- + drivers/dma-buf/udmabuf.c | 9 +++++---- + 1 file changed, 5 insertions(+), 4 deletions(-) + +diff --git a/drivers/dma-buf/udmabuf.c b/drivers/dma-buf/udmabuf.c +index 5c92834f3fc86d..b81fd91e30e777 100644 +--- a/drivers/dma-buf/udmabuf.c ++++ b/drivers/dma-buf/udmabuf.c +@@ -207,21 +207,22 @@ static int begin_cpu_udmabuf(struct dma_buf *buf, + { + struct udmabuf *ubuf = buf->priv; + struct device *dev = ubuf->device->this_device; +- int ret = 0; + + if (!ubuf->sg) { + ubuf->sg = get_sg_table(dev, buf, direction); + if (IS_ERR(ubuf->sg)) { ++ int ret; ++ + ret = PTR_ERR(ubuf->sg); + ubuf->sg = NULL; ++ return ret; + } else { + ubuf->sg_dir = direction; + } +- } else { +- dma_sync_sgtable_for_cpu(dev, ubuf->sg, direction); + } + +- return ret; ++ dma_sync_sgtable_for_cpu(dev, ubuf->sg, direction); ++ return 0; + } + + static int end_cpu_udmabuf(struct dma_buf *buf, +-- +2.53.0 + diff --git a/queue-6.12/wifi-brcmfmac-initialize-sdio-data-work-before-clean.patch b/queue-6.12/wifi-brcmfmac-initialize-sdio-data-work-before-clean.patch new file mode 100644 index 0000000000..f99446c832 --- /dev/null +++ b/queue-6.12/wifi-brcmfmac-initialize-sdio-data-work-before-clean.patch @@ -0,0 +1,61 @@ +From 4040c843abf926d16817742de708e2df1a150c40 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 19 Jun 2026 14:44:01 +0800 +Subject: wifi: brcmfmac: initialize SDIO data work before cleanup + +From: Runyu Xiao + +[ Upstream commit 2a665946e0407a05a3f81bd56a08553c446498e0 ] + +brcmf_sdio_probe() stores the newly allocated bus in sdiodev->bus before +allocating the ordered workqueue. If that allocation fails, the function +jumps to fail and calls brcmf_sdio_remove(). + +brcmf_sdio_remove() unconditionally cancels bus->datawork. Initialize the +work item before the first failure path that can reach brcmf_sdio_remove(), +so the cleanup path always observes a valid work object. + +This issue was found by our static analysis tool and then confirmed by +manual review of the probe error path and the remove-time work drain. The +problem pattern is an early setup failure that reaches a cleanup helper +which cancels an embedded work item before its initializer has run. + +A QEMU PoC forced alloc_ordered_workqueue() to fail at the same point in +brcmf_sdio_probe(), before INIT_WORK(&bus->datawork) is reached. The +resulting fail path calls brcmf_sdio_remove(), and DEBUG_OBJECTS reports +the invalid work drain with brcmf_sdio_probe() and brcmf_sdio_remove() in +the stack. + +Fixes: 9982464379e8 ("brcmfmac: make sdio suspend wait for threads to freeze") +Signed-off-by: Runyu Xiao +Acked-by: Arend van Spriel +Link: https://patch.msgid.link/20260619064401.1048976-1-runyu.xiao@seu.edu.cn +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c +index 71bb8b699731ba..a1b26144607698 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c +@@ -4458,6 +4458,7 @@ struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev) + bus->sdiodev = sdiodev; + sdiodev->bus = bus; + skb_queue_head_init(&bus->glom); ++ INIT_WORK(&bus->datawork, brcmf_sdio_dataworker); + bus->txbound = BRCMF_TXBOUND; + bus->rxbound = BRCMF_RXBOUND; + bus->txminmax = BRCMF_TXMINMAX; +@@ -4471,7 +4472,6 @@ struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev) + goto fail; + } + brcmf_sdiod_freezer_count(sdiodev); +- INIT_WORK(&bus->datawork, brcmf_sdio_dataworker); + bus->brcmf_wq = wq; + + /* attempt to attach to the dongle */ +-- +2.53.0 + diff --git a/queue-6.12/wifi-cfg80211-bound-element-id-read-when-checking-no.patch b/queue-6.12/wifi-cfg80211-bound-element-id-read-when-checking-no.patch new file mode 100644 index 0000000000..2c2a00b193 --- /dev/null +++ b/queue-6.12/wifi-cfg80211-bound-element-id-read-when-checking-no.patch @@ -0,0 +1,58 @@ +From 0b551a5d3f41fd078eeaed53139965b4868008dc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 7 Jul 2026 18:48:28 +0900 +Subject: wifi: cfg80211: bound element ID read when checking non-inheritance +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: HE WEI (ギカク) + +[ Upstream commit cb8afea4655ff004fa7feee825d5c79783525383 ] + +cfg80211_is_element_inherited() reads the first data octet of the +candidate element (id = elem->data[0]) to look it up in an extension +non-inheritance list. It does so after testing elem->id, but without +verifying that the element actually has a data octet. A zero-length +extension element (WLAN_EID_EXTENSION with length 0) therefore makes it +read one octet past the end of the element. + +_ieee802_11_parse_elems_full() runs this check for every element of a +frame once a non-inheritance context exists -- e.g. while parsing a +per-STA profile of a Multi-Link element in a (re)association response, +or a non-transmitted BSS profile -- so a crafted frame from an AP can +trigger a one-octet slab-out-of-bounds read during element parsing: + + BUG: KASAN: slab-out-of-bounds in cfg80211_is_element_inherited + Read of size 1 ... in net/wireless/scan.c + +Return early (treat the element as inherited) when an extension element +carries no data, mirroring the existing handling of empty ID lists. + +The bug was found by fuzzing ieee802_11_parse_elems_full() under KASAN. + +Fixes: f7dacfb11475 ("cfg80211: support non-inheritance element") +Signed-off-by: HE WEI (ギカク) +Link: https://patch.msgid.link/20260707094828.16465-1-skyexpoc@gmail.com +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + net/wireless/scan.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/wireless/scan.c b/net/wireless/scan.c +index b249f29454f9e1..3c439841578c49 100644 +--- a/net/wireless/scan.c ++++ b/net/wireless/scan.c +@@ -205,7 +205,7 @@ bool cfg80211_is_element_inherited(const struct element *elem, + return true; + + if (elem->id == WLAN_EID_EXTENSION) { +- if (!ext_id_len) ++ if (!ext_id_len || !elem->datalen) + return true; + loop_len = ext_id_len; + list = &non_inherit_elem->data[3 + id_len]; +-- +2.53.0 + diff --git a/queue-6.12/wifi-cfg80211-cancel-sched-scan-results-work-on-unre.patch b/queue-6.12/wifi-cfg80211-cancel-sched-scan-results-work-on-unre.patch new file mode 100644 index 0000000000..8244a224eb --- /dev/null +++ b/queue-6.12/wifi-cfg80211-cancel-sched-scan-results-work-on-unre.patch @@ -0,0 +1,83 @@ +From 927933b48d9b4deb3dedd3103591ac4598d36dd0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 20 Jun 2026 00:25:42 +0800 +Subject: wifi: cfg80211: cancel sched scan results work on unregister + +From: Cen Zhang + +[ Upstream commit edf0730be33696a1bd142792830d392129e495cc ] + +cfg80211_sched_scan_results() can queue rdev->sched_scan_res_wk from a +driver result notification while a scheduled scan request is present. The +work callback recovers the containing cfg80211_registered_device and then +locks the wiphy and walks the scheduled-scan request list. + +wiphy_unregister() already makes the wiphy unreachable and drains rdev work +items before cfg80211_dev_free() can release the object, but it does not +drain sched_scan_res_wk. A queued or running result work item can therefore +cross the unregister/free boundary and access freed rdev state. + +The buggy scenario involves two paths, with each column showing the order +within that path: + +scheduled-scan result path: unregister/free path: +1. cfg80211_sched_scan_results() 1. interface teardown stops and + queues rdev->sched_scan_res_wk. removes the scheduled scan request. +2. cfg80211_wq starts the work 2. wiphy_unregister() drains other + item and recovers rdev. rdev work items. +3. The worker locks rdev->wiphy 3. cfg80211_dev_free() destroys and + and walks rdev state. frees rdev. + +Cancel sched_scan_res_wk in wiphy_unregister() alongside the other rdev +work items. cancel_work_sync() removes a pending result notification and +waits for an already running callback, so cfg80211_dev_free() cannot free +rdev while this work item is still active. + +Validation reproduced this kernel report: +BUG: KASAN: use-after-free in cfg80211_sched_scan_results_wk+0x4a6/0x530 +Workqueue: cfg80211 cfg80211_sched_scan_results_wk [cfg80211] +Read of size 8 +Call trace: + dump_stack_lvl+0x66/0xa0 + print_report+0xce/0x630 + cfg80211_sched_scan_results_wk+0x4a6/0x530 + srso_alias_return_thunk+0x5/0xfbef5 + __virt_addr_valid+0x224/0x430 + kasan_report+0xac/0xe0 + lockdep_hardirqs_on_prepare+0xea/0x1a0 + process_one_work+0x8d0/0x18f0 (kernel/workqueue.c:3212) + lock_is_held_type+0x8f/0x100 + worker_thread+0x5ad/0xfd0 + __kthread_parkme+0xc6/0x200 + kthread+0x31e/0x410 + trace_hardirqs_on+0x1a/0x170 + ret_from_fork+0x576/0x810 + __switch_to+0x57e/0xe20 + __switch_to_asm+0x33/0x70 + ret_from_fork_asm+0x1a/0x30 + +Fixes: 807f8a8c3004 ("cfg80211/nl80211: add support for scheduled scans") +Assisted-by: Codex:gpt-5.5 +Signed-off-by: Cen Zhang +Link: https://patch.msgid.link/20260619162542.3878296-1-zzzccc427@gmail.com +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + net/wireless/core.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/net/wireless/core.c b/net/wireless/core.c +index 46e70f2e39ccf9..556b0d859d2dea 100644 +--- a/net/wireless/core.c ++++ b/net/wireless/core.c +@@ -1174,6 +1174,7 @@ void wiphy_unregister(struct wiphy *wiphy) + /* this has nothing to do now but make sure it's gone */ + cancel_work_sync(&rdev->wiphy_work); + ++ cancel_work_sync(&rdev->sched_scan_res_wk); + cancel_work_sync(&rdev->rfkill_block); + cancel_work_sync(&rdev->conn_work); + flush_work(&rdev->event_work); +-- +2.53.0 + diff --git a/queue-6.12/wifi-cfg80211-convert-pmsr_free_wk-to-wiphy_work-to-.patch b/queue-6.12/wifi-cfg80211-convert-pmsr_free_wk-to-wiphy_work-to-.patch new file mode 100644 index 0000000000..07679cbdaf --- /dev/null +++ b/queue-6.12/wifi-cfg80211-convert-pmsr_free_wk-to-wiphy_work-to-.patch @@ -0,0 +1,138 @@ +From 03f1b49e5d7ad52c6cec34ccac5420ea1e0791f1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 3 Jul 2026 13:55:23 +0530 +Subject: wifi: cfg80211: convert pmsr_free_wk to wiphy_work to fix deadlock + +From: Peddolla Harshavardhan Reddy + +[ Upstream commit 2b0eab425e1f658d8fe1df7590e3b9af5959505e ] + +When a netlink socket that owns a PMSR session is closed, +cfg80211_release_pmsr() clears the request's nl_portid and queues +pmsr_free_wk to call cfg80211_pmsr_process_abort() asynchronously. + +If the interface tears down concurrently, cfg80211_pmsr_wdev_down() +is called under wiphy_lock and calls cancel_work_sync(&pmsr_free_wk) +to wait for any running work. The work function acquires wiphy_lock +via guard(wiphy) before calling process_abort. + +This is a deadlock: wdev_down holds wiphy_lock and blocks inside +cancel_work_sync(); pmsr_free_wk blocks trying to acquire that same +wiphy_lock. Neither thread can proceed. + +The same deadlock is reachable from cfg80211_leave_locked(), which +calls cfg80211_pmsr_wdev_down() for all interface types under +wiphy_lock. + +Fix this by converting pmsr_free_wk from a plain work_struct to a +wiphy_work. The wiphy_work dispatcher holds wiphy_lock when running +work items, so the explicit guard(wiphy) in the work function is no +longer needed. wiphy_work_cancel() can be called safely while holding +wiphy_lock - since wiphy_lock prevents the work from running +concurrently, wiphy_work_cancel() never blocks, eliminating the +deadlock. + +Remove the cancel_work_sync() for pmsr_free_wk from the +NETDEV_GOING_DOWN handler. cfg80211_leave(), called unconditionally +just before it, already cancels any pending work under wiphy_lock +via wiphy_work_cancel() inside cfg80211_pmsr_wdev_down(). + +Fixes: 6dccbc9f3e1d ("wifi: cfg80211: cancel pmsr_free_wk in cfg80211_pmsr_wdev_down") +Signed-off-by: Peddolla Harshavardhan Reddy +Link: https://patch.msgid.link/20260703082523.2629324-1-peddolla.reddy@oss.qualcomm.com +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + include/net/cfg80211.h | 2 +- + net/wireless/core.c | 3 +-- + net/wireless/core.h | 2 +- + net/wireless/pmsr.c | 8 +++----- + 4 files changed, 6 insertions(+), 9 deletions(-) + +diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h +index a76e0459a8e63b..8dcb218e08047b 100644 +--- a/include/net/cfg80211.h ++++ b/include/net/cfg80211.h +@@ -6414,7 +6414,7 @@ struct wireless_dev { + + struct list_head pmsr_list; + spinlock_t pmsr_lock; +- struct work_struct pmsr_free_wk; ++ struct wiphy_work pmsr_free_wk; + + unsigned long unprot_beacon_reported; + +diff --git a/net/wireless/core.c b/net/wireless/core.c +index 7799cec95a9d99..5bc3e12e7b2de0 100644 +--- a/net/wireless/core.c ++++ b/net/wireless/core.c +@@ -1418,7 +1418,7 @@ void cfg80211_init_wdev(struct wireless_dev *wdev) + INIT_LIST_HEAD(&wdev->mgmt_registrations); + INIT_LIST_HEAD(&wdev->pmsr_list); + spin_lock_init(&wdev->pmsr_lock); +- INIT_WORK(&wdev->pmsr_free_wk, cfg80211_pmsr_free_wk); ++ wiphy_work_init(&wdev->pmsr_free_wk, cfg80211_pmsr_free_wk); + + #ifdef CONFIG_CFG80211_WEXT + wdev->wext.default_key = -1; +@@ -1551,7 +1551,6 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb, + } + /* since we just did cfg80211_leave() nothing to do there */ + cancel_work_sync(&wdev->disconnect_wk); +- cancel_work_sync(&wdev->pmsr_free_wk); + break; + case NETDEV_DOWN: + wiphy_lock(&rdev->wiphy); +diff --git a/net/wireless/core.h b/net/wireless/core.h +index a60883b6e43105..b02b456cfca379 100644 +--- a/net/wireless/core.h ++++ b/net/wireless/core.h +@@ -560,7 +560,7 @@ cfg80211_get_6ghz_power_type(const u8 *elems, size_t elems_len); + + void cfg80211_release_pmsr(struct wireless_dev *wdev, u32 portid); + void cfg80211_pmsr_wdev_down(struct wireless_dev *wdev); +-void cfg80211_pmsr_free_wk(struct work_struct *work); ++void cfg80211_pmsr_free_wk(struct wiphy *wiphy, struct wiphy_work *work); + + void cfg80211_remove_link(struct wireless_dev *wdev, unsigned int link_id); + void cfg80211_remove_links(struct wireless_dev *wdev); +diff --git a/net/wireless/pmsr.c b/net/wireless/pmsr.c +index 13801cf35e9fca..d2546c27879fa4 100644 +--- a/net/wireless/pmsr.c ++++ b/net/wireless/pmsr.c +@@ -625,13 +625,11 @@ static void cfg80211_pmsr_process_abort(struct wireless_dev *wdev) + } + } + +-void cfg80211_pmsr_free_wk(struct work_struct *work) ++void cfg80211_pmsr_free_wk(struct wiphy *wiphy, struct wiphy_work *work) + { + struct wireless_dev *wdev = container_of(work, struct wireless_dev, + pmsr_free_wk); + +- guard(wiphy)(wdev->wiphy); +- + cfg80211_pmsr_process_abort(wdev); + } + +@@ -647,7 +645,7 @@ void cfg80211_pmsr_wdev_down(struct wireless_dev *wdev) + } + spin_unlock_bh(&wdev->pmsr_lock); + +- cancel_work_sync(&wdev->pmsr_free_wk); ++ wiphy_work_cancel(wdev->wiphy, &wdev->pmsr_free_wk); + if (found) + cfg80211_pmsr_process_abort(wdev); + +@@ -662,7 +660,7 @@ void cfg80211_release_pmsr(struct wireless_dev *wdev, u32 portid) + list_for_each_entry(req, &wdev->pmsr_list, list) { + if (req->nl_portid == portid) { + req->nl_portid = 0; +- schedule_work(&wdev->pmsr_free_wk); ++ wiphy_work_queue(wdev->wiphy, &wdev->pmsr_free_wk); + } + } + spin_unlock_bh(&wdev->pmsr_lock); +-- +2.53.0 + diff --git a/queue-6.12/wifi-cfg80211-define-and-use-wiphy-guard.patch b/queue-6.12/wifi-cfg80211-define-and-use-wiphy-guard.patch new file mode 100644 index 0000000000..2fd9a73119 --- /dev/null +++ b/queue-6.12/wifi-cfg80211-define-and-use-wiphy-guard.patch @@ -0,0 +1,1638 @@ +From 7df3ae365bd25a21cf25aa135ef52fb4b0a4bbea Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 22 Nov 2024 09:42:25 +0100 +Subject: wifi: cfg80211: define and use wiphy guard + +From: Johannes Berg + +[ Upstream commit f42d22d3f79639c1b4e41daf28dad2505d6a5a8b ] + +Define a guard for the wiphy mutex, and use it in +most code in cfg80211, though not all due to some +interaction with RTNL and/or indentation. + +Suggested-by: Jeff Johnson +Reviewed-by: Jeff Johnson +Signed-off-by: Johannes Berg +Link: https://patch.msgid.link/20241122094225.88765cbaab65.I610c9b14f36902e75e1d13f0db29f8bef2298804@changeid +Signed-off-by: Johannes Berg +Stable-dep-of: 2b0eab425e1f ("wifi: cfg80211: convert pmsr_free_wk to wiphy_work to fix deadlock") +Signed-off-by: Sasha Levin +--- + include/net/cfg80211.h | 4 + + net/wireless/chan.c | 4 +- + net/wireless/core.c | 42 +++-- + net/wireless/mlme.c | 8 +- + net/wireless/nl80211.c | 190 +++++++++------------- + net/wireless/pmsr.c | 4 +- + net/wireless/reg.c | 55 +++---- + net/wireless/scan.c | 40 +++-- + net/wireless/sme.c | 12 +- + net/wireless/util.c | 7 +- + net/wireless/wext-compat.c | 317 +++++++++++++------------------------ + net/wireless/wext-sme.c | 43 ++--- + 12 files changed, 278 insertions(+), 448 deletions(-) + +diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h +index f1710d7af6656b..a76e0459a8e63b 100644 +--- a/include/net/cfg80211.h ++++ b/include/net/cfg80211.h +@@ -6030,6 +6030,10 @@ static inline void wiphy_unlock(struct wiphy *wiphy) + mutex_unlock(&wiphy->mtx); + } + ++DEFINE_GUARD(wiphy, struct wiphy *, ++ mutex_lock(&_T->mtx), ++ mutex_unlock(&_T->mtx)) ++ + struct wiphy_work; + typedef void (*wiphy_work_func_t)(struct wiphy *, struct wiphy_work *); + +diff --git a/net/wireless/chan.c b/net/wireless/chan.c +index eb8826e33d1757..515d40c09e7886 100644 +--- a/net/wireless/chan.c ++++ b/net/wireless/chan.c +@@ -1039,10 +1039,10 @@ bool cfg80211_any_wiphy_oper_chan(struct wiphy *wiphy, + if (!reg_dfs_domain_same(wiphy, &rdev->wiphy)) + continue; + +- wiphy_lock(&rdev->wiphy); ++ guard(wiphy)(&rdev->wiphy); ++ + found = cfg80211_is_wiphy_oper_chan(&rdev->wiphy, chan) || + cfg80211_offchan_chain_is_active(rdev, chan); +- wiphy_unlock(&rdev->wiphy); + + if (found) + return true; +diff --git a/net/wireless/core.c b/net/wireless/core.c +index 556b0d859d2dea..7799cec95a9d99 100644 +--- a/net/wireless/core.c ++++ b/net/wireless/core.c +@@ -191,7 +191,8 @@ int cfg80211_switch_netns(struct cfg80211_registered_device *rdev, + return err; + } + +- wiphy_lock(&rdev->wiphy); ++ guard(wiphy)(&rdev->wiphy); ++ + list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) { + if (!wdev->netdev) + continue; +@@ -212,7 +213,6 @@ int cfg80211_switch_netns(struct cfg80211_registered_device *rdev, + continue; + nl80211_notify_iface(rdev, wdev, NL80211_CMD_NEW_INTERFACE); + } +- wiphy_unlock(&rdev->wiphy); + + return 0; + } +@@ -221,9 +221,9 @@ static void cfg80211_rfkill_poll(struct rfkill *rfkill, void *data) + { + struct cfg80211_registered_device *rdev = data; + +- wiphy_lock(&rdev->wiphy); ++ guard(wiphy)(&rdev->wiphy); ++ + rdev_rfkill_poll(rdev); +- wiphy_unlock(&rdev->wiphy); + } + + void cfg80211_stop_p2p_device(struct cfg80211_registered_device *rdev, +@@ -283,7 +283,7 @@ void cfg80211_shutdown_all_interfaces(struct wiphy *wiphy) + + /* otherwise, check iftype */ + +- wiphy_lock(wiphy); ++ guard(wiphy)(wiphy); + + switch (wdev->iftype) { + case NL80211_IFTYPE_P2P_DEVICE: +@@ -295,8 +295,6 @@ void cfg80211_shutdown_all_interfaces(struct wiphy *wiphy) + default: + break; + } +- +- wiphy_unlock(wiphy); + } + } + EXPORT_SYMBOL_GPL(cfg80211_shutdown_all_interfaces); +@@ -331,9 +329,9 @@ static void cfg80211_event_work(struct work_struct *work) + rdev = container_of(work, struct cfg80211_registered_device, + event_work); + +- wiphy_lock(&rdev->wiphy); ++ guard(wiphy)(&rdev->wiphy); ++ + cfg80211_process_rdev_events(rdev); +- wiphy_unlock(&rdev->wiphy); + } + + void cfg80211_destroy_ifaces(struct cfg80211_registered_device *rdev) +@@ -347,10 +345,10 @@ void cfg80211_destroy_ifaces(struct cfg80211_registered_device *rdev) + if (wdev->netdev) + dev_close(wdev->netdev); + +- wiphy_lock(&rdev->wiphy); ++ guard(wiphy)(&rdev->wiphy); ++ + cfg80211_leave(rdev, wdev); + cfg80211_remove_virtual_intf(rdev, wdev); +- wiphy_unlock(&rdev->wiphy); + } + } + } +@@ -423,9 +421,9 @@ static void cfg80211_wiphy_work(struct work_struct *work) + + trace_wiphy_work_worker_start(&rdev->wiphy); + +- wiphy_lock(&rdev->wiphy); ++ guard(wiphy)(&rdev->wiphy); + if (rdev->suspended) +- goto out; ++ return; + + spin_lock_irq(&rdev->wiphy_work_lock); + wk = list_first_entry_or_null(&rdev->wiphy_work_list, +@@ -441,8 +439,6 @@ static void cfg80211_wiphy_work(struct work_struct *work) + } else { + spin_unlock_irq(&rdev->wiphy_work_lock); + } +-out: +- wiphy_unlock(&rdev->wiphy); + } + + /* exported functions */ +@@ -1532,9 +1528,9 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb, + break; + case NETDEV_REGISTER: + if (!wdev->registered) { +- wiphy_lock(&rdev->wiphy); ++ guard(wiphy)(&rdev->wiphy); ++ + cfg80211_register_wdev(rdev, wdev); +- wiphy_unlock(&rdev->wiphy); + } + break; + case NETDEV_UNREGISTER: +@@ -1543,16 +1539,16 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb, + * so check wdev->registered. + */ + if (wdev->registered && !wdev->registering) { +- wiphy_lock(&rdev->wiphy); ++ guard(wiphy)(&rdev->wiphy); ++ + _cfg80211_unregister_wdev(wdev, false); +- wiphy_unlock(&rdev->wiphy); + } + break; + case NETDEV_GOING_DOWN: +- wiphy_lock(&rdev->wiphy); +- cfg80211_leave(rdev, wdev); +- cfg80211_remove_links(wdev); +- wiphy_unlock(&rdev->wiphy); ++ scoped_guard(wiphy, &rdev->wiphy) { ++ cfg80211_leave(rdev, wdev); ++ cfg80211_remove_links(wdev); ++ } + /* since we just did cfg80211_leave() nothing to do there */ + cancel_work_sync(&wdev->disconnect_wk); + cancel_work_sync(&wdev->pmsr_free_wk); +diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c +index 26319522c7abc3..fbdf6acfcb7dc7 100644 +--- a/net/wireless/mlme.c ++++ b/net/wireless/mlme.c +@@ -627,10 +627,10 @@ void cfg80211_mgmt_registrations_update_wk(struct work_struct *wk) + rdev = container_of(wk, struct cfg80211_registered_device, + mgmt_registrations_update_wk); + +- wiphy_lock(&rdev->wiphy); ++ guard(wiphy)(&rdev->wiphy); ++ + list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) + cfg80211_mgmt_registrations_update(wdev); +- wiphy_unlock(&rdev->wiphy); + } + + int cfg80211_mlme_register_mgmt(struct wireless_dev *wdev, u32 snd_portid, +@@ -1194,10 +1194,10 @@ cfg80211_background_cac_event(struct cfg80211_registered_device *rdev, + const struct cfg80211_chan_def *chandef, + enum nl80211_radar_event event) + { +- wiphy_lock(&rdev->wiphy); ++ guard(wiphy)(&rdev->wiphy); ++ + __cfg80211_background_cac_event(rdev, rdev->background_radar_wdev, + chandef, event); +- wiphy_unlock(&rdev->wiphy); + } + + void cfg80211_background_cac_done_wk(struct work_struct *work) +diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c +index 90ff3ee8df6122..0af78812e38efe 100644 +--- a/net/wireless/nl80211.c ++++ b/net/wireless/nl80211.c +@@ -3632,7 +3632,7 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) + } else + wdev = netdev->ieee80211_ptr; + +- wiphy_lock(&rdev->wiphy); ++ guard(wiphy)(&rdev->wiphy); + + /* + * end workaround code, by now the rdev is available +@@ -3645,32 +3645,24 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) + rtnl_unlock(); + + if (result) +- goto out; ++ return result; + + if (info->attrs[NL80211_ATTR_WIPHY_TXQ_PARAMS]) { + struct ieee80211_txq_params txq_params; + struct nlattr *tb[NL80211_TXQ_ATTR_MAX + 1]; + +- if (!rdev->ops->set_txq_params) { +- result = -EOPNOTSUPP; +- goto out; +- } ++ if (!rdev->ops->set_txq_params) ++ return -EOPNOTSUPP; + +- if (!netdev) { +- result = -EINVAL; +- goto out; +- } ++ if (!netdev) ++ return -EINVAL; + + if (netdev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && +- netdev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) { +- result = -EINVAL; +- goto out; +- } ++ netdev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) ++ return -EINVAL; + +- if (!netif_running(netdev)) { +- result = -ENETDOWN; +- goto out; +- } ++ if (!netif_running(netdev)) ++ return -ENETDOWN; + + nla_for_each_nested(nl_txq_params, + info->attrs[NL80211_ATTR_WIPHY_TXQ_PARAMS], +@@ -3681,10 +3673,11 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) + txq_params_policy, + info->extack); + if (result) +- goto out; ++ return result; ++ + result = parse_txq_params(tb, &txq_params); + if (result) +- goto out; ++ return result; + + txq_params.link_id = + nl80211_link_id_or_invalid(info->attrs); +@@ -3700,7 +3693,7 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) + result = rdev_set_txq_params(rdev, netdev, + &txq_params); + if (result) +- goto out; ++ return result; + } + } + +@@ -3717,7 +3710,7 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) + } + + if (result) +- goto out; ++ return result; + } + + if (info->attrs[NL80211_ATTR_WIPHY_TX_POWER_SETTING]) { +@@ -3728,19 +3721,15 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) + if (!(rdev->wiphy.features & NL80211_FEATURE_VIF_TXPOWER)) + txp_wdev = NULL; + +- if (!rdev->ops->set_tx_power) { +- result = -EOPNOTSUPP; +- goto out; +- } ++ if (!rdev->ops->set_tx_power) ++ return -EOPNOTSUPP; + + idx = NL80211_ATTR_WIPHY_TX_POWER_SETTING; + type = nla_get_u32(info->attrs[idx]); + + if (!info->attrs[NL80211_ATTR_WIPHY_TX_POWER_LEVEL] && +- (type != NL80211_TX_POWER_AUTOMATIC)) { +- result = -EINVAL; +- goto out; +- } ++ (type != NL80211_TX_POWER_AUTOMATIC)) ++ return -EINVAL; + + if (type != NL80211_TX_POWER_AUTOMATIC) { + idx = NL80211_ATTR_WIPHY_TX_POWER_LEVEL; +@@ -3749,7 +3738,7 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) + + result = rdev_set_tx_power(rdev, txp_wdev, type, mbm); + if (result) +- goto out; ++ return result; + } + + if (info->attrs[NL80211_ATTR_WIPHY_ANTENNA_TX] && +@@ -3758,10 +3747,8 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) + + if ((!rdev->wiphy.available_antennas_tx && + !rdev->wiphy.available_antennas_rx) || +- !rdev->ops->set_antenna) { +- result = -EOPNOTSUPP; +- goto out; +- } ++ !rdev->ops->set_antenna) ++ return -EOPNOTSUPP; + + tx_ant = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_ANTENNA_TX]); + rx_ant = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_ANTENNA_RX]); +@@ -3769,17 +3756,15 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) + /* reject antenna configurations which don't match the + * available antenna masks, except for the "all" mask */ + if ((~tx_ant && (tx_ant & ~rdev->wiphy.available_antennas_tx)) || +- (~rx_ant && (rx_ant & ~rdev->wiphy.available_antennas_rx))) { +- result = -EINVAL; +- goto out; +- } ++ (~rx_ant && (rx_ant & ~rdev->wiphy.available_antennas_rx))) ++ return -EINVAL; + + tx_ant = tx_ant & rdev->wiphy.available_antennas_tx; + rx_ant = rx_ant & rdev->wiphy.available_antennas_rx; + + result = rdev_set_antenna(rdev, tx_ant, rx_ant); + if (result) +- goto out; ++ return result; + } + + changed = 0; +@@ -3801,10 +3786,8 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) + if (info->attrs[NL80211_ATTR_WIPHY_FRAG_THRESHOLD]) { + frag_threshold = nla_get_u32( + info->attrs[NL80211_ATTR_WIPHY_FRAG_THRESHOLD]); +- if (frag_threshold < 256) { +- result = -EINVAL; +- goto out; +- } ++ if (frag_threshold < 256) ++ return -EINVAL; + + if (frag_threshold != (u32) -1) { + /* +@@ -3825,10 +3808,8 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) + } + + if (info->attrs[NL80211_ATTR_WIPHY_COVERAGE_CLASS]) { +- if (info->attrs[NL80211_ATTR_WIPHY_DYN_ACK]) { +- result = -EINVAL; +- goto out; +- } ++ if (info->attrs[NL80211_ATTR_WIPHY_DYN_ACK]) ++ return -EINVAL; + + coverage_class = nla_get_u8( + info->attrs[NL80211_ATTR_WIPHY_COVERAGE_CLASS]); +@@ -3836,20 +3817,17 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) + } + + if (info->attrs[NL80211_ATTR_WIPHY_DYN_ACK]) { +- if (!(rdev->wiphy.features & NL80211_FEATURE_ACKTO_ESTIMATION)) { +- result = -EOPNOTSUPP; +- goto out; +- } ++ if (!(rdev->wiphy.features & NL80211_FEATURE_ACKTO_ESTIMATION)) ++ return -EOPNOTSUPP; + + changed |= WIPHY_PARAM_DYN_ACK; + } + + if (info->attrs[NL80211_ATTR_TXQ_LIMIT]) { + if (!wiphy_ext_feature_isset(&rdev->wiphy, +- NL80211_EXT_FEATURE_TXQS)) { +- result = -EOPNOTSUPP; +- goto out; +- } ++ NL80211_EXT_FEATURE_TXQS)) ++ return -EOPNOTSUPP; ++ + txq_limit = nla_get_u32( + info->attrs[NL80211_ATTR_TXQ_LIMIT]); + changed |= WIPHY_PARAM_TXQ_LIMIT; +@@ -3857,10 +3835,9 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) + + if (info->attrs[NL80211_ATTR_TXQ_MEMORY_LIMIT]) { + if (!wiphy_ext_feature_isset(&rdev->wiphy, +- NL80211_EXT_FEATURE_TXQS)) { +- result = -EOPNOTSUPP; +- goto out; +- } ++ NL80211_EXT_FEATURE_TXQS)) ++ return -EOPNOTSUPP; ++ + txq_memory_limit = nla_get_u32( + info->attrs[NL80211_ATTR_TXQ_MEMORY_LIMIT]); + changed |= WIPHY_PARAM_TXQ_MEMORY_LIMIT; +@@ -3868,10 +3845,9 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) + + if (info->attrs[NL80211_ATTR_TXQ_QUANTUM]) { + if (!wiphy_ext_feature_isset(&rdev->wiphy, +- NL80211_EXT_FEATURE_TXQS)) { +- result = -EOPNOTSUPP; +- goto out; +- } ++ NL80211_EXT_FEATURE_TXQS)) ++ return -EOPNOTSUPP; ++ + txq_quantum = nla_get_u32( + info->attrs[NL80211_ATTR_TXQ_QUANTUM]); + changed |= WIPHY_PARAM_TXQ_QUANTUM; +@@ -3883,10 +3859,8 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) + u8 old_coverage_class; + u32 old_txq_limit, old_txq_memory_limit, old_txq_quantum; + +- if (!rdev->ops->set_wiphy_params) { +- result = -EOPNOTSUPP; +- goto out; +- } ++ if (!rdev->ops->set_wiphy_params) ++ return -EOPNOTSUPP; + + old_retry_short = rdev->wiphy.retry_short; + old_retry_long = rdev->wiphy.retry_long; +@@ -3924,15 +3898,11 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) + rdev->wiphy.txq_limit = old_txq_limit; + rdev->wiphy.txq_memory_limit = old_txq_memory_limit; + rdev->wiphy.txq_quantum = old_txq_quantum; +- goto out; ++ return result; + } + } + +- result = 0; +- +-out: +- wiphy_unlock(&rdev->wiphy); +- return result; ++ return 0; + } + + int nl80211_send_chandef(struct sk_buff *msg, const struct cfg80211_chan_def *chandef) +@@ -4149,22 +4119,22 @@ static int nl80211_dump_interface(struct sk_buff *skb, struct netlink_callback * + + if_idx = 0; + +- wiphy_lock(&rdev->wiphy); ++ guard(wiphy)(&rdev->wiphy); ++ + list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) { + if (if_idx < if_start) { + if_idx++; + continue; + } ++ + if (nl80211_send_iface(skb, NETLINK_CB(cb->skb).portid, + cb->nlh->nlmsg_seq, NLM_F_MULTI, + rdev, wdev, +- NL80211_CMD_NEW_INTERFACE) < 0) { +- wiphy_unlock(&rdev->wiphy); ++ NL80211_CMD_NEW_INTERFACE) < 0) + goto out; +- } ++ + if_idx++; + } +- wiphy_unlock(&rdev->wiphy); + + if_start = 0; + wp_idx++; +@@ -4489,16 +4459,13 @@ static int _nl80211_new_interface(struct sk_buff *skb, struct genl_info *info) + static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info) + { + struct cfg80211_registered_device *rdev = info->user_ptr[0]; +- int ret; + + /* to avoid failing a new interface creation due to pending removal */ + cfg80211_destroy_ifaces(rdev); + +- wiphy_lock(&rdev->wiphy); +- ret = _nl80211_new_interface(skb, info); +- wiphy_unlock(&rdev->wiphy); ++ guard(wiphy)(&rdev->wiphy); + +- return ret; ++ return _nl80211_new_interface(skb, info); + } + + static int nl80211_del_interface(struct sk_buff *skb, struct genl_info *info) +@@ -10094,7 +10061,7 @@ static int nl80211_start_radar_detection(struct sk_buff *skb, + struct cfg80211_chan_def chandef; + enum nl80211_dfs_regions dfs_region; + unsigned int cac_time_ms; +- int err = -EINVAL; ++ int err; + + flush_delayed_work(&rdev->dfs_update_channels_wk); + +@@ -10109,35 +10076,29 @@ static int nl80211_start_radar_detection(struct sk_buff *skb, + return -EINVAL; + } + +- wiphy_lock(wiphy); ++ guard(wiphy)(wiphy); + + dfs_region = reg_get_dfs_region(wiphy); + if (dfs_region == NL80211_DFS_UNSET) +- goto unlock; ++ return -EINVAL; + + err = nl80211_parse_chandef(rdev, info, &chandef); + if (err) +- goto unlock; ++ return err; + + err = cfg80211_chandef_dfs_required(wiphy, &chandef, wdev->iftype); + if (err < 0) +- goto unlock; ++ return err; + +- if (err == 0) { +- err = -EINVAL; +- goto unlock; +- } ++ if (err == 0) ++ return -EINVAL; + +- if (!cfg80211_chandef_dfs_usable(wiphy, &chandef)) { +- err = -EINVAL; +- goto unlock; +- } ++ if (!cfg80211_chandef_dfs_usable(wiphy, &chandef)) ++ return -EINVAL; + +- if (nla_get_flag(info->attrs[NL80211_ATTR_RADAR_BACKGROUND])) { +- err = cfg80211_start_background_radar_detection(rdev, wdev, +- &chandef); +- goto unlock; +- } ++ if (nla_get_flag(info->attrs[NL80211_ATTR_RADAR_BACKGROUND])) ++ return cfg80211_start_background_radar_detection(rdev, wdev, ++ &chandef); + + if (cfg80211_beaconing_iface_active(wdev)) { + /* During MLO other link(s) can beacon, only the current link +@@ -10147,26 +10108,19 @@ static int nl80211_start_radar_detection(struct sk_buff *skb, + !wdev->links[link_id].ap.beacon_interval) { + /* nothing */ + } else { +- err = -EBUSY; +- goto unlock; ++ return -EBUSY; + } + } + +- if (wdev->links[link_id].cac_started) { +- err = -EBUSY; +- goto unlock; +- } ++ if (wdev->links[link_id].cac_started) ++ return -EBUSY; + + /* CAC start is offloaded to HW and can't be started manually */ +- if (wiphy_ext_feature_isset(wiphy, NL80211_EXT_FEATURE_DFS_OFFLOAD)) { +- err = -EOPNOTSUPP; +- goto unlock; +- } ++ if (wiphy_ext_feature_isset(wiphy, NL80211_EXT_FEATURE_DFS_OFFLOAD)) ++ return -EOPNOTSUPP; + +- if (!rdev->ops->start_radar_detection) { +- err = -EOPNOTSUPP; +- goto unlock; +- } ++ if (!rdev->ops->start_radar_detection) ++ return -EOPNOTSUPP; + + cac_time_ms = cfg80211_chandef_dfs_cac_time(&rdev->wiphy, &chandef); + if (WARN_ON(!cac_time_ms)) +@@ -10193,10 +10147,8 @@ static int nl80211_start_radar_detection(struct sk_buff *skb, + wdev->links[link_id].cac_start_time = jiffies; + wdev->links[link_id].cac_time_ms = cac_time_ms; + } +-unlock: +- wiphy_unlock(wiphy); + +- return err; ++ return 0; + } + + static int nl80211_notify_radar_detection(struct sk_buff *skb, +diff --git a/net/wireless/pmsr.c b/net/wireless/pmsr.c +index d2b61b6ba58db7..13801cf35e9fca 100644 +--- a/net/wireless/pmsr.c ++++ b/net/wireless/pmsr.c +@@ -630,9 +630,9 @@ void cfg80211_pmsr_free_wk(struct work_struct *work) + struct wireless_dev *wdev = container_of(work, struct wireless_dev, + pmsr_free_wk); + +- wiphy_lock(wdev->wiphy); ++ guard(wiphy)(wdev->wiphy); ++ + cfg80211_pmsr_process_abort(wdev); +- wiphy_unlock(wdev->wiphy); + } + + void cfg80211_pmsr_wdev_down(struct wireless_dev *wdev) +diff --git a/net/wireless/reg.c b/net/wireless/reg.c +index 9f8428dc418a50..daf51fb56648c4 100644 +--- a/net/wireless/reg.c ++++ b/net/wireless/reg.c +@@ -2468,11 +2468,11 @@ static void reg_leave_invalid_chans(struct wiphy *wiphy) + struct wireless_dev *wdev; + struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy); + +- wiphy_lock(wiphy); ++ guard(wiphy)(wiphy); ++ + list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) + if (!reg_wdev_chan_valid(wiphy, wdev)) + cfg80211_leave(rdev, wdev); +- wiphy_unlock(wiphy); + } + + static void reg_check_chans_work(struct work_struct *work) +@@ -2652,13 +2652,11 @@ void wiphy_apply_custom_regulatory(struct wiphy *wiphy, + return; + + rtnl_lock(); +- wiphy_lock(wiphy); +- +- tmp = get_wiphy_regdom(wiphy); +- rcu_assign_pointer(wiphy->regd, new_regd); +- rcu_free_regdom(tmp); +- +- wiphy_unlock(wiphy); ++ scoped_guard(wiphy, wiphy) { ++ tmp = get_wiphy_regdom(wiphy); ++ rcu_assign_pointer(wiphy->regd, new_regd); ++ rcu_free_regdom(tmp); ++ } + rtnl_unlock(); + } + EXPORT_SYMBOL(wiphy_apply_custom_regulatory); +@@ -2828,9 +2826,9 @@ reg_process_hint_driver(struct wiphy *wiphy, + + tmp = get_wiphy_regdom(wiphy); + ASSERT_RTNL(); +- wiphy_lock(wiphy); +- rcu_assign_pointer(wiphy->regd, regd); +- wiphy_unlock(wiphy); ++ scoped_guard(wiphy, wiphy) { ++ rcu_assign_pointer(wiphy->regd, regd); ++ } + rcu_free_regdom(tmp); + } + +@@ -3208,9 +3206,9 @@ static void reg_process_self_managed_hints(void) + ASSERT_RTNL(); + + for_each_rdev(rdev) { +- wiphy_lock(&rdev->wiphy); ++ guard(wiphy)(&rdev->wiphy); ++ + reg_process_self_managed_hint(&rdev->wiphy); +- wiphy_unlock(&rdev->wiphy); + } + + reg_check_channels(); +@@ -3603,14 +3601,12 @@ static bool is_wiphy_all_set_reg_flag(enum ieee80211_regulatory_flags flag) + struct wireless_dev *wdev; + + for_each_rdev(rdev) { +- wiphy_lock(&rdev->wiphy); ++ guard(wiphy)(&rdev->wiphy); ++ + list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) { +- if (!(wdev->wiphy->regulatory_flags & flag)) { +- wiphy_unlock(&rdev->wiphy); ++ if (!(wdev->wiphy->regulatory_flags & flag)) + return false; +- } + } +- wiphy_unlock(&rdev->wiphy); + } + + return true; +@@ -3886,19 +3882,18 @@ static int reg_set_rd_driver(const struct ieee80211_regdomain *rd, + + if (!driver_request->intersect) { + ASSERT_RTNL(); +- wiphy_lock(request_wiphy); +- if (request_wiphy->regd) +- tmp = get_wiphy_regdom(request_wiphy); +- +- regd = reg_copy_regd(rd); +- if (IS_ERR(regd)) { +- wiphy_unlock(request_wiphy); +- return PTR_ERR(regd); ++ scoped_guard(wiphy, request_wiphy) { ++ if (request_wiphy->regd) ++ tmp = get_wiphy_regdom(request_wiphy); ++ ++ regd = reg_copy_regd(rd); ++ if (IS_ERR(regd)) ++ return PTR_ERR(regd); ++ ++ rcu_assign_pointer(request_wiphy->regd, regd); ++ rcu_free_regdom(tmp); + } + +- rcu_assign_pointer(request_wiphy->regd, regd); +- rcu_free_regdom(tmp); +- wiphy_unlock(request_wiphy); + reset_regdomains(false, rd); + return 0; + } +diff --git a/net/wireless/scan.c b/net/wireless/scan.c +index 3fb31f17daf4ae..44973529687486 100644 +--- a/net/wireless/scan.c ++++ b/net/wireless/scan.c +@@ -1234,7 +1234,8 @@ void cfg80211_sched_scan_results_wk(struct work_struct *work) + rdev = container_of(work, struct cfg80211_registered_device, + sched_scan_res_wk); + +- wiphy_lock(&rdev->wiphy); ++ guard(wiphy)(&rdev->wiphy); ++ + list_for_each_entry_safe(req, tmp, &rdev->sched_scan_req_list, list) { + if (req->report_results) { + req->report_results = false; +@@ -1249,7 +1250,6 @@ void cfg80211_sched_scan_results_wk(struct work_struct *work) + NL80211_CMD_SCHED_SCAN_RESULTS); + } + } +- wiphy_unlock(&rdev->wiphy); + } + + void cfg80211_sched_scan_results(struct wiphy *wiphy, u64 reqid) +@@ -1284,9 +1284,9 @@ EXPORT_SYMBOL(cfg80211_sched_scan_stopped_locked); + + void cfg80211_sched_scan_stopped(struct wiphy *wiphy, u64 reqid) + { +- wiphy_lock(wiphy); ++ guard(wiphy)(wiphy); ++ + cfg80211_sched_scan_stopped_locked(wiphy, reqid); +- wiphy_unlock(wiphy); + } + EXPORT_SYMBOL(cfg80211_sched_scan_stopped); + +@@ -3558,10 +3558,8 @@ int cfg80211_wext_siwscan(struct net_device *dev, + /* translate "Scan for SSID" request */ + if (wreq) { + if (wrqu->data.flags & IW_SCAN_THIS_ESSID) { +- if (wreq->essid_len > IEEE80211_MAX_SSID_LEN) { +- err = -EINVAL; +- goto out; +- } ++ if (wreq->essid_len > IEEE80211_MAX_SSID_LEN) ++ return -EINVAL; + memcpy(creq->ssids[0].ssid, wreq->essid, wreq->essid_len); + creq->ssids[0].ssid_len = wreq->essid_len; + } +@@ -3577,20 +3575,20 @@ int cfg80211_wext_siwscan(struct net_device *dev, + + eth_broadcast_addr(creq->bssid); + +- wiphy_lock(&rdev->wiphy); +- +- rdev->scan_req = creq; +- err = rdev_scan(rdev, creq); +- if (err) { +- rdev->scan_req = NULL; +- /* creq will be freed below */ +- } else { +- nl80211_send_scan_start(rdev, dev->ieee80211_ptr); +- /* creq now owned by driver */ +- creq = NULL; +- dev_hold(dev); ++ scoped_guard(wiphy, &rdev->wiphy) { ++ rdev->scan_req = creq; ++ err = rdev_scan(rdev, creq); ++ if (err) { ++ rdev->scan_req = NULL; ++ /* creq will be freed below */ ++ } else { ++ nl80211_send_scan_start(rdev, dev->ieee80211_ptr); ++ /* creq now owned by driver */ ++ creq = NULL; ++ dev_hold(dev); ++ } + } +- wiphy_unlock(&rdev->wiphy); ++ + out: + kfree(creq); + return err; +diff --git a/net/wireless/sme.c b/net/wireless/sme.c +index d8250ae17d940b..ab57648ca57748 100644 +--- a/net/wireless/sme.c ++++ b/net/wireless/sme.c +@@ -252,7 +252,7 @@ void cfg80211_conn_work(struct work_struct *work) + u8 bssid_buf[ETH_ALEN], *bssid = NULL; + enum nl80211_timeout_reason treason; + +- wiphy_lock(&rdev->wiphy); ++ guard(wiphy)(&rdev->wiphy); + + list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) { + if (!wdev->netdev) +@@ -280,8 +280,6 @@ void cfg80211_conn_work(struct work_struct *work) + __cfg80211_connect_result(wdev->netdev, &cr, false); + } + } +- +- wiphy_unlock(&rdev->wiphy); + } + + static void cfg80211_step_auth_next(struct cfg80211_conn *conn, +@@ -693,13 +691,13 @@ static bool cfg80211_is_all_idle(void) + * as chan dfs state, etc. + */ + for_each_rdev(rdev) { +- wiphy_lock(&rdev->wiphy); ++ guard(wiphy)(&rdev->wiphy); ++ + list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) { + if (wdev->conn || wdev->connected || + cfg80211_beaconing_iface_active(wdev)) + is_all_idle = false; + } +- wiphy_unlock(&rdev->wiphy); + } + + return is_all_idle; +@@ -1586,7 +1584,7 @@ void cfg80211_autodisconnect_wk(struct work_struct *work) + container_of(work, struct wireless_dev, disconnect_wk); + struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy); + +- wiphy_lock(wdev->wiphy); ++ guard(wiphy)(wdev->wiphy); + + if (wdev->conn_owner_nlportid) { + switch (wdev->iftype) { +@@ -1622,6 +1620,4 @@ void cfg80211_autodisconnect_wk(struct work_struct *work) + break; + } + } +- +- wiphy_unlock(wdev->wiphy); + } +diff --git a/net/wireless/util.c b/net/wireless/util.c +index 5be4ccb8714110..8478f3a0e94021 100644 +--- a/net/wireless/util.c ++++ b/net/wireless/util.c +@@ -2601,7 +2601,6 @@ int cfg80211_get_station(struct net_device *dev, const u8 *mac_addr, + { + struct cfg80211_registered_device *rdev; + struct wireless_dev *wdev; +- int ret; + + wdev = dev->ieee80211_ptr; + if (!wdev) +@@ -2613,11 +2612,9 @@ int cfg80211_get_station(struct net_device *dev, const u8 *mac_addr, + + memset(sinfo, 0, sizeof(*sinfo)); + +- wiphy_lock(&rdev->wiphy); +- ret = rdev_get_station(rdev, dev, mac_addr, sinfo); +- wiphy_unlock(&rdev->wiphy); ++ guard(wiphy)(&rdev->wiphy); + +- return ret; ++ return rdev_get_station(rdev, dev, mac_addr, sinfo); + } + EXPORT_SYMBOL(cfg80211_get_station); + +diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c +index 32a695c8a4d2af..186f84b3679bf0 100644 +--- a/net/wireless/wext-compat.c ++++ b/net/wireless/wext-compat.c +@@ -40,7 +40,6 @@ int cfg80211_wext_siwmode(struct net_device *dev, struct iw_request_info *info, + struct cfg80211_registered_device *rdev; + struct vif_params vifparams; + enum nl80211_iftype type; +- int ret; + + rdev = wiphy_to_rdev(wdev->wiphy); + +@@ -63,11 +62,9 @@ int cfg80211_wext_siwmode(struct net_device *dev, struct iw_request_info *info, + + memset(&vifparams, 0, sizeof(vifparams)); + +- wiphy_lock(wdev->wiphy); +- ret = cfg80211_change_iface(rdev, dev, type, &vifparams); +- wiphy_unlock(wdev->wiphy); ++ guard(wiphy)(wdev->wiphy); + +- return ret; ++ return cfg80211_change_iface(rdev, dev, type, &vifparams); + } + EXPORT_WEXT_HANDLER(cfg80211_wext_siwmode); + +@@ -262,23 +259,17 @@ int cfg80211_wext_siwrts(struct net_device *dev, + u32 orts = wdev->wiphy->rts_threshold; + int err; + +- wiphy_lock(&rdev->wiphy); +- if (rts->disabled || !rts->fixed) { ++ guard(wiphy)(&rdev->wiphy); ++ if (rts->disabled || !rts->fixed) + wdev->wiphy->rts_threshold = (u32) -1; +- } else if (rts->value < 0) { +- err = -EINVAL; +- goto out; +- } else { ++ else if (rts->value < 0) ++ return -EINVAL; ++ else + wdev->wiphy->rts_threshold = rts->value; +- } + + err = rdev_set_wiphy_params(rdev, WIPHY_PARAM_RTS_THRESHOLD); +- + if (err) + wdev->wiphy->rts_threshold = orts; +- +-out: +- wiphy_unlock(&rdev->wiphy); + return err; + } + EXPORT_WEXT_HANDLER(cfg80211_wext_siwrts); +@@ -308,12 +299,12 @@ int cfg80211_wext_siwfrag(struct net_device *dev, + u32 ofrag = wdev->wiphy->frag_threshold; + int err; + +- wiphy_lock(&rdev->wiphy); ++ guard(wiphy)(&rdev->wiphy); ++ + if (frag->disabled || !frag->fixed) { + wdev->wiphy->frag_threshold = (u32) -1; + } else if (frag->value < 256) { +- err = -EINVAL; +- goto out; ++ return -EINVAL; + } else { + /* Fragment length must be even, so strip LSB. */ + wdev->wiphy->frag_threshold = frag->value & ~0x1; +@@ -322,9 +313,6 @@ int cfg80211_wext_siwfrag(struct net_device *dev, + err = rdev_set_wiphy_params(rdev, WIPHY_PARAM_FRAG_THRESHOLD); + if (err) + wdev->wiphy->frag_threshold = ofrag; +-out: +- wiphy_unlock(&rdev->wiphy); +- + return err; + } + EXPORT_WEXT_HANDLER(cfg80211_wext_siwfrag); +@@ -360,7 +348,8 @@ static int cfg80211_wext_siwretry(struct net_device *dev, + (retry->flags & IW_RETRY_TYPE) != IW_RETRY_LIMIT) + return -EINVAL; + +- wiphy_lock(&rdev->wiphy); ++ guard(wiphy)(&rdev->wiphy); ++ + if (retry->flags & IW_RETRY_LONG) { + wdev->wiphy->retry_long = retry->value; + changed |= WIPHY_PARAM_RETRY_LONG; +@@ -379,7 +368,6 @@ static int cfg80211_wext_siwretry(struct net_device *dev, + wdev->wiphy->retry_short = oshort; + wdev->wiphy->retry_long = olong; + } +- wiphy_unlock(&rdev->wiphy); + + return err; + } +@@ -587,9 +575,9 @@ static int cfg80211_wext_siwencode(struct net_device *dev, + struct iw_point *erq = &wrqu->encoding; + struct wireless_dev *wdev = dev->ieee80211_ptr; + struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy); +- int idx, err; +- bool remove = false; + struct key_params params; ++ bool remove = false; ++ int idx; + + if (wdev->iftype != NL80211_IFTYPE_STATION && + wdev->iftype != NL80211_IFTYPE_ADHOC) +@@ -601,11 +589,9 @@ static int cfg80211_wext_siwencode(struct net_device *dev, + !rdev->ops->set_default_key) + return -EOPNOTSUPP; + +- wiphy_lock(&rdev->wiphy); +- if (wdev->valid_links) { +- err = -EOPNOTSUPP; +- goto out; +- } ++ guard(wiphy)(&rdev->wiphy); ++ if (wdev->valid_links) ++ return -EOPNOTSUPP; + + idx = erq->flags & IW_ENCODE_INDEX; + if (idx == 0) { +@@ -613,8 +599,7 @@ static int cfg80211_wext_siwencode(struct net_device *dev, + if (idx < 0) + idx = 0; + } else if (idx < 1 || idx > 4) { +- err = -EINVAL; +- goto out; ++ return -EINVAL; + } else { + idx--; + } +@@ -623,7 +608,8 @@ static int cfg80211_wext_siwencode(struct net_device *dev, + remove = true; + else if (erq->length == 0) { + /* No key data - just set the default TX key index */ +- err = 0; ++ int err = 0; ++ + if (wdev->connected || + (wdev->iftype == NL80211_IFTYPE_ADHOC && + wdev->u.ibss.current_bss)) +@@ -631,28 +617,22 @@ static int cfg80211_wext_siwencode(struct net_device *dev, + true); + if (!err) + wdev->wext.default_key = idx; +- goto out; ++ return err; + } + + memset(¶ms, 0, sizeof(params)); + params.key = keybuf; + params.key_len = erq->length; +- if (erq->length == 5) { ++ if (erq->length == 5) + params.cipher = WLAN_CIPHER_SUITE_WEP40; +- } else if (erq->length == 13) { ++ else if (erq->length == 13) + params.cipher = WLAN_CIPHER_SUITE_WEP104; +- } else if (!remove) { +- err = -EINVAL; +- goto out; +- } +- +- err = cfg80211_set_encryption(rdev, dev, false, NULL, remove, +- wdev->wext.default_key == -1, +- idx, ¶ms); +-out: +- wiphy_unlock(&rdev->wiphy); ++ else if (!remove) ++ return -EINVAL; + +- return err; ++ return cfg80211_set_encryption(rdev, dev, false, NULL, remove, ++ wdev->wext.default_key == -1, ++ idx, ¶ms); + } + + static int cfg80211_wext_siwencodeext(struct net_device *dev, +@@ -668,7 +648,6 @@ static int cfg80211_wext_siwencodeext(struct net_device *dev, + bool remove = false; + struct key_params params; + u32 cipher; +- int ret; + + if (wdev->iftype != NL80211_IFTYPE_STATION && + wdev->iftype != NL80211_IFTYPE_ADHOC) +@@ -743,16 +722,13 @@ static int cfg80211_wext_siwencodeext(struct net_device *dev, + params.seq_len = 6; + } + +- wiphy_lock(wdev->wiphy); +- ret = cfg80211_set_encryption( +- rdev, dev, +- !(ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY), +- addr, remove, +- ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY, +- idx, ¶ms); +- wiphy_unlock(wdev->wiphy); ++ guard(wiphy)(wdev->wiphy); + +- return ret; ++ return cfg80211_set_encryption(rdev, dev, ++ !(ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY), ++ addr, remove, ++ ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY, ++ idx, ¶ms); + } + + static int cfg80211_wext_giwencode(struct net_device *dev, +@@ -803,61 +779,41 @@ static int cfg80211_wext_siwfreq(struct net_device *dev, + struct cfg80211_chan_def chandef = { + .width = NL80211_CHAN_WIDTH_20_NOHT, + }; +- int freq, ret; ++ int freq; + +- wiphy_lock(&rdev->wiphy); ++ guard(wiphy)(&rdev->wiphy); + + switch (wdev->iftype) { + case NL80211_IFTYPE_STATION: +- ret = cfg80211_mgd_wext_siwfreq(dev, info, wextfreq, extra); +- break; ++ return cfg80211_mgd_wext_siwfreq(dev, info, wextfreq, extra); + case NL80211_IFTYPE_ADHOC: +- ret = cfg80211_ibss_wext_siwfreq(dev, info, wextfreq, extra); +- break; ++ return cfg80211_ibss_wext_siwfreq(dev, info, wextfreq, extra); + case NL80211_IFTYPE_MONITOR: + freq = cfg80211_wext_freq(wextfreq); +- if (freq < 0) { +- ret = freq; +- break; +- } +- if (freq == 0) { +- ret = -EINVAL; +- break; +- } ++ if (freq < 0) ++ return freq; ++ if (freq == 0) ++ return -EINVAL; ++ + chandef.center_freq1 = freq; + chandef.chan = ieee80211_get_channel(&rdev->wiphy, freq); +- if (!chandef.chan) { +- ret = -EINVAL; +- break; +- } +- ret = cfg80211_set_monitor_channel(rdev, dev, &chandef); +- break; ++ if (!chandef.chan) ++ return -EINVAL; ++ return cfg80211_set_monitor_channel(rdev, dev, &chandef); + case NL80211_IFTYPE_MESH_POINT: + freq = cfg80211_wext_freq(wextfreq); +- if (freq < 0) { +- ret = freq; +- break; +- } +- if (freq == 0) { +- ret = -EINVAL; +- break; +- } ++ if (freq < 0) ++ return freq; ++ if (freq == 0) ++ return -EINVAL; + chandef.center_freq1 = freq; + chandef.chan = ieee80211_get_channel(&rdev->wiphy, freq); +- if (!chandef.chan) { +- ret = -EINVAL; +- break; +- } +- ret = cfg80211_set_mesh_channel(rdev, wdev, &chandef); +- break; ++ if (!chandef.chan) ++ return -EINVAL; ++ return cfg80211_set_mesh_channel(rdev, wdev, &chandef); + default: +- ret = -EOPNOTSUPP; +- break; ++ return -EOPNOTSUPP; + } +- +- wiphy_unlock(&rdev->wiphy); +- +- return ret; + } + + static int cfg80211_wext_giwfreq(struct net_device *dev, +@@ -870,35 +826,26 @@ static int cfg80211_wext_giwfreq(struct net_device *dev, + struct cfg80211_chan_def chandef = {}; + int ret; + +- wiphy_lock(&rdev->wiphy); ++ guard(wiphy)(&rdev->wiphy); ++ + switch (wdev->iftype) { + case NL80211_IFTYPE_STATION: +- ret = cfg80211_mgd_wext_giwfreq(dev, info, freq, extra); +- break; ++ return cfg80211_mgd_wext_giwfreq(dev, info, freq, extra); + case NL80211_IFTYPE_ADHOC: +- ret = cfg80211_ibss_wext_giwfreq(dev, info, freq, extra); +- break; ++ return cfg80211_ibss_wext_giwfreq(dev, info, freq, extra); + case NL80211_IFTYPE_MONITOR: +- if (!rdev->ops->get_channel) { +- ret = -EINVAL; +- break; +- } ++ if (!rdev->ops->get_channel) ++ return -EINVAL; + + ret = rdev_get_channel(rdev, wdev, 0, &chandef); + if (ret) +- break; ++ return ret; + freq->m = chandef.chan->center_freq; + freq->e = 6; +- ret = 0; +- break; ++ return ret; + default: +- ret = -EINVAL; +- break; ++ return -EINVAL; + } +- +- wiphy_unlock(&rdev->wiphy); +- +- return ret; + } + + static int cfg80211_wext_siwtxpower(struct net_device *dev, +@@ -909,7 +856,6 @@ static int cfg80211_wext_siwtxpower(struct net_device *dev, + struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy); + enum nl80211_tx_power_setting type; + int dbm = 0; +- int ret; + + if ((data->txpower.flags & IW_TXPOW_TYPE) != IW_TXPOW_DBM) + return -EINVAL; +@@ -951,11 +897,9 @@ static int cfg80211_wext_siwtxpower(struct net_device *dev, + return 0; + } + +- wiphy_lock(&rdev->wiphy); +- ret = rdev_set_tx_power(rdev, wdev, type, DBM_TO_MBM(dbm)); +- wiphy_unlock(&rdev->wiphy); ++ guard(wiphy)(&rdev->wiphy); + +- return ret; ++ return rdev_set_tx_power(rdev, wdev, type, DBM_TO_MBM(dbm)); + } + + static int cfg80211_wext_giwtxpower(struct net_device *dev, +@@ -974,9 +918,9 @@ static int cfg80211_wext_giwtxpower(struct net_device *dev, + if (!rdev->ops->get_tx_power) + return -EOPNOTSUPP; + +- wiphy_lock(&rdev->wiphy); +- err = rdev_get_tx_power(rdev, wdev, &val); +- wiphy_unlock(&rdev->wiphy); ++ scoped_guard(wiphy, &rdev->wiphy) { ++ err = rdev_get_tx_power(rdev, wdev, &val); ++ } + if (err) + return err; + +@@ -1218,9 +1162,9 @@ static int cfg80211_wext_siwpower(struct net_device *dev, + timeout = wrq->value / 1000; + } + +- wiphy_lock(&rdev->wiphy); ++ guard(wiphy)(&rdev->wiphy); ++ + err = rdev_set_power_mgmt(rdev, dev, ps, timeout); +- wiphy_unlock(&rdev->wiphy); + if (err) + return err; + +@@ -1253,8 +1197,8 @@ static int cfg80211_wext_siwrate(struct net_device *dev, + struct cfg80211_bitrate_mask mask; + u32 fixed, maxrate; + struct ieee80211_supported_band *sband; +- int band, ridx, ret; + bool match = false; ++ int band, ridx; + + if (!rdev->ops->set_bitrate_mask) + return -EOPNOTSUPP; +@@ -1292,14 +1236,12 @@ static int cfg80211_wext_siwrate(struct net_device *dev, + if (!match) + return -EINVAL; + +- wiphy_lock(&rdev->wiphy); +- if (dev->ieee80211_ptr->valid_links) +- ret = -EOPNOTSUPP; +- else +- ret = rdev_set_bitrate_mask(rdev, dev, 0, NULL, &mask); +- wiphy_unlock(&rdev->wiphy); ++ guard(wiphy)(&rdev->wiphy); + +- return ret; ++ if (dev->ieee80211_ptr->valid_links) ++ return -EOPNOTSUPP; ++ ++ return rdev_set_bitrate_mask(rdev, dev, 0, NULL, &mask); + } + + static int cfg80211_wext_giwrate(struct net_device *dev, +@@ -1328,9 +1270,9 @@ static int cfg80211_wext_giwrate(struct net_device *dev, + if (err) + return err; + +- wiphy_lock(&rdev->wiphy); +- err = rdev_get_station(rdev, dev, addr, &sinfo); +- wiphy_unlock(&rdev->wiphy); ++ scoped_guard(wiphy, &rdev->wiphy) { ++ err = rdev_get_station(rdev, dev, addr, &sinfo); ++ } + if (err) + return err; + +@@ -1429,23 +1371,17 @@ static int cfg80211_wext_siwap(struct net_device *dev, + struct sockaddr *ap_addr = &wrqu->ap_addr; + struct wireless_dev *wdev = dev->ieee80211_ptr; + struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy); +- int ret; + +- wiphy_lock(&rdev->wiphy); ++ guard(wiphy)(&rdev->wiphy); ++ + switch (wdev->iftype) { + case NL80211_IFTYPE_ADHOC: +- ret = cfg80211_ibss_wext_siwap(dev, info, ap_addr, extra); +- break; ++ return cfg80211_ibss_wext_siwap(dev, info, ap_addr, extra); + case NL80211_IFTYPE_STATION: +- ret = cfg80211_mgd_wext_siwap(dev, info, ap_addr, extra); +- break; ++ return cfg80211_mgd_wext_siwap(dev, info, ap_addr, extra); + default: +- ret = -EOPNOTSUPP; +- break; ++ return -EOPNOTSUPP; + } +- wiphy_unlock(&rdev->wiphy); +- +- return ret; + } + + static int cfg80211_wext_giwap(struct net_device *dev, +@@ -1455,23 +1391,17 @@ static int cfg80211_wext_giwap(struct net_device *dev, + struct sockaddr *ap_addr = &wrqu->ap_addr; + struct wireless_dev *wdev = dev->ieee80211_ptr; + struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy); +- int ret; + +- wiphy_lock(&rdev->wiphy); ++ guard(wiphy)(&rdev->wiphy); ++ + switch (wdev->iftype) { + case NL80211_IFTYPE_ADHOC: +- ret = cfg80211_ibss_wext_giwap(dev, info, ap_addr, extra); +- break; ++ return cfg80211_ibss_wext_giwap(dev, info, ap_addr, extra); + case NL80211_IFTYPE_STATION: +- ret = cfg80211_mgd_wext_giwap(dev, info, ap_addr, extra); +- break; ++ return cfg80211_mgd_wext_giwap(dev, info, ap_addr, extra); + default: +- ret = -EOPNOTSUPP; +- break; ++ return -EOPNOTSUPP; + } +- wiphy_unlock(&rdev->wiphy); +- +- return ret; + } + + static int cfg80211_wext_siwessid(struct net_device *dev, +@@ -1481,23 +1411,17 @@ static int cfg80211_wext_siwessid(struct net_device *dev, + struct iw_point *data = &wrqu->data; + struct wireless_dev *wdev = dev->ieee80211_ptr; + struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy); +- int ret; + +- wiphy_lock(&rdev->wiphy); ++ guard(wiphy)(&rdev->wiphy); ++ + switch (wdev->iftype) { + case NL80211_IFTYPE_ADHOC: +- ret = cfg80211_ibss_wext_siwessid(dev, info, data, ssid); +- break; ++ return cfg80211_ibss_wext_siwessid(dev, info, data, ssid); + case NL80211_IFTYPE_STATION: +- ret = cfg80211_mgd_wext_siwessid(dev, info, data, ssid); +- break; ++ return cfg80211_mgd_wext_siwessid(dev, info, data, ssid); + default: +- ret = -EOPNOTSUPP; +- break; ++ return -EOPNOTSUPP; + } +- wiphy_unlock(&rdev->wiphy); +- +- return ret; + } + + static int cfg80211_wext_giwessid(struct net_device *dev, +@@ -1507,26 +1431,20 @@ static int cfg80211_wext_giwessid(struct net_device *dev, + struct iw_point *data = &wrqu->data; + struct wireless_dev *wdev = dev->ieee80211_ptr; + struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy); +- int ret; + + data->flags = 0; + data->length = 0; + +- wiphy_lock(&rdev->wiphy); ++ guard(wiphy)(&rdev->wiphy); ++ + switch (wdev->iftype) { + case NL80211_IFTYPE_ADHOC: +- ret = cfg80211_ibss_wext_giwessid(dev, info, data, ssid); +- break; ++ return cfg80211_ibss_wext_giwessid(dev, info, data, ssid); + case NL80211_IFTYPE_STATION: +- ret = cfg80211_mgd_wext_giwessid(dev, info, data, ssid); +- break; ++ return cfg80211_mgd_wext_giwessid(dev, info, data, ssid); + default: +- ret = -EOPNOTSUPP; +- break; ++ return -EOPNOTSUPP; + } +- wiphy_unlock(&rdev->wiphy); +- +- return ret; + } + + static int cfg80211_wext_siwpmksa(struct net_device *dev, +@@ -1537,7 +1455,6 @@ static int cfg80211_wext_siwpmksa(struct net_device *dev, + struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy); + struct cfg80211_pmksa cfg_pmksa; + struct iw_pmksa *pmksa = (struct iw_pmksa *)extra; +- int ret; + + memset(&cfg_pmksa, 0, sizeof(struct cfg80211_pmksa)); + +@@ -1547,39 +1464,27 @@ static int cfg80211_wext_siwpmksa(struct net_device *dev, + cfg_pmksa.bssid = pmksa->bssid.sa_data; + cfg_pmksa.pmkid = pmksa->pmkid; + +- wiphy_lock(&rdev->wiphy); ++ guard(wiphy)(&rdev->wiphy); ++ + switch (pmksa->cmd) { + case IW_PMKSA_ADD: +- if (!rdev->ops->set_pmksa) { +- ret = -EOPNOTSUPP; +- break; +- } ++ if (!rdev->ops->set_pmksa) ++ return -EOPNOTSUPP; + +- ret = rdev_set_pmksa(rdev, dev, &cfg_pmksa); +- break; ++ return rdev_set_pmksa(rdev, dev, &cfg_pmksa); + case IW_PMKSA_REMOVE: +- if (!rdev->ops->del_pmksa) { +- ret = -EOPNOTSUPP; +- break; +- } ++ if (!rdev->ops->del_pmksa) ++ return -EOPNOTSUPP; + +- ret = rdev_del_pmksa(rdev, dev, &cfg_pmksa); +- break; ++ return rdev_del_pmksa(rdev, dev, &cfg_pmksa); + case IW_PMKSA_FLUSH: +- if (!rdev->ops->flush_pmksa) { +- ret = -EOPNOTSUPP; +- break; +- } ++ if (!rdev->ops->flush_pmksa) ++ return -EOPNOTSUPP; + +- ret = rdev_flush_pmksa(rdev, dev); +- break; ++ return rdev_flush_pmksa(rdev, dev); + default: +- ret = -EOPNOTSUPP; +- break; ++ return -EOPNOTSUPP; + } +- wiphy_unlock(&rdev->wiphy); +- +- return ret; + } + + static const iw_handler cfg80211_handlers[] = { +diff --git a/net/wireless/wext-sme.c b/net/wireless/wext-sme.c +index 8edd9ada69d0bd..573b6b15a446ec 100644 +--- a/net/wireless/wext-sme.c ++++ b/net/wireless/wext-sme.c +@@ -302,8 +302,8 @@ int cfg80211_wext_siwgenie(struct net_device *dev, + struct iw_point *data = &wrqu->data; + struct wireless_dev *wdev = dev->ieee80211_ptr; + struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy); ++ int ie_len = data->length; + u8 *ie = extra; +- int ie_len = data->length, err; + + if (wdev->iftype != NL80211_IFTYPE_STATION) + return -EOPNOTSUPP; +@@ -311,39 +311,31 @@ int cfg80211_wext_siwgenie(struct net_device *dev, + if (!ie_len) + ie = NULL; + +- wiphy_lock(wdev->wiphy); ++ guard(wiphy)(wdev->wiphy); + + /* no change */ +- err = 0; + if (wdev->wext.ie_len == ie_len && + memcmp(wdev->wext.ie, ie, ie_len) == 0) +- goto out; ++ return 0; + + if (ie_len) { + ie = kmemdup(extra, ie_len, GFP_KERNEL); +- if (!ie) { +- err = -ENOMEM; +- goto out; +- } +- } else ++ if (!ie) ++ return -ENOMEM; ++ } else { + ie = NULL; ++ } + + kfree(wdev->wext.ie); + wdev->wext.ie = ie; + wdev->wext.ie_len = ie_len; + +- if (wdev->conn) { +- err = cfg80211_disconnect(rdev, dev, +- WLAN_REASON_DEAUTH_LEAVING, false); +- if (err) +- goto out; +- } ++ if (wdev->conn) ++ return cfg80211_disconnect(rdev, dev, ++ WLAN_REASON_DEAUTH_LEAVING, false); + + /* userspace better not think we'll reconnect */ +- err = 0; +- out: +- wiphy_unlock(wdev->wiphy); +- return err; ++ return 0; + } + + int cfg80211_wext_siwmlme(struct net_device *dev, +@@ -353,7 +345,6 @@ int cfg80211_wext_siwmlme(struct net_device *dev, + struct wireless_dev *wdev = dev->ieee80211_ptr; + struct iw_mlme *mlme = (struct iw_mlme *)extra; + struct cfg80211_registered_device *rdev; +- int err; + + if (!wdev) + return -EOPNOTSUPP; +@@ -366,17 +357,13 @@ int cfg80211_wext_siwmlme(struct net_device *dev, + if (mlme->addr.sa_family != ARPHRD_ETHER) + return -EINVAL; + +- wiphy_lock(&rdev->wiphy); ++ guard(wiphy)(&rdev->wiphy); ++ + switch (mlme->cmd) { + case IW_MLME_DEAUTH: + case IW_MLME_DISASSOC: +- err = cfg80211_disconnect(rdev, dev, mlme->reason_code, true); +- break; ++ return cfg80211_disconnect(rdev, dev, mlme->reason_code, true); + default: +- err = -EOPNOTSUPP; +- break; ++ return -EOPNOTSUPP; + } +- wiphy_unlock(&rdev->wiphy); +- +- return err; + } +-- +2.53.0 + diff --git a/queue-6.12/wifi-cfg80211-derive-s1g-beacon-tsf-from-s1g-fields.patch b/queue-6.12/wifi-cfg80211-derive-s1g-beacon-tsf-from-s1g-fields.patch new file mode 100644 index 0000000000..682bfc9369 --- /dev/null +++ b/queue-6.12/wifi-cfg80211-derive-s1g-beacon-tsf-from-s1g-fields.patch @@ -0,0 +1,54 @@ +From 77c4f802d7206e268a3c4a60413fc39bea572390 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 12 Jun 2026 00:19:46 +0800 +Subject: wifi: cfg80211: derive S1G beacon TSF from S1G fields + +From: Zhao Li + +[ Upstream commit 4e5a4641e7b4763656336b7891d01359aaf363cd ] + +cfg80211_inform_bss_frame_data() parses S1G beacons with the extension +frame layout, but still reads the TSF from the regular probe response +layout after the S1G branch. For S1G beacons that reads bytes at the +regular management-frame timestamp offset instead of the S1G timestamp. + +Use the 32-bit S1G beacon timestamp and the S1G Beacon Compatibility +element's TSF completion field when informing an S1G BSS. Keep the +regular management-frame timestamp read in the non-S1G branch. + +Fixes: 9eaffe5078ca ("cfg80211: convert S1G beacon to scan results") +Signed-off-by: Zhao Li +Tested-by: Lachlan Hodges +Reviewed-by: Lachlan Hodges +Link: https://patch.msgid.link/20260611161943.91069-6-enderaoelyther@gmail.com +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + net/wireless/scan.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/net/wireless/scan.c b/net/wireless/scan.c +index 44973529687486..b249f29454f9e1 100644 +--- a/net/wireless/scan.c ++++ b/net/wireless/scan.c +@@ -3262,14 +3262,15 @@ cfg80211_inform_bss_frame_data(struct wiphy *wiphy, + bssid = ext->u.s1g_beacon.sa; + capability = le16_to_cpu(compat->compat_info); + beacon_interval = le16_to_cpu(compat->beacon_int); ++ tsf = le32_to_cpu(ext->u.s1g_beacon.timestamp); ++ tsf |= (u64)le32_to_cpu(compat->tsf_completion) << 32; + } else { + bssid = mgmt->bssid; + beacon_interval = le16_to_cpu(mgmt->u.probe_resp.beacon_int); + capability = le16_to_cpu(mgmt->u.probe_resp.capab_info); ++ tsf = le64_to_cpu(mgmt->u.probe_resp.timestamp); + } + +- tsf = le64_to_cpu(mgmt->u.probe_resp.timestamp); +- + if (ieee80211_is_probe_resp(mgmt->frame_control)) + ftype = CFG80211_BSS_FTYPE_PRESP; + else if (ext) +-- +2.53.0 + diff --git a/queue-6.12/wifi-cfg80211-pass-net_device-to-.set_monitor_channe.patch b/queue-6.12/wifi-cfg80211-pass-net_device-to-.set_monitor_channe.patch new file mode 100644 index 0000000000..aa34eccfda --- /dev/null +++ b/queue-6.12/wifi-cfg80211-pass-net_device-to-.set_monitor_channe.patch @@ -0,0 +1,211 @@ +From 841cf7964c622070e8551f0abfa6ecab2894361a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 9 Oct 2024 10:25:47 +0200 +Subject: wifi: cfg80211: pass net_device to .set_monitor_channel + +From: Felix Fietkau + +[ Upstream commit 9c4f830927750a2bf9fd9426a5257f0fdce3b662 ] + +Preparation for allowing multiple monitor interfaces with different channels +on a multi-radio wiphy. + +Signed-off-by: Felix Fietkau +Link: https://patch.msgid.link/35fa652dbfebf93343f8b9a08fdef0467a2a02dc.1728462320.git-series.nbd@nbd.name +Signed-off-by: Johannes Berg +Stable-dep-of: 2b0eab425e1f ("wifi: cfg80211: convert pmsr_free_wk to wiphy_work to fix deadlock") +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/wil6210/cfg80211.c | 1 + + drivers/net/wireless/marvell/libertas/cfg.c | 1 + + drivers/net/wireless/microchip/wilc1000/cfg80211.c | 3 ++- + include/net/cfg80211.h | 1 + + net/mac80211/cfg.c | 1 + + net/wireless/chan.c | 3 ++- + net/wireless/core.h | 1 + + net/wireless/nl80211.c | 2 +- + net/wireless/rdev-ops.h | 5 +++-- + net/wireless/trace.h | 10 ++++++---- + net/wireless/wext-compat.c | 2 +- + 11 files changed, 20 insertions(+), 10 deletions(-) + +diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c +index e8f1d30a8d73c5..a1a0a9223e74ac 100644 +--- a/drivers/net/wireless/ath/wil6210/cfg80211.c ++++ b/drivers/net/wireless/ath/wil6210/cfg80211.c +@@ -1493,6 +1493,7 @@ int wil_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, + } + + static int wil_cfg80211_set_channel(struct wiphy *wiphy, ++ struct net_device *dev, + struct cfg80211_chan_def *chandef) + { + struct wil6210_priv *wil = wiphy_to_wil(wiphy); +diff --git a/drivers/net/wireless/marvell/libertas/cfg.c b/drivers/net/wireless/marvell/libertas/cfg.c +index 37bb788f83e36e..309556541a83ed 100644 +--- a/drivers/net/wireless/marvell/libertas/cfg.c ++++ b/drivers/net/wireless/marvell/libertas/cfg.c +@@ -486,6 +486,7 @@ static int lbs_add_wps_enrollee_tlv(u8 *tlv, const u8 *ie, size_t ie_len) + */ + + static int lbs_cfg_set_monitor_channel(struct wiphy *wiphy, ++ struct net_device *dev, + struct cfg80211_chan_def *chandef) + { + struct lbs_private *priv = wiphy_priv(wiphy); +diff --git a/drivers/net/wireless/microchip/wilc1000/cfg80211.c b/drivers/net/wireless/microchip/wilc1000/cfg80211.c +index eb37b228d54ea0..9977be0020fe76 100644 +--- a/drivers/net/wireless/microchip/wilc1000/cfg80211.c ++++ b/drivers/net/wireless/microchip/wilc1000/cfg80211.c +@@ -231,6 +231,7 @@ struct wilc_vif *wilc_get_wl_to_vif(struct wilc *wl) + } + + static int set_channel(struct wiphy *wiphy, ++ struct net_device *dev, + struct cfg80211_chan_def *chandef) + { + struct wilc *wl = wiphy_priv(wiphy); +@@ -1424,7 +1425,7 @@ static int start_ap(struct wiphy *wiphy, struct net_device *dev, + struct wilc_vif *vif = netdev_priv(dev); + int ret; + +- ret = set_channel(wiphy, &settings->chandef); ++ ret = set_channel(wiphy, dev, &settings->chandef); + if (ret != 0) + netdev_err(dev, "Error in setting channel\n"); + +diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h +index 96121dc14e8263..f1710d7af6656b 100644 +--- a/include/net/cfg80211.h ++++ b/include/net/cfg80211.h +@@ -4699,6 +4699,7 @@ struct cfg80211_ops { + struct ieee80211_channel *chan); + + int (*set_monitor_channel)(struct wiphy *wiphy, ++ struct net_device *dev, + struct cfg80211_chan_def *chandef); + + int (*scan)(struct wiphy *wiphy, +diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c +index b9ed82b8321a6a..cfd02f48935450 100644 +--- a/net/mac80211/cfg.c ++++ b/net/mac80211/cfg.c +@@ -893,6 +893,7 @@ static int ieee80211_get_station(struct wiphy *wiphy, struct net_device *dev, + } + + static int ieee80211_set_monitor_channel(struct wiphy *wiphy, ++ struct net_device *dev, + struct cfg80211_chan_def *chandef) + { + struct ieee80211_local *local = wiphy_priv(wiphy); +diff --git a/net/wireless/chan.c b/net/wireless/chan.c +index c4f3fefeb35444..eb8826e33d1757 100644 +--- a/net/wireless/chan.c ++++ b/net/wireless/chan.c +@@ -1634,6 +1634,7 @@ bool cfg80211_reg_check_beaconing(struct wiphy *wiphy, + EXPORT_SYMBOL(cfg80211_reg_check_beaconing); + + int cfg80211_set_monitor_channel(struct cfg80211_registered_device *rdev, ++ struct net_device *dev, + struct cfg80211_chan_def *chandef) + { + if (!rdev->ops->set_monitor_channel) +@@ -1641,7 +1642,7 @@ int cfg80211_set_monitor_channel(struct cfg80211_registered_device *rdev, + if (!cfg80211_has_monitors_only(rdev)) + return -EBUSY; + +- return rdev_set_monitor_channel(rdev, chandef); ++ return rdev_set_monitor_channel(rdev, dev, chandef); + } + + bool cfg80211_any_usable_channels(struct wiphy *wiphy, +diff --git a/net/wireless/core.h b/net/wireless/core.h +index d4b26cbe3342d0..a60883b6e43105 100644 +--- a/net/wireless/core.h ++++ b/net/wireless/core.h +@@ -517,6 +517,7 @@ static inline unsigned int elapsed_jiffies_msecs(unsigned long start) + } + + int cfg80211_set_monitor_channel(struct cfg80211_registered_device *rdev, ++ struct net_device *dev, + struct cfg80211_chan_def *chandef); + + int ieee80211_get_ratemask(struct ieee80211_supported_band *sband, +diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c +index 15a8237f79bffa..90ff3ee8df6122 100644 +--- a/net/wireless/nl80211.c ++++ b/net/wireless/nl80211.c +@@ -3568,7 +3568,7 @@ static int __nl80211_set_channel(struct cfg80211_registered_device *rdev, + case NL80211_IFTYPE_MESH_POINT: + return cfg80211_set_mesh_channel(rdev, wdev, &chandef); + case NL80211_IFTYPE_MONITOR: +- return cfg80211_set_monitor_channel(rdev, &chandef); ++ return cfg80211_set_monitor_channel(rdev, dev, &chandef); + default: + break; + } +diff --git a/net/wireless/rdev-ops.h b/net/wireless/rdev-ops.h +index f5adbf6b5c846c..adb6105bbb7d1d 100644 +--- a/net/wireless/rdev-ops.h ++++ b/net/wireless/rdev-ops.h +@@ -445,11 +445,12 @@ rdev_libertas_set_mesh_channel(struct cfg80211_registered_device *rdev, + + static inline int + rdev_set_monitor_channel(struct cfg80211_registered_device *rdev, ++ struct net_device *dev, + struct cfg80211_chan_def *chandef) + { + int ret; +- trace_rdev_set_monitor_channel(&rdev->wiphy, chandef); +- ret = rdev->ops->set_monitor_channel(&rdev->wiphy, chandef); ++ trace_rdev_set_monitor_channel(&rdev->wiphy, dev, chandef); ++ ret = rdev->ops->set_monitor_channel(&rdev->wiphy, dev, chandef); + trace_rdev_return_int(&rdev->wiphy, ret); + return ret; + } +diff --git a/net/wireless/trace.h b/net/wireless/trace.h +index 945013185c9860..68bbf3a778ce1f 100644 +--- a/net/wireless/trace.h ++++ b/net/wireless/trace.h +@@ -1339,19 +1339,21 @@ TRACE_EVENT(rdev_libertas_set_mesh_channel, + ); + + TRACE_EVENT(rdev_set_monitor_channel, +- TP_PROTO(struct wiphy *wiphy, ++ TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, + struct cfg80211_chan_def *chandef), +- TP_ARGS(wiphy, chandef), ++ TP_ARGS(wiphy, netdev, chandef), + TP_STRUCT__entry( + WIPHY_ENTRY ++ NETDEV_ENTRY + CHAN_DEF_ENTRY + ), + TP_fast_assign( + WIPHY_ASSIGN; ++ NETDEV_ASSIGN; + CHAN_DEF_ASSIGN(chandef); + ), +- TP_printk(WIPHY_PR_FMT ", " CHAN_DEF_PR_FMT, +- WIPHY_PR_ARG, CHAN_DEF_PR_ARG) ++ TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", " CHAN_DEF_PR_FMT, ++ WIPHY_PR_ARG, NETDEV_PR_ARG, CHAN_DEF_PR_ARG) + ); + + TRACE_EVENT(rdev_auth, +diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c +index 3af11dae0942ae..32a695c8a4d2af 100644 +--- a/net/wireless/wext-compat.c ++++ b/net/wireless/wext-compat.c +@@ -830,7 +830,7 @@ static int cfg80211_wext_siwfreq(struct net_device *dev, + ret = -EINVAL; + break; + } +- ret = cfg80211_set_monitor_channel(rdev, &chandef); ++ ret = cfg80211_set_monitor_channel(rdev, dev, &chandef); + break; + case NL80211_IFTYPE_MESH_POINT: + freq = cfg80211_wext_freq(wextfreq); +-- +2.53.0 + diff --git a/queue-6.12/wifi-cfg80211-reject-unsupported-pmsr-ftm-location-r.patch b/queue-6.12/wifi-cfg80211-reject-unsupported-pmsr-ftm-location-r.patch new file mode 100644 index 0000000000..565a08cf68 --- /dev/null +++ b/queue-6.12/wifi-cfg80211-reject-unsupported-pmsr-ftm-location-r.patch @@ -0,0 +1,50 @@ +From 8108710b4cb9784576e07a25b79a29681c193c2b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 12 Jun 2026 21:37:11 +0800 +Subject: wifi: cfg80211: reject unsupported PMSR FTM location requests + +From: Zhao Li + +[ Upstream commit 69ef6a7ec277f16d216be8da2b3cbe872786c999 ] + +PMSR FTM location request flags are syntactically valid, but they must +be rejected when the device capability does not advertise support for +them. + +Return an error immediately after rejecting unsupported LCI or civic +location request bits so the request cannot reach the driver. + +Fixes: 9bb7e0f24e7e7 ("cfg80211: add peer measurement with FTM initiator API") +Assisted-by: Codex:gpt-5.5 +Assisted-by: Claude:claude-opus-4.8 +Signed-off-by: Zhao Li +Link: https://patch.msgid.link/20260612133710.93544-2-enderaoelyther@gmail.com +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + net/wireless/pmsr.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/net/wireless/pmsr.c b/net/wireless/pmsr.c +index fd14a3c2eab45b..06563f60848705 100644 +--- a/net/wireless/pmsr.c ++++ b/net/wireless/pmsr.c +@@ -114,6 +114,7 @@ static int pmsr_parse_ftm(struct cfg80211_registered_device *rdev, + NL_SET_ERR_MSG_ATTR(info->extack, + tb[NL80211_PMSR_FTM_REQ_ATTR_REQUEST_LCI], + "FTM: LCI request not supported"); ++ return -EOPNOTSUPP; + } + + out->ftm.request_civicloc = +@@ -122,6 +123,7 @@ static int pmsr_parse_ftm(struct cfg80211_registered_device *rdev, + NL_SET_ERR_MSG_ATTR(info->extack, + tb[NL80211_PMSR_FTM_REQ_ATTR_REQUEST_CIVICLOC], + "FTM: civic location request not supported"); ++ return -EOPNOTSUPP; + } + + out->ftm.trigger_based = +-- +2.53.0 + diff --git a/queue-6.12/wifi-cfg80211-validate-pmsr-ftm-preamble-range.patch b/queue-6.12/wifi-cfg80211-validate-pmsr-ftm-preamble-range.patch new file mode 100644 index 0000000000..fd6ded1341 --- /dev/null +++ b/queue-6.12/wifi-cfg80211-validate-pmsr-ftm-preamble-range.patch @@ -0,0 +1,45 @@ +From c40f1be27715d634efd6c7a93b2631c35e68e2e8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 12 Jun 2026 21:37:04 +0800 +Subject: wifi: cfg80211: validate PMSR FTM preamble range + +From: Zhao Li + +[ Upstream commit 36230936468f0ba4930e94aef496fc229d4bb951 ] + +PMSR FTM request parsing accepts preamble values outside the +enumerated nl80211 preamble range. + +Reject out-of-range values before using them in the parser capability +bit test using the policy. + +Fixes: 9bb7e0f24e7e7 ("cfg80211: add peer measurement with FTM initiator API") +Assisted-by: Codex:gpt-5.5 +Assisted-by: Claude:claude-opus-4.8 +Signed-off-by: Zhao Li +Link: https://patch.msgid.link/20260612133703.93274-2-enderaoelyther@gmail.com +[drop unnecessary check] +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + net/wireless/nl80211.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c +index 1702616d9e1c9a..b54da0f83247a9 100644 +--- a/net/wireless/nl80211.c ++++ b/net/wireless/nl80211.c +@@ -312,7 +312,9 @@ nl80211_ftm_responder_policy[NL80211_FTM_RESP_ATTR_MAX + 1] = { + static const struct nla_policy + nl80211_pmsr_ftm_req_attr_policy[NL80211_PMSR_FTM_REQ_ATTR_MAX + 1] = { + [NL80211_PMSR_FTM_REQ_ATTR_ASAP] = { .type = NLA_FLAG }, +- [NL80211_PMSR_FTM_REQ_ATTR_PREAMBLE] = { .type = NLA_U32 }, ++ [NL80211_PMSR_FTM_REQ_ATTR_PREAMBLE] = ++ NLA_POLICY_RANGE(NLA_U32, NL80211_PREAMBLE_LEGACY, ++ NL80211_PREAMBLE_HE), + [NL80211_PMSR_FTM_REQ_ATTR_NUM_BURSTS_EXP] = + NLA_POLICY_MAX(NLA_U8, 15), + [NL80211_PMSR_FTM_REQ_ATTR_BURST_PERIOD] = { .type = NLA_U16 }, +-- +2.53.0 + diff --git a/queue-6.12/wifi-cfg80211-validate-pmsr-measurement-type-data.patch b/queue-6.12/wifi-cfg80211-validate-pmsr-measurement-type-data.patch new file mode 100644 index 0000000000..74f5388236 --- /dev/null +++ b/queue-6.12/wifi-cfg80211-validate-pmsr-measurement-type-data.patch @@ -0,0 +1,76 @@ +From 20f0e3de3b8083932eb9d49686ba02caec4c5032 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 12 Jun 2026 21:36:57 +0800 +Subject: wifi: cfg80211: validate PMSR measurement type data + +From: Zhao Li + +[ Upstream commit 41aa973eb05922848dded26875c55ef982ac1c49 ] + +PMSR request parsing accepts missing or duplicated measurement type +entries in NL80211_PMSR_REQ_ATTR_DATA. + +Track whether one measurement type was already provided, reject a +second one immediately, and return an error if the request data block +contains no measurement type at all. + +Fixes: 9bb7e0f24e7e7 ("cfg80211: add peer measurement with FTM initiator API") +Assisted-by: Codex:gpt-5.5 +Assisted-by: Claude:claude-opus-4.8 +Signed-off-by: Zhao Li +Link: https://patch.msgid.link/20260612133656.92900-2-enderaoelyther@gmail.com +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + net/wireless/pmsr.c | 19 +++++++++++++++++-- + 1 file changed, 17 insertions(+), 2 deletions(-) + +diff --git a/net/wireless/pmsr.c b/net/wireless/pmsr.c +index d2546c27879fa4..fd14a3c2eab45b 100644 +--- a/net/wireless/pmsr.c ++++ b/net/wireless/pmsr.c +@@ -196,6 +196,7 @@ static int pmsr_parse_peer(struct cfg80211_registered_device *rdev, + { + struct nlattr *tb[NL80211_PMSR_PEER_ATTR_MAX + 1]; + struct nlattr *req[NL80211_PMSR_REQ_ATTR_MAX + 1]; ++ bool have_measurement_type = false; + struct nlattr *treq; + int err, rem; + +@@ -248,6 +249,14 @@ static int pmsr_parse_peer(struct cfg80211_registered_device *rdev, + } + + nla_for_each_nested(treq, req[NL80211_PMSR_REQ_ATTR_DATA], rem) { ++ if (have_measurement_type) { ++ NL_SET_ERR_MSG_ATTR(info->extack, treq, ++ "multiple measurement types in request data"); ++ return -EINVAL; ++ } ++ ++ have_measurement_type = true; ++ + switch (nla_type(treq)) { + case NL80211_PMSR_TYPE_FTM: + err = pmsr_parse_ftm(rdev, treq, out, info); +@@ -257,10 +266,16 @@ static int pmsr_parse_peer(struct cfg80211_registered_device *rdev, + "unsupported measurement type"); + err = -EINVAL; + } ++ if (err) ++ return err; + } + +- if (err) +- return err; ++ if (!have_measurement_type) { ++ NL_SET_ERR_MSG_ATTR(info->extack, ++ req[NL80211_PMSR_REQ_ATTR_DATA], ++ "missing measurement type in request data"); ++ return -EINVAL; ++ } + + return 0; + } +-- +2.53.0 + diff --git a/queue-6.12/wifi-ipw2100-fix-potential-memory-leak-in-ipw2100_pc.patch b/queue-6.12/wifi-ipw2100-fix-potential-memory-leak-in-ipw2100_pc.patch new file mode 100644 index 0000000000..1c10ec9209 --- /dev/null +++ b/queue-6.12/wifi-ipw2100-fix-potential-memory-leak-in-ipw2100_pc.patch @@ -0,0 +1,60 @@ +From 2a3d00838a25c50bf592d82cd625a821fe2d8813 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 20 Jun 2026 12:22:39 +0530 +Subject: wifi: ipw2100: fix potential memory leak in ipw2100_pci_init_one() + +From: Abdun Nihaal + +[ Upstream commit 0d388f62031dbabcba0f44bb91b59f10e88cac17 ] + +The memory allocated in the ipw2100_alloc_device() function is not freed +in some of the error paths in ipw2100_pci_init_one(). Fix that by +converting the direct return into a goto to the error path return. + +The error path when pci_enable_device() fails cannot jump to fail, since +at this point priv is not set, so perform error handling inline. + +Fixes: 2c86c275015c ("Add ipw2100 wireless driver.") +Signed-off-by: Abdun Nihaal +Link: https://patch.msgid.link/20260620065242.93798-1-nihaal@cse.iitm.ac.in +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/intel/ipw2x00/ipw2100.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/drivers/net/wireless/intel/ipw2x00/ipw2100.c b/drivers/net/wireless/intel/ipw2x00/ipw2100.c +index fe75941c584d15..95778dfdfa6d81 100644 +--- a/drivers/net/wireless/intel/ipw2x00/ipw2100.c ++++ b/drivers/net/wireless/intel/ipw2x00/ipw2100.c +@@ -6167,6 +6167,8 @@ static int ipw2100_pci_init_one(struct pci_dev *pci_dev, + if (err) { + printk(KERN_WARNING DRV_NAME + "Error calling pci_enable_device.\n"); ++ free_libipw(dev, 0); ++ pci_iounmap(pci_dev, ioaddr); + return err; + } + +@@ -6179,16 +6181,14 @@ static int ipw2100_pci_init_one(struct pci_dev *pci_dev, + if (err) { + printk(KERN_WARNING DRV_NAME + "Error calling pci_set_dma_mask.\n"); +- pci_disable_device(pci_dev); +- return err; ++ goto fail; + } + + err = pci_request_regions(pci_dev, DRV_NAME); + if (err) { + printk(KERN_WARNING DRV_NAME + "Error calling pci_request_regions.\n"); +- pci_disable_device(pci_dev); +- return err; ++ goto fail; + } + + /* We disable the RETRY_TIMEOUT register (0x41) to keep +-- +2.53.0 + diff --git a/queue-6.12/wifi-libertas-fix-memory-leak-in-helper_firmware_cb.patch b/queue-6.12/wifi-libertas-fix-memory-leak-in-helper_firmware_cb.patch new file mode 100644 index 0000000000..bca6c728e1 --- /dev/null +++ b/queue-6.12/wifi-libertas-fix-memory-leak-in-helper_firmware_cb.patch @@ -0,0 +1,50 @@ +From a75d4833af94b0f61887c16fdc03daf006485c6f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 24 Jun 2026 16:53:43 +0800 +Subject: wifi: libertas: fix memory leak in helper_firmware_cb() + +From: Dawei Feng + +[ Upstream commit 63c2391deefb31e1b801b7f32bd502ca4808639b ] + +helper_firmware_cb() neglects to free the single-stage firmware image +after a successful async load, leading to a memory leak in the USB +firmware-download path. + +Fix this memory leak by calling release_firmware() immediately after +lbs_fw_loaded() returns. + +The bug was first flagged by an experimental analysis tool we are +developing for kernel memory-management bugs while analyzing +v6.13-rc1. The tool is still under development and is not yet publicly +available. Manual inspection confirms that the bug is still present in +the current wireless tree. + +An x86_64 allyesconfig build showed no new warnings. As we do not have +compatible Libertas USB hardware for exercising this firmware-download +path, no runtime testing was able to be performed. + +Fixes: 1dfba3060fe7 ("libertas: move firmware lifetime handling to firmware.c") +Signed-off-by: Dawei Feng +Link: https://patch.msgid.link/20260624085343.575508-1-dawei.feng@seu.edu.cn +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/marvell/libertas/firmware.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/net/wireless/marvell/libertas/firmware.c b/drivers/net/wireless/marvell/libertas/firmware.c +index f124110944b7e9..9bf7d4c207b9ed 100644 +--- a/drivers/net/wireless/marvell/libertas/firmware.c ++++ b/drivers/net/wireless/marvell/libertas/firmware.c +@@ -78,6 +78,7 @@ static void helper_firmware_cb(const struct firmware *firmware, void *context) + } else { + /* No main firmware needed for this helper --> success! */ + lbs_fw_loaded(priv, 0, firmware, NULL); ++ release_firmware(firmware); + } + } + +-- +2.53.0 + diff --git a/queue-6.12/wifi-mac80211-fix-fils_discovery-double-free-on-allo.patch b/queue-6.12/wifi-mac80211-fix-fils_discovery-double-free-on-allo.patch new file mode 100644 index 0000000000..c17fefd23e --- /dev/null +++ b/queue-6.12/wifi-mac80211-fix-fils_discovery-double-free-on-allo.patch @@ -0,0 +1,66 @@ +From da55bbb6a3d87f3650ef5f3a6c5854afa4b665b8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 21 Jun 2026 02:35:32 -0700 +Subject: wifi: mac80211: fix fils_discovery double free on alloc failure + +From: Xiang Mei + +[ Upstream commit 286e52a799fa158bdbd77da1426c4d93f9a6e7ad ] + +ieee80211_set_fils_discovery() calls kfree_rcu() on the old template +before allocating the replacement. If the kzalloc() then fails, it +returns -ENOMEM while link->u.ap.fils_discovery still points at the +object already queued for freeing. A later update or AP teardown +(ieee80211_stop_ap()) re-queues that same rcu_head; the second free is +caught by KASAN when the RCU sheaf is processed in softirq: + + BUG: KASAN: double-free in rcu_free_sheaf (mm/slub.c:5850) + Free of addr ffff88800c065280 by task swapper/0/0 + ... + __rcu_free_sheaf_prepare (mm/slub.c:2634 mm/slub.c:2940) + rcu_free_sheaf (mm/slub.c:5850) + rcu_core (kernel/rcu/tree.c:2617 kernel/rcu/tree.c:2869) + handle_softirqs (kernel/softirq.c:622) + The buggy address belongs to the cache kmalloc-96 of size 96 + +Queue the old object for kfree_rcu() only after the new one is published, +matching ieee80211_set_probe_resp() and ieee80211_set_s1g_short_beacon(). + +Fixes: 3b1c256eb4ae ("wifi: mac80211: fixes in FILS discovery updates") +Reported-by: Weiming Shi +Assisted-by: Claude:claude-opus-4-8 +Signed-off-by: Xiang Mei +Link: https://patch.msgid.link/20260621093532.884188-2-xmei5@asu.edu +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + net/mac80211/cfg.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c +index 981f316df9cd9e..b9ed82b8321a6a 100644 +--- a/net/mac80211/cfg.c ++++ b/net/mac80211/cfg.c +@@ -977,9 +977,6 @@ static int ieee80211_set_fils_discovery(struct ieee80211_sub_if_data *sdata, + fd->max_interval = params->max_interval; + + old = sdata_dereference(link->u.ap.fils_discovery, sdata); +- if (old) +- kfree_rcu(old, rcu_head); +- + if (params->tmpl && params->tmpl_len) { + new = kzalloc(sizeof(*new) + params->tmpl_len, GFP_KERNEL); + if (!new) +@@ -991,6 +988,9 @@ static int ieee80211_set_fils_discovery(struct ieee80211_sub_if_data *sdata, + RCU_INIT_POINTER(link->u.ap.fils_discovery, NULL); + } + ++ if (old) ++ kfree_rcu(old, rcu_head); ++ + *changed |= BSS_CHANGED_FILS_DISCOVERY; + return 0; + } +-- +2.53.0 + diff --git a/queue-6.12/wifi-mac80211-fix-unsol_bcast_probe_resp-double-free.patch b/queue-6.12/wifi-mac80211-fix-unsol_bcast_probe_resp-double-free.patch new file mode 100644 index 0000000000..337cb591ad --- /dev/null +++ b/queue-6.12/wifi-mac80211-fix-unsol_bcast_probe_resp-double-free.patch @@ -0,0 +1,66 @@ +From c05ecc94382d54b996553be55a70fc3975616dfc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 21 Jun 2026 02:35:31 -0700 +Subject: wifi: mac80211: fix unsol_bcast_probe_resp double free on alloc + failure + +From: Xiang Mei + +[ Upstream commit 1d067abcd37062426c59ec73dbc4e87a63f33fea ] + +ieee80211_set_unsol_bcast_probe_resp() calls kfree_rcu() on the old +template before allocating the replacement. If the kzalloc() then fails, +it returns -ENOMEM while link->u.ap.unsol_bcast_probe_resp still points +at the object already queued for freeing. A later update or AP teardown +re-queues that same rcu_head; the second free is caught by KASAN when the +RCU sheaf is processed in softirq: + + BUG: KASAN: double-free in rcu_free_sheaf (mm/slub.c:5850) + Free of addr ffff88800d06f300 by task exploit/145 + ... + __rcu_free_sheaf_prepare (mm/slub.c:2634 mm/slub.c:2940) + rcu_free_sheaf (mm/slub.c:5850) + rcu_core (kernel/rcu/tree.c:2617 kernel/rcu/tree.c:2869) + handle_softirqs (kernel/softirq.c:622) + The buggy address belongs to the cache kmalloc-128 of size 128 + +Queue the old object for kfree_rcu() only after the new one is published, +matching ieee80211_set_probe_resp() and ieee80211_set_s1g_short_beacon(). + +Fixes: 3b1c256eb4ae ("wifi: mac80211: fixes in FILS discovery updates") +Reported-by: Weiming Shi +Assisted-by: Claude:claude-opus-4-8 +Signed-off-by: Xiang Mei +Link: https://patch.msgid.link/20260621093532.884188-1-xmei5@asu.edu +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + net/mac80211/cfg.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c +index 0abb687fd58d5c..981f316df9cd9e 100644 +--- a/net/mac80211/cfg.c ++++ b/net/mac80211/cfg.c +@@ -1010,8 +1010,6 @@ ieee80211_set_unsol_bcast_probe_resp(struct ieee80211_sub_if_data *sdata, + link_conf->unsol_bcast_probe_resp_interval = params->interval; + + old = sdata_dereference(link->u.ap.unsol_bcast_probe_resp, sdata); +- if (old) +- kfree_rcu(old, rcu_head); + + if (params->tmpl && params->tmpl_len) { + new = kzalloc(sizeof(*new) + params->tmpl_len, GFP_KERNEL); +@@ -1024,6 +1022,9 @@ ieee80211_set_unsol_bcast_probe_resp(struct ieee80211_sub_if_data *sdata, + RCU_INIT_POINTER(link->u.ap.unsol_bcast_probe_resp, NULL); + } + ++ if (old) ++ kfree_rcu(old, rcu_head); ++ + *changed |= BSS_CHANGED_UNSOL_BCAST_PROBE_RESP; + return 0; + } +-- +2.53.0 + diff --git a/queue-6.12/wifi-mac80211-free-ap_vlan-bc_buf-skbs-outside-irq-l.patch b/queue-6.12/wifi-mac80211-free-ap_vlan-bc_buf-skbs-outside-irq-l.patch new file mode 100644 index 0000000000..8f9b3607d3 --- /dev/null +++ b/queue-6.12/wifi-mac80211-free-ap_vlan-bc_buf-skbs-outside-irq-l.patch @@ -0,0 +1,77 @@ +From aced6dcd068d212ed15eaba321b2e7527cd0e325 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 6 Jul 2026 22:08:41 +0800 +Subject: wifi: mac80211: free AP_VLAN bc_buf SKBs outside IRQ lock + +From: Cen Zhang + +[ Upstream commit f3858d5b1432098c1936e03d6e03dd0e33facf60 ] + +ieee80211_do_stop() removes AP_VLAN packets from the parent AP +ps->bc_buf while holding ps->bc_buf.lock with IRQs disabled. It then +calls ieee80211_free_txskb() before dropping the lock. + +ieee80211_free_txskb() is not just a passive SKB release. For SKBs with +TX status state it can report a dropped frame through cfg80211/nl80211, +and that path can reach netlink tap transmit. This is the same reason +the pending queue cleanup in ieee80211_do_stop() already unlinks SKBs +under the queue lock and frees them after IRQ state is restored. + +The buggy scenario involves two paths, with each column showing the +order within that path: + +AP_VLAN management TX: AP_VLAN stop: +1. attach ACK-status state 1. clear the running state +2. queue a multicast SKB on 2. take ps->bc_buf.lock with IRQs + parent ps->bc_buf disabled + 3. unlink the AP_VLAN SKB + 4. call ieee80211_free_txskb() + +Unlink matching AP_VLAN SKBs from ps->bc_buf under the existing lock, +but move them to a local free queue. Drop the lock and restore IRQ state +before calling ieee80211_free_txskb(). + +WARNING: kernel/softirq.c:430 at __local_bh_enable_ip + +Fixes: 397a7a24ef8c ("mac80211: free ps->bc_buf skbs on vlan device stop") +Assisted-by: Codex:gpt-5.5 +Signed-off-by: Cen Zhang +Link: https://patch.msgid.link/20260706140841.581566-1-zzzccc427@gmail.com +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + net/mac80211/iface.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c +index 7e1b6a9d9f3ad8..7a79b40d23b36b 100644 +--- a/net/mac80211/iface.c ++++ b/net/mac80211/iface.c +@@ -590,6 +590,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, bool going_do + WARN_ON(!list_empty(&sdata->u.ap.vlans)); + } else if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) { + /* remove all packets in parent bc_buf pointing to this dev */ ++ __skb_queue_head_init(&freeq); + ps = &sdata->bss->ps; + + spin_lock_irqsave(&ps->bc_buf.lock, flags); +@@ -597,10 +598,15 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, bool going_do + if (skb->dev == sdata->dev) { + __skb_unlink(skb, &ps->bc_buf); + local->total_ps_buffered--; +- ieee80211_free_txskb(&local->hw, skb); ++ __skb_queue_tail(&freeq, skb); + } + } + spin_unlock_irqrestore(&ps->bc_buf.lock, flags); ++ ++ skb_queue_walk_safe(&freeq, skb, tmp) { ++ __skb_unlink(skb, &freeq); ++ ieee80211_free_txskb(&local->hw, skb); ++ } + } + + if (going_down) +-- +2.53.0 + diff --git a/queue-6.12/wifi-mac80211_hwsim-clamp-virtio-rx-length-before-sk.patch b/queue-6.12/wifi-mac80211_hwsim-clamp-virtio-rx-length-before-sk.patch new file mode 100644 index 0000000000..7145c940ca --- /dev/null +++ b/queue-6.12/wifi-mac80211_hwsim-clamp-virtio-rx-length-before-sk.patch @@ -0,0 +1,46 @@ +From 8eeca5782fb027401d74da3039e2060f7d83190b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 20 Jun 2026 21:45:18 -0500 +Subject: wifi: mac80211_hwsim: clamp virtio RX length before skb_put + +From: Bryam Vargas + +[ Upstream commit 10a2b430f8f06ae14b9590b6f6faa6b588ef0654 ] + +hwsim_virtio_rx_work() passes the virtqueue used-ring length reported by +the device straight to skb_put() on a fixed-size receive skb. A backend +reporting a length larger than the skb tailroom drives skb_put() past the +buffer end and hits skb_over_panic() -- a host-triggerable guest panic +(denial of service). + +Clamp the length to the skb's available room before skb_put(). A +conforming device never reports more than the posted buffer size, so valid +frames are unaffected; a truncated over-report then fails the +length/header checks in hwsim_virtio_handle_cmd() and is dropped, so +truncating rather than dropping here cannot be turned into a parsing +problem. + +Fixes: 5d44fe7c9808 ("mac80211_hwsim: add frame transmission support over virtio") +Signed-off-by: Bryam Vargas +Link: https://patch.msgid.link/20260620-b4-disp-474bee37-v1-1-1a4d37f3e2d4@proton.me +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/virtual/mac80211_hwsim.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/net/wireless/virtual/mac80211_hwsim.c b/drivers/net/wireless/virtual/mac80211_hwsim.c +index e992e59b591892..63fae67c816225 100644 +--- a/drivers/net/wireless/virtual/mac80211_hwsim.c ++++ b/drivers/net/wireless/virtual/mac80211_hwsim.c +@@ -6605,6 +6605,7 @@ static void hwsim_virtio_rx_work(struct work_struct *work) + + skb->data = skb->head; + skb_reset_tail_pointer(skb); ++ len = min(len, skb_end_offset(skb)); + skb_put(skb, len); + hwsim_virtio_handle_cmd(skb); + +-- +2.53.0 + diff --git a/queue-6.12/wifi-nl80211-free-rnr-data-on-mbssid-mismatch.patch b/queue-6.12/wifi-nl80211-free-rnr-data-on-mbssid-mismatch.patch new file mode 100644 index 0000000000..2da71502f6 --- /dev/null +++ b/queue-6.12/wifi-nl80211-free-rnr-data-on-mbssid-mismatch.patch @@ -0,0 +1,43 @@ +From ff4e822f3898e1175f5a465c21d683066c6af39c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 10 Jun 2026 19:22:09 +0800 +Subject: wifi: nl80211: free RNR data on MBSSID mismatch + +From: Zhao Li + +[ Upstream commit 07a95ec2b54774201fdf4ef7ffb0ca2ab19ed29c ] + +nl80211_parse_beacon() rejects EMA RNR data when there are fewer RNR +entries than MBSSID entries. + +The rejected RNR allocation has not been attached to the beacon data yet, +so free it before returning the error. + +Fixes: dbbb27e183b1 ("cfg80211: support RNR for EMA AP") +Signed-off-by: Zhao Li +Link: https://patch.msgid.link/20260610112208.1308-2-enderaoelyther@gmail.com +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + net/wireless/nl80211.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c +index 0af78812e38efe..60e00a24bc249a 100644 +--- a/net/wireless/nl80211.c ++++ b/net/wireless/nl80211.c +@@ -5711,8 +5711,10 @@ static int nl80211_parse_beacon(struct cfg80211_registered_device *rdev, + if (IS_ERR(rnr)) + return PTR_ERR(rnr); + +- if (rnr && rnr->cnt < bcn->mbssid_ies->cnt) ++ if (rnr && rnr->cnt < bcn->mbssid_ies->cnt) { ++ kfree(rnr); + return -EINVAL; ++ } + + bcn->rnr_ies = rnr; + } +-- +2.53.0 + diff --git a/queue-6.12/wifi-nl80211-validate-nested-mbssid-ie-blobs.patch b/queue-6.12/wifi-nl80211-validate-nested-mbssid-ie-blobs.patch new file mode 100644 index 0000000000..24106cb139 --- /dev/null +++ b/queue-6.12/wifi-nl80211-validate-nested-mbssid-ie-blobs.patch @@ -0,0 +1,67 @@ +From e2df574aac651b9f169d1a42b43cfa4160145509 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 12 Jun 2026 21:18:55 +0800 +Subject: wifi: nl80211: validate nested MBSSID IE blobs + +From: Zhao Li + +[ Upstream commit 7f4b01812323443b55e4c65381c9dc851ff009e3 ] + +Validate each nested NL80211_ATTR_MBSSID_ELEMS entry as a well-formed +information-element stream before storing it for beacon construction. + +RNR parsing already validates each nested blob with validate_ie_attr() +before storing it. Apply the same syntactic IE validation to MBSSID +entries before counting and copying their data and length pointers. + +Fixes: dc1e3cb8da8b ("nl80211: MBSSID and EMA support in AP mode") +Assisted-by: Codex:gpt-5.5 +Assisted-by: Claude:claude-opus-4.8 +Signed-off-by: Zhao Li +Link: https://patch.msgid.link/20260612131854.43575-3-enderaoelyther@gmail.com +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + net/wireless/nl80211.c | 12 ++++++++++-- + 1 file changed, 10 insertions(+), 2 deletions(-) + +diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c +index 60e00a24bc249a..1702616d9e1c9a 100644 +--- a/net/wireless/nl80211.c ++++ b/net/wireless/nl80211.c +@@ -5513,7 +5513,8 @@ static int nl80211_parse_mbssid_config(struct wiphy *wiphy, + } + + static struct cfg80211_mbssid_elems * +-nl80211_parse_mbssid_elems(struct wiphy *wiphy, struct nlattr *attrs) ++nl80211_parse_mbssid_elems(struct wiphy *wiphy, struct nlattr *attrs, ++ struct netlink_ext_ack *extack) + { + struct nlattr *nl_elems; + struct cfg80211_mbssid_elems *elems; +@@ -5524,6 +5525,12 @@ nl80211_parse_mbssid_elems(struct wiphy *wiphy, struct nlattr *attrs) + return ERR_PTR(-EINVAL); + + nla_for_each_nested(nl_elems, attrs, rem_elems) { ++ int ret; ++ ++ ret = validate_ie_attr(nl_elems, extack); ++ if (ret) ++ return ERR_PTR(ret); ++ + if (num_elems >= 255) + return ERR_PTR(-EINVAL); + num_elems++; +@@ -5695,7 +5702,8 @@ static int nl80211_parse_beacon(struct cfg80211_registered_device *rdev, + if (attrs[NL80211_ATTR_MBSSID_ELEMS]) { + struct cfg80211_mbssid_elems *mbssid = + nl80211_parse_mbssid_elems(&rdev->wiphy, +- attrs[NL80211_ATTR_MBSSID_ELEMS]); ++ attrs[NL80211_ATTR_MBSSID_ELEMS], ++ extack); + + if (IS_ERR(mbssid)) + return PTR_ERR(mbssid); +-- +2.53.0 + diff --git a/queue-6.12/wifi-p54-validate-rx-frame-length-in-p54_rx_eeprom_r.patch b/queue-6.12/wifi-p54-validate-rx-frame-length-in-p54_rx_eeprom_r.patch new file mode 100644 index 0000000000..22d299908a --- /dev/null +++ b/queue-6.12/wifi-p54-validate-rx-frame-length-in-p54_rx_eeprom_r.patch @@ -0,0 +1,80 @@ +From 631075b811c2966a440bb55654e31b80df10ab20 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 27 Jun 2026 17:05:10 -0700 +Subject: wifi: p54: validate RX frame length in p54_rx_eeprom_readback() + +From: Xiang Mei + +[ Upstream commit ebd6d37fa94bee929e0b4c9ca19fdf9b1dcf6cea ] + +p54_rx_eeprom_readback() copies the requested EEPROM slice out of a +device-supplied readback frame without checking that the skb actually holds +that many bytes. Commit da1b9a55ff11 ("wifi: p54: prevent buffer-overflow in +p54_rx_eeprom_readback()") closed the destination overflow by copying a +fixed priv->eeprom_slice_size (and rejecting a mismatched advertised len), +but the source side is still unbounded: nothing verifies the frame is long +enough to supply that many bytes. + +A malicious USB device can send a short frame whose advertised len matches +priv->eeprom_slice_size while the payload is truncated. The equality check +passes and memcpy() reads past the end of the skb, leaking adjacent heap: + + BUG: KASAN: slab-out-of-bounds in p54_rx (drivers/net/wireless/intersil/p54/txrx.c:507) + Read of size 1016 at addr ffff88800f077114 by task swapper/0/0 + Call Trace: + + ... + __asan_memcpy (mm/kasan/shadow.c:105) + p54_rx (drivers/net/wireless/intersil/p54/txrx.c:507) + p54u_rx_cb (drivers/net/wireless/intersil/p54/p54usb.c:163) + __usb_hcd_giveback_urb (drivers/usb/core/hcd.c:1657) + dummy_timer (drivers/usb/gadget/udc/dummy_hcd.c:2005) + ... + + + The buggy address belongs to the object at ffff88800f0770c0 + which belongs to the cache skbuff_small_head of size 704 + The buggy address is located 84 bytes inside of + allocated 704-byte region [ffff88800f0770c0, ffff88800f077380) + +Check that the slice fits in the skb before copying. + +Fixes: 7cb770729ba8 ("p54: move eeprom code into common library") +Reported-by: Weiming Shi +Assisted-by: Claude:claude-opus-4-8 +Signed-off-by: Xiang Mei +Acked-by: Christian Lamparter +Link: https://patch.msgid.link/20260628000510.4152481-1-xmei5@asu.edu +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/intersil/p54/txrx.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/drivers/net/wireless/intersil/p54/txrx.c b/drivers/net/wireless/intersil/p54/txrx.c +index 2deb1bb54f24bd..dc7bf54e30bba1 100644 +--- a/drivers/net/wireless/intersil/p54/txrx.c ++++ b/drivers/net/wireless/intersil/p54/txrx.c +@@ -499,11 +499,19 @@ static void p54_rx_eeprom_readback(struct p54_common *priv, + if (le16_to_cpu(eeprom->v2.len) != priv->eeprom_slice_size) + return; + ++ if (eeprom->v2.data + priv->eeprom_slice_size > ++ skb_tail_pointer(skb)) ++ return; ++ + memcpy(priv->eeprom, eeprom->v2.data, priv->eeprom_slice_size); + } else { + if (le16_to_cpu(eeprom->v1.len) != priv->eeprom_slice_size) + return; + ++ if (eeprom->v1.data + priv->eeprom_slice_size > ++ skb_tail_pointer(skb)) ++ return; ++ + memcpy(priv->eeprom, eeprom->v1.data, priv->eeprom_slice_size); + } + +-- +2.53.0 + diff --git a/queue-6.12/xfrm-policy-preallocate-inexact-bins-before-xfrm_has.patch b/queue-6.12/xfrm-policy-preallocate-inexact-bins-before-xfrm_has.patch new file mode 100644 index 0000000000..b82a22b40c --- /dev/null +++ b/queue-6.12/xfrm-policy-preallocate-inexact-bins-before-xfrm_has.patch @@ -0,0 +1,75 @@ +From 1926c3b31486e8f99512e2186e11b8ff8149a699 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 3 Jul 2026 05:19:32 +0000 +Subject: xfrm: policy: preallocate inexact bins before xfrm_hash_rebuild + reinsert + +From: Xiang Mei (Microsoft) + +[ Upstream commit f38f8cce2f7e79775b3db7e8a5eacda04ac908e4 ] + +xfrm_hash_rebuild()'s first loop preallocates the bins/chains the reinsert +loop needs, so the reinsert (after hlist_del_rcu()) cannot allocate or +fail. But its guard is inverted: it skips policies with prefixlen < +threshold and preallocates for the rest. + +prefixlen < threshold is exactly when policy_hash_bysel() returns NULL and +the reinsert takes the allocating xfrm_policy_inexact_insert() path. So the +loop preallocates for the exact policies (which never allocate) and skips +the inexact ones, whose bin/node is then allocated GFP_ATOMIC during +reinsert. On failure the error path only WARN_ONCE()s and continues, +leaving a poisoned bydst node; the next rebuild's hlist_del_rcu() +dereferences LIST_POISON2 and takes a GPF. Reachable under memory pressure, +deterministic via failslab. + +Invert the guard so preallocation covers exactly the reinserted policies; +the reinsert then allocates nothing and cannot fail. + +Crash: + Oops: general protection fault, probably for non-canonical address + 0xfbd59c0000000024: 0000 [#1] SMP KASAN NOPTI + KASAN: maybe wild-memory-access in range [0xdead...] + ... + Workqueue: events xfrm_hash_rebuild + RIP: 0010:xfrm_hash_rebuild+0x5b3/0x1190 + RAX: dead000000000122 (LIST_POISON2 + offset) + ... + Call Trace: + hlist_del_rcu (include/linux/rculist.h:599) + xfrm_hash_rebuild (net/xfrm/xfrm_policy.c:1365) + process_one_work (kernel/workqueue.c:3322) + worker_thread (kernel/workqueue.c:3486) + kthread (kernel/kthread.c:436) + ret_from_fork (arch/x86/kernel/process.c:158) + ret_from_fork_asm (arch/x86/entry/entry_64.S:245) + ... + Kernel panic - not syncing: Fatal exception in interrupt + +Fixes: 24969facd704 ("xfrm: policy: store inexact policies in an rhashtable") +Reported-by: AutonomousCodeSecurity@microsoft.com +Signed-off-by: Xiang Mei (Microsoft) +Reviewed-by: Florian Westphal +Signed-off-by: Steffen Klassert +Signed-off-by: Sasha Levin +--- + net/xfrm/xfrm_policy.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c +index f74e45a34b70df..e033390e77855c 100644 +--- a/net/xfrm/xfrm_policy.c ++++ b/net/xfrm/xfrm_policy.c +@@ -1329,8 +1329,8 @@ static void xfrm_hash_rebuild(struct work_struct *work) + } + } + +- if (policy->selector.prefixlen_d < dbits || +- policy->selector.prefixlen_s < sbits) ++ if (policy->selector.prefixlen_d >= dbits && ++ policy->selector.prefixlen_s >= sbits) + continue; + + bin = xfrm_policy_inexact_alloc_bin(policy, dir); +-- +2.53.0 + diff --git a/queue-6.12/xfrm6-clear-dst.dev-on-error-to-avoid-double-netdev_.patch b/queue-6.12/xfrm6-clear-dst.dev-on-error-to-avoid-double-netdev_.patch new file mode 100644 index 0000000000..9070f3c1b3 --- /dev/null +++ b/queue-6.12/xfrm6-clear-dst.dev-on-error-to-avoid-double-netdev_.patch @@ -0,0 +1,60 @@ +From 1c4738fc6785be94388c67976211b05c61403d2e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 2 Jul 2026 01:05:16 +0000 +Subject: xfrm6: clear dst.dev on error to avoid double netdev_put in + xfrm6_fill_dst() + +From: Xiang Mei (Microsoft) + +[ Upstream commit 136992de9bb91871084ae52d172610541c76e4d2 ] + +On the error path where in6_dev_get(dev) returns NULL, xfrm6_fill_dst() +releases the device reference with netdev_put() but leaves +xdst->u.dst.dev set. dst_destroy() later calls netdev_put(dst->dev) +again, so the same net_device reference is released twice, underflowing +its refcount (ref_tracker WARNING + "unregister_netdevice: waiting for + to become free"). + +Clear xdst->u.dst.dev after the netdev_put(), the same way the XFRM +device-offload paths xfrm_dev_state_add() and xfrm_dev_policy_add() in +net/xfrm/xfrm_device.c NULL ->dev when releasing the reference on error. + + ref_tracker: reference already released. + ref_tracker: allocated in: + xfrm6_fill_dst (net/ipv6/xfrm6_policy.c:86) + ... + udpv6_sendmsg (net/ipv6/udp.c:1696) + ... + ref_tracker: freed in: + xfrm6_fill_dst (net/ipv6/xfrm6_policy.c:90) + ... + WARNING: lib/ref_tracker.c:322 at ref_tracker_free+0x58b/0x780 + dst_destroy (net/core/dst.c:115) + rcu_core + handle_softirqs + ... + +Fixes: 84c4a9dfbf43 ("xfrm6: release dev before returning error") +Reported-by: AutonomousCodeSecurity@microsoft.com +Signed-off-by: Xiang Mei (Microsoft) +Signed-off-by: Steffen Klassert +Signed-off-by: Sasha Levin +--- + net/ipv6/xfrm6_policy.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c +index 125ea9a5b8a082..3b749475f6ed65 100644 +--- a/net/ipv6/xfrm6_policy.c ++++ b/net/ipv6/xfrm6_policy.c +@@ -88,6 +88,7 @@ static int xfrm6_fill_dst(struct xfrm_dst *xdst, struct net_device *dev, + xdst->u.rt6.rt6i_idev = in6_dev_get(dev); + if (!xdst->u.rt6.rt6i_idev) { + netdev_put(dev, &xdst->u.dst.dev_tracker); ++ xdst->u.dst.dev = NULL; + return -ENODEV; + } + +-- +2.53.0 + diff --git a/queue-6.18/accel-amdxdna-fix-use-after-free-of-mm_struct-in-job.patch b/queue-6.18/accel-amdxdna-fix-use-after-free-of-mm_struct-in-job.patch new file mode 100644 index 0000000000..5025588723 --- /dev/null +++ b/queue-6.18/accel-amdxdna-fix-use-after-free-of-mm_struct-in-job.patch @@ -0,0 +1,58 @@ +From ec2be4ebe29381d69855593c14309b0d65defc80 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 16 Jul 2026 08:13:05 -0700 +Subject: accel/amdxdna: Fix use-after-free of mm_struct in job scheduler + +From: Lizhi Hou + +[ Upstream commit faebb7ba1ac65fa5810b640df02ce04e509fdc11 ] + +amdxdna_cmd_submit() stores current->mm in job->mm without holding any +reference. aie2_sched_job_run() later access job->mm from the DRM +scheduler worker thread. With only a raw pointer and no structural +reference, the mm_struct can be freed before the scheduler runs the job. + +Fix this by calling mmgrab() to hold a structural mm_count reference for +the lifetime of the job, paired with mmdrop() in every cleanup path. + +Fixes: aac243092b70 ("accel/amdxdna: Add command execution") +Reviewed-by: Max Zhen +Signed-off-by: Lizhi Hou +Link: https://patch.msgid.link/20260716151305.1595780-1-lizhi.hou@amd.com +Signed-off-by: Sasha Levin +--- + drivers/accel/amdxdna/amdxdna_ctx.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/drivers/accel/amdxdna/amdxdna_ctx.c b/drivers/accel/amdxdna/amdxdna_ctx.c +index cfee89681ff3cf..347e046d2a0fba 100644 +--- a/drivers/accel/amdxdna/amdxdna_ctx.c ++++ b/drivers/accel/amdxdna/amdxdna_ctx.c +@@ -393,6 +393,7 @@ void amdxdna_sched_job_cleanup(struct amdxdna_sched_job *job) + amdxdna_arg_bos_put(job); + amdxdna_gem_put_obj(job->cmd_bo); + dma_fence_put(job->fence); ++ mmdrop(job->mm); + } + + int amdxdna_cmd_submit(struct amdxdna_client *client, +@@ -443,6 +444,7 @@ int amdxdna_cmd_submit(struct amdxdna_client *client, + + job->hwctx = hwctx; + job->mm = current->mm; ++ mmgrab(job->mm); + + job->fence = amdxdna_fence_create(hwctx); + if (!job->fence) { +@@ -475,6 +477,8 @@ int amdxdna_cmd_submit(struct amdxdna_client *client, + cmd_put: + amdxdna_gem_put_obj(job->cmd_bo); + free_job: ++ if (job->mm) ++ mmdrop(job->mm); + kfree(job); + return ret; + } +-- +2.53.0 + diff --git a/queue-6.18/accel-ivpu-fix-wrong-register-read-in-lnl-failure-di.patch b/queue-6.18/accel-ivpu-fix-wrong-register-read-in-lnl-failure-di.patch new file mode 100644 index 0000000000..aa18bf2e6f --- /dev/null +++ b/queue-6.18/accel-ivpu-fix-wrong-register-read-in-lnl-failure-di.patch @@ -0,0 +1,40 @@ +From 8ecc0a58c6ddc06e466591cba89b0a08baac02c8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 10 Jul 2026 12:13:31 +0200 +Subject: accel/ivpu: Fix wrong register read in LNL failure diagnostics + +From: Karol Wachowski + +[ Upstream commit e4159045c2704dfe146f0ccb0445d9d074cd6882 ] + +diagnose_failure_lnl() read VPU_HW_BTRS_MTL_INTERRUPT_STAT instead of +VPU_HW_BTRS_LNL_INTERRUPT_STAT, which on LNL and newer parts is a +different register with a different bit layout, so failure diagnostics +decoded the wrong register and reported a bogus error cause. +Read the LNL interrupt status register instead. + +Fixes: 8a27ad81f7d3 ("accel/ivpu: Split IP and buttress code") +Reviewed-by: Andrzej Kacprowski +Signed-off-by: Karol Wachowski +Link: https://patch.msgid.link/20260710101331.1899505-1-karol.wachowski@linux.intel.com +Signed-off-by: Sasha Levin +--- + drivers/accel/ivpu/ivpu_hw_btrs.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/accel/ivpu/ivpu_hw_btrs.c b/drivers/accel/ivpu/ivpu_hw_btrs.c +index aa33f562d29c12..e9786204feca43 100644 +--- a/drivers/accel/ivpu/ivpu_hw_btrs.c ++++ b/drivers/accel/ivpu/ivpu_hw_btrs.c +@@ -845,7 +845,7 @@ static void diagnose_failure_mtl(struct ivpu_device *vdev) + + static void diagnose_failure_lnl(struct ivpu_device *vdev) + { +- u32 reg = REGB_RD32(VPU_HW_BTRS_MTL_INTERRUPT_STAT) & BTRS_LNL_IRQ_MASK; ++ u32 reg = REGB_RD32(VPU_HW_BTRS_LNL_INTERRUPT_STAT) & BTRS_LNL_IRQ_MASK; + + if (REG_TEST_FLD(VPU_HW_BTRS_LNL_INTERRUPT_STAT, ATS_ERR, reg)) { + ivpu_err(vdev, "ATS_ERR_LOG1 0x%08x ATS_ERR_LOG2 0x%08x\n", +-- +2.53.0 + diff --git a/queue-6.18/alsa-usb-audio-skip-dsd-quirk-for-musical-fidelity-m.patch b/queue-6.18/alsa-usb-audio-skip-dsd-quirk-for-musical-fidelity-m.patch new file mode 100644 index 0000000000..f6ab0e5623 --- /dev/null +++ b/queue-6.18/alsa-usb-audio-skip-dsd-quirk-for-musical-fidelity-m.patch @@ -0,0 +1,47 @@ +From ebcdd88f5a72c7b268446e6381c72fabbcf63a5b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 9 Jul 2026 11:56:06 +0200 +Subject: ALSA: usb-audio: Skip DSD quirk for Musical Fidelity M6s DAC + +From: Takashi Iwai + +[ Upstream commit 93b47e66cc6d6c6382d44b44f5e7f6fc3a7b38c3 ] + +Salvador reported that the recent fix for applying the DSD quirk to +Musical Fidelity devices broke for his M6s DAC model (2772:0502). + +Although this is basically a firmware bug, the model in question is +fairly old, and no further firmware update can be expected, so it'd be +better to address in the driver side. + +As an ad hoc workaround, skip the DSD quirk for this device by adding +an empty quirk entry of 2772:0502; this essentially skips the later +DSD quirk entry by the match with the vendor 2772. + +Fixes: da3a7efff64e ("ALSA: usb-audio: Update for native DSD support quirks") +Reported-by: Salvador Blaya +Closes: https://lore.kernel.org/CAOdyq+qFaqCh=tK_wNnA64hv5pQuA1Y09ANxQ=xK8yR-t4mf9Q@mail.gmail.com +Tested-by: Salvador Blaya +Signed-off-by: Takashi Iwai +Link: https://patch.msgid.link/20260709095614.1418838-1-tiwai@suse.de +Signed-off-by: Sasha Levin +--- + sound/usb/quirks.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c +index 1b4cfc2b68f9dc..3d81b003a5109b 100644 +--- a/sound/usb/quirks.c ++++ b/sound/usb/quirks.c +@@ -2380,6 +2380,8 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = { + QUIRK_FLAG_DSD_RAW), + DEVICE_FLG(0x2708, 0x0002, /* Audient iD14 */ + QUIRK_FLAG_IGNORE_CTL_ERROR), ++ DEVICE_FLG(0x2772, 0x0502, /* Musical Fidelity M6s DAC */ ++ 0), /* for avoiding QUIRK_FLAG_DSD_RAW with vendor match */ + DEVICE_FLG(0x2912, 0x30c8, /* Audioengine D1 */ + QUIRK_FLAG_GET_SAMPLE_RATE), + DEVICE_FLG(0x2a70, 0x1881, /* OnePlus Technology (Shenzhen) Co., Ltd. BE02T */ +-- +2.53.0 + diff --git a/queue-6.18/arm64-tegra-fix-cpu-compatible-string-to-cortex-a78a.patch b/queue-6.18/arm64-tegra-fix-cpu-compatible-string-to-cortex-a78a.patch new file mode 100644 index 0000000000..405adb33c5 --- /dev/null +++ b/queue-6.18/arm64-tegra-fix-cpu-compatible-string-to-cortex-a78a.patch @@ -0,0 +1,144 @@ +From 22169e3929e3816300cac3f41ba1e6fd00620abe Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 21 Jan 2026 16:15:34 +0530 +Subject: arm64: tegra: Fix CPU compatible string to cortex-a78ae on Tegra234 + +From: Sumit Gupta + +[ Upstream commit 0dfa1e960f86e032007882b032c5cc7d14ebe73e ] + +The Tegra234 SoC uses Cortex-A78AE cores, not Cortex-A78. Update the +compatible string for all CPU nodes to match the actual hardware. + +Tegra234 hardware reports: + # head /proc/cpuinfo | egrep 'implementer|part' + CPU implementer : 0x41 + CPU part : 0xd42 + +Which maps to (from arch/arm64/include/asm/cputype.h): + #define ARM_CPU_IMP_ARM 0x41 + #define ARM_CPU_PART_CORTEX_A78AE 0xD42 + +Fixes: a12cf5c339b08 ("arm64: tegra: Describe Tegra234 CPU hierarchy") +Signed-off-by: Sumit Gupta +Signed-off-by: Thierry Reding +Signed-off-by: Sasha Levin +--- + arch/arm64/boot/dts/nvidia/tegra234.dtsi | 24 ++++++++++++------------ + 1 file changed, 12 insertions(+), 12 deletions(-) + +diff --git a/arch/arm64/boot/dts/nvidia/tegra234.dtsi b/arch/arm64/boot/dts/nvidia/tegra234.dtsi +index 5b245977d6a037..345587fa1d9ad0 100644 +--- a/arch/arm64/boot/dts/nvidia/tegra234.dtsi ++++ b/arch/arm64/boot/dts/nvidia/tegra234.dtsi +@@ -5345,7 +5345,7 @@ cpus { + #size-cells = <0>; + + cpu0_0: cpu@0 { +- compatible = "arm,cortex-a78"; ++ compatible = "arm,cortex-a78ae"; + device_type = "cpu"; + reg = <0x00000>; + +@@ -5364,7 +5364,7 @@ cpu0_0: cpu@0 { + }; + + cpu0_1: cpu@100 { +- compatible = "arm,cortex-a78"; ++ compatible = "arm,cortex-a78ae"; + device_type = "cpu"; + reg = <0x00100>; + +@@ -5383,7 +5383,7 @@ cpu0_1: cpu@100 { + }; + + cpu0_2: cpu@200 { +- compatible = "arm,cortex-a78"; ++ compatible = "arm,cortex-a78ae"; + device_type = "cpu"; + reg = <0x00200>; + +@@ -5402,7 +5402,7 @@ cpu0_2: cpu@200 { + }; + + cpu0_3: cpu@300 { +- compatible = "arm,cortex-a78"; ++ compatible = "arm,cortex-a78ae"; + device_type = "cpu"; + reg = <0x00300>; + +@@ -5421,7 +5421,7 @@ cpu0_3: cpu@300 { + }; + + cpu1_0: cpu@10000 { +- compatible = "arm,cortex-a78"; ++ compatible = "arm,cortex-a78ae"; + device_type = "cpu"; + reg = <0x10000>; + +@@ -5440,7 +5440,7 @@ cpu1_0: cpu@10000 { + }; + + cpu1_1: cpu@10100 { +- compatible = "arm,cortex-a78"; ++ compatible = "arm,cortex-a78ae"; + device_type = "cpu"; + reg = <0x10100>; + +@@ -5459,7 +5459,7 @@ cpu1_1: cpu@10100 { + }; + + cpu1_2: cpu@10200 { +- compatible = "arm,cortex-a78"; ++ compatible = "arm,cortex-a78ae"; + device_type = "cpu"; + reg = <0x10200>; + +@@ -5478,7 +5478,7 @@ cpu1_2: cpu@10200 { + }; + + cpu1_3: cpu@10300 { +- compatible = "arm,cortex-a78"; ++ compatible = "arm,cortex-a78ae"; + device_type = "cpu"; + reg = <0x10300>; + +@@ -5497,7 +5497,7 @@ cpu1_3: cpu@10300 { + }; + + cpu2_0: cpu@20000 { +- compatible = "arm,cortex-a78"; ++ compatible = "arm,cortex-a78ae"; + device_type = "cpu"; + reg = <0x20000>; + +@@ -5516,7 +5516,7 @@ cpu2_0: cpu@20000 { + }; + + cpu2_1: cpu@20100 { +- compatible = "arm,cortex-a78"; ++ compatible = "arm,cortex-a78ae"; + device_type = "cpu"; + reg = <0x20100>; + +@@ -5535,7 +5535,7 @@ cpu2_1: cpu@20100 { + }; + + cpu2_2: cpu@20200 { +- compatible = "arm,cortex-a78"; ++ compatible = "arm,cortex-a78ae"; + device_type = "cpu"; + reg = <0x20200>; + +@@ -5554,7 +5554,7 @@ cpu2_2: cpu@20200 { + }; + + cpu2_3: cpu@20300 { +- compatible = "arm,cortex-a78"; ++ compatible = "arm,cortex-a78ae"; + device_type = "cpu"; + reg = <0x20300>; + +-- +2.53.0 + diff --git a/queue-6.18/arm64-tegra-remove-fallback-compatible-for-gpcdma.patch b/queue-6.18/arm64-tegra-remove-fallback-compatible-for-gpcdma.patch new file mode 100644 index 0000000000..dcf5376d04 --- /dev/null +++ b/queue-6.18/arm64-tegra-remove-fallback-compatible-for-gpcdma.patch @@ -0,0 +1,38 @@ +From 1fb97d6b9bed1d5c877197781c430f3b0095bf44 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 31 Mar 2026 15:52:55 +0530 +Subject: arm64: tegra: Remove fallback compatible for GPCDMA + +From: Akhil R + +[ Upstream commit ee7863e43228a3143398dc5bbb943c9a735a8fca ] + +Remove the fallback compatible string "nvidia,tegra186-gpcdma" for GPCDMA +in Tegra264. Tegra186 compatible cannot work on Tegra264 because of the +register offset changes and absence of the reset property. + +Fixes: 65ef237e4810 ("arm64: tegra: Add Tegra264 support") +Signed-off-by: Akhil R +Reviewed-by: Jon Hunter +Signed-off-by: Thierry Reding +Signed-off-by: Sasha Levin +--- + arch/arm64/boot/dts/nvidia/tegra264.dtsi | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/arm64/boot/dts/nvidia/tegra264.dtsi b/arch/arm64/boot/dts/nvidia/tegra264.dtsi +index 872a69553e3c82..b16d380209a50a 100644 +--- a/arch/arm64/boot/dts/nvidia/tegra264.dtsi ++++ b/arch/arm64/boot/dts/nvidia/tegra264.dtsi +@@ -50,7 +50,7 @@ timer@8000000 { + }; + + gpcdma: dma-controller@8400000 { +- compatible = "nvidia,tegra264-gpcdma", "nvidia,tegra186-gpcdma"; ++ compatible = "nvidia,tegra264-gpcdma"; + reg = <0x0 0x08400000 0x0 0x210000>; + interrupts = , + , +-- +2.53.0 + diff --git a/queue-6.18/asoc-amd-ps-disable-msi-on-resume-in-acp-pci-driver.patch b/queue-6.18/asoc-amd-ps-disable-msi-on-resume-in-acp-pci-driver.patch new file mode 100644 index 0000000000..153f175324 --- /dev/null +++ b/queue-6.18/asoc-amd-ps-disable-msi-on-resume-in-acp-pci-driver.patch @@ -0,0 +1,73 @@ +From ccc922ef8f86a5210e67a78b7044f9d160a886be Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 7 Jul 2026 11:29:36 +0530 +Subject: ASoC: amd: ps: disable MSI on resume in ACP PCI driver + +From: Vijendar Mukunda + +[ Upstream commit 5893013efabb056399a01e267f410cf76eba25eb ] + +BIOS/firmware may re-enable MSI in PCI config space during system +level resume even though this driver only uses legacy INTx interrupts. +If MSI is left enabled with stale address/data registers, the device +will write interrupts to a bogus address causing IOMMU IO_PAGE_FAULT +and interrupt delivery failure. + +Clear the MSI Enable bit before reinitializing the ACP hardware on +system level resume. + +Fixes: 491628388005 ("ASoC: amd: ps: add callback functions for acp pci driver pm ops") +Signed-off-by: Vijendar Mukunda +Reviewed-by: Mario Limonciello (AMD) +Link: https://patch.msgid.link/20260707060130.2514138-2-Vijendar.Mukunda@amd.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/amd/ps/pci-ps.c | 29 +++++++++++++++++++++++++++++ + 1 file changed, 29 insertions(+) + +diff --git a/sound/soc/amd/ps/pci-ps.c b/sound/soc/amd/ps/pci-ps.c +index c62299b2920417..34efb42be768fb 100644 +--- a/sound/soc/amd/ps/pci-ps.c ++++ b/sound/soc/amd/ps/pci-ps.c +@@ -683,8 +683,37 @@ static int snd_acp_runtime_resume(struct device *dev) + return acp_hw_runtime_resume(dev); + } + ++static void acp_disable_msi_on_resume(struct pci_dev *pdev) ++{ ++ u16 control; ++ ++ if (!pdev->msi_cap) ++ return; ++ ++ pci_read_config_word(pdev, pdev->msi_cap + PCI_MSI_FLAGS, &control); ++ if (control & PCI_MSI_FLAGS_ENABLE) { ++ dev_warn(&pdev->dev, ++ "ACP: MSI unexpectedly enabled after resume (flags=0x%04x), disabling\n", ++ control); ++ control &= ~PCI_MSI_FLAGS_ENABLE; ++ pci_write_config_word(pdev, pdev->msi_cap + PCI_MSI_FLAGS, control); ++ } ++} ++ + static int snd_acp_resume(struct device *dev) + { ++ struct pci_dev *pdev = to_pci_dev(dev); ++ ++ /* ++ * BIOS/firmware may re-enable MSI in PCI config space during ++ * system resume even though this driver only uses legacy INTx ++ * interrupts. If MSI is left enabled with stale address/data ++ * registers, the device will write interrupts to a bogus address ++ * causing IOMMU IO_PAGE_FAULT and interrupt delivery failure. ++ * Explicitly clear the MSI Enable bit before reinitializing ++ * the ACP hardware. ++ */ ++ acp_disable_msi_on_resume(pdev); + return acp_hw_resume(dev); + } + +-- +2.53.0 + diff --git a/queue-6.18/asoc-amd-ps-fix-wrong-acp-version-string-in-pci_requ.patch b/queue-6.18/asoc-amd-ps-fix-wrong-acp-version-string-in-pci_requ.patch new file mode 100644 index 0000000000..8c94ce9f4c --- /dev/null +++ b/queue-6.18/asoc-amd-ps-fix-wrong-acp-version-string-in-pci_requ.patch @@ -0,0 +1,39 @@ +From f0a526e2c0f97b713749c1b5b7f15e8e391a4ebf Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 7 Jul 2026 11:29:37 +0530 +Subject: ASoC: amd: ps: fix wrong ACP version string in pci_request_regions() + +From: Vijendar Mukunda + +[ Upstream commit f7697ecf6eab9d4887dd731038b3dc405c7e755e ] + +The driver handles ACP6.3/7.0/7.1/7.2 platforms but the region was +claimed with the stale name "AMD ACP6.2 audio" left over from the +original ACP6.2 driver. Correct it to "AMD ACP6.3 audio". + +Fixes: 95e43a170bb1 ("ASoC: amd: add Pink Sardine ACP PCI driver") +Signed-off-by: Vijendar Mukunda +Reviewed-by: Mario Limonciello (AMD) +Link: https://patch.msgid.link/20260707060130.2514138-3-Vijendar.Mukunda@amd.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/amd/ps/pci-ps.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/sound/soc/amd/ps/pci-ps.c b/sound/soc/amd/ps/pci-ps.c +index 34efb42be768fb..8f37c250d4b895 100644 +--- a/sound/soc/amd/ps/pci-ps.c ++++ b/sound/soc/amd/ps/pci-ps.c +@@ -595,7 +595,7 @@ static int snd_acp63_probe(struct pci_dev *pci, + return -ENODEV; + } + +- ret = pci_request_regions(pci, "AMD ACP6.2 audio"); ++ ret = pci_request_regions(pci, "AMD ACP6.3 audio"); + if (ret < 0) { + dev_err(&pci->dev, "pci_request_regions failed\n"); + goto disable_pci; +-- +2.53.0 + diff --git a/queue-6.18/asoc-amd-ps-replace-bitwise-or-with-logical-or-in-ir.patch b/queue-6.18/asoc-amd-ps-replace-bitwise-or-with-logical-or-in-ir.patch new file mode 100644 index 0000000000..e33ad34ee6 --- /dev/null +++ b/queue-6.18/asoc-amd-ps-replace-bitwise-or-with-logical-or-in-ir.patch @@ -0,0 +1,39 @@ +From b81b43034a70f0c65427aceec64eb7fae330169a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 7 Jul 2026 11:29:38 +0530 +Subject: ASoC: amd: ps: replace bitwise OR with logical OR in IRQ return check + +From: Vijendar Mukunda + +[ Upstream commit dec5aaa27603e1d7b426ce3504af6d1a62e4d444 ] + +The condition 'irq_flag | wake_irq_flag' uses bitwise OR to combine two +integer flags that are used as booleans. Replace with logical OR '||' to +correctly express the intended boolean check. + +Signed-off-by: Vijendar Mukunda +Reviewed-by: Mario Limonciello (AMD) +Fixes: 7f91f012c1df0 ("ASoC: amd: ps: fix for irq handler return status") +Link: https://patch.msgid.link/20260707060130.2514138-4-Vijendar.Mukunda@amd.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/amd/ps/pci-ps.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/sound/soc/amd/ps/pci-ps.c b/sound/soc/amd/ps/pci-ps.c +index 8f37c250d4b895..cf06d4ae299b51 100644 +--- a/sound/soc/amd/ps/pci-ps.c ++++ b/sound/soc/amd/ps/pci-ps.c +@@ -248,7 +248,7 @@ static irqreturn_t acp63_irq_handler(int irq, void *dev_id) + if (sdw_dma_irq_flag) + return IRQ_WAKE_THREAD; + +- if (irq_flag | wake_irq_flag) ++ if (irq_flag || wake_irq_flag) + return IRQ_HANDLED; + else + return IRQ_NONE; +-- +2.53.0 + diff --git a/queue-6.18/asoc-cs42l43-correct-report-for-forced-microphone-ja.patch b/queue-6.18/asoc-cs42l43-correct-report-for-forced-microphone-ja.patch new file mode 100644 index 0000000000..9acbcb4956 --- /dev/null +++ b/queue-6.18/asoc-cs42l43-correct-report-for-forced-microphone-ja.patch @@ -0,0 +1,45 @@ +From e40563c9c4dbfd3cc456842151b8458eae1e3cac Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 8 Jul 2026 11:34:30 +0100 +Subject: ASoC: cs42l43: Correct report for forced microphone jack + +From: Charles Keepax + +[ Upstream commit f74e6e15485b68b92b2807071e822db6309b7e38 ] + +Currently if the jack is forced to the microphone mode, it will report +as line in. Correct the report to microphone. + +Fixes: fc918cbe874e ("ASoC: cs42l43: Add support for the cs42l43") +Signed-off-by: Charles Keepax +Link: https://patch.msgid.link/20260708103430.1395207-1-ckeepax@opensource.cirrus.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/codecs/cs42l43-jack.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/sound/soc/codecs/cs42l43-jack.c b/sound/soc/codecs/cs42l43-jack.c +index ecba6c79523840..36fb67059e0652 100644 +--- a/sound/soc/codecs/cs42l43-jack.c ++++ b/sound/soc/codecs/cs42l43-jack.c +@@ -310,6 +310,7 @@ irqreturn_t cs42l43_bias_detect_clamp(int irq, void *data) + #define CS42L43_JACK_ABSENT 0x0 + + #define CS42L43_JACK_OPTICAL (SND_JACK_MECHANICAL | SND_JACK_AVOUT) ++#define CS42L43_JACK_MICROPHONE (SND_JACK_MECHANICAL | SND_JACK_MICROPHONE) + #define CS42L43_JACK_HEADPHONE (SND_JACK_MECHANICAL | SND_JACK_HEADPHONE) + #define CS42L43_JACK_HEADSET (SND_JACK_MECHANICAL | SND_JACK_HEADSET) + #define CS42L43_JACK_LINEOUT (SND_JACK_MECHANICAL | SND_JACK_LINEOUT) +@@ -871,7 +872,7 @@ static const struct cs42l43_jack_override_mode { + .hsdet_mode = CS42L43_JACK_3_POLE_SWITCHES, + .mic_ctrl = (0x3 << CS42L43_JACK_STEREO_CONFIG_SHIFT) | + CS42L43_HS1_BIAS_EN_MASK | CS42L43_HS2_BIAS_EN_MASK, +- .report = CS42L43_JACK_LINEIN, ++ .report = CS42L43_JACK_MICROPHONE, + }, + [CS42L43_JACK_RAW_OPTICAL] = { + .hsdet_mode = CS42L43_JACK_3_POLE_SWITCHES, +-- +2.53.0 + diff --git a/queue-6.18/asoc-meson-aiu-fifo-spdif-soft-reset-the-s-pdif-data.patch b/queue-6.18/asoc-meson-aiu-fifo-spdif-soft-reset-the-s-pdif-data.patch new file mode 100644 index 0000000000..236d77d0e4 --- /dev/null +++ b/queue-6.18/asoc-meson-aiu-fifo-spdif-soft-reset-the-s-pdif-data.patch @@ -0,0 +1,64 @@ +From 7dd4077e63cb3788a5526bfac6a44fc8f774924f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 27 Jun 2026 13:12:05 +0000 +Subject: ASoC: meson: aiu: fifo-spdif: soft reset the S/PDIF datapath on + start/stop + +From: Christian Hewitt + +[ Upstream commit 6b59c53c8adc2b522327407af5e1793a65b67e4b ] + +The I2S FIFO soft-resets its fast domain on start (AIU_RST_SOFT bit 0 + +AIU_I2S_SYNC read in aiu_fifo_i2s_trigger), mirroring the downstream +vendor driver's audio_out_i2s_enable(). The S/PDIF FIFO has no equivalent: +it only toggles the IEC958 DCU, so a stale datapath FIFO can be replayed, +producing the "machine gun noise" buffer underrun - on start when switching +outputs, and on stop when playback ends. The latter is audible on devices +with an always-on S/PDIF-fed DAC (e.g. the ES7144 on the WeTek Play2). + +The vendor driver resets the IEC958 fast domain (AIU_RST_SOFT bit 2) on +both enable and disable (audio_hw_958_enable), and when reconfiguring +(audio_hw_958_reset clears AIU_958_DCU_FF_CTRL then resets). Do the same: +reset before enabling the DCU on start, and before disabling on stop. + +Fixes: 6ae9ca9ce986bf ("ASoC: meson: aiu: add i2s and spdif support") +Signed-off-by: Christian Hewitt +Reviewed-by: Martin Blumenstingl +Link: https://patch.msgid.link/20260627131205.808800-1-christianshewitt@gmail.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/meson/aiu-fifo-spdif.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/sound/soc/meson/aiu-fifo-spdif.c b/sound/soc/meson/aiu-fifo-spdif.c +index e0e00ec026dcc4..a9861c5d663745 100644 +--- a/sound/soc/meson/aiu-fifo-spdif.c ++++ b/sound/soc/meson/aiu-fifo-spdif.c +@@ -24,6 +24,7 @@ + #define AIU_MEM_IEC958_CONTROL_MODE_16BIT BIT(7) + #define AIU_MEM_IEC958_CONTROL_MODE_LINEAR BIT(8) + #define AIU_MEM_IEC958_BUF_CNTL_INIT BIT(0) ++#define AIU_RST_SOFT_958_FAST BIT(2) + + #define AIU_FIFO_SPDIF_BLOCK 8 + +@@ -68,11 +69,15 @@ static int fifo_spdif_trigger(struct snd_pcm_substream *substream, int cmd, + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: ++ snd_soc_component_write(component, AIU_RST_SOFT, ++ AIU_RST_SOFT_958_FAST); + fifo_spdif_dcu_enable(component, true); + break; + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + case SNDRV_PCM_TRIGGER_STOP: ++ snd_soc_component_write(component, AIU_RST_SOFT, ++ AIU_RST_SOFT_958_FAST); + fifo_spdif_dcu_enable(component, false); + break; + default: +-- +2.53.0 + diff --git a/queue-6.18/asoc-tas2562-fix-deprecated-shut-down-gpio-always-cl.patch b/queue-6.18/asoc-tas2562-fix-deprecated-shut-down-gpio-always-cl.patch new file mode 100644 index 0000000000..b16cb17e9f --- /dev/null +++ b/queue-6.18/asoc-tas2562-fix-deprecated-shut-down-gpio-always-cl.patch @@ -0,0 +1,62 @@ +From ca998965196564c302c5f85f854a2bbf537c00f3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 6 Jul 2026 21:01:09 +0530 +Subject: ASoC: tas2562: fix deprecated 'shut-down' GPIO always cleared after + lookup + +From: Uday Khare + +[ Upstream commit 3238c634725afbb2a137fdda762208510828f71d ] + +In tas2562_parse_dt(), the fallback lookup for the deprecated +"shut-down" GPIO property is broken due to a missing pair of braces. + +The code intends to reset sdz_gpio to NULL only when the lookup +returns an error that is not -EPROBE_DEFER (so the driver gracefully +continues without a GPIO). However, without braces the statement: + + tas2562->sdz_gpio = NULL; + +falls outside the IS_ERR() check and is executed unconditionally +for every path through the if block, including a successful GPIO +lookup. + +This means any device using the deprecated 'shut-down' DT property +will always have sdz_gpio == NULL after probe, making the GPIO +completely non-functional. + +Fix this by adding the missing braces to scope the NULL assignment +inside the IS_ERR() branch, matching the pattern already used for +the primary 'shutdown' GPIO lookup above. + +Fixes: f78a97003b8b ("ASoC: tas2562: Update shutdown GPIO property") +Signed-off-by: Uday Khare +Link: https://patch.msgid.link/20260706153109.10953-1-udaykhare77@gmail.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/codecs/tas2562.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/sound/soc/codecs/tas2562.c b/sound/soc/codecs/tas2562.c +index 8e00dcc09d0c28..795c66cb47134e 100644 +--- a/sound/soc/codecs/tas2562.c ++++ b/sound/soc/codecs/tas2562.c +@@ -675,11 +675,12 @@ static int tas2562_parse_dt(struct tas2562_data *tas2562) + if (tas2562->sdz_gpio == NULL) { + tas2562->sdz_gpio = devm_gpiod_get_optional(dev, "shut-down", + GPIOD_OUT_HIGH); +- if (IS_ERR(tas2562->sdz_gpio)) ++ if (IS_ERR(tas2562->sdz_gpio)) { + if (PTR_ERR(tas2562->sdz_gpio) == -EPROBE_DEFER) + return -EPROBE_DEFER; + +- tas2562->sdz_gpio = NULL; ++ tas2562->sdz_gpio = NULL; ++ } + } + + if (tas2562->model_id == TAS2110) +-- +2.53.0 + diff --git a/queue-6.18/ata-sata_dwc_460ex-enable-sata-interrupts-only-after.patch b/queue-6.18/ata-sata_dwc_460ex-enable-sata-interrupts-only-after.patch new file mode 100644 index 0000000000..321001ca32 --- /dev/null +++ b/queue-6.18/ata-sata_dwc_460ex-enable-sata-interrupts-only-after.patch @@ -0,0 +1,56 @@ +From 1935ba20ba3c331f966222aeb753b781a0fac26d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 12 Jul 2026 14:37:26 -0700 +Subject: ata: sata_dwc_460ex: enable SATA interrupts only after IRQ handler is + registered + +From: Rosen Penev + +[ Upstream commit 4bbc16a353a98023e5ddfca7c1fc0e49971cf4d0 ] + +sata_dwc_enable_interrupts() is called before platform_get_irq() and +ata_host_activate(), leaving the SATA controller's interrupt mask +enabled without a registered handler. If a later step fails (irq +request, phy init, etc.) or if the controller asserts an interrupt +during probe, the irq line may fire with no handler, causing a +spurious interrupt storm. + +Move sata_dwc_enable_interrupts() after ata_host_activate() so that +interrupts are only unmasked once the handler is registered and the +core is fully initialized. + +Fixes: 62936009f35a ("[libata] Add 460EX on-chip SATA driver, sata_dwc_460ex") +Assisted-by: opencode:big-pickle +Signed-off-by: Rosen Penev +Signed-off-by: Damien Le Moal +Signed-off-by: Sasha Levin +--- + drivers/ata/sata_dwc_460ex.c | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c +index 7a4f59202156ec..4029e082577fe1 100644 +--- a/drivers/ata/sata_dwc_460ex.c ++++ b/drivers/ata/sata_dwc_460ex.c +@@ -1168,9 +1168,6 @@ static int sata_dwc_probe(struct platform_device *ofdev) + /* Save dev for later use in dev_xxx() routines */ + hsdev->dev = dev; + +- /* Enable SATA Interrupts */ +- sata_dwc_enable_interrupts(hsdev); +- + /* Get SATA interrupt number */ + irq = irq_of_parse_and_map(np, 0); + if (!irq) { +@@ -1203,6 +1200,8 @@ static int sata_dwc_probe(struct platform_device *ofdev) + if (err) + dev_err(dev, "failed to activate host"); + ++ /* Enable SATA Interrupts */ ++ sata_dwc_enable_interrupts(hsdev); + return 0; + + error_out: +-- +2.53.0 + diff --git a/queue-6.18/ata-sata_dwc_460ex-fix-clear_interrupt_bit-clearing-.patch b/queue-6.18/ata-sata_dwc_460ex-fix-clear_interrupt_bit-clearing-.patch new file mode 100644 index 0000000000..a3e31c1c6b --- /dev/null +++ b/queue-6.18/ata-sata_dwc_460ex-fix-clear_interrupt_bit-clearing-.patch @@ -0,0 +1,45 @@ +From 81ce6f1555511424aeac0ad1fed203d191529c98 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 12 Jul 2026 14:37:27 -0700 +Subject: ata: sata_dwc_460ex: fix clear_interrupt_bit() clearing all pending + interrupts + +From: Rosen Penev + +[ Upstream commit 66c4e310ad71f41e41736d33dd8a1fb5eaaec7f3 ] + +clear_interrupt_bit() ignores the bit argument and performs a +read-write-back of the entire INTPR register. If INTPR uses standard +Write-1-to-Clear semantics, this clears every pending interrupt bit, +not just the intended one. Coalesced interrupts (e.g. DMAT + NEWFP) +would be cleared together, silently losing the second event. + +Write only the specific bit to clear so that other pending interrupts +are preserved. + +Fixes: 62936009f35a ("[libata] Add 460EX on-chip SATA driver, sata_dwc_460ex") +Assisted-by: opencode:big-pickle +Signed-off-by: Rosen Penev +Signed-off-by: Damien Le Moal +Signed-off-by: Sasha Levin +--- + drivers/ata/sata_dwc_460ex.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c +index 639eab75210f29..d3472bfc606ffc 100644 +--- a/drivers/ata/sata_dwc_460ex.c ++++ b/drivers/ata/sata_dwc_460ex.c +@@ -394,8 +394,7 @@ static void clear_serror(struct ata_port *ap) + + static void clear_interrupt_bit(struct sata_dwc_device *hsdev, u32 bit) + { +- sata_dwc_writel(&hsdev->sata_dwc_regs->intpr, +- sata_dwc_readl(&hsdev->sata_dwc_regs->intpr)); ++ sata_dwc_writel(&hsdev->sata_dwc_regs->intpr, bit); + } + + static u32 qcmd_tag_to_mask(u8 tag) +-- +2.53.0 + diff --git a/queue-6.18/ata-sata_dwc_460ex-fix-infinite-loop-in-ncq-tag-comp.patch b/queue-6.18/ata-sata_dwc_460ex-fix-infinite-loop-in-ncq-tag-comp.patch new file mode 100644 index 0000000000..fdda961dc8 --- /dev/null +++ b/queue-6.18/ata-sata_dwc_460ex-fix-infinite-loop-in-ncq-tag-comp.patch @@ -0,0 +1,54 @@ +From f4c361e679256c00d9e5154147a53b1d052eeeef Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 12 Jul 2026 14:37:28 -0700 +Subject: ata: sata_dwc_460ex: fix infinite loop in NCQ tag completion + bit-scanning + +From: Rosen Penev + +[ Upstream commit c2130f6553f4a5cbdc259de069600117a995f197 ] + +The hand-rolled bit-scanning loop in the NCQ completion path has an +infinite loop bug. When tag_mask has only high bits set (e.g. +0x80000000), the inner while loop left-shifts tag_mask until it +overflows to 0. At that point !(0 & 1) is always true and 0 <<= 1 +stays 0, causing an infinite loop in hardirq context with a spinlock +held. + +Replace the open-coded bit-scanning with __ffs() which correctly +finds the least significant set bit and is bounded by the width of +the argument. + +Fixes: 62936009f35a ("[libata] Add 460EX on-chip SATA driver, sata_dwc_460ex") +Assisted-by: opencode:big-pickle +Signed-off-by: Rosen Penev +Signed-off-by: Damien Le Moal +Signed-off-by: Sasha Levin +--- + drivers/ata/sata_dwc_460ex.c | 9 ++------- + 1 file changed, 2 insertions(+), 7 deletions(-) + +diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c +index d3472bfc606ffc..36cc28b8986509 100644 +--- a/drivers/ata/sata_dwc_460ex.c ++++ b/drivers/ata/sata_dwc_460ex.c +@@ -607,14 +607,9 @@ static irqreturn_t sata_dwc_isr(int irq, void *dev_instance) + status = ap->ops->sff_check_status(ap); + dev_dbg(ap->dev, "%s ATA status register=0x%x\n", __func__, status); + +- tag = 0; + while (tag_mask) { +- while (!(tag_mask & 0x00000001)) { +- tag++; +- tag_mask <<= 1; +- } +- +- tag_mask &= (~0x00000001); ++ tag = __ffs(tag_mask); ++ tag_mask &= ~(1U << tag); + qc = ata_qc_from_tag(ap, tag); + if (unlikely(!qc)) { + dev_err(ap->dev, "failed to get qc"); +-- +2.53.0 + diff --git a/queue-6.18/ata-sata_dwc_460ex-use-platform_get_irq.patch b/queue-6.18/ata-sata_dwc_460ex-use-platform_get_irq.patch new file mode 100644 index 0000000000..71923e4e3e --- /dev/null +++ b/queue-6.18/ata-sata_dwc_460ex-use-platform_get_irq.patch @@ -0,0 +1,92 @@ +From bef03e3a63b02f4077b15404f33fad34451edc0e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 12 Jul 2026 14:37:25 -0700 +Subject: ata: sata_dwc_460ex: use platform_get_irq() + +From: Rosen Penev + +[ Upstream commit a4af122106f73ea510bb35a9ea1dedd980fc0db7 ] + +Replace irq_of_parse_and_map() with platform_get_irq() in both +sata_dwc_dma_init_old() and sata_dwc_probe(). This is the preferred +way to obtain IRQs for platform devices and provides better error +reporting. Remove the now-unnecessary #include . + +irq_of_parse_and_map() requires irq_dispose_mapping(), which is missing. + +Also fix unused variable when CONFIG_SATA_DWC_OLD_DMA is disabled. + +Fixes: 62936009f35a ("[libata] Add 460EX on-chip SATA driver, sata_dwc_460ex") +Assisted-by: opencode:big-pickle +Signed-off-by: Rosen Penev +Signed-off-by: Damien Le Moal +Signed-off-by: Sasha Levin +--- + drivers/ata/sata_dwc_460ex.c | 21 +++++++-------------- + 1 file changed, 7 insertions(+), 14 deletions(-) + +diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c +index 4029e082577fe1..639eab75210f29 100644 +--- a/drivers/ata/sata_dwc_460ex.c ++++ b/drivers/ata/sata_dwc_460ex.c +@@ -19,7 +19,6 @@ + #include + #include + #include +-#include + #include + #include + #include +@@ -226,7 +225,6 @@ static int sata_dwc_dma_init_old(struct platform_device *pdev, + struct sata_dwc_device *hsdev) + { + struct device *dev = &pdev->dev; +- struct device_node *np = dev->of_node; + + hsdev->dma = devm_kzalloc(dev, sizeof(*hsdev->dma), GFP_KERNEL); + if (!hsdev->dma) +@@ -236,11 +234,9 @@ static int sata_dwc_dma_init_old(struct platform_device *pdev, + hsdev->dma->id = pdev->id; + + /* Get SATA DMA interrupt number */ +- hsdev->dma->irq = irq_of_parse_and_map(np, 1); +- if (!hsdev->dma->irq) { +- dev_err(dev, "no SATA DMA irq\n"); +- return -ENODEV; +- } ++ hsdev->dma->irq = platform_get_irq(pdev, 1); ++ if (hsdev->dma->irq < 0) ++ return hsdev->dma->irq; + + /* Get physical SATA DMA register base address */ + hsdev->dma->regs = devm_platform_ioremap_resource(pdev, 1); +@@ -1125,7 +1121,6 @@ static const struct ata_port_info sata_dwc_port_info[] = { + static int sata_dwc_probe(struct platform_device *ofdev) + { + struct device *dev = &ofdev->dev; +- struct device_node *np = dev->of_node; + struct sata_dwc_device *hsdev; + u32 idr, versionr; + char *ver = (char *)&versionr; +@@ -1169,14 +1164,12 @@ static int sata_dwc_probe(struct platform_device *ofdev) + hsdev->dev = dev; + + /* Get SATA interrupt number */ +- irq = irq_of_parse_and_map(np, 0); +- if (!irq) { +- dev_err(dev, "no SATA DMA irq\n"); +- return -ENODEV; +- } ++ irq = platform_get_irq(ofdev, 0); ++ if (irq < 0) ++ return irq; + + #ifdef CONFIG_SATA_DWC_OLD_DMA +- if (!of_property_present(np, "dmas")) { ++ if (!of_property_present(dev->of_node, "dmas")) { + err = sata_dwc_dma_init_old(ofdev, hsdev); + if (err) + return err; +-- +2.53.0 + diff --git a/queue-6.18/bluetooth-hci_qca-clear-memdump-state-on-invalid-dum.patch b/queue-6.18/bluetooth-hci_qca-clear-memdump-state-on-invalid-dum.patch new file mode 100644 index 0000000000..c31ac2d0fa --- /dev/null +++ b/queue-6.18/bluetooth-hci_qca-clear-memdump-state-on-invalid-dum.patch @@ -0,0 +1,55 @@ +From 4c415a68cb5d4050914a41ee8646c0e6c1d324e1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 9 Jul 2026 14:22:50 +0800 +Subject: Bluetooth: hci_qca: Clear memdump state on invalid dump size + +From: Ruoyu Wang + +[ Upstream commit bf587a10c33e5571a299742e45bc18960b9912e7 ] + +qca_controller_memdump() allocates qca->qca_memdump before processing +the first dump packet. For a sequence-zero packet it then disables IBS, +marks memdump collection active, and reads the advertised dump size. + +If the controller reports a zero dump size, the error path frees the +local qca_memdump object and returns without clearing qca->qca_memdump +or undoing the collection state. A later memdump work item initializes +its local pointer from qca->qca_memdump and skips allocation when that +pointer is non-NULL, so it can operate on freed memory. The stale +collection and IBS-disabled flags can also leave waiters or later +transmit handling blocked behind an aborted dump. + +Clear the saved pointer and memdump state before returning from the +invalid-size path, matching the cleanup used when hci_devcd_init() fails. + +A static analysis checker reported the stale memdump state, and manual +source review confirmed the invalid-size failure path. + +Fixes: 06d3fdfcdf5c ("Bluetooth: hci_qca: Add qcom devcoredump support") +Signed-off-by: Ruoyu Wang +Reviewed-by: Paul Menzel +Reviewed-by: Zijun Hu +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + drivers/bluetooth/hci_qca.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c +index c649a3f702c042..b510b03dae870f 100644 +--- a/drivers/bluetooth/hci_qca.c ++++ b/drivers/bluetooth/hci_qca.c +@@ -1083,6 +1083,10 @@ static void qca_controller_memdump(struct work_struct *work) + if (!(qca_memdump->ram_dump_size)) { + bt_dev_err(hu->hdev, "Rx invalid memdump size"); + kfree(qca_memdump); ++ qca->qca_memdump = NULL; ++ qca->memdump_state = QCA_MEMDUMP_COLLECTED; ++ clear_and_wake_up_bit(QCA_MEMDUMP_COLLECTION, &qca->flags); ++ clear_bit(QCA_IBS_DISABLED, &qca->flags); + kfree_skb(skb); + mutex_unlock(&qca->hci_memdump_lock); + return; +-- +2.53.0 + diff --git a/queue-6.18/bluetooth-hci_sync-extend-conn_hash-lookup-critical-.patch b/queue-6.18/bluetooth-hci_sync-extend-conn_hash-lookup-critical-.patch new file mode 100644 index 0000000000..5ce5bff2a8 --- /dev/null +++ b/queue-6.18/bluetooth-hci_sync-extend-conn_hash-lookup-critical-.patch @@ -0,0 +1,193 @@ +From bd174f5559e4720fd3022438ffd02a2958c47df2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 10 Jul 2026 11:23:40 +0300 +Subject: Bluetooth: hci_sync: extend conn_hash lookup critical sections + +From: Pauli Virtanen + +[ Upstream commit d5efd6e4b8b0634af6843178fe1a7dd2b2178a3d ] + +Using RCU-protected pointers outside the critical sections without +refcount is incorrect and may result to UAF. + +Extend critical section to cover both hci_conn_hash lookup and use of +the returned conn. + +Add surrounding rcu_read_lock() also when return value is not used, in +preparation for RCU lockdep requirement to hci_lookup_le_connect(). + +This avoids concurrent deletion of the conn before we are done +dereferencing it. + +Also, make sure to hold hdev->lock when accessing hdev->accept_list. + +Fixes: 6d0417e4e1cf ("Bluetooth: hci_conn: Fix not setting conn_timeout for Broadcast Receiver") +Signed-off-by: Pauli Virtanen +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/hci_sync.c | 42 +++++++++++++++++++++++++++++++++++++--- + 1 file changed, 39 insertions(+), 3 deletions(-) + +diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c +index a8404027724de8..651caa4a05d36e 100644 +--- a/net/bluetooth/hci_sync.c ++++ b/net/bluetooth/hci_sync.c +@@ -1054,14 +1054,19 @@ static int hci_set_random_addr_sync(struct hci_dev *hdev, bdaddr_t *rpa) + * In this kind of scenario skip the update and let the random + * address be updated at the next cycle. + */ ++ rcu_read_lock(); ++ + if (bacmp(&hdev->random_addr, BDADDR_ANY) && + (hci_dev_test_flag(hdev, HCI_LE_ADV) || + hci_lookup_le_connect(hdev))) { + bt_dev_dbg(hdev, "Deferring random address update"); + hci_dev_set_flag(hdev, HCI_RPA_EXPIRED); ++ rcu_read_unlock(); + return 0; + } + ++ rcu_read_unlock(); ++ + return __hci_cmd_sync_status(hdev, HCI_OP_LE_SET_RANDOM_ADDR, + 6, rpa, HCI_CMD_TIMEOUT); + } +@@ -2647,12 +2652,17 @@ static int hci_pause_addr_resolution(struct hci_dev *hdev) + /* Cannot disable addr resolution if scanning is enabled or + * when initiating an LE connection. + */ ++ rcu_read_lock(); ++ + if (hci_dev_test_flag(hdev, HCI_LE_SCAN) || + hci_lookup_le_connect(hdev)) { ++ rcu_read_unlock(); + bt_dev_err(hdev, "Command not allowed when scan/LE connect"); + return -EPERM; + } + ++ rcu_read_unlock(); ++ + /* Cannot disable addr resolution if advertising is enabled. */ + err = hci_pause_advertising_sync(hdev); + if (err) { +@@ -2790,6 +2800,8 @@ static u8 hci_update_accept_list_sync(struct hci_dev *hdev) + if (hci_dev_test_flag(hdev, HCI_PA_SYNC)) { + struct hci_conn *conn; + ++ rcu_read_lock(); ++ + conn = hci_conn_hash_lookup_create_pa_sync(hdev); + if (conn) { + struct conn_params pa; +@@ -2799,6 +2811,8 @@ static u8 hci_update_accept_list_sync(struct hci_dev *hdev) + bacpy(&pa.addr, &conn->dst); + pa.addr_type = conn->dst_type; + ++ rcu_read_unlock(); ++ + /* Clear first since there could be addresses left + * behind. + */ +@@ -2808,6 +2822,8 @@ static u8 hci_update_accept_list_sync(struct hci_dev *hdev) + err = hci_le_add_accept_list_sync(hdev, &pa, + &num_entries); + goto done; ++ } else { ++ rcu_read_unlock(); + } + } + +@@ -2818,10 +2834,13 @@ static u8 hci_update_accept_list_sync(struct hci_dev *hdev) + * the controller. + */ + list_for_each_entry_safe(b, t, &hdev->le_accept_list, list) { +- if (hci_conn_hash_lookup_le(hdev, &b->bdaddr, b->bdaddr_type)) ++ rcu_read_lock(); ++ ++ if (hci_conn_hash_lookup_le(hdev, &b->bdaddr, b->bdaddr_type)) { ++ rcu_read_unlock(); + continue; ++ } + +- /* Pointers not dereferenced, no locks needed */ + pend_conn = hci_pend_le_action_lookup(&hdev->pend_le_conns, + &b->bdaddr, + b->bdaddr_type); +@@ -2829,6 +2848,8 @@ static u8 hci_update_accept_list_sync(struct hci_dev *hdev) + &b->bdaddr, + b->bdaddr_type); + ++ rcu_read_unlock(); ++ + /* If the device is not likely to connect or report, + * remove it from the acceptlist. + */ +@@ -2955,6 +2976,8 @@ static int hci_le_set_ext_scan_param_sync(struct hci_dev *hdev, u8 type, + if (sent) { + struct hci_conn *conn; + ++ rcu_read_lock(); ++ + conn = hci_conn_hash_lookup_ba(hdev, PA_LINK, + &sent->bdaddr); + if (conn) { +@@ -2979,8 +3002,12 @@ static int hci_le_set_ext_scan_param_sync(struct hci_dev *hdev, u8 type, + phy++; + } + ++ rcu_read_unlock(); ++ + if (num_phy) + goto done; ++ } else { ++ rcu_read_unlock(); + } + } + } +@@ -3231,12 +3258,16 @@ int hci_update_passive_scan_sync(struct hci_dev *hdev) + /* If there is at least one pending LE connection, we should + * keep the background scan running. + */ ++ bool exists; + + /* If controller is connecting, we should not start scanning + * since some controllers are not able to scan and connect at + * the same time. + */ +- if (hci_lookup_le_connect(hdev)) ++ rcu_read_lock(); ++ exists = hci_lookup_le_connect(hdev); ++ rcu_read_unlock(); ++ if (exists) + return 0; + + bt_dev_dbg(hdev, "start background scanning"); +@@ -3451,6 +3482,7 @@ int hci_write_fast_connectable_sync(struct hci_dev *hdev, bool enable) + } + + static bool disconnected_accept_list_entries(struct hci_dev *hdev) ++ __must_hold(&hdev->lock) + { + struct bdaddr_list *b; + +@@ -3491,12 +3523,16 @@ int hci_update_scan_sync(struct hci_dev *hdev) + if (hdev->scanning_paused) + return 0; + ++ hci_dev_lock(hdev); ++ + if (hci_dev_test_flag(hdev, HCI_CONNECTABLE) || + disconnected_accept_list_entries(hdev)) + scan = SCAN_PAGE; + else + scan = SCAN_DISABLED; + ++ hci_dev_unlock(hdev); ++ + if (hci_dev_test_flag(hdev, HCI_DISCOVERABLE)) + scan |= SCAN_INQUIRY; + +-- +2.53.0 + diff --git a/queue-6.18/bluetooth-mgmt-fix-locking-in-unpair_device-disconne.patch b/queue-6.18/bluetooth-mgmt-fix-locking-in-unpair_device-disconne.patch new file mode 100644 index 0000000000..0c3c09b518 --- /dev/null +++ b/queue-6.18/bluetooth-mgmt-fix-locking-in-unpair_device-disconne.patch @@ -0,0 +1,88 @@ +From 388f30bacb0a8e5a3b42914f547ded7cd8ebea97 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 10 Jul 2026 11:23:41 +0300 +Subject: Bluetooth: mgmt: fix locking in unpair_device/disconnect_sync + +From: Pauli Virtanen + +[ Upstream commit 16cd66443957e4ad42155c6fec401012f600c6f8 ] + +Dereferencing RCU-protected pointers outside critical sections is +invalid and may lead to UAF. + +Take hdev->lock for hci_conn lookup and hci_abort_conn(). Don't use RCU +to ensure the conn is fully initialized at this point. + +Fixes: 227a0cdf4a028 ("Bluetooth: MGMT: Fix not generating command complete for MGMT_OP_DISCONNECT") +Signed-off-by: Pauli Virtanen +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/mgmt.c | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + +diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c +index 4c8b172e85d006..0ef1192e5e452e 100644 +--- a/net/bluetooth/mgmt.c ++++ b/net/bluetooth/mgmt.c +@@ -3082,6 +3082,8 @@ static int unpair_device_sync(struct hci_dev *hdev, void *data) + struct mgmt_cp_unpair_device *cp = cmd->param; + struct hci_conn *conn; + ++ hci_dev_lock(hdev); ++ + if (cp->addr.type == BDADDR_BREDR) + conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, + &cp->addr.bdaddr); +@@ -3089,6 +3091,11 @@ static int unpair_device_sync(struct hci_dev *hdev, void *data) + conn = hci_conn_hash_lookup_le(hdev, &cp->addr.bdaddr, + le_addr_type(cp->addr.type)); + ++ if (conn) ++ hci_conn_get(conn); ++ ++ hci_dev_unlock(hdev); ++ + if (!conn) + return 0; + +@@ -3096,6 +3103,7 @@ static int unpair_device_sync(struct hci_dev *hdev, void *data) + * will clean up the connection no matter the error. + */ + hci_abort_conn(conn, HCI_ERROR_REMOTE_USER_TERM); ++ hci_conn_put(conn); + + return 0; + } +@@ -3243,6 +3251,8 @@ static int disconnect_sync(struct hci_dev *hdev, void *data) + struct mgmt_cp_disconnect *cp = cmd->param; + struct hci_conn *conn; + ++ hci_dev_lock(hdev); ++ + if (cp->addr.type == BDADDR_BREDR) + conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, + &cp->addr.bdaddr); +@@ -3250,6 +3260,11 @@ static int disconnect_sync(struct hci_dev *hdev, void *data) + conn = hci_conn_hash_lookup_le(hdev, &cp->addr.bdaddr, + le_addr_type(cp->addr.type)); + ++ if (conn) ++ hci_conn_get(conn); ++ ++ hci_dev_unlock(hdev); ++ + if (!conn) + return -ENOTCONN; + +@@ -3257,6 +3272,7 @@ static int disconnect_sync(struct hci_dev *hdev, void *data) + * will clean up the connection no matter the error. + */ + hci_abort_conn(conn, HCI_ERROR_REMOTE_USER_TERM); ++ hci_conn_put(conn); + + return 0; + } +-- +2.53.0 + diff --git a/queue-6.18/bluetooth-mgmt-hold-reference-for-hci_conn-in-mgmt_p.patch b/queue-6.18/bluetooth-mgmt-hold-reference-for-hci_conn-in-mgmt_p.patch new file mode 100644 index 0000000000..f9700d731e --- /dev/null +++ b/queue-6.18/bluetooth-mgmt-hold-reference-for-hci_conn-in-mgmt_p.patch @@ -0,0 +1,107 @@ +From b98ea4835443e40bf36e6911cf7dcbf88f67fcfa Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 10 Jul 2026 11:23:42 +0300 +Subject: Bluetooth: mgmt: hold reference for hci_conn in mgmt_pending_cmds + +From: Pauli Virtanen + +[ Upstream commit da55f570191d5d72f10c607a7043b947eb05ea46 ] + +Dereferencing RCU-protected pointers outside critical sections is +invalid and may lead to UAF. Use of hci_conn in hci_sync callbacks also +needs to hold refcount to avoid UAF. + +Take appropriate locks for hci_conn lookups, and take refcount for +hci_conn pointers stored in mgmt_pending_cmd so that the pointer stays +valid. + +When accessing conn->state, ensure hdev->lock is held to avoid data +race. + +Fixes: 7b445e220db9 ("Bluetooth: MGMT: Fix holding hci_conn reference while command is queued") +Signed-off-by: Pauli Virtanen +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/mgmt.c | 26 ++++++++++++++++++++++---- + 1 file changed, 22 insertions(+), 4 deletions(-) + +diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c +index 0ef1192e5e452e..79eb605be2804c 100644 +--- a/net/bluetooth/mgmt.c ++++ b/net/bluetooth/mgmt.c +@@ -7325,6 +7325,9 @@ static void get_conn_info_complete(struct hci_dev *hdev, void *data, int err) + rp.max_tx_power = HCI_TX_POWER_INVALID; + } + ++ if (conn) ++ hci_conn_put(conn); ++ + mgmt_cmd_complete(cmd->sk, cmd->hdev->id, MGMT_OP_GET_CONN_INFO, status, + &rp, sizeof(rp)); + +@@ -7339,6 +7342,8 @@ static int get_conn_info_sync(struct hci_dev *hdev, void *data) + int err; + __le16 handle; + ++ hci_dev_lock(hdev); ++ + /* Make sure we are still connected */ + if (cp->addr.type == BDADDR_BREDR) + conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, +@@ -7346,12 +7351,16 @@ static int get_conn_info_sync(struct hci_dev *hdev, void *data) + else + conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr); + +- if (!conn || conn->state != BT_CONNECTED) ++ if (!conn || conn->state != BT_CONNECTED) { ++ hci_dev_unlock(hdev); + return MGMT_STATUS_NOT_CONNECTED; ++ } + +- cmd->user_data = conn; ++ cmd->user_data = hci_conn_get(conn); + handle = cpu_to_le16(conn->handle); + ++ hci_dev_unlock(hdev); ++ + /* Refresh RSSI each time */ + err = hci_read_rssi_sync(hdev, handle); + +@@ -7485,6 +7494,9 @@ static void get_clock_info_complete(struct hci_dev *hdev, void *data, int err) + } + + complete: ++ if (conn) ++ hci_conn_put(conn); ++ + mgmt_cmd_complete(cmd->sk, cmd->hdev->id, cmd->opcode, status, &rp, + sizeof(rp)); + +@@ -7501,15 +7513,21 @@ static int get_clock_info_sync(struct hci_dev *hdev, void *data) + memset(&hci_cp, 0, sizeof(hci_cp)); + hci_read_clock_sync(hdev, &hci_cp); + ++ hci_dev_lock(hdev); ++ + /* Make sure connection still exists */ + conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->addr.bdaddr); +- if (!conn || conn->state != BT_CONNECTED) ++ if (!conn || conn->state != BT_CONNECTED) { ++ hci_dev_unlock(hdev); + return MGMT_STATUS_NOT_CONNECTED; ++ } + +- cmd->user_data = conn; ++ cmd->user_data = hci_conn_get(conn); + hci_cp.handle = cpu_to_le16(conn->handle); + hci_cp.which = 0x01; /* Piconet clock */ + ++ hci_dev_unlock(hdev); ++ + return hci_read_clock_sync(hdev, &hci_cp); + } + +-- +2.53.0 + diff --git a/queue-6.18/bluetooth-mgmt-revalidate-load_conn_param-queued-upd.patch b/queue-6.18/bluetooth-mgmt-revalidate-load_conn_param-queued-upd.patch new file mode 100644 index 0000000000..3528f6163d --- /dev/null +++ b/queue-6.18/bluetooth-mgmt-revalidate-load_conn_param-queued-upd.patch @@ -0,0 +1,131 @@ +From 6709dfd15a30e38b2f47b9898dbece5c60b0baf8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 7 Jul 2026 12:15:18 +0800 +Subject: Bluetooth: MGMT: revalidate LOAD_CONN_PARAM queued update + +From: Cen Zhang + +[ Upstream commit 2bf282f8f715f5d05d6f4c49ffb3bd241c5e667e ] + +MGMT_OP_LOAD_CONN_PARAM queues conn_update_sync() when a single parameter +update changes an existing LE central connection. The queued work currently +stores a borrowed hci_conn_params entry from hdev->le_conn_params. A later +LOAD_CONN_PARAM request can clear disabled parameters and free that entry +before hci_cmd_sync_work() runs the queued callback. + +Do not keep the borrowed hci_conn_params pointer in queued work. Queue the +hci_conn instead and hold a reference until the queued callback completes. +When the work runs, revalidate that the connection is still present, look +up the current hci_conn_params entry, and cancel the update if userspace +removed that entry while the work was pending. + +Copy the interval values from the current params entry under hdev->lock, +then drop the lock and keep using hci_le_conn_update_sync() to issue the +update. + +Validation reproduced this kernel report: +BUG: KASAN: slab-use-after-free in conn_update_sync+0x2a/0xf0 [bluetooth] +Read of size 1 at addr ffff88810c697126 by task kworker/u17:0/377 +Workqueue: hci0 hci_cmd_sync_work [bluetooth] + +Call Trace: + + dump_stack_lvl+0x66/0xa0 + print_report+0xce/0x5f0 + kasan_report+0xe0/0x110 + conn_update_sync+0x2a/0xf0 [bluetooth] + hci_cmd_sync_work+0x187/0x210 [bluetooth] + process_one_work+0x4fd/0xbc0 + worker_thread+0x2d8/0x570 + kthread+0x1ad/0x1f0 + ret_from_fork+0x3c9/0x540 + ret_from_fork_asm+0x1a/0x30 + +Allocated by task 466: + hci_conn_params_add+0xa6/0x240 [bluetooth] + load_conn_param+0x4e1/0x850 [bluetooth] + hci_sock_sendmsg+0x96b/0xf80 [bluetooth] + +Freed by task 474: + kfree+0x313/0x590 + hci_conn_params_clear_disabled+0x9b/0xc0 [bluetooth] + load_conn_param+0x4bf/0x850 [bluetooth] + hci_sock_sendmsg+0x96b/0xf80 [bluetooth] + +Fixes: 0ece498c27d8c ("Bluetooth: MGMT: Make MGMT_OP_LOAD_CONN_PARAM update existing connection") +Suggested-by: Luiz Augusto von Dentz +Assisted-by: Codex:gpt-5.5 +Signed-off-by: Cen Zhang +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/mgmt.c | 44 +++++++++++++++++++++++++++++++++++--------- + 1 file changed, 35 insertions(+), 9 deletions(-) + +diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c +index 410910f64c1c49..4c8b172e85d006 100644 +--- a/net/bluetooth/mgmt.c ++++ b/net/bluetooth/mgmt.c +@@ -7924,14 +7924,36 @@ static int remove_device(struct sock *sk, struct hci_dev *hdev, + + static int conn_update_sync(struct hci_dev *hdev, void *data) + { +- struct hci_conn_params *params = data; +- struct hci_conn *conn; ++ struct hci_conn *conn = data; ++ struct hci_conn_params *params; ++ struct hci_conn_params local = {}; + +- conn = hci_conn_hash_lookup_le(hdev, ¶ms->addr, params->addr_type); +- if (!conn) +- return -ECANCELED; ++ hci_dev_lock(hdev); ++ ++ if (!hci_conn_valid(hdev, conn) || conn->role != HCI_ROLE_MASTER) ++ goto cancel; ++ ++ params = hci_conn_params_lookup(hdev, &conn->dst, conn->dst_type); ++ if (!params) ++ goto cancel; ++ ++ local.conn_min_interval = params->conn_min_interval; ++ local.conn_max_interval = params->conn_max_interval; ++ local.conn_latency = params->conn_latency; ++ local.supervision_timeout = params->supervision_timeout; + +- return hci_le_conn_update_sync(hdev, conn, params); ++ hci_dev_unlock(hdev); ++ ++ return hci_le_conn_update_sync(hdev, conn, &local); ++ ++cancel: ++ hci_dev_unlock(hdev); ++ return -ECANCELED; ++} ++ ++static void conn_update_sync_destroy(struct hci_dev *hdev, void *data, int err) ++{ ++ hci_conn_put(data); + } + + static int load_conn_param(struct sock *sk, struct hci_dev *hdev, void *data, +@@ -8041,9 +8063,13 @@ static int load_conn_param(struct sock *sk, struct hci_dev *hdev, void *data, + (conn->le_conn_min_interval != min || + conn->le_conn_max_interval != max || + conn->le_conn_latency != latency || +- conn->le_supv_timeout != timeout)) +- hci_cmd_sync_queue(hdev, conn_update_sync, +- hci_param, NULL); ++ conn->le_supv_timeout != timeout)) { ++ hci_conn_get(conn); ++ if (hci_cmd_sync_queue(hdev, conn_update_sync, ++ conn, ++ conn_update_sync_destroy) < 0) ++ hci_conn_put(conn); ++ } + } + } + +-- +2.53.0 + diff --git a/queue-6.18/bluetooth-qca-fix-nvm-tag-length-underflow-in-tlv-pa.patch b/queue-6.18/bluetooth-qca-fix-nvm-tag-length-underflow-in-tlv-pa.patch new file mode 100644 index 0000000000..4e06729c44 --- /dev/null +++ b/queue-6.18/bluetooth-qca-fix-nvm-tag-length-underflow-in-tlv-pa.patch @@ -0,0 +1,68 @@ +From 103e94ee11876df59d78882d3f385a804e1077da Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 4 Jul 2026 16:10:30 -0700 +Subject: Bluetooth: qca: fix NVM tag length underflow in TLV parser + +From: Xiang Mei + +[ Upstream commit c90164ca0f7036942ba088eb7ea8d3f6c2352020 ] + +In the TLV_TYPE_NVM branch of qca_tlv_check_data() the tag loop bound is +"while (idx < length - sizeof(struct tlv_type_nvm))". "length" is a signed +int from the firmware TLV header and sizeof(struct tlv_type_nvm) is a +size_t (12), so "length" is converted to size_t and any firmware-supplied +"length" < 12 makes the subtraction wrap to a huge value. The loop body +then reads a 12-byte struct tlv_type_nvm past the end of the short +vmalloc'd firmware buffer (and the EDL_TAG_ID_* handlers can write past it). + +Rewrite the bound as "idx + sizeof(struct tlv_type_nvm) <= length"; both +operands are non-negative, so it no longer underflows and a "length" too +small for one record correctly skips the loop. + + BUG: KASAN: vmalloc-out-of-bounds in qca_download_firmware.isra.0 (drivers/bluetooth/btqca.c:421) + Read of size 2 at addr ffffc900000e5004 by task kworker/u9:0/52 + Workqueue: hci0 hci_power_on + Call Trace: + ... + kasan_report (mm/kasan/report.c:595) + qca_download_firmware.isra.0 (drivers/bluetooth/btqca.c:421 drivers/bluetooth/btqca.c:617) + qca_uart_setup (drivers/bluetooth/btqca.c:948) + qca_setup (drivers/bluetooth/hci_qca.c:2029) + hci_uart_setup (drivers/bluetooth/hci_ldisc.c:438) + hci_dev_open_sync (net/bluetooth/hci_sync.c:5227) + hci_power_on (net/bluetooth/hci_core.c:920) + process_one_work (kernel/workqueue.c:3322) + worker_thread (kernel/workqueue.c:3486) + kthread (kernel/kthread.c:436) + ret_from_fork (arch/x86/kernel/process.c:158) + ret_from_fork_asm (arch/x86/entry/entry_64.S:245) + +Fixes: 2e4edfa1e2bd ("Bluetooth: qca: add missing firmware sanity checks") +Reported-by: Weiming Shi +Assisted-by: Claude:claude-opus-4-8 +Signed-off-by: Xiang Mei +Reported-by: Weiming Shi +Reviewed-by: Johan Hovold +Acked-by: Bartosz Golaszewski +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + drivers/bluetooth/btqca.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/bluetooth/btqca.c b/drivers/bluetooth/btqca.c +index 86a48d009d1ba2..afab479ac89448 100644 +--- a/drivers/bluetooth/btqca.c ++++ b/drivers/bluetooth/btqca.c +@@ -413,7 +413,7 @@ static int qca_tlv_check_data(struct hci_dev *hdev, + + idx = 0; + data = tlv->data; +- while (idx < length - sizeof(struct tlv_type_nvm)) { ++ while (idx + sizeof(struct tlv_type_nvm) <= length) { + tlv_nvm = (struct tlv_type_nvm *)(data + idx); + + tag_id = le16_to_cpu(tlv_nvm->tag_id); +-- +2.53.0 + diff --git a/queue-6.18/bpf-sockmap-reject-unhashed-udp-sockets-on-sockmap-u.patch b/queue-6.18/bpf-sockmap-reject-unhashed-udp-sockets-on-sockmap-u.patch new file mode 100644 index 0000000000..683a8b3d7b --- /dev/null +++ b/queue-6.18/bpf-sockmap-reject-unhashed-udp-sockets-on-sockmap-u.patch @@ -0,0 +1,74 @@ +From c3c1459465ebd5f82daa1c053b57917a83cc13c8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 7 Jul 2026 06:23:57 +0200 +Subject: bpf, sockmap: Reject unhashed UDP sockets on sockmap update + +From: Michal Luczaj + +[ Upstream commit 66efd3368ae10d05e08fbe6425b50fdec7186ac7 ] + +UDP sockets get SOCK_RCU_FREE set when (auto-)bound. This means +sk_is_refcounted(unbound) = true, while sk_is_refcounted(bound) = false. + +Because sockmap accepts unbound UDP sockets, a BPF program can increment a +socket's refcount via lookup. If the socket is subsequently bound, the +transition from unbound to bound causes bpf_sk_release() to skip the +decrement of the refcount, causing a memory leak. + +unreferenced object 0xffff88810bc2eb40 (size 1984): + comm "test_progs", pid 2451, jiffies 4295320596 + hex dump (first 32 bytes): + 7f 00 00 01 7f 00 00 01 d2 04 1b b7 04 d2 00 00 ................ + 02 00 01 40 00 00 00 00 00 00 00 00 00 00 00 00 ...@............ + backtrace (crc bdee079d): + kmem_cache_alloc_noprof+0x557/0x660 + sk_prot_alloc+0x69/0x240 + sk_alloc+0x30/0x460 + inet_create+0x2ce/0xf80 + __sock_create+0x25b/0x5c0 + __sys_socket+0x119/0x1d0 + __x64_sys_socket+0x72/0xd0 + do_syscall_64+0xa1/0x5f0 + entry_SYSCALL_64_after_hwframe+0x76/0x7e + +Instead of special-casing for refcounted sockets, reject unhashed UDP +sockets during sockmap updates, as there is no benefit to supporting those. +This effectively reverts the commit under Fixes, with two exceptions: + +1. sock_map_sk_state_allowed() maintains a fall-through `return true`. +2. In the spirit of commit b8b8315e39ff ("bpf, sockmap: Remove unhash + handler for BPF sockmap usage"), the proto::unhash BPF handler is not + reintroduced. + +Historical note: this issue is related to commit 67312adc96b5 ("bpf: reject +unhashed sockets in bpf_sk_assign"). + +Fixes: 0c48eefae712 ("sock_map: Lift socket state restriction for datagram sockets") +Suggested-by: Kuniyuki Iwashima +Signed-off-by: Michal Luczaj +Reviewed-by: Kuniyuki Iwashima +Reviewed-by: Jakub Sitnicki +Reviewed-by: John Fastabend +Link: https://lore.kernel.org/bpf/20260707-sockmap-lookup-udp-leak-v4-2-f878346f27ab@rbox.co +Signed-off-by: Kumar Kartikeya Dwivedi +Signed-off-by: Sasha Levin +--- + net/core/sock_map.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/net/core/sock_map.c b/net/core/sock_map.c +index 5947b38e4f8b6f..70bbc78fb079f7 100644 +--- a/net/core/sock_map.c ++++ b/net/core/sock_map.c +@@ -542,6 +542,8 @@ static bool sock_map_sk_state_allowed(const struct sock *sk) + { + if (sk_is_tcp(sk)) + return (1 << sk->sk_state) & (TCPF_ESTABLISHED | TCPF_LISTEN); ++ if (sk_is_udp(sk)) ++ return sk_hashed(sk); + if (sk_is_stream_unix(sk)) + return (1 << sk->sk_state) & TCPF_ESTABLISHED; + if (sk_is_vsock(sk) && +-- +2.53.0 + diff --git a/queue-6.18/btrfs-fallback-to-transaction-csum-tree-on-a-commit-.patch b/queue-6.18/btrfs-fallback-to-transaction-csum-tree-on-a-commit-.patch new file mode 100644 index 0000000000..c854ebd144 --- /dev/null +++ b/queue-6.18/btrfs-fallback-to-transaction-csum-tree-on-a-commit-.patch @@ -0,0 +1,92 @@ +From 4682a68a4c4295fcfc9bb5346e066e9d085ab158 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 11 Jun 2026 14:40:17 -0700 +Subject: btrfs: fallback to transaction csum tree on a commit root csum miss + +From: Boris Burkov + +[ Upstream commit 3dcd50730814e5220072d2b26d0587af6bfb6dbe ] + +We have been running with commit root csums enabled for some time and +have noticed a slight uptick in zero csum errors. Investigating those +revealed that they were same transaction reads of extents that were just +relocated, but the extent map generation was long ago. + +It turns out that relocation intentionally does not update the extent +generation (replace_file_extents()), but must write a new csum since the +data has moved, so we must account for this with commit root csum reading. + +Luckily this is a short lived condition: after the relocation transaction +the commit root will once again have the csum. So we can add a generic +fallback to the lookup to try again with the transaction csum root. + +Fixes: f07b855c56b1 ("btrfs: try to search for data csums in commit root") +Reviewed-by: Filipe Manana +Signed-off-by: Boris Burkov +Signed-off-by: David Sterba +Signed-off-by: Sasha Levin +--- + fs/btrfs/file-item.c | 26 +++++++++++++++++++++++++- + 1 file changed, 25 insertions(+), 1 deletion(-) + +diff --git a/fs/btrfs/file-item.c b/fs/btrfs/file-item.c +index a2f851eaadca06..9b19b33e85b687 100644 +--- a/fs/btrfs/file-item.c ++++ b/fs/btrfs/file-item.c +@@ -350,6 +350,7 @@ int btrfs_lookup_bio_sums(struct btrfs_bio *bbio) + const unsigned int nblocks = orig_len >> fs_info->sectorsize_bits; + int ret = 0; + u32 bio_offset = 0; ++ bool using_commit_root = false; + + if ((inode->flags & BTRFS_INODE_NODATASUM) || + test_bit(BTRFS_FS_STATE_NO_DATA_CSUMS, &fs_info->fs_state)) +@@ -423,6 +424,7 @@ int btrfs_lookup_bio_sums(struct btrfs_bio *bbio) + * from across transactions. + */ + if (bbio->csum_search_commit_root) { ++ using_commit_root = true; + path->search_commit_root = true; + path->skip_locking = true; + down_read(&fs_info->commit_root_sem); +@@ -455,6 +457,28 @@ int btrfs_lookup_bio_sums(struct btrfs_bio *bbio) + * assume this is the case. + */ + if (count == 0) { ++ /* ++ * If an extent is relocated in the current transaction ++ * then relocation writes a new csum without updating ++ * the extent map generation. Until the next commit, we ++ * will see a hole in that case, so we need to fallback ++ * to searching the transaction csum root. ++ * ++ * Note that a commit root lookup of a referenced extent can ++ * only miss, not return a stale csum. A freed extent's csum ++ * is deleted in the same transaction and its bytenr is not ++ * reusable until that transaction has committed and the ++ * extent is unpinned. ++ */ ++ if (using_commit_root) { ++ up_read(&fs_info->commit_root_sem); ++ using_commit_root = false; ++ path->search_commit_root = false; ++ path->skip_locking = false; ++ btrfs_release_path(path); ++ continue; ++ } ++ + memset(csum_dst, 0, csum_size); + count = 1; + +@@ -473,7 +497,7 @@ int btrfs_lookup_bio_sums(struct btrfs_bio *bbio) + bio_offset += count * sectorsize; + } + +- if (bbio->csum_search_commit_root) ++ if (using_commit_root) + up_read(&fs_info->commit_root_sem); + return ret; + } +-- +2.53.0 + diff --git a/queue-6.18/btrfs-fix-root-leak-if-its-reloc-root-is-unexpected-.patch b/queue-6.18/btrfs-fix-root-leak-if-its-reloc-root-is-unexpected-.patch new file mode 100644 index 0000000000..d386ddda16 --- /dev/null +++ b/queue-6.18/btrfs-fix-root-leak-if-its-reloc-root-is-unexpected-.patch @@ -0,0 +1,40 @@ +From 60d215f225a2032a43dd753403713225c06217ba Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 11 Jun 2026 15:16:21 +0100 +Subject: btrfs: fix root leak if its reloc root is unexpected in + merge_reloc_roots() + +From: Filipe Manana + +[ Upstream commit ce6050bafb4e33377dc17fcc357736bfc351180c ] + +If we have an unexpected reloc_root for our root, we jump to the out label +but never drop the reference we obtained for root, resulting in a leak. +Add a missing btrfs_put_root() call. + +Fixes: 24213fa46c70 ("btrfs: do proper error handling in merge_reloc_roots") +Reviewed-by: Qu Wenruo +Reviewed-by: Johannes Thumshirn +Signed-off-by: Filipe Manana +Reviewed-by: David Sterba +Signed-off-by: David Sterba +Signed-off-by: Sasha Levin +--- + fs/btrfs/relocation.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c +index fc76013b1a3e01..ea68328d289cba 100644 +--- a/fs/btrfs/relocation.c ++++ b/fs/btrfs/relocation.c +@@ -1857,6 +1857,7 @@ void merge_reloc_roots(struct reloc_control *rc) + * corruption, e.g. bad reloc tree key offset. + */ + ret = -EINVAL; ++ btrfs_put_root(root); + goto out; + } + ret = merge_reloc_root(rc, root); +-- +2.53.0 + diff --git a/queue-6.18/btrfs-reject-free-space-cache-with-more-entries-than.patch b/queue-6.18/btrfs-reject-free-space-cache-with-more-entries-than.patch new file mode 100644 index 0000000000..ba58a907ce --- /dev/null +++ b/queue-6.18/btrfs-reject-free-space-cache-with-more-entries-than.patch @@ -0,0 +1,88 @@ +From bf749f2fdd002d98273707f500af4488e493c66c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 10 Jun 2026 10:29:26 -0700 +Subject: btrfs: reject free space cache with more entries than pages + +From: Xiang Mei + +[ Upstream commit a2d8d5647ed854e38f941741aea45b9eb15a6350 ] + +When loading a v1 free space cache, __load_free_space_cache() takes +num_entries and num_bitmaps straight from the on-disk +btrfs_free_space_header. That header is stored in the tree_root under a key +with type 0, which the tree-checker has no case for, so neither count is +validated before the load trusts it. + +The load loops num_entries times and maps the next page whenever the current +one runs out, going through io_ctl_check_crc() -> io_ctl_map_page(), which +does io_ctl->pages[io_ctl->index++]. But pages[] is allocated in +io_ctl_init() from the cache inode's i_size, not from num_entries: + + num_pages = DIV_ROUND_UP(i_size_read(inode), PAGE_SIZE); + io_ctl->pages = kcalloc(num_pages, sizeof(struct page *), GFP_NOFS); + +So if num_entries claims more records than the pages can hold, io_ctl->index +runs off the end of pages[]. The write side never hits this because +io_ctl_add_entry() and io_ctl_add_bitmap() both stop once +io_ctl->index >= io_ctl->num_pages; the read side just never had the same +check. + +To trigger it, take a clean cache (num_entries = here), set num_entries +in the header to 0x10000, and fix up the leaf checksum so it still passes +the tree-checker. The cache inode has i_size = 65536, so num_pages is 16 and +pages[] is a 16-pointer (kmalloc-128) array. The load now tries to read +65536 entries, io_ctl->index walks up to 16, and pages[16] is read past the +array: + + BUG: KASAN: slab-out-of-bounds in io_ctl_check_crc (fs/btrfs/free-space-cache.c:420 fs/btrfs/free-space-cache.c:565) + Read of size 8 at addr ffff88800c833a80 by task kworker/u8:3/58 + io_ctl_check_crc (fs/btrfs/free-space-cache.c:420 fs/btrfs/free-space-cache.c:565) + __load_free_space_cache (fs/btrfs/free-space-cache.c:655 fs/btrfs/free-space-cache.c:820) + load_free_space_cache (fs/btrfs/free-space-cache.c:1017) + caching_thread (fs/btrfs/block-group.c:880) + btrfs_work_helper (fs/btrfs/async-thread.c:312) + process_one_work + worker_thread + kthread + ret_from_fork + +free-space-cache.c:420 is io_ctl_map_page(), inlined into io_ctl_check_crc() +at line 565, which is why that is the frame KASAN names. The out-of-bounds +slot is then treated as a struct page and handed to crc32c(), so the bad +read turns into a GP fault. + +Add the missing check to io_ctl_check_crc(), which is where both the entry +loop and the bitmap loop end up. When num_entries is too large the load now +fails like any corrupt cache: __load_free_space_cache() drops it and rebuilds +the free space from the extent tree, so a valid cache is never rejected. + +Reported-by: Weiming Shi +Fixes: 5b0e95bf607d ("Btrfs: inline checksums into the disk free space cache") +Link: https://lore.kernel.org/linux-btrfs/CAPpSM+RMPByMCKXvM5QFKToxsyNccfuFLWMdD0mfd0wh2Ja62w@mail.gmail.com/ +Assisted-by: Claude:claude-opus-4-8 +Reviewed-by: Qu Wenruo +Signed-off-by: Xiang Mei +Reviewed-by: David Sterba +Signed-off-by: David Sterba +Signed-off-by: Sasha Levin +--- + fs/btrfs/free-space-cache.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c +index ab873bd6719209..9828da12765f5c 100644 +--- a/fs/btrfs/free-space-cache.c ++++ b/fs/btrfs/free-space-cache.c +@@ -554,6 +554,9 @@ static int io_ctl_check_crc(struct btrfs_io_ctl *io_ctl, int index) + u32 crc = ~(u32)0; + unsigned offset = 0; + ++ if (index >= io_ctl->num_pages) ++ return -EIO; ++ + if (index == 0) + offset = sizeof(u32) * io_ctl->num_pages; + +-- +2.53.0 + diff --git a/queue-6.18/btrfs-use-bool-type-for-btrfs_path-members-used-as-b.patch b/queue-6.18/btrfs-use-bool-type-for-btrfs_path-members-used-as-b.patch new file mode 100644 index 0000000000..ee57edd801 --- /dev/null +++ b/queue-6.18/btrfs-use-bool-type-for-btrfs_path-members-used-as-b.patch @@ -0,0 +1,660 @@ +From 4465c4ee97df08c5f2f06664b0ded2b4939da058 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 14 Nov 2025 16:00:04 +0000 +Subject: btrfs: use bool type for btrfs_path members used as booleans + +From: Filipe Manana + +[ Upstream commit d7fe41044b3ac8f9b5965de499a13ac9ae947e79 ] + +Many fields of struct btrfs_path are used as booleans but their type is +an unsigned int (of one 1 bit width to save space). Change the type to +bool keeping the :1 suffix so that they combine with the previous u8 +fields in order to save space. This makes the code more clear by using +explicit true/false and more in line with the preferred style, preserving +the size of the structure. + +Reviewed-by: Johannes Thumshirn +Signed-off-by: Filipe Manana +Reviewed-by: David Sterba +Signed-off-by: David Sterba +Stable-dep-of: 3dcd50730814 ("btrfs: fallback to transaction csum tree on a commit root csum miss") +Signed-off-by: Sasha Levin +--- + fs/btrfs/backref.c | 16 ++++++++-------- + fs/btrfs/block-group.c | 8 ++++---- + fs/btrfs/ctree.c | 28 ++++++++++++++-------------- + fs/btrfs/ctree.h | 16 ++++++++-------- + fs/btrfs/defrag.c | 4 ++-- + fs/btrfs/dev-replace.c | 4 ++-- + fs/btrfs/extent-tree.c | 8 ++++---- + fs/btrfs/file-item.c | 12 ++++++------ + fs/btrfs/free-space-cache.c | 4 ++-- + fs/btrfs/free-space-tree.c | 4 ++-- + fs/btrfs/inode-item.c | 2 +- + fs/btrfs/inode.c | 4 ++-- + fs/btrfs/qgroup.c | 4 ++-- + fs/btrfs/raid-stripe-tree.c | 4 ++-- + fs/btrfs/relocation.c | 8 ++++---- + fs/btrfs/scrub.c | 20 ++++++++++---------- + fs/btrfs/send.c | 14 +++++++------- + fs/btrfs/tree-log.c | 20 ++++++++++---------- + fs/btrfs/volumes.c | 6 +++--- + fs/btrfs/xattr.c | 2 +- + 20 files changed, 94 insertions(+), 94 deletions(-) + +diff --git a/fs/btrfs/backref.c b/fs/btrfs/backref.c +index e050d0938dc45f..0c47b4570a7bf8 100644 +--- a/fs/btrfs/backref.c ++++ b/fs/btrfs/backref.c +@@ -1408,12 +1408,12 @@ static int find_parent_nodes(struct btrfs_backref_walk_ctx *ctx, + if (!path) + return -ENOMEM; + if (!ctx->trans) { +- path->search_commit_root = 1; +- path->skip_locking = 1; ++ path->search_commit_root = true; ++ path->skip_locking = true; + } + + if (ctx->time_seq == BTRFS_SEQ_LAST) +- path->skip_locking = 1; ++ path->skip_locking = true; + + again: + head = NULL; +@@ -1560,7 +1560,7 @@ static int find_parent_nodes(struct btrfs_backref_walk_ctx *ctx, + + btrfs_release_path(path); + +- ret = add_missing_keys(ctx->fs_info, &preftrees, path->skip_locking == 0); ++ ret = add_missing_keys(ctx->fs_info, &preftrees, !path->skip_locking); + if (ret) + goto out; + +@@ -2833,8 +2833,8 @@ struct btrfs_backref_iter *btrfs_backref_iter_alloc(struct btrfs_fs_info *fs_inf + } + + /* Current backref iterator only supports iteration in commit root */ +- ret->path->search_commit_root = 1; +- ret->path->skip_locking = 1; ++ ret->path->search_commit_root = true; ++ ret->path->skip_locking = true; + ret->fs_info = fs_info; + + return ret; +@@ -3307,8 +3307,8 @@ static int handle_indirect_tree_backref(struct btrfs_trans_handle *trans, + level = cur->level + 1; + + /* Search the tree to find parent blocks referring to the block */ +- path->search_commit_root = 1; +- path->skip_locking = 1; ++ path->search_commit_root = true; ++ path->skip_locking = true; + path->lowest_level = level; + ret = btrfs_search_slot(NULL, root, tree_key, path, 0, 0); + path->lowest_level = 0; +diff --git a/fs/btrfs/block-group.c b/fs/btrfs/block-group.c +index 1e57f7d04c47ec..e6bac34ebe83d6 100644 +--- a/fs/btrfs/block-group.c ++++ b/fs/btrfs/block-group.c +@@ -613,8 +613,8 @@ static int sample_block_group_extent_item(struct btrfs_caching_control *caching_ + extent_root = btrfs_extent_root(fs_info, max_t(u64, block_group->start, + BTRFS_SUPER_INFO_OFFSET)); + +- path->skip_locking = 1; +- path->search_commit_root = 1; ++ path->skip_locking = true; ++ path->search_commit_root = true; + path->reada = READA_FORWARD; + + search_offset = index * div_u64(block_group->length, max_index); +@@ -744,8 +744,8 @@ static int load_extent_tree_free(struct btrfs_caching_control *caching_ctl) + * root to add free space. So we skip locking and search the commit + * root, since its read-only + */ +- path->skip_locking = 1; +- path->search_commit_root = 1; ++ path->skip_locking = true; ++ path->search_commit_root = true; + path->reada = READA_FORWARD; + + key.objectid = last; +diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c +index 27e2adc2ee717b..0f2e9f33dd0cbc 100644 +--- a/fs/btrfs/ctree.c ++++ b/fs/btrfs/ctree.c +@@ -1709,9 +1709,9 @@ static struct extent_buffer *btrfs_search_slot_get_root(struct btrfs_root *root, + level = btrfs_header_level(b); + /* + * Ensure that all callers have set skip_locking when +- * p->search_commit_root = 1. ++ * p->search_commit_root is true. + */ +- ASSERT(p->skip_locking == 1); ++ ASSERT(p->skip_locking); + + goto out; + } +@@ -3858,10 +3858,10 @@ static noinline int setup_leaf_for_split(struct btrfs_trans_handle *trans, + } + btrfs_release_path(path); + +- path->keep_locks = 1; +- path->search_for_split = 1; ++ path->keep_locks = true; ++ path->search_for_split = true; + ret = btrfs_search_slot(trans, root, &key, path, 0, 1); +- path->search_for_split = 0; ++ path->search_for_split = false; + if (ret > 0) + ret = -EAGAIN; + if (ret < 0) +@@ -3888,11 +3888,11 @@ static noinline int setup_leaf_for_split(struct btrfs_trans_handle *trans, + if (ret) + goto err; + +- path->keep_locks = 0; ++ path->keep_locks = false; + btrfs_unlock_up_safe(path, 1); + return 0; + err: +- path->keep_locks = 0; ++ path->keep_locks = false; + return ret; + } + +@@ -4610,11 +4610,11 @@ int btrfs_search_forward(struct btrfs_root *root, struct btrfs_key *min_key, + u32 nritems; + int level; + int ret = 1; +- int keep_locks = path->keep_locks; ++ const bool keep_locks = path->keep_locks; + + ASSERT(!path->nowait); + ASSERT(path->lowest_level == 0); +- path->keep_locks = 1; ++ path->keep_locks = true; + again: + cur = btrfs_read_lock_root_node(root); + level = btrfs_header_level(cur); +@@ -4704,7 +4704,7 @@ int btrfs_search_forward(struct btrfs_root *root, struct btrfs_key *min_key, + * 0 is returned if another key is found, < 0 if there are any errors + * and 1 is returned if there are no higher keys in the tree + * +- * path->keep_locks should be set to 1 on the search made before ++ * path->keep_locks should be set to true on the search made before + * calling this function. + */ + int btrfs_find_next_key(struct btrfs_root *root, struct btrfs_path *path, +@@ -4803,13 +4803,13 @@ int btrfs_next_old_leaf(struct btrfs_root *root, struct btrfs_path *path, + next = NULL; + btrfs_release_path(path); + +- path->keep_locks = 1; ++ path->keep_locks = true; + + if (time_seq) { + ret = btrfs_search_old_slot(root, &key, path, time_seq); + } else { + if (path->need_commit_sem) { +- path->need_commit_sem = 0; ++ path->need_commit_sem = false; + need_commit_sem = true; + if (path->nowait) { + if (!down_read_trylock(&fs_info->commit_root_sem)) { +@@ -4822,7 +4822,7 @@ int btrfs_next_old_leaf(struct btrfs_root *root, struct btrfs_path *path, + } + ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); + } +- path->keep_locks = 0; ++ path->keep_locks = false; + + if (ret < 0) + goto done; +@@ -4961,7 +4961,7 @@ int btrfs_next_old_leaf(struct btrfs_root *root, struct btrfs_path *path, + if (need_commit_sem) { + int ret2; + +- path->need_commit_sem = 1; ++ path->need_commit_sem = true; + ret2 = finish_need_commit_sem_search(path); + up_read(&fs_info->commit_root_sem); + if (ret2) +diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h +index 16dd11c4853130..692370fc07b280 100644 +--- a/fs/btrfs/ctree.h ++++ b/fs/btrfs/ctree.h +@@ -65,21 +65,21 @@ struct btrfs_path { + * set by btrfs_split_item, tells search_slot to keep all locks + * and to force calls to keep space in the nodes + */ +- unsigned int search_for_split:1; ++ bool search_for_split:1; + /* Keep some upper locks as we walk down. */ +- unsigned int keep_locks:1; +- unsigned int skip_locking:1; +- unsigned int search_commit_root:1; +- unsigned int need_commit_sem:1; +- unsigned int skip_release_on_error:1; ++ bool keep_locks:1; ++ bool skip_locking:1; ++ bool search_commit_root:1; ++ bool need_commit_sem:1; ++ bool skip_release_on_error:1; + /* + * Indicate that new item (btrfs_search_slot) is extending already + * existing item and ins_len contains only the data size and not item + * header (ie. sizeof(struct btrfs_item) is not included). + */ +- unsigned int search_for_extension:1; ++ bool search_for_extension:1; + /* Stop search if any locks need to be taken (for read) */ +- unsigned int nowait:1; ++ bool nowait:1; + }; + + #define BTRFS_PATH_AUTO_FREE(path_name) \ +diff --git a/fs/btrfs/defrag.c b/fs/btrfs/defrag.c +index a4cc1bc6356227..2e3c011d410a6f 100644 +--- a/fs/btrfs/defrag.c ++++ b/fs/btrfs/defrag.c +@@ -472,7 +472,7 @@ static int btrfs_defrag_leaves(struct btrfs_trans_handle *trans, + memcpy(&key, &root->defrag_progress, sizeof(key)); + } + +- path->keep_locks = 1; ++ path->keep_locks = true; + + ret = btrfs_search_forward(root, &key, path, BTRFS_OLDEST_GENERATION); + if (ret < 0) +@@ -515,7 +515,7 @@ static int btrfs_defrag_leaves(struct btrfs_trans_handle *trans, + /* + * Now that we reallocated the node we can find the next key. Note that + * btrfs_find_next_key() can release our path and do another search +- * without COWing, this is because even with path->keep_locks = 1, ++ * without COWing, this is because even with path->keep_locks == true, + * btrfs_search_slot() / ctree.c:unlock_up() does not keeps a lock on a + * node when path->slots[node_level - 1] does not point to the last + * item or a slot beyond the last item (ctree.c:unlock_up()). Therefore +diff --git a/fs/btrfs/dev-replace.c b/fs/btrfs/dev-replace.c +index a4eaef60549eed..b6c7da8e1bc8b1 100644 +--- a/fs/btrfs/dev-replace.c ++++ b/fs/btrfs/dev-replace.c +@@ -489,8 +489,8 @@ static int mark_block_group_to_copy(struct btrfs_fs_info *fs_info, + } + + path->reada = READA_FORWARD; +- path->search_commit_root = 1; +- path->skip_locking = 1; ++ path->search_commit_root = true; ++ path->skip_locking = true; + + key.objectid = src_dev->devid; + key.type = BTRFS_DEV_EXTENT_KEY; +diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c +index 6ef7cc116bfcca..d2d96f366dac31 100644 +--- a/fs/btrfs/extent-tree.c ++++ b/fs/btrfs/extent-tree.c +@@ -788,7 +788,7 @@ int lookup_inline_extent_backref(struct btrfs_trans_handle *trans, + want = extent_ref_type(parent, owner); + if (insert) { + extra_size = btrfs_extent_inline_ref_size(want); +- path->search_for_extension = 1; ++ path->search_for_extension = true; + } else + extra_size = -1; + +@@ -954,7 +954,7 @@ int lookup_inline_extent_backref(struct btrfs_trans_handle *trans, + + if (!path->keep_locks) { + btrfs_release_path(path); +- path->keep_locks = 1; ++ path->keep_locks = true; + goto again; + } + +@@ -975,11 +975,11 @@ int lookup_inline_extent_backref(struct btrfs_trans_handle *trans, + *ref_ret = (struct btrfs_extent_inline_ref *)ptr; + out: + if (path->keep_locks) { +- path->keep_locks = 0; ++ path->keep_locks = false; + btrfs_unlock_up_safe(path, 1); + } + if (insert) +- path->search_for_extension = 0; ++ path->search_for_extension = false; + return ret; + } + +diff --git a/fs/btrfs/file-item.c b/fs/btrfs/file-item.c +index 4b7c40f05e8f9e..a2f851eaadca06 100644 +--- a/fs/btrfs/file-item.c ++++ b/fs/btrfs/file-item.c +@@ -394,8 +394,8 @@ int btrfs_lookup_bio_sums(struct btrfs_bio *bbio) + * between reading the free space cache and updating the csum tree. + */ + if (btrfs_is_free_space_inode(inode)) { +- path->search_commit_root = 1; +- path->skip_locking = 1; ++ path->search_commit_root = true; ++ path->skip_locking = true; + } + + /* +@@ -423,8 +423,8 @@ int btrfs_lookup_bio_sums(struct btrfs_bio *bbio) + * from across transactions. + */ + if (bbio->csum_search_commit_root) { +- path->search_commit_root = 1; +- path->skip_locking = 1; ++ path->search_commit_root = true; ++ path->skip_locking = true; + down_read(&fs_info->commit_root_sem); + } + +@@ -1168,10 +1168,10 @@ int btrfs_csum_file_blocks(struct btrfs_trans_handle *trans, + } + + btrfs_release_path(path); +- path->search_for_extension = 1; ++ path->search_for_extension = true; + ret = btrfs_search_slot(trans, root, &file_key, path, + csum_size, 1); +- path->search_for_extension = 0; ++ path->search_for_extension = false; + if (ret < 0) + goto out; + +diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c +index 9828da12765f5c..7ee3d8f05c1a21 100644 +--- a/fs/btrfs/free-space-cache.c ++++ b/fs/btrfs/free-space-cache.c +@@ -971,8 +971,8 @@ int load_free_space_cache(struct btrfs_block_group *block_group) + path = btrfs_alloc_path(); + if (!path) + return 0; +- path->search_commit_root = 1; +- path->skip_locking = 1; ++ path->search_commit_root = true; ++ path->skip_locking = true; + + /* + * We must pass a path with search_commit_root set to btrfs_iget in +diff --git a/fs/btrfs/free-space-tree.c b/fs/btrfs/free-space-tree.c +index c3734892d6548b..f9ffb1c8988d90 100644 +--- a/fs/btrfs/free-space-tree.c ++++ b/fs/btrfs/free-space-tree.c +@@ -1699,8 +1699,8 @@ int btrfs_load_free_space_tree(struct btrfs_caching_control *caching_ctl) + * Just like caching_thread() doesn't want to deadlock on the extent + * tree, we don't want to deadlock on the free space tree. + */ +- path->skip_locking = 1; +- path->search_commit_root = 1; ++ path->skip_locking = true; ++ path->search_commit_root = true; + path->reada = READA_FORWARD; + + info = btrfs_search_free_space_info(NULL, block_group, path, 0); +diff --git a/fs/btrfs/inode-item.c b/fs/btrfs/inode-item.c +index 7e14e1bbcf389b..b73e1dd97208a8 100644 +--- a/fs/btrfs/inode-item.c ++++ b/fs/btrfs/inode-item.c +@@ -312,7 +312,7 @@ int btrfs_insert_inode_ref(struct btrfs_trans_handle *trans, + if (!path) + return -ENOMEM; + +- path->skip_release_on_error = 1; ++ path->skip_release_on_error = true; + ret = btrfs_insert_empty_item(trans, root, path, &key, + ins_len); + if (ret == -EEXIST) { +diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c +index 30a34cd905ba48..36f75c6a8344d4 100644 +--- a/fs/btrfs/inode.c ++++ b/fs/btrfs/inode.c +@@ -7170,8 +7170,8 @@ struct extent_map *btrfs_get_extent(struct btrfs_inode *inode, + * point the commit_root has everything we need. + */ + if (btrfs_is_free_space_inode(inode)) { +- path->search_commit_root = 1; +- path->skip_locking = 1; ++ path->search_commit_root = true; ++ path->skip_locking = true; + } + + ret = btrfs_lookup_file_extent(NULL, root, path, objectid, start, 0); +diff --git a/fs/btrfs/qgroup.c b/fs/btrfs/qgroup.c +index 261aa65019207f..b4c6cbbcd168e6 100644 +--- a/fs/btrfs/qgroup.c ++++ b/fs/btrfs/qgroup.c +@@ -3882,8 +3882,8 @@ static void btrfs_qgroup_rescan_worker(struct btrfs_work *work) + * Rescan should only search for commit root, and any later difference + * should be recorded by qgroup + */ +- path->search_commit_root = 1; +- path->skip_locking = 1; ++ path->search_commit_root = true; ++ path->skip_locking = true; + + while (!ret && !(stopped = rescan_should_stop(fs_info))) { + trans = btrfs_start_transaction(fs_info->fs_root, 0); +diff --git a/fs/btrfs/raid-stripe-tree.c b/fs/btrfs/raid-stripe-tree.c +index cc6f6095cc9fd0..f6f02463dd1a9b 100644 +--- a/fs/btrfs/raid-stripe-tree.c ++++ b/fs/btrfs/raid-stripe-tree.c +@@ -394,8 +394,8 @@ int btrfs_get_raid_extent_offset(struct btrfs_fs_info *fs_info, + return -ENOMEM; + + if (stripe->rst_search_commit_root) { +- path->skip_locking = 1; +- path->search_commit_root = 1; ++ path->skip_locking = true; ++ path->search_commit_root = true; + } + + ret = btrfs_search_slot(NULL, stripe_root, &stripe_key, path, 0, 0); +diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c +index ea68328d289cba..86430435d3acc7 100644 +--- a/fs/btrfs/relocation.c ++++ b/fs/btrfs/relocation.c +@@ -3176,8 +3176,8 @@ static int __add_tree_block(struct reloc_control *rc, + key.offset = blocksize; + } + +- path->search_commit_root = 1; +- path->skip_locking = 1; ++ path->search_commit_root = true; ++ path->skip_locking = true; + ret = btrfs_search_slot(NULL, rc->extent_root, &key, path, 0, 0); + if (ret < 0) + return ret; +@@ -3369,8 +3369,8 @@ int find_next_extent(struct reloc_control *rc, struct btrfs_path *path, + key.type = BTRFS_EXTENT_ITEM_KEY; + key.offset = 0; + +- path->search_commit_root = 1; +- path->skip_locking = 1; ++ path->search_commit_root = true; ++ path->skip_locking = true; + ret = btrfs_search_slot(NULL, rc->extent_root, &key, path, + 0, 0); + if (ret < 0) +diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c +index 16936d17166eef..368f1d44449351 100644 +--- a/fs/btrfs/scrub.c ++++ b/fs/btrfs/scrub.c +@@ -463,10 +463,10 @@ static noinline_for_stack struct scrub_ctx *scrub_setup_ctx( + refcount_set(&sctx->refs, 1); + sctx->is_dev_replace = is_dev_replace; + sctx->fs_info = fs_info; +- sctx->extent_path.search_commit_root = 1; +- sctx->extent_path.skip_locking = 1; +- sctx->csum_path.search_commit_root = 1; +- sctx->csum_path.skip_locking = 1; ++ sctx->extent_path.search_commit_root = true; ++ sctx->extent_path.skip_locking = true; ++ sctx->csum_path.search_commit_root = true; ++ sctx->csum_path.skip_locking = true; + for (i = 0; i < SCRUB_TOTAL_STRIPES; i++) { + int ret; + +@@ -2103,10 +2103,10 @@ static int scrub_raid56_parity_stripe(struct scrub_ctx *sctx, + * as the data stripe bytenr may be smaller than previous extent. Thus + * we have to use our own extent/csum paths. + */ +- extent_path.search_commit_root = 1; +- extent_path.skip_locking = 1; +- csum_path.search_commit_root = 1; +- csum_path.skip_locking = 1; ++ extent_path.search_commit_root = true; ++ extent_path.skip_locking = true; ++ csum_path.search_commit_root = true; ++ csum_path.skip_locking = true; + + for (int i = 0; i < data_stripes; i++) { + int stripe_index; +@@ -2630,8 +2630,8 @@ int scrub_enumerate_chunks(struct scrub_ctx *sctx, + return -ENOMEM; + + path->reada = READA_FORWARD; +- path->search_commit_root = 1; +- path->skip_locking = 1; ++ path->search_commit_root = true; ++ path->skip_locking = true; + + key.objectid = scrub_dev->devid; + key.type = BTRFS_DEV_EXTENT_KEY; +diff --git a/fs/btrfs/send.c b/fs/btrfs/send.c +index 04473387ee8bf0..34a57f11e4bb9c 100644 +--- a/fs/btrfs/send.c ++++ b/fs/btrfs/send.c +@@ -633,9 +633,9 @@ static struct btrfs_path *alloc_path_for_send(void) + path = btrfs_alloc_path(); + if (!path) + return NULL; +- path->search_commit_root = 1; +- path->skip_locking = 1; +- path->need_commit_sem = 1; ++ path->search_commit_root = true; ++ path->skip_locking = true; ++ path->need_commit_sem = true; + return path; + } + +@@ -7643,10 +7643,10 @@ static int btrfs_compare_trees(struct btrfs_root *left_root, + goto out; + } + +- left_path->search_commit_root = 1; +- left_path->skip_locking = 1; +- right_path->search_commit_root = 1; +- right_path->skip_locking = 1; ++ left_path->search_commit_root = true; ++ left_path->skip_locking = true; ++ right_path->search_commit_root = true; ++ right_path->skip_locking = true; + + /* + * Strategy: Go to the first items of both trees. Then do +diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c +index a0e12b4fb95614..f84065b69464c7 100644 +--- a/fs/btrfs/tree-log.c ++++ b/fs/btrfs/tree-log.c +@@ -602,9 +602,9 @@ static int overwrite_item(struct walk_control *wc) + insert: + btrfs_release_path(wc->subvol_path); + /* try to insert the key into the destination tree */ +- wc->subvol_path->skip_release_on_error = 1; ++ wc->subvol_path->skip_release_on_error = true; + ret = btrfs_insert_empty_item(trans, root, wc->subvol_path, &wc->log_key, item_size); +- wc->subvol_path->skip_release_on_error = 0; ++ wc->subvol_path->skip_release_on_error = false; + + dst_eb = wc->subvol_path->nodes[0]; + dst_slot = wc->subvol_path->slots[0]; +@@ -5734,8 +5734,8 @@ static int btrfs_check_ref_name_override(struct extent_buffer *eb, + search_path = btrfs_alloc_path(); + if (!search_path) + return -ENOMEM; +- search_path->search_commit_root = 1; +- search_path->skip_locking = 1; ++ search_path->search_commit_root = true; ++ search_path->skip_locking = true; + + while (cur_offset < item_size) { + u64 parent; +@@ -6052,8 +6052,8 @@ static int conflicting_inode_is_dir(struct btrfs_root *root, u64 ino, + key.type = BTRFS_INODE_ITEM_KEY; + key.offset = 0; + +- path->search_commit_root = 1; +- path->skip_locking = 1; ++ path->search_commit_root = true; ++ path->skip_locking = true; + + ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); + if (WARN_ON_ONCE(ret > 0)) { +@@ -6073,8 +6073,8 @@ static int conflicting_inode_is_dir(struct btrfs_root *root, u64 ino, + } + + btrfs_release_path(path); +- path->search_commit_root = 0; +- path->skip_locking = 0; ++ path->search_commit_root = false; ++ path->skip_locking = false; + + return ret; + } +@@ -7232,8 +7232,8 @@ static int btrfs_log_all_parents(struct btrfs_trans_handle *trans, + path = btrfs_alloc_path(); + if (!path) + return -ENOMEM; +- path->skip_locking = 1; +- path->search_commit_root = 1; ++ path->skip_locking = true; ++ path->search_commit_root = true; + + key.objectid = ino; + key.type = BTRFS_INODE_REF_KEY; +diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c +index 630fb5885692b1..863f69b9cf14bd 100644 +--- a/fs/btrfs/volumes.c ++++ b/fs/btrfs/volumes.c +@@ -1839,8 +1839,8 @@ static int find_free_dev_extent(struct btrfs_device *device, u64 num_bytes, + } + + path->reada = READA_FORWARD; +- path->search_commit_root = 1; +- path->skip_locking = 1; ++ path->search_commit_root = true; ++ path->skip_locking = true; + + key.objectid = device->devid; + key.type = BTRFS_DEV_EXTENT_KEY; +@@ -7627,7 +7627,7 @@ int btrfs_read_chunk_tree(struct btrfs_fs_info *fs_info) + * chunk tree, to keep it simple, just skip locking on the chunk tree. + */ + ASSERT(!test_bit(BTRFS_FS_OPEN, &fs_info->flags)); +- path->skip_locking = 1; ++ path->skip_locking = true; + + /* + * Read all device items, and then all the chunk items. All +diff --git a/fs/btrfs/xattr.c b/fs/btrfs/xattr.c +index b6f01d6c79e7f3..b6e91e8fb7e388 100644 +--- a/fs/btrfs/xattr.c ++++ b/fs/btrfs/xattr.c +@@ -97,7 +97,7 @@ int btrfs_setxattr(struct btrfs_trans_handle *trans, struct inode *inode, + path = btrfs_alloc_path(); + if (!path) + return -ENOMEM; +- path->skip_release_on_error = 1; ++ path->skip_release_on_error = true; + + if (!value) { + di = btrfs_lookup_xattr(trans, root, path, +-- +2.53.0 + diff --git a/queue-6.18/can-j1939-fix-lockless-local-destination-check.patch b/queue-6.18/can-j1939-fix-lockless-local-destination-check.patch new file mode 100644 index 0000000000..a9f82b36f2 --- /dev/null +++ b/queue-6.18/can-j1939-fix-lockless-local-destination-check.patch @@ -0,0 +1,81 @@ +From b8109ce34ff7d62d1ce7304795aec5816801c679 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 7 May 2026 10:22:26 +0200 +Subject: can: j1939: fix lockless local-destination check + +From: Shuhao Fu + +[ Upstream commit e4e8af62adab2fdcca230006f829407a953070cd ] + +j1939_priv.ents[].nusers is documented as protected by priv->lock, and +its updates already happen under that lock. j1939_can_recv() also reads +it under read_lock_bh(). However, j1939_session_skb_queue() and +j1939_tp_send() still read priv->ents[da].nusers without taking the +lock. + +Those transport-side checks decide whether to set J1939_ECU_LOCAL_DST, so +they can race with j1939_local_ecu_get() and j1939_local_ecu_put() while +userspace is binding or releasing sockets concurrently with TP traffic. +This can misclassify TP/ETP sessions as local or remote and take the wrong +transport path. + +Fix both transport paths by routing the destination-locality check through +a helper that reads ents[].nusers under read_lock_bh(&priv->lock). + +Fixes: 9d71dd0c7009 ("can: add support of SAE J1939 protocol") +Signed-off-by: Shuhao Fu +Tested-by: Oleksij Rempel +Acked-by: Oleksij Rempel +Link: https://patch.msgid.link/20260419140614.GA4041240@chcpu16 +Signed-off-by: Marc Kleine-Budde +Signed-off-by: Sasha Levin +--- + net/can/j1939/transport.c | 18 ++++++++++++++---- + 1 file changed, 14 insertions(+), 4 deletions(-) + +diff --git a/net/can/j1939/transport.c b/net/can/j1939/transport.c +index 8656ab388c83e6..9ec929bc0c0da4 100644 +--- a/net/can/j1939/transport.c ++++ b/net/can/j1939/transport.c +@@ -350,6 +350,18 @@ static void j1939_session_skb_drop_old(struct j1939_session *session) + } + } + ++static bool j1939_address_is_local(struct j1939_priv *priv, u8 addr) ++{ ++ bool local = false; ++ ++ read_lock_bh(&priv->lock); ++ if (j1939_address_is_unicast(addr) && priv->ents[addr].nusers) ++ local = true; ++ read_unlock_bh(&priv->lock); ++ ++ return local; ++} ++ + void j1939_session_skb_queue(struct j1939_session *session, + struct sk_buff *skb) + { +@@ -358,8 +370,7 @@ void j1939_session_skb_queue(struct j1939_session *session, + + j1939_ac_fixup(priv, skb); + +- if (j1939_address_is_unicast(skcb->addr.da) && +- priv->ents[skcb->addr.da].nusers) ++ if (j1939_address_is_local(priv, skcb->addr.da)) + skcb->flags |= J1939_ECU_LOCAL_DST; + + skcb->flags |= J1939_ECU_LOCAL_SRC; +@@ -2017,8 +2028,7 @@ struct j1939_session *j1939_tp_send(struct j1939_priv *priv, + return ERR_PTR(ret); + + /* fix DST flags, it may be used there soon */ +- if (j1939_address_is_unicast(skcb->addr.da) && +- priv->ents[skcb->addr.da].nusers) ++ if (j1939_address_is_local(priv, skcb->addr.da)) + skcb->flags |= J1939_ECU_LOCAL_DST; + + /* src is always local, I'm sending ... */ +-- +2.53.0 + diff --git a/queue-6.18/can-raw-add-locking-for-raw-flags-bitfield.patch b/queue-6.18/can-raw-add-locking-for-raw-flags-bitfield.patch new file mode 100644 index 0000000000..2902a388fc --- /dev/null +++ b/queue-6.18/can-raw-add-locking-for-raw-flags-bitfield.patch @@ -0,0 +1,172 @@ +From fb1b444827869f2be258864c66f0d754c63685e5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 7 May 2026 10:22:23 +0200 +Subject: can: raw: add locking for raw flags bitfield + +From: Oliver Hartkopp + +[ Upstream commit 1e5185c090589f4146d728ab36417d8a5419f127 ] + +With commit 890e5198a6e5 ("can: raw: use bitfields to store flags in +struct raw_sock") the formerly separate integer values have been integrated +into a single bitfield. This led to a read-modify-write operation when +changing a flag in raw_setsockopt() which now needs a locking to prevent +concurrent access. + +Instead of adding a lock/unlock hell in each of the flag manipulations this +patch introduces a wrapper for a new raw_setsockopt_locked() function +analogue to the isotp_setsockopt[_locked]() approach in net/can/isotp.c + +Fixes: 890e5198a6e5 ("can: raw: use bitfields to store flags in struct raw_sock") +Reported-by: Eulgyu Kim +Closes: https://lore.kernel.org/linux-can/20260503112200.22727-1-eulgyukim@snu.ac.kr/ +Tested-by: Eulgyu Kim +Signed-off-by: Oliver Hartkopp +Reviewed-by: Vincent Mailhol +Tested-by: Vincent Mailhol +Link: https://patch.msgid.link/20260504111928.41856-1-socketcan@hartkopp.net +[mkl: use Closes tag instead of Link] +Signed-off-by: Marc Kleine-Budde +Signed-off-by: Sasha Levin +--- + net/can/raw.c | 66 +++++++++++++++++++++++---------------------------- + 1 file changed, 30 insertions(+), 36 deletions(-) + +diff --git a/net/can/raw.c b/net/can/raw.c +index 263e7167d2f529..365559d19dc323 100644 +--- a/net/can/raw.c ++++ b/net/can/raw.c +@@ -560,8 +560,8 @@ static int raw_getname(struct socket *sock, struct sockaddr *uaddr, + return RAW_MIN_NAMELEN; + } + +-static int raw_setsockopt(struct socket *sock, int level, int optname, +- sockptr_t optval, unsigned int optlen) ++static int raw_setsockopt_locked(struct socket *sock, int optname, ++ sockptr_t optval, unsigned int optlen) + { + struct sock *sk = sock->sk; + struct raw_sock *ro = raw_sk(sk); +@@ -573,9 +573,6 @@ static int raw_setsockopt(struct socket *sock, int level, int optname, + int flag; + int err = 0; + +- if (level != SOL_CAN_RAW) +- return -EINVAL; +- + switch (optname) { + case CAN_RAW_FILTER: + if (optlen % sizeof(struct can_filter) != 0) +@@ -596,17 +593,11 @@ static int raw_setsockopt(struct socket *sock, int level, int optname, + return -EFAULT; + } + +- rtnl_lock(); +- lock_sock(sk); +- + dev = ro->dev; +- if (ro->bound && dev) { +- if (dev->reg_state != NETREG_REGISTERED) { +- if (count > 1) +- kfree(filter); +- err = -ENODEV; +- goto out_fil; +- } ++ if (ro->bound && dev && dev->reg_state != NETREG_REGISTERED) { ++ if (count > 1) ++ kfree(filter); ++ return -ENODEV; + } + + if (ro->bound) { +@@ -620,7 +611,7 @@ static int raw_setsockopt(struct socket *sock, int level, int optname, + if (err) { + if (count > 1) + kfree(filter); +- goto out_fil; ++ return err; + } + + /* remove old filter registrations */ +@@ -640,11 +631,6 @@ static int raw_setsockopt(struct socket *sock, int level, int optname, + } + ro->filter = filter; + ro->count = count; +- +- out_fil: +- release_sock(sk); +- rtnl_unlock(); +- + break; + + case CAN_RAW_ERR_FILTER: +@@ -656,16 +642,9 @@ static int raw_setsockopt(struct socket *sock, int level, int optname, + + err_mask &= CAN_ERR_MASK; + +- rtnl_lock(); +- lock_sock(sk); +- + dev = ro->dev; +- if (ro->bound && dev) { +- if (dev->reg_state != NETREG_REGISTERED) { +- err = -ENODEV; +- goto out_err; +- } +- } ++ if (ro->bound && dev && dev->reg_state != NETREG_REGISTERED) ++ return -ENODEV; + + /* remove current error mask */ + if (ro->bound) { +@@ -674,7 +653,7 @@ static int raw_setsockopt(struct socket *sock, int level, int optname, + err_mask); + + if (err) +- goto out_err; ++ return err; + + /* remove old err_mask registration */ + raw_disable_errfilter(sock_net(sk), dev, sk, +@@ -683,11 +662,6 @@ static int raw_setsockopt(struct socket *sock, int level, int optname, + + /* link new err_mask to the socket */ + ro->err_mask = err_mask; +- +- out_err: +- release_sock(sk); +- rtnl_unlock(); +- + break; + + case CAN_RAW_LOOPBACK: +@@ -767,6 +741,26 @@ static int raw_setsockopt(struct socket *sock, int level, int optname, + return err; + } + ++static int raw_setsockopt(struct socket *sock, int level, int optname, ++ sockptr_t optval, unsigned int optlen) ++{ ++ struct sock *sk = sock->sk; ++ int err; ++ ++ if (level != SOL_CAN_RAW) ++ return -EINVAL; ++ ++ rtnl_lock(); ++ lock_sock(sk); ++ ++ err = raw_setsockopt_locked(sock, optname, optval, optlen); ++ ++ release_sock(sk); ++ rtnl_unlock(); ++ ++ return err; ++} ++ + static int raw_getsockopt(struct socket *sock, int level, int optname, + char __user *optval, int __user *optlen) + { +-- +2.53.0 + diff --git a/queue-6.18/cpufreq-make-cpufreq_update_pressure-fall-back-to-cp.patch b/queue-6.18/cpufreq-make-cpufreq_update_pressure-fall-back-to-cp.patch new file mode 100644 index 0000000000..f0bdd5d959 --- /dev/null +++ b/queue-6.18/cpufreq-make-cpufreq_update_pressure-fall-back-to-cp.patch @@ -0,0 +1,55 @@ +From 1b4cd226c425467cf0aa973b27c15bd20810686d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 7 Jul 2026 19:25:39 +0200 +Subject: cpufreq: Make cpufreq_update_pressure() fall back to cpuinfo.max_freq + +From: Rafael J. Wysocki + +[ Upstream commit d2d5c129d07ea8eb91cd8a8633b5774116c4d171 ] + +If arch_scale_freq_ref() is not defined for a given arch (like x86, for +example), cpufreq_update_pressure() will always set cpufreq_pressure to +zero for all CPUs in the system, which is generally problematic on +systems with asymmetric capacity [1]. + +However, in the absence of arch_scale_freq_ref(), it is reasonable +to assume that cpuinfo.max_freq is the maximum sustainable frequency +for the given cpufreq policy. Moreover, there are cases in which +arch_scale_freq_ref() would need to be defined to return essentially +the cpuinfo.max_freq value anyway (for example, intel_pstate on +hybrid platforms). + +For the above reasons, update cpufreq_update_pressure() to fall back to +using cpuinfo.max_freq as the reference frequency if zero is returned by +arch_scale_freq_ref(). + +Fixes: 75d659317bb1 ("cpufreq: Add a cpufreq pressure feedback for the scheduler") +Link: https://lore.kernel.org/lkml/CAKfTPtBuRLfYNnR4w--cFZYZy-R8gaPEgVwCcaMmbCcJ2H-muQ@mail.gmail.com/ [1] +Signed-off-by: Rafael J. Wysocki +Acked-by: Viresh Kumar +Reviewed-by: Zhongqiu Han +Tested-by: Ricardo Neri # cluster scheduling +Acked-by: Vincent Guittot +Link: https://patch.msgid.link/5086499.GXAFRqVoOG@rafael.j.wysocki +Signed-off-by: Sasha Levin +--- + drivers/cpufreq/cpufreq.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c +index a70df77f9b7d11..ced96d9e254ee4 100644 +--- a/drivers/cpufreq/cpufreq.c ++++ b/drivers/cpufreq/cpufreq.c +@@ -2584,6 +2584,9 @@ static void cpufreq_update_pressure(struct cpufreq_policy *policy) + + cpu = cpumask_first(policy->related_cpus); + max_freq = arch_scale_freq_ref(cpu); ++ if (!max_freq) ++ max_freq = policy->cpuinfo.max_freq; ++ + capped_freq = policy->max; + + /* +-- +2.53.0 + diff --git a/queue-6.18/dpll-fix-null-pointer-dereference-in-dpll_msg_add_pi.patch b/queue-6.18/dpll-fix-null-pointer-dereference-in-dpll_msg_add_pi.patch new file mode 100644 index 0000000000..97835e3f82 --- /dev/null +++ b/queue-6.18/dpll-fix-null-pointer-dereference-in-dpll_msg_add_pi.patch @@ -0,0 +1,71 @@ +From 8fcd1113346ecc3b538ae26ea697913096d274ff Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 10 Jul 2026 21:36:25 +0200 +Subject: dpll: fix NULL pointer dereference in dpll_msg_add_pin_ref_sync() + +From: Ivan Vecera + +[ Upstream commit d2e914a4a0d0f753dbae830264850d044026167c ] + +When a dpll_pin is shared across multiple dpll_device instances and +those devices are being unregistered (e.g. during driver module removal), +a NULL pointer dereference can occur in dpll_msg_add_pin_ref_sync(). + +This happens under the following conditions: + - A pin is registered with two or more dpll devices (dpll_A, dpll_B) + - The pin has ref_sync pairs with other pins + - During unregistration of dpll_A's pins, a ref_sync partner pin is + unregistered first, removing it from dpll_A->pin_refs + - But since the partner pin is still registered with dpll_B, its + dpll_refs is not empty, so dpll_pin_ref_sync_pair_del() does NOT + run and the partner stays in the pin's ref_sync_pins xarray + - When the pin itself is then unregistered from dpll_A, the delete + notification calls dpll_msg_add_pin_ref_sync() which finds the + partner in ref_sync_pins, passes dpll_pin_available() (partner is + still registered with dpll_B), but dpll_pin_on_dpll_priv(dpll_A, + partner) returns NULL because partner was already removed from + dpll_A->pin_refs + - The NULL priv pointer is passed to the driver's ref_sync_get + callback, which dereferences it + + BUG: kernel NULL pointer dereference, address: 0000000000000034 + Oops: Oops: 0000 [#1] SMP NOPTI + RIP: 0010:zl3073x_dpll_input_pin_ref_sync_get+0x73/0x80 [zl3073x] + Call Trace: + dpll_msg_add_pin_ref_sync+0xb8/0x200 + dpll_cmd_pin_get_one+0x3b6/0x4b0 + dpll_pin_event_send+0x72/0x140 + __dpll_pin_unregister+0x5a/0x2b0 + dpll_pin_unregister+0x49/0x70 + +Fix this by skipping ref_sync pins whose priv pointer cannot be resolved +for the current dpll device. + +Fixes: 58256a26bfb3 ("dpll: add reference sync get/set") +Signed-off-by: Ivan Vecera +Reviewed-by: Vadim Fedorenko +Reviewed-by: Jiri Pirko +Link: https://patch.msgid.link/20260710193625.1378822-1-ivecera@redhat.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/dpll/dpll_netlink.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/dpll/dpll_netlink.c b/drivers/dpll/dpll_netlink.c +index de8b065280d15d..eb23ee401aaef8 100644 +--- a/drivers/dpll/dpll_netlink.c ++++ b/drivers/dpll/dpll_netlink.c +@@ -486,6 +486,9 @@ dpll_msg_add_pin_ref_sync(struct sk_buff *msg, struct dpll_pin *pin, + if (!dpll_pin_available(ref_sync_pin)) + continue; + ref_sync_pin_priv = dpll_pin_on_dpll_priv(dpll, ref_sync_pin); ++ /* Pin may have been unregistered from this dpll already */ ++ if (!ref_sync_pin_priv) ++ continue; + if (WARN_ON(!ops->ref_sync_get)) + return -EOPNOTSUPP; + ret = ops->ref_sync_get(pin, pin_priv, ref_sync_pin, +-- +2.53.0 + diff --git a/queue-6.18/drm-i915-gt-use-correct-selftest-config-symbol.patch b/queue-6.18/drm-i915-gt-use-correct-selftest-config-symbol.patch new file mode 100644 index 0000000000..e31cbaf9b9 --- /dev/null +++ b/queue-6.18/drm-i915-gt-use-correct-selftest-config-symbol.patch @@ -0,0 +1,50 @@ +From 4961a8f4a362d21fc182c1f9381bbc33ce9de051 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 5 Jul 2026 16:02:25 +0800 +Subject: drm/i915/gt: use correct selftest config symbol + +From: Pengpeng Hou + +[ Upstream commit a82f1bb8191aec98a971a2196136016ef70c0880 ] + +intel_engine_user.c checks CONFIG_DRM_I915_SELFTESTS before running +the engine UABI isolation check. Kconfig defines DRM_I915_SELFTEST, +without the trailing "S", and the rest of i915 uses +CONFIG_DRM_I915_SELFTEST. + +Because CONFIG_DRM_I915_SELFTESTS is not backed by any Kconfig symbol, +the IS_ENABLED() test is always false. Use the existing selftest symbol +so the debug/selftest guarded path can be reached when selftests are +enabled. + +This is a source-level fix. It does not claim dynamic hardware +reproduction; the evidence is the Kconfig definition and the inconsistent +guard in intel_engine_user.c. + +Fixes: 750e76b4f9f6 ("drm/i915/gt: Move the [class][inst] lookup for engines onto the GT") +Signed-off-by: Pengpeng Hou +Signed-off-by: Tvrtko Ursulin +Link: https://lore.kernel.org/r/20260705080225.436-1-pengpeng@iscas.ac.cn +(cherry picked from commit 14a2012a490258f3f93857bc4f1b203405964be7) +Signed-off-by: Rodrigo Vivi +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/i915/gt/intel_engine_user.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/i915/gt/intel_engine_user.c b/drivers/gpu/drm/i915/gt/intel_engine_user.c +index 833987015b8bbc..ed42b9d05a07d5 100644 +--- a/drivers/gpu/drm/i915/gt/intel_engine_user.c ++++ b/drivers/gpu/drm/i915/gt/intel_engine_user.c +@@ -257,7 +257,7 @@ void intel_engines_driver_register(struct drm_i915_private *i915) + p = &prev->rb_right; + } + +- if (IS_ENABLED(CONFIG_DRM_I915_SELFTESTS) && ++ if (IS_ENABLED(CONFIG_DRM_I915_SELFTEST) && + IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM)) { + struct intel_engine_cs *engine; + unsigned int isolation; +-- +2.53.0 + diff --git a/queue-6.18/drm-i915-selftests-fix-gt-pm-sort-comparators.patch b/queue-6.18/drm-i915-selftests-fix-gt-pm-sort-comparators.patch new file mode 100644 index 0000000000..6a9f711825 --- /dev/null +++ b/queue-6.18/drm-i915-selftests-fix-gt-pm-sort-comparators.patch @@ -0,0 +1,55 @@ +From d20f79d2e94584c0ea1adefbb118ca8f570270ad Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 15 Jul 2026 01:04:30 +0300 +Subject: drm/i915/selftests: Fix GT PM sort comparators + +From: Emre Cecanpunar + +[ Upstream commit 612978b83f45bf7018815209db5395d759db6f26 ] + +Compare the sampled clock values instead of their addresses. Comparing +addresses leaves the samples unsorted, preventing the code from discarding +the minimum and maximum samples. + +Fixes: 1a5392479207 ("drm/i915/selftests: Measure CS_TIMESTAMP") +Signed-off-by: Emre Cecanpunar +Signed-off-by: Tvrtko Ursulin +Link: https://lore.kernel.org/r/20260714220430.238433-1-emreleno@gmail.com +(cherry picked from commit 682ea2d28d18bb06f9fc663cb5ab7e80dc0e606a) +Signed-off-by: Rodrigo Vivi +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/i915/gt/selftest_gt_pm.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/drivers/gpu/drm/i915/gt/selftest_gt_pm.c b/drivers/gpu/drm/i915/gt/selftest_gt_pm.c +index 33351deeea4f0b..07eaf71955c447 100644 +--- a/drivers/gpu/drm/i915/gt/selftest_gt_pm.c ++++ b/drivers/gpu/drm/i915/gt/selftest_gt_pm.c +@@ -16,9 +16,9 @@ static int cmp_u64(const void *A, const void *B) + { + const u64 *a = A, *b = B; + +- if (a < b) ++ if (*a < *b) + return -1; +- else if (a > b) ++ else if (*a > *b) + return 1; + else + return 0; +@@ -28,9 +28,9 @@ static int cmp_u32(const void *A, const void *B) + { + const u32 *a = A, *b = B; + +- if (a < b) ++ if (*a < *b) + return -1; +- else if (a > b) ++ else if (*a > *b) + return 1; + else + return 0; +-- +2.53.0 + diff --git a/queue-6.18/drm-i915-wm-clear-the-plane-ddb_y-entries-on-plane-d.patch b/queue-6.18/drm-i915-wm-clear-the-plane-ddb_y-entries-on-plane-d.patch new file mode 100644 index 0000000000..1063936337 --- /dev/null +++ b/queue-6.18/drm-i915-wm-clear-the-plane-ddb_y-entries-on-plane-d.patch @@ -0,0 +1,41 @@ +From 5863741f59e6d8e1109884611d7272af269d1f17 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 15 Jun 2026 23:33:49 +0300 +Subject: drm/i915/wm: clear the plane ddb_y entries on plane disable + +From: Vinod Govindapillai + +[ Upstream commit e89978c1cff54e265345c66e1177d19ea5a8bc00 ] + +The UV/Y plane DDB entriess are never cleared on +sk_wm_plane_disable_noatomic() and can leave stale DDB state +for NV12 planes on pre-Gen11 devices + +Fixes: d34b59d5ba41 ("drm/i915: Add skl_wm_plane_disable_noatomic()") +Assisted-by: Copilot:claude-sonnet-4.6 +Signed-off-by: Vinod Govindapillai +Reviewed-by: Suraj Kandpal +Link: https://patch.msgid.link/20260615203355.218578-2-vinod.govindapillai@intel.com +(cherry picked from commit 60f68a6ba298fd1e971a2d91576304bee89a16fc) +Signed-off-by: Rodrigo Vivi +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/i915/display/skl_watermark.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/i915/display/skl_watermark.c b/drivers/gpu/drm/i915/display/skl_watermark.c +index a5862998bf1447..eb54fffc698864 100644 +--- a/drivers/gpu/drm/i915/display/skl_watermark.c ++++ b/drivers/gpu/drm/i915/display/skl_watermark.c +@@ -3815,7 +3815,7 @@ void skl_wm_plane_disable_noatomic(struct intel_crtc *crtc, + return; + + skl_ddb_entry_init(&crtc_state->wm.skl.plane_ddb[plane->id], 0, 0); +- skl_ddb_entry_init(&crtc_state->wm.skl.plane_ddb[plane->id], 0, 0); ++ skl_ddb_entry_init(&crtc_state->wm.skl.plane_ddb_y[plane->id], 0, 0); + + crtc_state->wm.skl.plane_min_ddb[plane->id] = 0; + crtc_state->wm.skl.plane_interim_ddb[plane->id] = 0; +-- +2.53.0 + diff --git a/queue-6.18/drm-panthor-check-debugfs-gem-lock-initialization.patch b/queue-6.18/drm-panthor-check-debugfs-gem-lock-initialization.patch new file mode 100644 index 0000000000..9d1857e61a --- /dev/null +++ b/queue-6.18/drm-panthor-check-debugfs-gem-lock-initialization.patch @@ -0,0 +1,46 @@ +From 019e8c37c65e6ecdd8f3ac9e374d7df3a2dcfb09 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 13 Jul 2026 16:29:12 +0800 +Subject: drm/panthor: Check debugfs GEM lock initialization + +From: Linmao Li + +[ Upstream commit 022e901333c3054656a640794e842bab7af5a75c ] + +drmm_mutex_init() can fail while registering the managed cleanup action. +When that happens, drmm_add_action_or_reset() destroys the mutex before +returning the error. Continuing initialization would therefore leave the +debugfs GEM object list with an unusable lock. + +Propagate the error as is already done for the other managed mutexes in +panthor_device_init(). + +Fixes: a3707f53eb3f ("drm/panthor: show device-wide list of DRM GEM objects over DebugFS") +Signed-off-by: Linmao Li +Reviewed-by: Liviu Dudau +Link: https://patch.msgid.link/20260713082912.321021-1-lilinmao@kylinos.cn +Signed-off-by: Liviu Dudau +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/panthor/panthor_device.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/panthor/panthor_device.c b/drivers/gpu/drm/panthor/panthor_device.c +index 962a10e00848ef..cdf82d83de7abe 100644 +--- a/drivers/gpu/drm/panthor/panthor_device.c ++++ b/drivers/gpu/drm/panthor/panthor_device.c +@@ -182,7 +182,10 @@ int panthor_device_init(struct panthor_device *ptdev) + return ret; + + #ifdef CONFIG_DEBUG_FS +- drmm_mutex_init(&ptdev->base, &ptdev->gems.lock); ++ ret = drmm_mutex_init(&ptdev->base, &ptdev->gems.lock); ++ if (ret) ++ return ret; ++ + INIT_LIST_HEAD(&ptdev->gems.node); + #endif + +-- +2.53.0 + diff --git a/queue-6.18/drm-xe-allow-the-caller-to-pass-guc_buf_cache-size.patch b/queue-6.18/drm-xe-allow-the-caller-to-pass-guc_buf_cache-size.patch new file mode 100644 index 0000000000..45ec84ea22 --- /dev/null +++ b/queue-6.18/drm-xe-allow-the-caller-to-pass-guc_buf_cache-size.patch @@ -0,0 +1,115 @@ +From b76da5fcd731e219b22f12dd45f16ff21d62b48a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 12 Nov 2025 14:22:07 +0100 +Subject: drm/xe: Allow the caller to pass guc_buf_cache size +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Michał Winiarski + +[ Upstream commit dca2701a6277399f9d255f09b4c34d9a7171c09b ] + +An upcoming change will use GuC buffer cache as a place where GuC +migration data will be stored, and the memory requirement for that is +larger than indirect data. +Allow the caller to pass the size based on the intended usecase. + +Reviewed-by: Michal Wajdeczko +Link: https://patch.msgid.link/20251112132220.516975-12-michal.winiarski@intel.com +Signed-off-by: Michał Winiarski +Stable-dep-of: 56441f9e08ad ("drm/xe/vf: Fix VF CCS attach/detach race with in-flight BO moves") +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/xe/xe_guc_buf.c | 44 ++++++++++++++++++++++++--------- + drivers/gpu/drm/xe/xe_guc_buf.h | 1 + + 2 files changed, 34 insertions(+), 11 deletions(-) + +diff --git a/drivers/gpu/drm/xe/xe_guc_buf.c b/drivers/gpu/drm/xe/xe_guc_buf.c +index 502ca3a4ee6064..989c546d05689d 100644 +--- a/drivers/gpu/drm/xe/xe_guc_buf.c ++++ b/drivers/gpu/drm/xe/xe_guc_buf.c +@@ -13,6 +13,8 @@ + #include "xe_guc_buf.h" + #include "xe_sa.h" + ++#define XE_GUC_BUF_CACHE_DEFAULT_SIZE SZ_8K ++ + static struct xe_guc *cache_to_guc(struct xe_guc_buf_cache *cache) + { + return container_of(cache, struct xe_guc, buf); +@@ -23,21 +25,12 @@ static struct xe_gt *cache_to_gt(struct xe_guc_buf_cache *cache) + return guc_to_gt(cache_to_guc(cache)); + } + +-/** +- * xe_guc_buf_cache_init() - Initialize the GuC Buffer Cache. +- * @cache: the &xe_guc_buf_cache to initialize +- * +- * The Buffer Cache allows to obtain a reusable buffer that can be used to pass +- * indirect H2G data to GuC without a need to create a ad-hoc allocation. +- * +- * Return: 0 on success or a negative error code on failure. +- */ +-int xe_guc_buf_cache_init(struct xe_guc_buf_cache *cache) ++static int guc_buf_cache_init(struct xe_guc_buf_cache *cache, u32 size) + { + struct xe_gt *gt = cache_to_gt(cache); + struct xe_sa_manager *sam; + +- sam = __xe_sa_bo_manager_init(gt_to_tile(gt), SZ_8K, 0, sizeof(u32)); ++ sam = __xe_sa_bo_manager_init(gt_to_tile(gt), size, 0, sizeof(u32)); + if (IS_ERR(sam)) + return PTR_ERR(sam); + cache->sam = sam; +@@ -48,6 +41,35 @@ int xe_guc_buf_cache_init(struct xe_guc_buf_cache *cache) + return 0; + } + ++/** ++ * xe_guc_buf_cache_init() - Initialize the GuC Buffer Cache. ++ * @cache: the &xe_guc_buf_cache to initialize ++ * ++ * The Buffer Cache allows to obtain a reusable buffer that can be used to pass ++ * data to GuC or read data from GuC without a need to create a ad-hoc allocation. ++ * ++ * Return: 0 on success or a negative error code on failure. ++ */ ++int xe_guc_buf_cache_init(struct xe_guc_buf_cache *cache) ++{ ++ return guc_buf_cache_init(cache, XE_GUC_BUF_CACHE_DEFAULT_SIZE); ++} ++ ++/** ++ * xe_guc_buf_cache_init_with_size() - Initialize the GuC Buffer Cache. ++ * @cache: the &xe_guc_buf_cache to initialize ++ * @size: size in bytes ++ * ++ * Like xe_guc_buf_cache_init(), except it allows the caller to make the cache ++ * buffer larger, allowing to accommodate larger objects. ++ * ++ * Return: 0 on success or a negative error code on failure. ++ */ ++int xe_guc_buf_cache_init_with_size(struct xe_guc_buf_cache *cache, u32 size) ++{ ++ return guc_buf_cache_init(cache, max(XE_GUC_BUF_CACHE_DEFAULT_SIZE, size)); ++} ++ + /** + * xe_guc_buf_cache_dwords() - Number of dwords the GuC Buffer Cache supports. + * @cache: the &xe_guc_buf_cache to query +diff --git a/drivers/gpu/drm/xe/xe_guc_buf.h b/drivers/gpu/drm/xe/xe_guc_buf.h +index 0d67604d96bdd7..8204e589625013 100644 +--- a/drivers/gpu/drm/xe/xe_guc_buf.h ++++ b/drivers/gpu/drm/xe/xe_guc_buf.h +@@ -12,6 +12,7 @@ + #include "xe_guc_buf_types.h" + + int xe_guc_buf_cache_init(struct xe_guc_buf_cache *cache); ++int xe_guc_buf_cache_init_with_size(struct xe_guc_buf_cache *cache, u32 size); + u32 xe_guc_buf_cache_dwords(struct xe_guc_buf_cache *cache); + struct xe_guc_buf xe_guc_buf_reserve(struct xe_guc_buf_cache *cache, u32 dwords); + struct xe_guc_buf xe_guc_buf_from_data(struct xe_guc_buf_cache *cache, +-- +2.53.0 + diff --git a/queue-6.18/drm-xe-sa-shadow-buffer-support-in-the-sub-allocator.patch b/queue-6.18/drm-xe-sa-shadow-buffer-support-in-the-sub-allocator.patch new file mode 100644 index 0000000000..f9283a5ab6 --- /dev/null +++ b/queue-6.18/drm-xe-sa-shadow-buffer-support-in-the-sub-allocator.patch @@ -0,0 +1,228 @@ +From 9ed4608b529ad9ac9038c01670054875f1cd47d9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 18 Nov 2025 12:07:44 +0000 +Subject: drm/xe/sa: Shadow buffer support in the sub-allocator pool + +From: Satyanarayana K V P + +[ Upstream commit 1f2cf5295cdba71818288c9e495b4ef5097565ed ] + +The existing sub-allocator is limited to managing a single buffer object. +This enhancement introduces shadow buffer functionality to support +scenarios requiring dual buffer management. + +The changes include added shadow buffer object creation capability, +Management for both primary and shadow buffers, and appropriate locking +mechanisms for thread-safe operations. + +This enables more flexible buffer allocation strategies in scenarios where +shadow buffering is required. + +Signed-off-by: Satyanarayana K V P +Suggested-by: Matthew Brost +Cc: Michal Wajdeczko +Cc: Matthew Auld +Reviewed-by: Matthew Brost +Signed-off-by: Matthew Brost +Link: https://patch.msgid.link/20251118120745.3460172-2-satyanarayana.k.v.p@intel.com +Stable-dep-of: 56441f9e08ad ("drm/xe/vf: Fix VF CCS attach/detach race with in-flight BO moves") +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/xe/xe_guc_buf.c | 2 +- + drivers/gpu/drm/xe/xe_sa.c | 67 +++++++++++++++++++++++++++- + drivers/gpu/drm/xe/xe_sa.h | 20 ++++++++- + drivers/gpu/drm/xe/xe_sa_types.h | 3 ++ + drivers/gpu/drm/xe/xe_sriov_vf_ccs.c | 3 ++ + 5 files changed, 91 insertions(+), 4 deletions(-) + +diff --git a/drivers/gpu/drm/xe/xe_guc_buf.c b/drivers/gpu/drm/xe/xe_guc_buf.c +index 989c546d05689d..3de6377ae2d521 100644 +--- a/drivers/gpu/drm/xe/xe_guc_buf.c ++++ b/drivers/gpu/drm/xe/xe_guc_buf.c +@@ -30,7 +30,7 @@ static int guc_buf_cache_init(struct xe_guc_buf_cache *cache, u32 size) + struct xe_gt *gt = cache_to_gt(cache); + struct xe_sa_manager *sam; + +- sam = __xe_sa_bo_manager_init(gt_to_tile(gt), size, 0, sizeof(u32)); ++ sam = __xe_sa_bo_manager_init(gt_to_tile(gt), size, 0, sizeof(u32), 0); + if (IS_ERR(sam)) + return PTR_ERR(sam); + cache->sam = sam; +diff --git a/drivers/gpu/drm/xe/xe_sa.c b/drivers/gpu/drm/xe/xe_sa.c +index fedd017d6dd36a..d9e0d30f8135e9 100644 +--- a/drivers/gpu/drm/xe/xe_sa.c ++++ b/drivers/gpu/drm/xe/xe_sa.c +@@ -29,6 +29,7 @@ static void xe_sa_bo_manager_fini(struct drm_device *drm, void *arg) + kvfree(sa_manager->cpu_ptr); + + sa_manager->bo = NULL; ++ sa_manager->shadow = NULL; + } + + /** +@@ -37,12 +38,14 @@ static void xe_sa_bo_manager_fini(struct drm_device *drm, void *arg) + * @size: number of bytes to allocate + * @guard: number of bytes to exclude from suballocations + * @align: alignment for each suballocated chunk ++ * @flags: flags for suballocator + * + * Prepares the suballocation manager for suballocations. + * + * Return: a pointer to the &xe_sa_manager or an ERR_PTR on failure. + */ +-struct xe_sa_manager *__xe_sa_bo_manager_init(struct xe_tile *tile, u32 size, u32 guard, u32 align) ++struct xe_sa_manager *__xe_sa_bo_manager_init(struct xe_tile *tile, u32 size, ++ u32 guard, u32 align, u32 flags) + { + struct xe_device *xe = tile_to_xe(tile); + struct xe_sa_manager *sa_manager; +@@ -79,6 +82,26 @@ struct xe_sa_manager *__xe_sa_bo_manager_init(struct xe_tile *tile, u32 size, u3 + memset(sa_manager->cpu_ptr, 0, bo->ttm.base.size); + } + ++ if (flags & XE_SA_BO_MANAGER_FLAG_SHADOW) { ++ struct xe_bo *shadow; ++ ++ ret = drmm_mutex_init(&xe->drm, &sa_manager->swap_guard); ++ if (ret) ++ return ERR_PTR(ret); ++ ++ shadow = xe_managed_bo_create_pin_map(xe, tile, size, ++ XE_BO_FLAG_VRAM_IF_DGFX(tile) | ++ XE_BO_FLAG_GGTT | ++ XE_BO_FLAG_GGTT_INVALIDATE | ++ XE_BO_FLAG_PINNED_NORESTORE); ++ if (IS_ERR(shadow)) { ++ drm_err(&xe->drm, "Failed to prepare %uKiB BO for SA manager (%pe)\n", ++ size / SZ_1K, shadow); ++ return ERR_CAST(shadow); ++ } ++ sa_manager->shadow = shadow; ++ } ++ + drm_suballoc_manager_init(&sa_manager->base, managed_size, align); + ret = drmm_add_action_or_reset(&xe->drm, xe_sa_bo_manager_fini, + sa_manager); +@@ -88,6 +111,48 @@ struct xe_sa_manager *__xe_sa_bo_manager_init(struct xe_tile *tile, u32 size, u3 + return sa_manager; + } + ++/** ++ * xe_sa_bo_swap_shadow() - Swap the SA BO with shadow BO. ++ * @sa_manager: the XE sub allocator manager ++ * ++ * Swaps the sub-allocator primary buffer object with shadow buffer object. ++ * ++ * Return: None. ++ */ ++void xe_sa_bo_swap_shadow(struct xe_sa_manager *sa_manager) ++{ ++ struct xe_device *xe = tile_to_xe(sa_manager->bo->tile); ++ ++ xe_assert(xe, sa_manager->shadow); ++ lockdep_assert_held(&sa_manager->swap_guard); ++ ++ swap(sa_manager->bo, sa_manager->shadow); ++ if (!sa_manager->bo->vmap.is_iomem) ++ sa_manager->cpu_ptr = sa_manager->bo->vmap.vaddr; ++} ++ ++/** ++ * xe_sa_bo_sync_shadow() - Sync the SA Shadow BO with primary BO. ++ * @sa_bo: the sub-allocator buffer object. ++ * ++ * Synchronize sub-allocator shadow buffer object with primary buffer object. ++ * ++ * Return: None. ++ */ ++void xe_sa_bo_sync_shadow(struct drm_suballoc *sa_bo) ++{ ++ struct xe_sa_manager *sa_manager = to_xe_sa_manager(sa_bo->manager); ++ struct xe_device *xe = tile_to_xe(sa_manager->bo->tile); ++ ++ xe_assert(xe, sa_manager->shadow); ++ lockdep_assert_held(&sa_manager->swap_guard); ++ ++ xe_map_memcpy_to(xe, &sa_manager->shadow->vmap, ++ drm_suballoc_soffset(sa_bo), ++ xe_sa_bo_cpu_addr(sa_bo), ++ drm_suballoc_size(sa_bo)); ++} ++ + /** + * __xe_sa_bo_new() - Make a suballocation but use custom gfp flags. + * @sa_manager: the &xe_sa_manager +diff --git a/drivers/gpu/drm/xe/xe_sa.h b/drivers/gpu/drm/xe/xe_sa.h +index 99dbf0eea54025..90ffa93a000ce4 100644 +--- a/drivers/gpu/drm/xe/xe_sa.h ++++ b/drivers/gpu/drm/xe/xe_sa.h +@@ -14,12 +14,14 @@ + struct dma_fence; + struct xe_tile; + +-struct xe_sa_manager *__xe_sa_bo_manager_init(struct xe_tile *tile, u32 size, u32 guard, u32 align); ++#define XE_SA_BO_MANAGER_FLAG_SHADOW BIT(0) ++struct xe_sa_manager *__xe_sa_bo_manager_init(struct xe_tile *tile, u32 size, ++ u32 guard, u32 align, u32 flags); + struct drm_suballoc *__xe_sa_bo_new(struct xe_sa_manager *sa_manager, u32 size, gfp_t gfp); + + static inline struct xe_sa_manager *xe_sa_bo_manager_init(struct xe_tile *tile, u32 size, u32 align) + { +- return __xe_sa_bo_manager_init(tile, size, SZ_4K, align); ++ return __xe_sa_bo_manager_init(tile, size, SZ_4K, align, 0); + } + + /** +@@ -68,4 +70,18 @@ static inline void *xe_sa_bo_cpu_addr(struct drm_suballoc *sa) + drm_suballoc_soffset(sa); + } + ++void xe_sa_bo_swap_shadow(struct xe_sa_manager *sa_manager); ++void xe_sa_bo_sync_shadow(struct drm_suballoc *sa_bo); ++ ++/** ++ * xe_sa_bo_swap_guard() - Retrieve the SA BO swap guard within sub-allocator. ++ * @sa_manager: the &xe_sa_manager ++ * ++ * Return: Sub alloctor swap guard mutex. ++ */ ++static inline struct mutex *xe_sa_bo_swap_guard(struct xe_sa_manager *sa_manager) ++{ ++ return &sa_manager->swap_guard; ++} ++ + #endif +diff --git a/drivers/gpu/drm/xe/xe_sa_types.h b/drivers/gpu/drm/xe/xe_sa_types.h +index cb7238799dcb20..1085c9c37d6b61 100644 +--- a/drivers/gpu/drm/xe/xe_sa_types.h ++++ b/drivers/gpu/drm/xe/xe_sa_types.h +@@ -12,6 +12,9 @@ struct xe_bo; + struct xe_sa_manager { + struct drm_suballoc_manager base; + struct xe_bo *bo; ++ struct xe_bo *shadow; ++ /** @swap_guard: Timeline guard updating @bo and @shadow */ ++ struct mutex swap_guard; + void *cpu_ptr; + bool is_iomem; + }; +diff --git a/drivers/gpu/drm/xe/xe_sriov_vf_ccs.c b/drivers/gpu/drm/xe/xe_sriov_vf_ccs.c +index 739a3eb180b53c..1a7d767632dadf 100644 +--- a/drivers/gpu/drm/xe/xe_sriov_vf_ccs.c ++++ b/drivers/gpu/drm/xe/xe_sriov_vf_ccs.c +@@ -160,9 +160,12 @@ static int alloc_bb_pool(struct xe_tile *tile, struct xe_sriov_vf_ccs_ctx *ctx) + offset = 0; + xe_map_memset(xe, &sa_manager->bo->vmap, offset, MI_NOOP, + bb_pool_size); ++ xe_map_memset(xe, &sa_manager->shadow->vmap, offset, MI_NOOP, ++ bb_pool_size); + + offset = bb_pool_size - sizeof(u32); + xe_map_wr(xe, &sa_manager->bo->vmap, offset, u32, MI_BATCH_BUFFER_END); ++ xe_map_wr(xe, &sa_manager->shadow->vmap, offset, u32, MI_BATCH_BUFFER_END); + + ctx->mem.ccs_bb_pool = sa_manager; + +-- +2.53.0 + diff --git a/queue-6.18/drm-xe-vf-fix-vf-ccs-attach-detach-race-with-in-flig.patch b/queue-6.18/drm-xe-vf-fix-vf-ccs-attach-detach-race-with-in-flig.patch new file mode 100644 index 0000000000..4e4859ea8b --- /dev/null +++ b/queue-6.18/drm-xe-vf-fix-vf-ccs-attach-detach-race-with-in-flig.patch @@ -0,0 +1,235 @@ +From c2cefd16b8e59282a2e881419b34f12dcecc4c0d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 13 Jul 2026 23:24:40 -0700 +Subject: drm/xe/vf: Fix VF CCS attach/detach race with in-flight BO moves +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Matthew Brost + +[ Upstream commit 56441f9e08ad68697295b8835266d2bc48ab59b5 ] + +xe_bo_move() attaches VF CCS read/write batch buffers (BBs) to a BO +after it transitions NULL/SYSTEM -> TT, and detaches them after it +transitions TT -> SYSTEM. Both operations were done synchronously on +the CPU immediately after building the move's copy/clear fence, +without waiting for that fence to signal. This creates two races with +VF migration: + +- Attach happens too late relative to the copy job it is meant to + protect. If the copy job is submitted before the CCS BBs are + attached, a VF migration event that pauses execution mid-copy can + observe partially copied CCS metadata without the attach state + needed to correctly save/restore it. + +- Detach happens too early relative to the copy job that moves data + out of TT. The CCS BBs are torn down right after the copy fence is + obtained, while the actual blit may still be in flight. A VF + migration event that pauses execution mid-copy can then race the + save/restore path against the still-running blit, and the CCS BBs + it would need to make sense of the paused state have already been + removed. + +Fix both races: + +- Move the attach call to before the copy/clear job is submitted, so + the CCS BBs are already registered by the time the copy runs. On + attach failure, unwind and bail out of the move. xe_migrate_ccs_rw_copy() + now takes the destination resource explicitly, since bo->ttm.resource + is not updated to the new resource until after the move commits. + +- Detach only after explicitly waiting for the copy fence to signal, + instead of tearing down the CCS BBs immediately after obtaining it. + +While here, also fix xe_sriov_vf_ccs_attach_bo() to properly unwind and +propagate errors: the per-context loop previously never broke out on +error, silently discarding earlier failures. Unwind by clearing each +attached context directly via xe_migrate_ccs_rw_copy_clear() instead of +reusing xe_sriov_vf_ccs_detach_bo(), which requires both contexts to be +attached before it will clean up either one. + +Fixes: 864690cf4dd6 ("drm/xe/vf: Attach and detach CCS copy commands with BO") +Cc: Michal Wajdeczko +Cc: Matthew Auld +Cc: Michał Winiarski +Cc: Satyanarayana K V P +Assisted-by: GitHub_Copilot:claude-sonnet-5 +Signed-off-by: Matthew Brost +Acked-by: Satyanarayana K V P +Reviewed-by: Matthew Auld +Link: https://patch.msgid.link/20260714062440.3421225-1-matthew.brost@intel.com +(cherry picked from commit d45ad0aa7a1eb5d7288b5ed948b05695611dc39e) +Signed-off-by: Thomas Hellström +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/xe/xe_bo.c | 34 +++++++++++++++++++--------- + drivers/gpu/drm/xe/xe_migrate.c | 5 +++- + drivers/gpu/drm/xe/xe_migrate.h | 1 + + drivers/gpu/drm/xe/xe_sriov_vf_ccs.c | 20 ++++++++++++++-- + drivers/gpu/drm/xe/xe_sriov_vf_ccs.h | 3 ++- + 5 files changed, 48 insertions(+), 15 deletions(-) + +diff --git a/drivers/gpu/drm/xe/xe_bo.c b/drivers/gpu/drm/xe/xe_bo.c +index 0dabe85351392e..1d46b61bf1285d 100644 +--- a/drivers/gpu/drm/xe/xe_bo.c ++++ b/drivers/gpu/drm/xe/xe_bo.c +@@ -930,6 +930,21 @@ static int xe_bo_move(struct ttm_buffer_object *ttm_bo, bool evict, + xe_pm_runtime_get_noresume(xe); + } + ++ /* ++ * Attach CCS BBs before submitting the copy job below so a VF ++ * migration racing the copy sees valid, up to date attach state. ++ */ ++ if (IS_VF_CCS_READY(xe) && ++ ((move_lacks_source && new_mem->mem_type == XE_PL_TT) || ++ (old_mem_type == XE_PL_SYSTEM && new_mem->mem_type == XE_PL_TT)) && ++ handle_system_ccs) { ++ ret = xe_sriov_vf_ccs_attach_bo(bo, new_mem); ++ if (ret) { ++ xe_pm_runtime_put(xe); ++ goto out; ++ } ++ } ++ + if (move_lacks_source) { + u32 flags = 0; + +@@ -967,22 +982,19 @@ static int xe_bo_move(struct ttm_buffer_object *ttm_bo, bool evict, + ttm_bo_move_null(ttm_bo, new_mem); + } + +- dma_fence_put(fence); +- xe_pm_runtime_put(xe); +- + /* +- * CCS meta data is migrated from TT -> SMEM. So, let us detach the +- * BBs from BO as it is no longer needed. ++ * Detach must wait for the copy above to complete: a VF migration ++ * racing an in-flight copy must still see valid CCS BBs, so don't ++ * tear them down until the copy fence has signaled. + */ + if (IS_VF_CCS_READY(xe) && old_mem_type == XE_PL_TT && +- new_mem->mem_type == XE_PL_SYSTEM) ++ new_mem->mem_type == XE_PL_SYSTEM) { ++ dma_fence_wait(fence, false); + xe_sriov_vf_ccs_detach_bo(bo); ++ } + +- if (IS_VF_CCS_READY(xe) && +- ((move_lacks_source && new_mem->mem_type == XE_PL_TT) || +- (old_mem_type == XE_PL_SYSTEM && new_mem->mem_type == XE_PL_TT)) && +- handle_system_ccs) +- ret = xe_sriov_vf_ccs_attach_bo(bo); ++ dma_fence_put(fence); ++ xe_pm_runtime_put(xe); + + out: + if ((!ttm_bo->resource || ttm_bo->resource->mem_type == XE_PL_SYSTEM) && +diff --git a/drivers/gpu/drm/xe/xe_migrate.c b/drivers/gpu/drm/xe/xe_migrate.c +index 6a0c088d09fb33..e0a14360d312e0 100644 +--- a/drivers/gpu/drm/xe/xe_migrate.c ++++ b/drivers/gpu/drm/xe/xe_migrate.c +@@ -1001,6 +1001,8 @@ static int emit_flush_invalidate(struct xe_exec_queue *q, u32 *dw, int i, + * @tile: Tile whose migration context to be used. + * @q : Execution to be used along with migration context. + * @src_bo: The buffer object @src is currently bound to. ++ * @new_mem: The (not yet committed) destination resource @src_bo is being ++ * moved into; src_bo->ttm.resource is still the old resource. + * @read_write : Creates BB commands for CCS read/write. + * + * Creates batch buffer instructions to copy CCS metadata from CCS pool to +@@ -1012,12 +1014,13 @@ static int emit_flush_invalidate(struct xe_exec_queue *q, u32 *dw, int i, + */ + int xe_migrate_ccs_rw_copy(struct xe_tile *tile, struct xe_exec_queue *q, + struct xe_bo *src_bo, ++ struct ttm_resource *new_mem, + enum xe_sriov_vf_ccs_rw_ctxs read_write) + + { + bool src_is_pltt = read_write == XE_SRIOV_VF_CCS_READ_CTX; + bool dst_is_pltt = read_write == XE_SRIOV_VF_CCS_WRITE_CTX; +- struct ttm_resource *src = src_bo->ttm.resource; ++ struct ttm_resource *src = new_mem; + struct xe_migrate *m = tile->migrate; + struct xe_gt *gt = tile->primary_gt; + u32 batch_size, batch_size_allocated; +diff --git a/drivers/gpu/drm/xe/xe_migrate.h b/drivers/gpu/drm/xe/xe_migrate.h +index 438c3bb66d9b24..8bac669685ee92 100644 +--- a/drivers/gpu/drm/xe/xe_migrate.h ++++ b/drivers/gpu/drm/xe/xe_migrate.h +@@ -129,6 +129,7 @@ struct dma_fence *xe_migrate_copy(struct xe_migrate *m, + + int xe_migrate_ccs_rw_copy(struct xe_tile *tile, struct xe_exec_queue *q, + struct xe_bo *src_bo, ++ struct ttm_resource *new_mem, + enum xe_sriov_vf_ccs_rw_ctxs read_write); + + void xe_migrate_ccs_rw_copy_clear(struct xe_bo *src_bo, +diff --git a/drivers/gpu/drm/xe/xe_sriov_vf_ccs.c b/drivers/gpu/drm/xe/xe_sriov_vf_ccs.c +index d62156195f321b..e03714ef7ae996 100644 +--- a/drivers/gpu/drm/xe/xe_sriov_vf_ccs.c ++++ b/drivers/gpu/drm/xe/xe_sriov_vf_ccs.c +@@ -330,6 +330,8 @@ void xe_sriov_vf_ccs_rw_update_bb_addr(struct xe_sriov_vf_ccs_ctx *ctx) + /** + * xe_sriov_vf_ccs_attach_bo - Insert CCS read write commands in the BO. + * @bo: the &buffer object to which batch buffer commands will be added. ++ * @new_mem: the (not yet committed) destination resource @bo is being moved ++ * into; bo->ttm.resource is still the old resource at this point. + * + * This function shall be called only by VF. It inserts the PTEs and copy + * command instructions in the BO by calling xe_migrate_ccs_rw_copy() +@@ -337,7 +339,7 @@ void xe_sriov_vf_ccs_rw_update_bb_addr(struct xe_sriov_vf_ccs_ctx *ctx) + * + * Returns: 0 if successful, negative error code on failure. + */ +-int xe_sriov_vf_ccs_attach_bo(struct xe_bo *bo) ++int xe_sriov_vf_ccs_attach_bo(struct xe_bo *bo, struct ttm_resource *new_mem) + { + struct xe_device *xe = xe_bo_device(bo); + enum xe_sriov_vf_ccs_rw_ctxs ctx_id; +@@ -356,7 +358,21 @@ int xe_sriov_vf_ccs_attach_bo(struct xe_bo *bo) + xe_assert(xe, !bb); + + ctx = &xe->sriov.vf.ccs.contexts[ctx_id]; +- err = xe_migrate_ccs_rw_copy(tile, ctx->mig_q, bo, ctx_id); ++ err = xe_migrate_ccs_rw_copy(tile, ctx->mig_q, bo, new_mem, ctx_id); ++ if (err) ++ goto err_unwind; ++ } ++ return 0; ++ ++err_unwind: ++ /* ++ * Clean up any contexts already attached. Can't reuse ++ * xe_sriov_vf_ccs_detach_bo() here as it requires both contexts ++ * attached before cleaning up either one. ++ */ ++ for_each_ccs_rw_ctx(ctx_id) { ++ if (bo->bb_ccs[ctx_id]) ++ xe_migrate_ccs_rw_copy_clear(bo, ctx_id); + } + return err; + } +diff --git a/drivers/gpu/drm/xe/xe_sriov_vf_ccs.h b/drivers/gpu/drm/xe/xe_sriov_vf_ccs.h +index a9c6512f87034f..00d2c9dbe00d9a 100644 +--- a/drivers/gpu/drm/xe/xe_sriov_vf_ccs.h ++++ b/drivers/gpu/drm/xe/xe_sriov_vf_ccs.h +@@ -11,11 +11,12 @@ + #include "xe_sriov_vf_ccs_types.h" + + struct drm_printer; ++struct ttm_resource; + struct xe_device; + struct xe_bo; + + int xe_sriov_vf_ccs_init(struct xe_device *xe); +-int xe_sriov_vf_ccs_attach_bo(struct xe_bo *bo); ++int xe_sriov_vf_ccs_attach_bo(struct xe_bo *bo, struct ttm_resource *new_mem); + int xe_sriov_vf_ccs_detach_bo(struct xe_bo *bo); + int xe_sriov_vf_ccs_register_context(struct xe_device *xe); + void xe_sriov_vf_ccs_print(struct xe_device *xe, struct drm_printer *p); +-- +2.53.0 + diff --git a/queue-6.18/drm-xe-vf-shadow-buffer-management-for-ccs-read-writ.patch b/queue-6.18/drm-xe-vf-shadow-buffer-management-for-ccs-read-writ.patch new file mode 100644 index 0000000000..be99bfbb7b --- /dev/null +++ b/queue-6.18/drm-xe-vf-shadow-buffer-management-for-ccs-read-writ.patch @@ -0,0 +1,206 @@ +From b96a726fb586a35949b47299a8eda7661b50d883 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 18 Nov 2025 12:07:45 +0000 +Subject: drm/xe/vf: Shadow buffer management for CCS read/write operations + +From: Satyanarayana K V P + +[ Upstream commit fa18290bf0723b02bfa8d30d2e14722f0d096c2c ] + +CCS copy command consist of 5-dword sequence. If vCPU halts during +save/restore operations while these sequences are being programmed, +incomplete writes can cause page faults during IGPU CCS metadata saving. + +Use shadow buffer management to prevent partial write issues during CCS +operations. + +Signed-off-by: Satyanarayana K V P +Suggested-by: Matthew Brost +Cc: Michal Wajdeczko +Cc: Matthew Auld +Reviewed-by: Matthew Brost +Signed-off-by: Matthew Brost +Link: https://patch.msgid.link/20251118120745.3460172-3-satyanarayana.k.v.p@intel.com +Stable-dep-of: 56441f9e08ad ("drm/xe/vf: Fix VF CCS attach/detach race with in-flight BO moves") +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/xe/xe_migrate.c | 57 ++++++++++++++++++++++++++-- + drivers/gpu/drm/xe/xe_migrate.h | 3 ++ + drivers/gpu/drm/xe/xe_sriov_vf_ccs.c | 19 ++++++++-- + drivers/gpu/drm/xe/xe_sriov_vf_ccs.h | 1 + + 4 files changed, 73 insertions(+), 7 deletions(-) + +diff --git a/drivers/gpu/drm/xe/xe_migrate.c b/drivers/gpu/drm/xe/xe_migrate.c +index b6905f35d6c81f..6a0c088d09fb33 100644 +--- a/drivers/gpu/drm/xe/xe_migrate.c ++++ b/drivers/gpu/drm/xe/xe_migrate.c +@@ -33,6 +33,7 @@ + #include "xe_res_cursor.h" + #include "xe_sa.h" + #include "xe_sched_job.h" ++#include "xe_sriov_vf_ccs.h" + #include "xe_sync.h" + #include "xe_trace_bo.h" + #include "xe_validation.h" +@@ -1022,12 +1023,16 @@ int xe_migrate_ccs_rw_copy(struct xe_tile *tile, struct xe_exec_queue *q, + u32 batch_size, batch_size_allocated; + struct xe_device *xe = gt_to_xe(gt); + struct xe_res_cursor src_it, ccs_it; ++ struct xe_sriov_vf_ccs_ctx *ctx; ++ struct xe_sa_manager *bb_pool; + u64 size = xe_bo_size(src_bo); + struct xe_bb *bb = NULL; + u64 src_L0, src_L0_ofs; + u32 src_L0_pt; + int err; + ++ ctx = &xe->sriov.vf.ccs.contexts[read_write]; ++ + xe_res_first_sg(xe_bo_sg(src_bo), 0, size, &src_it); + + xe_res_first_sg(xe_bo_sg(src_bo), xe_bo_ccs_pages_start(src_bo), +@@ -1060,11 +1065,15 @@ int xe_migrate_ccs_rw_copy(struct xe_tile *tile, struct xe_exec_queue *q, + size -= src_L0; + } + ++ bb_pool = ctx->mem.ccs_bb_pool; ++ guard(mutex) (xe_sa_bo_swap_guard(bb_pool)); ++ xe_sa_bo_swap_shadow(bb_pool); ++ + bb = xe_bb_ccs_new(gt, batch_size, read_write); + if (IS_ERR(bb)) { + drm_err(&xe->drm, "BB allocation failed.\n"); + err = PTR_ERR(bb); +- goto err_ret; ++ return err; + } + + batch_size_allocated = batch_size; +@@ -1113,10 +1122,52 @@ int xe_migrate_ccs_rw_copy(struct xe_tile *tile, struct xe_exec_queue *q, + xe_assert(xe, (batch_size_allocated == bb->len)); + src_bo->bb_ccs[read_write] = bb; + ++ xe_sriov_vf_ccs_rw_update_bb_addr(ctx); ++ xe_sa_bo_sync_shadow(bb->bo); + return 0; ++} + +-err_ret: +- return err; ++/** ++ * xe_migrate_ccs_rw_copy_clear() - Clear the CCS read/write batch buffer ++ * content. ++ * @src_bo: The buffer object @src is currently bound to. ++ * @read_write : Creates BB commands for CCS read/write. ++ * ++ * Directly clearing the BB lacks atomicity and can lead to undefined ++ * behavior if the vCPU is halted mid-operation during the clearing ++ * process. To avoid this issue, we use a shadow buffer object approach. ++ * ++ * First swap the SA BO address with the shadow BO, perform the clearing ++ * operation on the BB, update the shadow BO in the ring buffer, then ++ * sync the shadow and the actual buffer to maintain consistency. ++ * ++ * Returns: None. ++ */ ++void xe_migrate_ccs_rw_copy_clear(struct xe_bo *src_bo, ++ enum xe_sriov_vf_ccs_rw_ctxs read_write) ++{ ++ struct xe_bb *bb = src_bo->bb_ccs[read_write]; ++ struct xe_device *xe = xe_bo_device(src_bo); ++ struct xe_sriov_vf_ccs_ctx *ctx; ++ struct xe_sa_manager *bb_pool; ++ u32 *cs; ++ ++ xe_assert(xe, IS_SRIOV_VF(xe)); ++ ++ ctx = &xe->sriov.vf.ccs.contexts[read_write]; ++ bb_pool = ctx->mem.ccs_bb_pool; ++ ++ guard(mutex) (xe_sa_bo_swap_guard(bb_pool)); ++ xe_sa_bo_swap_shadow(bb_pool); ++ ++ cs = xe_sa_bo_cpu_addr(bb->bo); ++ memset(cs, MI_NOOP, bb->len * sizeof(u32)); ++ xe_sriov_vf_ccs_rw_update_bb_addr(ctx); ++ ++ xe_sa_bo_sync_shadow(bb->bo); ++ ++ xe_bb_free(bb, NULL); ++ src_bo->bb_ccs[read_write] = NULL; + } + + /** +diff --git a/drivers/gpu/drm/xe/xe_migrate.h b/drivers/gpu/drm/xe/xe_migrate.h +index bc55f650204b83..438c3bb66d9b24 100644 +--- a/drivers/gpu/drm/xe/xe_migrate.h ++++ b/drivers/gpu/drm/xe/xe_migrate.h +@@ -131,6 +131,9 @@ int xe_migrate_ccs_rw_copy(struct xe_tile *tile, struct xe_exec_queue *q, + struct xe_bo *src_bo, + enum xe_sriov_vf_ccs_rw_ctxs read_write); + ++void xe_migrate_ccs_rw_copy_clear(struct xe_bo *src_bo, ++ enum xe_sriov_vf_ccs_rw_ctxs read_write); ++ + struct xe_lrc *xe_migrate_lrc(struct xe_migrate *migrate); + struct xe_exec_queue *xe_migrate_exec_queue(struct xe_migrate *migrate); + int xe_migrate_access_memory(struct xe_migrate *m, struct xe_bo *bo, +diff --git a/drivers/gpu/drm/xe/xe_sriov_vf_ccs.c b/drivers/gpu/drm/xe/xe_sriov_vf_ccs.c +index 1a7d767632dadf..d62156195f321b 100644 +--- a/drivers/gpu/drm/xe/xe_sriov_vf_ccs.c ++++ b/drivers/gpu/drm/xe/xe_sriov_vf_ccs.c +@@ -148,7 +148,8 @@ static int alloc_bb_pool(struct xe_tile *tile, struct xe_sriov_vf_ccs_ctx *ctx) + xe_sriov_info(xe, "Allocating %s CCS BB pool size = %lldMB\n", + ctx->ctx_id ? "Restore" : "Save", bb_pool_size / SZ_1M); + +- sa_manager = xe_sa_bo_manager_init(tile, bb_pool_size, SZ_16); ++ sa_manager = __xe_sa_bo_manager_init(tile, bb_pool_size, SZ_4K, SZ_16, ++ XE_SA_BO_MANAGER_FLAG_SHADOW); + + if (IS_ERR(sa_manager)) { + xe_sriov_err(xe, "Suballocator init failed with error: %pe\n", +@@ -314,6 +315,18 @@ int xe_sriov_vf_ccs_init(struct xe_device *xe) + return err; + } + ++#define XE_SRIOV_VF_CCS_RW_BB_ADDR_OFFSET (2 * sizeof(u32)) ++void xe_sriov_vf_ccs_rw_update_bb_addr(struct xe_sriov_vf_ccs_ctx *ctx) ++{ ++ u64 addr = xe_sa_manager_gpu_addr(ctx->mem.ccs_bb_pool); ++ struct xe_lrc *lrc = xe_exec_queue_lrc(ctx->mig_q); ++ struct xe_device *xe = gt_to_xe(ctx->mig_q->gt); ++ ++ xe_device_wmb(xe); ++ xe_map_wr(xe, &lrc->bo->vmap, XE_SRIOV_VF_CCS_RW_BB_ADDR_OFFSET, u32, addr); ++ xe_device_wmb(xe); ++} ++ + /** + * xe_sriov_vf_ccs_attach_bo - Insert CCS read write commands in the BO. + * @bo: the &buffer object to which batch buffer commands will be added. +@@ -374,9 +387,7 @@ int xe_sriov_vf_ccs_detach_bo(struct xe_bo *bo) + if (!bb) + continue; + +- memset(bb->cs, MI_NOOP, bb->len * sizeof(u32)); +- xe_bb_free(bb, NULL); +- bo->bb_ccs[ctx_id] = NULL; ++ xe_migrate_ccs_rw_copy_clear(bo, ctx_id); + } + return 0; + } +diff --git a/drivers/gpu/drm/xe/xe_sriov_vf_ccs.h b/drivers/gpu/drm/xe/xe_sriov_vf_ccs.h +index 0745c0ff022828..a9c6512f87034f 100644 +--- a/drivers/gpu/drm/xe/xe_sriov_vf_ccs.h ++++ b/drivers/gpu/drm/xe/xe_sriov_vf_ccs.h +@@ -19,6 +19,7 @@ int xe_sriov_vf_ccs_attach_bo(struct xe_bo *bo); + int xe_sriov_vf_ccs_detach_bo(struct xe_bo *bo); + int xe_sriov_vf_ccs_register_context(struct xe_device *xe); + void xe_sriov_vf_ccs_print(struct xe_device *xe, struct drm_printer *p); ++void xe_sriov_vf_ccs_rw_update_bb_addr(struct xe_sriov_vf_ccs_ctx *ctx); + + static inline bool xe_sriov_vf_ccs_ready(struct xe_device *xe) + { +-- +2.53.0 + diff --git a/queue-6.18/drm-xe-wopcm-fix-wopcm-size-for-lnl.patch b/queue-6.18/drm-xe-wopcm-fix-wopcm-size-for-lnl.patch new file mode 100644 index 0000000000..734ec0af8b --- /dev/null +++ b/queue-6.18/drm-xe-wopcm-fix-wopcm-size-for-lnl.patch @@ -0,0 +1,71 @@ +From 32df72a99bfd5c3da5abda26c1f6ce96ec99147d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 13 Jul 2026 15:17:59 -0700 +Subject: drm/xe/wopcm: fix WOPCM size for LNL+ +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Daniele Ceraolo Spurio + +[ Upstream commit ad87e2476b3b246580f407afc8ffa91d621bc849 ] + +Starting on LNL the WOPCM size is 8MB instead of 4, so we need to avoid +using the [0, 8MB) range of the GGTT as that can be unaccessible from +the microcontrollers. + +Note that the proper long-term fix here is to read the WOPCM size from +the HW, but that is a more serious rework that would be difficult to +backport, so we can do that as a follow-up. + +Fixes: 9c57bc08652a ("drm/xe/lnl: Drop force_probe requirement") +Signed-off-by: Daniele Ceraolo Spurio +Cc: Rodrigo Vivi +Cc: Shuicheng Lin +Cc: Matt Roper +Reviewed-by: Shuicheng Lin +Link: https://patch.msgid.link/20260713221758.3285744-2-daniele.ceraolospurio@intel.com +(cherry picked from commit 3033b0b24ed0e2f5e56bdd4d9c183417c365a45b) +Signed-off-by: Thomas Hellström +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/xe/xe_wopcm.c | 15 ++++++++++----- + 1 file changed, 10 insertions(+), 5 deletions(-) + +diff --git a/drivers/gpu/drm/xe/xe_wopcm.c b/drivers/gpu/drm/xe/xe_wopcm.c +index ada0d0aa6b7494..2fd2a82be89f87 100644 +--- a/drivers/gpu/drm/xe/xe_wopcm.c ++++ b/drivers/gpu/drm/xe/xe_wopcm.c +@@ -49,9 +49,9 @@ + */ + + /* Default WOPCM size is 2MB from Gen11, 1MB on previous platforms */ +-/* FIXME: Larger size require for 2 tile PVC, do a proper probe sooner or later */ ++/* FIXME: Larger size require for some platforms, do a proper probe sooner or later */ + #define DGFX_WOPCM_SIZE SZ_4M +-/* FIXME: Larger size require for MTL, do a proper probe sooner or later */ ++#define LNL_WOPCM_SIZE SZ_8M + #define MTL_WOPCM_SIZE SZ_4M + #define WOPCM_SIZE SZ_2M + +@@ -181,9 +181,14 @@ static int __wopcm_init_regs(struct xe_device *xe, struct xe_gt *gt, + + u32 xe_wopcm_size(struct xe_device *xe) + { +- return IS_DGFX(xe) ? DGFX_WOPCM_SIZE : +- xe->info.platform == XE_METEORLAKE ? MTL_WOPCM_SIZE : +- WOPCM_SIZE; ++ if (xe->info.platform >= XE_LUNARLAKE) ++ return LNL_WOPCM_SIZE; ++ else if (IS_DGFX(xe)) ++ return DGFX_WOPCM_SIZE; ++ else if (xe->info.platform == XE_METEORLAKE) ++ return MTL_WOPCM_SIZE; ++ else ++ return WOPCM_SIZE; + } + + /** +-- +2.53.0 + diff --git a/queue-6.18/firmware-arm_ffa-fix-endpoint-memory-access-descript.patch b/queue-6.18/firmware-arm_ffa-fix-endpoint-memory-access-descript.patch new file mode 100644 index 0000000000..3922525c49 --- /dev/null +++ b/queue-6.18/firmware-arm_ffa-fix-endpoint-memory-access-descript.patch @@ -0,0 +1,93 @@ +From fe1596ba834ff982f0ac18326b7fdd2997d6a2f9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 2 Jul 2026 10:38:39 +0000 +Subject: firmware: arm_ffa: Fix Endpoint Memory Access Descriptor offset + calculation + +From: Sebastian Ene + +[ Upstream commit b4d961351aa84fdf0148783fb1f3a1391b8a0adb ] + +Use the descriptor's `ep_mem_offset` to calculate the start of the endpoint +memory access array and to comply with the FF-A spec instead of defaulting +to `sizeof(struct ffa_mem_region)`. +This requires moving `ffa_mem_region_additional_setup()` earlier in the setup +flow. +Also, add sanity checks to ensure the calculated descriptor offsets do not +exceed `max_fragsize`. + +Fixes: 113580530ee7 ("firmware: arm_ffa: Update memory descriptor to support v1.1 format") +Reviewed-by: Sudeep Holla +Signed-off-by: Mostafa Saleh +Signed-off-by: Sebastian Ene +Link: https://patch.msgid.link/20260702103848.1647249-3-sebastianene@google.com +Signed-off-by: Marc Zyngier +Signed-off-by: Sasha Levin +--- + drivers/firmware/arm_ffa/driver.c | 20 +++++++++++++++----- + include/linux/arm_ffa.h | 2 +- + 2 files changed, 16 insertions(+), 6 deletions(-) + +diff --git a/drivers/firmware/arm_ffa/driver.c b/drivers/firmware/arm_ffa/driver.c +index 6f576c39e4832a..1d0bd586da4d6f 100644 +--- a/drivers/firmware/arm_ffa/driver.c ++++ b/drivers/firmware/arm_ffa/driver.c +@@ -707,19 +707,30 @@ ffa_setup_and_transmit(u32 func_id, void *buffer, u32 max_fragsize, + struct ffa_composite_mem_region *composite; + struct ffa_mem_region_addr_range *constituents; + struct ffa_mem_region_attributes *ep_mem_access; +- u32 idx, frag_len, length, buf_sz = 0, num_entries = sg_nents(args->sg); ++ u32 idx, frag_len, length, buf_sz = 0, num_entries = sg_nents(args->sg), ep_offset; ++ u32 emad_end, emad_size = ffa_emad_size_get(drv_info->version); + + mem_region->tag = args->tag; + mem_region->flags = args->flags; + mem_region->sender_id = drv_info->vm_id; + mem_region->attributes = ffa_memory_attributes_get(func_id); ++ ++ ffa_mem_region_additional_setup(drv_info->version, mem_region); + composite_offset = ffa_mem_desc_offset(buffer, args->nattrs, + drv_info->version); ++ if (composite_offset + sizeof(*composite) > max_fragsize) ++ return -ENXIO; + + for (idx = 0; idx < args->nattrs; idx++) { +- ep_mem_access = buffer + +- ffa_mem_desc_offset(buffer, idx, drv_info->version); +- memset(ep_mem_access, 0, ffa_emad_size_get(drv_info->version)); ++ ep_offset = ffa_mem_desc_offset(buffer, idx, drv_info->version); ++ if (check_add_overflow(ep_offset, emad_size, &emad_end)) ++ return -ENXIO; ++ ++ if (emad_end > max_fragsize) ++ return -ENXIO; ++ ++ ep_mem_access = buffer + ep_offset; ++ memset(ep_mem_access, 0, emad_size); + ep_mem_access->receiver = args->attrs[idx].receiver; + ep_mem_access->attrs = args->attrs[idx].attrs; + ep_mem_access->composite_off = composite_offset; +@@ -729,7 +740,6 @@ ffa_setup_and_transmit(u32 func_id, void *buffer, u32 max_fragsize, + } + mem_region->handle = 0; + mem_region->ep_count = args->nattrs; +- ffa_mem_region_additional_setup(drv_info->version, mem_region); + + composite = buffer + composite_offset; + composite->total_pg_cnt = ffa_get_num_pages_sg(args->sg); +diff --git a/include/linux/arm_ffa.h b/include/linux/arm_ffa.h +index 81e603839c4a51..62d67dae8b7033 100644 +--- a/include/linux/arm_ffa.h ++++ b/include/linux/arm_ffa.h +@@ -445,7 +445,7 @@ ffa_mem_desc_offset(struct ffa_mem_region *buf, int count, u32 ffa_version) + if (!FFA_MEM_REGION_HAS_EP_MEM_OFFSET(ffa_version)) + offset += offsetof(struct ffa_mem_region, ep_mem_offset); + else +- offset += sizeof(struct ffa_mem_region); ++ offset += buf->ep_mem_offset; + + return offset; + } +-- +2.53.0 + diff --git a/queue-6.18/firmware-arm_ffa-fix-null-dereference-in-ffa_partiti.patch b/queue-6.18/firmware-arm_ffa-fix-null-dereference-in-ffa_partiti.patch new file mode 100644 index 0000000000..0aadc2912a --- /dev/null +++ b/queue-6.18/firmware-arm_ffa-fix-null-dereference-in-ffa_partiti.patch @@ -0,0 +1,48 @@ +From 83644e951404bdf4b05c075b5c39100cc48aed32 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 17 Jun 2026 16:35:00 -0700 +Subject: firmware: arm_ffa: Fix NULL dereference in ffa_partition_info_get() + +From: Unnathi Chalicheemala + +[ Upstream commit 8ae5f8e4836667fcaffdf2e3c6068b0a8b364dd8 ] + +ffa_partition_info_get() passes uuid_str directly to uuid_parse() +without a NULL check. When a caller passes NULL, uuid_parse() -> +__uuid_parse() -> uuid_is_valid() dereferences the pointer, causing +a kernel panic: + + | Unable to handle kernel NULL pointer dereference at virtual address + | 0000000000000040 + | pc : uuid_parse+0x40/0xac + | lr : ffa_partition_info_get+0x1c/0x94 [arm_ffa] + +Add a NULL guard before uuid_parse() so a NULL argument returns +-ENODEV instead of crashing. Callers are expected to always supply +a valid partition UUID, so NULL is not a supported input. + +Fixes: d0c0bce83122 ("firmware: arm_ffa: Setup in-kernel users of FFA partitions") +Signed-off-by: Unnathi Chalicheemala +Link: https://patch.msgid.link/20260617-ffa_partition_nullptr_fix-v2-1-bc801b4ce34c@oss.qualcomm.com +Signed-off-by: Sudeep Holla +Signed-off-by: Sasha Levin +--- + drivers/firmware/arm_ffa/driver.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/firmware/arm_ffa/driver.c b/drivers/firmware/arm_ffa/driver.c +index c76eabb8436a85..feded15bb5e921 100644 +--- a/drivers/firmware/arm_ffa/driver.c ++++ b/drivers/firmware/arm_ffa/driver.c +@@ -1133,7 +1133,7 @@ static int ffa_partition_info_get(const char *uuid_str, + uuid_t uuid; + struct ffa_partition_info *pbuf; + +- if (uuid_parse(uuid_str, &uuid)) { ++ if (!uuid_str || uuid_parse(uuid_str, &uuid)) { + pr_err("invalid uuid (%s)\n", uuid_str); + return -ENODEV; + } +-- +2.53.0 + diff --git a/queue-6.18/firmware-arm_ffa-fix-out-of-bound-writes-in-ffa_setu.patch b/queue-6.18/firmware-arm_ffa-fix-out-of-bound-writes-in-ffa_setu.patch new file mode 100644 index 0000000000..22e86537ff --- /dev/null +++ b/queue-6.18/firmware-arm_ffa-fix-out-of-bound-writes-in-ffa_setu.patch @@ -0,0 +1,72 @@ +From cbb38410e93528c776d9a2f9ae3bfc3c5ba84af8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 2 Jul 2026 10:38:38 +0000 +Subject: firmware: arm_ffa: Fix out-of-bound writes in + ffa_setup_and_transmit() + +From: Mostafa Saleh + +[ Upstream commit 3383ffb7ef937317361713ffcc21921a7848511a ] + +Sashiko (locally) reports multiple out-of-bound issues in +ffa_setup_and_transmit: +1) Writing ep_mem_access->reserved can write out of bounds for FFA + versions < 1.2 as ffa_emad_size_get() returns 16 bytes in that case + while reserved has an offset of 24. + Instead of zeroing fields, memset the struct to zero first based on + the FFA version. + +2) Make sure there is enough size to write constituents. + +While at it, convert the only sizeof() in the driver that uses a +type instead of variable. + +Reviewed-by: Sudeep Holla +Fixes: 111a833dc5cb ("firmware: arm_ffa: Set reserved/MBZ fields to zero in the memory descriptors") +Signed-off-by: Mostafa Saleh +Signed-off-by: Sebastian Ene +Link: https://patch.msgid.link/20260702103848.1647249-2-sebastianene@google.com +Signed-off-by: Marc Zyngier +Signed-off-by: Sasha Levin +--- + drivers/firmware/arm_ffa/driver.c | 7 +++---- + 1 file changed, 3 insertions(+), 4 deletions(-) + +diff --git a/drivers/firmware/arm_ffa/driver.c b/drivers/firmware/arm_ffa/driver.c +index feded15bb5e921..6f576c39e4832a 100644 +--- a/drivers/firmware/arm_ffa/driver.c ++++ b/drivers/firmware/arm_ffa/driver.c +@@ -719,11 +719,10 @@ ffa_setup_and_transmit(u32 func_id, void *buffer, u32 max_fragsize, + for (idx = 0; idx < args->nattrs; idx++) { + ep_mem_access = buffer + + ffa_mem_desc_offset(buffer, idx, drv_info->version); ++ memset(ep_mem_access, 0, ffa_emad_size_get(drv_info->version)); + ep_mem_access->receiver = args->attrs[idx].receiver; + ep_mem_access->attrs = args->attrs[idx].attrs; + ep_mem_access->composite_off = composite_offset; +- ep_mem_access->flag = 0; +- ep_mem_access->reserved = 0; + ffa_emad_impdef_value_init(drv_info->version, + ep_mem_access->impdef_val, + args->attrs[idx].impdef_val); +@@ -763,7 +762,7 @@ ffa_setup_and_transmit(u32 func_id, void *buffer, u32 max_fragsize, + constituents = buffer; + } + +- if ((void *)constituents - buffer > max_fragsize) { ++ if ((void *)constituents + sizeof(*constituents) - buffer > max_fragsize) { + pr_err("Memory Region Fragment > Tx Buffer size\n"); + return -EFAULT; + } +@@ -772,7 +771,7 @@ ffa_setup_and_transmit(u32 func_id, void *buffer, u32 max_fragsize, + constituents->pg_cnt = args->sg->length / FFA_PAGE_SIZE; + constituents->reserved = 0; + constituents++; +- frag_len += sizeof(struct ffa_mem_region_addr_range); ++ frag_len += sizeof(*constituents); + } while ((args->sg = sg_next(args->sg))); + + return ffa_transmit_fragment(func_id, addr, buf_sz, frag_len, +-- +2.53.0 + diff --git a/queue-6.18/firmware-arm_ffa-respect-firmware-advertised-rx-tx-b.patch b/queue-6.18/firmware-arm_ffa-respect-firmware-advertised-rx-tx-b.patch new file mode 100644 index 0000000000..c9e3df41a7 --- /dev/null +++ b/queue-6.18/firmware-arm_ffa-respect-firmware-advertised-rx-tx-b.patch @@ -0,0 +1,118 @@ +From 227331a2b0bd055779f0175d8d7e3a7a664a1996 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 2 Jun 2026 21:54:06 +0000 +Subject: firmware: arm_ffa: Respect firmware advertised RX/TX buffer size + limits + +From: Seth Forshee + +[ Upstream commit 53716a4d745f1dac7aff33f3d1494b701eb2f888 ] + +FFA_FEATURES reports the minimum size and alignment boundary required +for RXTX_MAP. In FF-A v1.2 and later it can also report a maximum buffer +size, with zero meaning that no maximum is enforced. + +The driver only used the minimum value and then rounded it up to PAGE_SIZE +before invoking RXTX_MAP after commit 83210251fd70 ("firmware: arm_ffa: +Use the correct buffer size during RXTX_MAP"). On systems where PAGE_SIZE +is larger than the advertised minimum, this can exceed a non-zero maximum +reported by firmware. Older implementations do not advertise a maximum and +may also reject the rounded-up size. + +Decode the maximum size and clamp the page-aligned minimum to it when it +is present. If no maximum is advertised and RXTX_MAP rejects the rounded +size with INVALID_PARAMETERS, retry with the advertised minimum size. +Record drv_info->rxtx_bufsz only after RXTX_MAP succeeds so it reflects +the size registered with firmware. + +While there, also update RXTX_MAP_MIN_BUFSZ() to use FIELD_GET() for +consistency. + +Fixes: 83210251fd70 ("firmware: arm_ffa: Use the correct buffer size during RXTX_MAP") +Suggested-by: Sudeep Holla +Signed-off-by: Seth Forshee +Link: https://patch.msgid.link/20260602-b4-ffa-rxtx-map-fixes-v2-1-7cb06508da84@nvidia.com +(sudeep.holla: Minor rewording subject and commit message) +Signed-off-by: Sudeep Holla +Signed-off-by: Sasha Levin +--- + drivers/firmware/arm_ffa/driver.c | 27 ++++++++++++++++++++------- + 1 file changed, 20 insertions(+), 7 deletions(-) + +diff --git a/drivers/firmware/arm_ffa/driver.c b/drivers/firmware/arm_ffa/driver.c +index 3fbc75caf0c506..c76eabb8436a85 100644 +--- a/drivers/firmware/arm_ffa/driver.c ++++ b/drivers/firmware/arm_ffa/driver.c +@@ -32,6 +32,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -55,7 +56,9 @@ + (FIELD_PREP(SENDER_ID_MASK, (s)) | FIELD_PREP(RECEIVER_ID_MASK, (r))) + + #define RXTX_MAP_MIN_BUFSZ_MASK GENMASK(1, 0) +-#define RXTX_MAP_MIN_BUFSZ(x) ((x) & RXTX_MAP_MIN_BUFSZ_MASK) ++#define RXTX_MAP_MAX_BUFSZ_MASK GENMASK(31, 16) ++#define RXTX_MAP_MIN_BUFSZ(x) (FIELD_GET(RXTX_MAP_MIN_BUFSZ_MASK, (x))) ++#define RXTX_MAP_MAX_BUFSZ(x) (FIELD_GET(RXTX_MAP_MAX_BUFSZ_MASK, (x))) + + #define FFA_MAX_NOTIFICATIONS 64 + +@@ -2088,7 +2091,7 @@ static int __init ffa_init(void) + { + int ret; + u32 buf_sz; +- size_t rxtx_bufsz = SZ_4K; ++ size_t rxtx_min_bufsz = SZ_4K, rxtx_max_bufsz = 0, rxtx_bufsz; + + ret = ffa_transport_init(&invoke_ffa_fn); + if (ret) +@@ -2111,15 +2114,18 @@ static int __init ffa_init(void) + ret = ffa_features(FFA_FN_NATIVE(RXTX_MAP), 0, &buf_sz, NULL); + if (!ret) { + if (RXTX_MAP_MIN_BUFSZ(buf_sz) == 1) +- rxtx_bufsz = SZ_64K; ++ rxtx_min_bufsz = SZ_64K; + else if (RXTX_MAP_MIN_BUFSZ(buf_sz) == 2) +- rxtx_bufsz = SZ_16K; ++ rxtx_min_bufsz = SZ_16K; + else +- rxtx_bufsz = SZ_4K; ++ rxtx_min_bufsz = SZ_4K; ++ ++ rxtx_max_bufsz = RXTX_MAP_MAX_BUFSZ(buf_sz) * SZ_4K; ++ if (rxtx_max_bufsz != 0 && rxtx_max_bufsz < rxtx_min_bufsz) ++ rxtx_max_bufsz = rxtx_min_bufsz; + } + +- rxtx_bufsz = PAGE_ALIGN(rxtx_bufsz); +- drv_info->rxtx_bufsz = rxtx_bufsz; ++ rxtx_bufsz = min_not_zero(PAGE_ALIGN(rxtx_min_bufsz), rxtx_max_bufsz); + drv_info->rx_buffer = alloc_pages_exact(rxtx_bufsz, GFP_KERNEL); + if (!drv_info->rx_buffer) { + ret = -ENOMEM; +@@ -2135,10 +2141,17 @@ static int __init ffa_init(void) + ret = ffa_rxtx_map(virt_to_phys(drv_info->tx_buffer), + virt_to_phys(drv_info->rx_buffer), + rxtx_bufsz / FFA_PAGE_SIZE); ++ if (ret == -EINVAL && !rxtx_max_bufsz && rxtx_min_bufsz < rxtx_bufsz) { ++ rxtx_bufsz = rxtx_min_bufsz; ++ ret = ffa_rxtx_map(virt_to_phys(drv_info->tx_buffer), ++ virt_to_phys(drv_info->rx_buffer), ++ rxtx_bufsz / FFA_PAGE_SIZE); ++ } + if (ret) { + pr_err("failed to register FFA RxTx buffers\n"); + goto free_pages; + } ++ drv_info->rxtx_bufsz = rxtx_bufsz; + + mutex_init(&drv_info->rx_lock); + mutex_init(&drv_info->tx_lock); +-- +2.53.0 + diff --git a/queue-6.18/firmware-arm_scmi-rate-limit-queue-full-warnings-in-.patch b/queue-6.18/firmware-arm_scmi-rate-limit-queue-full-warnings-in-.patch new file mode 100644 index 0000000000..dbebfed3d7 --- /dev/null +++ b/queue-6.18/firmware-arm_scmi-rate-limit-queue-full-warnings-in-.patch @@ -0,0 +1,54 @@ +From fbfe39523ff2e4a23e0b98818301b3a0bc8bad8b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 8 Jul 2026 12:53:39 +0530 +Subject: firmware: arm_scmi: Rate-limit queue-full warnings in IRQ context + +From: Pushpendra Singh + +[ Upstream commit a4447c0693830d5ecadd6e755cb7fdc55d86aacc ] + +The scmi_notify() function is called from interrupt context to queue +received notification events onto a per-protocol kfifo. When the kfifo +is full, it logs a warning via dev_warn() for every dropped event. + +Under conditions where the platform sends a burst of SCMI notifications +faster than the deferred worker can drain the queue, this results in a +flood of dev_warn() calls from IRQ context. Each call acquires the +console lock and may execute blocking console writes, causing the CPU +to be held in interrupt context for an extended period and leading to +observable system stalls. + +Fix this by switching to dev_warn_ratelimited() to limit the frequency +of log messages when the notification queue is full. This reduces +console overhead in interrupt context and prevents CPU stalls caused by +excessive logging, while still preserving diagnostic visibility. + +Fixes: bd31b249692e ("firmware: arm_scmi: Add notification dispatch and delivery") +Signed-off-by: Pushpendra Singh +Link: https://patch.msgid.link/20260708072339.3021140-1-pushpendra.singh@oss.qualcomm.com +Signed-off-by: Sudeep Holla +Signed-off-by: Sasha Levin +--- + drivers/firmware/arm_scmi/notify.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/firmware/arm_scmi/notify.c b/drivers/firmware/arm_scmi/notify.c +index 2047edbdc5f6b1..9bf7f43ab868c8 100644 +--- a/drivers/firmware/arm_scmi/notify.c ++++ b/drivers/firmware/arm_scmi/notify.c +@@ -600,9 +600,9 @@ int scmi_notify(const struct scmi_handle *handle, u8 proto_id, u8 evt_id, + return -EINVAL; + } + if (kfifo_avail(&r_evt->proto->equeue.kfifo) < sizeof(eh) + len) { +- dev_warn(handle->dev, +- "queue full, dropping proto_id:%d evt_id:%d ts:%lld\n", +- proto_id, evt_id, ktime_to_ns(ts)); ++ dev_warn_ratelimited(handle->dev, ++ "queue full, dropping proto_id:%d evt_id:%d ts:%lld\n", ++ proto_id, evt_id, ktime_to_ns(ts)); + return -ENOMEM; + } + +-- +2.53.0 + diff --git a/queue-6.18/ib-mad-drop-unmatched-rmpp-responses-before-reassemb.patch b/queue-6.18/ib-mad-drop-unmatched-rmpp-responses-before-reassemb.patch new file mode 100644 index 0000000000..6525422838 --- /dev/null +++ b/queue-6.18/ib-mad-drop-unmatched-rmpp-responses-before-reassemb.patch @@ -0,0 +1,90 @@ +From f15286f9c2d54e719ae8351dd6dc3cd00f78a5d8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 6 Jun 2026 16:01:55 -0400 +Subject: IB/mad: Drop unmatched RMPP responses before reassembly + +From: Michael Bommarito + +[ Upstream commit d2e52d610b9b09694261632340b801a421e0b0c5 ] + +Kernel-handled RMPP receive processing starts reassembly for active +DATA responses before the response is matched to an outstanding send. +The normal match happens later, after ib_process_rmpp_recv_wc() has +either assembled a complete message or consumed the segment. + +That ordering lets an unsolicited response that routes to a kernel +RMPP agent by the high TID bits allocate or extend RMPP receive state +before the full TID and source address are checked against a real +request. A reordered burst can therefore reach the receive-side +insertion path even though the response would not match any send. + +For kernel-handled RMPP DATA responses, require the existing +ib_find_send_mad() match before entering RMPP reassembly. The matcher +already checks the full TID, management class and source address/GID +against the agent wait, backlog and in-flight send lists. If there is +no match, drop the response without creating RMPP state. + +This leaves the RMPP window behavior unchanged and only rejects +responses that have no corresponding request. + +Fixes: fa619a77046b ("[PATCH] IB: Add RMPP implementation") +Assisted-by: Codex:gpt-5-5-xhigh +Signed-off-by: Michael Bommarito +Link: https://patch.msgid.link/3170ff3bc389a930bb1641f2caa394a0b2241579.1780774907.git.michael.bommarito@gmail.com +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + drivers/infiniband/core/mad.c | 30 ++++++++++++++++++++++++++++++ + 1 file changed, 30 insertions(+) + +diff --git a/drivers/infiniband/core/mad.c b/drivers/infiniband/core/mad.c +index 8f26bfb695861f..5150cd53d4435a 100644 +--- a/drivers/infiniband/core/mad.c ++++ b/drivers/infiniband/core/mad.c +@@ -2031,6 +2031,24 @@ void ib_mark_mad_done(struct ib_mad_send_wr_private *mad_send_wr) + change_mad_state(mad_send_wr, IB_MAD_STATE_EARLY_RESP); + } + ++static bool is_kernel_rmpp_data_response(struct ib_mad_agent_private *agent, ++ struct ib_mad_recv_wc *mad_recv_wc) ++{ ++ const struct ib_mad_hdr *mad_hdr = &mad_recv_wc->recv_buf.mad->mad_hdr; ++ struct ib_rmpp_mad *rmpp_mad; ++ ++ if (!ib_mad_kernel_rmpp_agent(&agent->agent) || ++ !ib_response_mad(mad_hdr) || ++ !ib_is_mad_class_rmpp(mad_hdr->mgmt_class)) ++ return false; ++ ++ rmpp_mad = (struct ib_rmpp_mad *)mad_recv_wc->recv_buf.mad; ++ ++ return (ib_get_rmpp_flags(&rmpp_mad->rmpp_hdr) & ++ IB_MGMT_RMPP_FLAG_ACTIVE) && ++ rmpp_mad->rmpp_hdr.rmpp_type == IB_MGMT_RMPP_TYPE_DATA; ++} ++ + static void ib_mad_complete_recv(struct ib_mad_agent_private *mad_agent_priv, + struct ib_mad_recv_wc *mad_recv_wc) + { +@@ -2050,6 +2068,18 @@ static void ib_mad_complete_recv(struct ib_mad_agent_private *mad_agent_priv, + } + + list_add(&mad_recv_wc->recv_buf.list, &mad_recv_wc->rmpp_list); ++ if (is_kernel_rmpp_data_response(mad_agent_priv, mad_recv_wc)) { ++ spin_lock_irqsave(&mad_agent_priv->lock, flags); ++ mad_send_wr = ib_find_send_mad(mad_agent_priv, mad_recv_wc); ++ spin_unlock_irqrestore(&mad_agent_priv->lock, flags); ++ ++ if (!mad_send_wr) { ++ ib_free_recv_mad(mad_recv_wc); ++ deref_mad_agent(mad_agent_priv); ++ return; ++ } ++ } ++ + if (ib_mad_kernel_rmpp_agent(&mad_agent_priv->agent)) { + mad_recv_wc = ib_process_rmpp_recv_wc(mad_agent_priv, + mad_recv_wc); +-- +2.53.0 + diff --git a/queue-6.18/ipv4-fib-free-fib_alias-with-kfree_rcu-on-insert-err.patch b/queue-6.18/ipv4-fib-free-fib_alias-with-kfree_rcu-on-insert-err.patch new file mode 100644 index 0000000000..7ca9714898 --- /dev/null +++ b/queue-6.18/ipv4-fib-free-fib_alias-with-kfree_rcu-on-insert-err.patch @@ -0,0 +1,67 @@ +From 89ec4c759a1ec41bc62cf4c40657173eb34e0219 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 4 Jul 2026 10:14:21 -0700 +Subject: ipv4: fib: free fib_alias with kfree_rcu() on insert error path + +From: Weiming Shi + +[ Upstream commit f2f152e94a67bc746afaf05a1b2702c195553112 ] + +fib_table_insert() publishes new_fa into the leaf's fa_list with +fib_insert_alias() before calling the fib entry notifiers. When a +notifier fails, the error path removes new_fa with fib_remove_alias() +(hlist_del_rcu) and frees it right away with kmem_cache_free(). + +fib_table_lookup() walks that list under rcu_read_lock() only, so a +concurrent lookup that already reached new_fa keeps reading it after the +free: + + BUG: KASAN: slab-use-after-free in fib_table_lookup (net/ipv4/fib_trie.c:1601) + Read of size 1 at addr ffff88810676d4eb by task exploit/297 + Call Trace: + fib_table_lookup (net/ipv4/fib_trie.c:1601) + ip_route_output_key_hash_rcu (net/ipv4/route.c:2814) + ip_route_output_key_hash (net/ipv4/route.c:2705) + __ip4_datagram_connect (net/ipv4/datagram.c:49) + udp_connect (net/ipv4/udp.c:2144) + __sys_connect (net/socket.c:2167) + __x64_sys_connect (net/socket.c:2173) + do_syscall_64 + entry_SYSCALL_64_after_hwframe + which belongs to the cache ip_fib_alias of size 56 + +Triggering the error path needs CAP_NET_ADMIN and a registered fib +notifier that can reject a route; a netdevsim device whose IPv4 FIB +resource is exhausted is enough. + +Free new_fa with alias_free_mem_rcu(), as fib_table_delete() already +does for a fib_alias removed from the trie. + +Fixes: a6c76c17df02 ("ipv4: Notify route after insertion to the routing table") +Reported-by: Xiang Mei +Assisted-by: Claude:claude-opus-4-8 +Signed-off-by: Weiming Shi +Reviewed-by: Ido Schimmel +Link: https://patch.msgid.link/20260704171421.1786806-1-bestswngs@gmail.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/ipv4/fib_trie.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c +index 1308213791f19d..2dc87e2156d373 100644 +--- a/net/ipv4/fib_trie.c ++++ b/net/ipv4/fib_trie.c +@@ -1385,7 +1385,7 @@ int fib_table_insert(struct net *net, struct fib_table *tb, + out_remove_new_fa: + fib_remove_alias(t, tp, l, new_fa); + out_free_new_fa: +- kmem_cache_free(fn_alias_kmem, new_fa); ++ alias_free_mem_rcu(new_fa); + out: + fib_release_info(fi); + err: +-- +2.53.0 + diff --git a/queue-6.18/ksmbd-pin-conn-during-async-oplock-break-notificatio.patch b/queue-6.18/ksmbd-pin-conn-during-async-oplock-break-notificatio.patch new file mode 100644 index 0000000000..c8010f1a48 --- /dev/null +++ b/queue-6.18/ksmbd-pin-conn-during-async-oplock-break-notificatio.patch @@ -0,0 +1,75 @@ +From 83fab616aa69e03fa73b34c2b31e7c8ab56a2e47 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 9 Jul 2026 22:49:55 +0800 +Subject: ksmbd: pin conn during async oplock break notification + +From: Qihang + +[ Upstream commit aa5d8f3f96aa11a4a54ce993c11ce8af11c546f9 ] + +smb2_oplock_break_noti() and smb2_lease_break_noti() store a ksmbd_conn +pointer in an async ksmbd_work and then queue that work on ksmbd-io. The +work only increments conn->r_count, which prevents teardown from passing +the pending-request wait after the increment, but it does not pin the +struct ksmbd_conn object. + +If connection teardown races with an oplock break notification, the last +conn reference can be dropped before the queued worker finishes. The +worker then uses the freed conn in ksmbd_conn_write() and +ksmbd_conn_r_count_dec(). + +Take a real conn reference when publishing the conn pointer to the async +work item, and drop it after the notification work has decremented +r_count. Apply the same lifetime rule to lease break notification, which +uses the same work->conn pattern. + +Fixes: 3aa660c05924 ("ksmbd: prevent connection release during oplock break notification") +Signed-off-by: Qihang +Acked-by: Namjae Jeon +Signed-off-by: Steve French +Signed-off-by: Sasha Levin +--- + fs/smb/server/oplock.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/fs/smb/server/oplock.c b/fs/smb/server/oplock.c +index a019c4496ae433..ff0dbf3f8cbf49 100644 +--- a/fs/smb/server/oplock.c ++++ b/fs/smb/server/oplock.c +@@ -705,6 +705,7 @@ static void __smb2_oplock_break_noti(struct work_struct *wk) + out: + ksmbd_free_work_struct(work); + ksmbd_conn_r_count_dec(conn); ++ ksmbd_conn_put(conn); + } + + /** +@@ -740,7 +741,7 @@ static int smb2_oplock_break_noti(struct oplock_info *opinfo) + br_info->open_trunc = opinfo->open_trunc; + + work->request_buf = (char *)br_info; +- work->conn = conn; ++ work->conn = ksmbd_conn_get(conn); + work->sess = opinfo->sess; + + ksmbd_conn_r_count_inc(conn); +@@ -814,6 +815,7 @@ static void __smb2_lease_break_noti(struct work_struct *wk) + out: + ksmbd_free_work_struct(work); + ksmbd_conn_r_count_dec(conn); ++ ksmbd_conn_put(conn); + } + + /** +@@ -853,7 +855,7 @@ static int smb2_lease_break_noti(struct oplock_info *opinfo) + memcpy(br_info->lease_key, lease->lease_key, SMB2_LEASE_KEY_SIZE); + + work->request_buf = (char *)br_info; +- work->conn = conn; ++ work->conn = ksmbd_conn_get(conn); + work->sess = opinfo->sess; + + ksmbd_conn_r_count_inc(conn); +-- +2.53.0 + diff --git a/queue-6.18/ksmbd-validate-compound-request-size-before-reading-.patch b/queue-6.18/ksmbd-validate-compound-request-size-before-reading-.patch new file mode 100644 index 0000000000..da1b9f4304 --- /dev/null +++ b/queue-6.18/ksmbd-validate-compound-request-size-before-reading-.patch @@ -0,0 +1,69 @@ +From 8781db4f567c616ea34bb0721d63d7f46431d296 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 13 Jul 2026 21:55:10 +0000 +Subject: ksmbd: validate compound request size before reading StructureSize2 + +From: Xiang Mei (Microsoft) + +[ Upstream commit 15b38176fd1530372905c602fde51fe89ec8c877 ] + +When ksmbd validates a compound (chained) SMB2 request, +ksmbd_smb2_check_message() reads pdu->StructureSize2 without first +checking that the compound element is large enough to contain it. +StructureSize2 is a 2-byte field at offset 64 +(__SMB2_HEADER_STRUCTURE_SIZE) from the start of each element. + +The compound-walking logic only guarantees that a full 64-byte SMB2 +header is present for the trailing element: when NextCommand is 0, len is +reduced to the number of bytes remaining after next_smb2_rcv_hdr_off. A +remote client can craft a compound request whose last element has exactly +64 bytes, so the 2-byte StructureSize2 read at offset 64 extends one byte +past the receive buffer, producing a slab-out-of-bounds read. + + BUG: KASAN: slab-out-of-bounds in ksmbd_smb2_check_message (fs/smb/server/smb2misc.c:402) + Read of size 2 at addr ffff888012ae31ac by task kworker/0:1/14 + The buggy address is located 172 bytes inside of allocated 173-byte region + Workqueue: ksmbd-io handle_ksmbd_work + Call Trace: + ... + kasan_report (mm/kasan/report.c:595) + ksmbd_smb2_check_message (fs/smb/server/smb2misc.c:402) + handle_ksmbd_work (fs/smb/server/server.c:119) + process_one_work (kernel/workqueue.c:3314) + worker_thread (kernel/workqueue.c:3397) + kthread (kernel/kthread.c:436) + ret_from_fork (arch/x86/kernel/process.c:158) + ret_from_fork_asm (arch/x86/entry/entry_64.S:245) + +Reject any compound element that is too small to hold StructureSize2 +before dereferencing it. + +Fixes: e2f34481b24d ("cifsd: add server-side procedures for SMB3") +Reported-by: AutonomousCodeSecurity@microsoft.com +Signed-off-by: Xiang Mei (Microsoft) +Acked-by: Namjae Jeon +Signed-off-by: Steve French +Signed-off-by: Sasha Levin +--- + fs/smb/server/smb2misc.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/fs/smb/server/smb2misc.c b/fs/smb/server/smb2misc.c +index 67a2d7a793f6ed..b11d854d3fcfba 100644 +--- a/fs/smb/server/smb2misc.c ++++ b/fs/smb/server/smb2misc.c +@@ -400,6 +400,11 @@ int ksmbd_smb2_check_message(struct ksmbd_work *work) + return 1; + } + ++ if (len < __SMB2_HEADER_STRUCTURE_SIZE + sizeof(__le16)) { ++ ksmbd_debug(SMB, "Message is too small for StructureSize2\n"); ++ return 1; ++ } ++ + if (smb2_req_struct_sizes[command] != pdu->StructureSize2) { + if (!(command == SMB2_OPLOCK_BREAK_HE && + (le16_to_cpu(pdu->StructureSize2) == OP_BREAK_STRUCT_SIZE_20 || +-- +2.53.0 + diff --git a/queue-6.18/mpls-fix-null-deref-in-mpls_valid_fib_dump_req-on-co.patch b/queue-6.18/mpls-fix-null-deref-in-mpls_valid_fib_dump_req-on-co.patch new file mode 100644 index 0000000000..7aae14b295 --- /dev/null +++ b/queue-6.18/mpls-fix-null-deref-in-mpls_valid_fib_dump_req-on-co.patch @@ -0,0 +1,68 @@ +From 4647fcd37d6cd8027f92793114ee5ad39dbcf447 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 11 Jul 2026 04:50:00 -0700 +Subject: mpls: fix NULL deref in mpls_valid_fib_dump_req() on CONFIG_INET=n + +From: Weiming Shi + +[ Upstream commit 56d96fededd61192cd7cc8d2b0f36adfd59036c3 ] + +On CONFIG_INET=n builds, mpls_valid_fib_dump_req() walks the parsed +attribute table itself instead of calling ip_valid_fib_dump_req(). The +RTA_OIF arm passes tb[RTA_OIF] to nla_get_u32() without checking it is +present, so an RTM_GETROUTE dump for AF_MPLS with strict checking and no +RTA_OIF hits a NULL dereference. + +RTM_GETROUTE is RTNL_KIND_GET, which rtnetlink_rcv_msg() permits without +CAP_NET_ADMIN, so an unprivileged user can trigger it. + + Oops: general protection fault, probably for non-canonical address + 0xdffffc0000000000: 0000 [#1] SMP KASAN NOPTI + KASAN: null-ptr-deref in range [0x0000000000000000-0x0000000000000007] + RIP: 0010:mpls_valid_fib_dump_req (net/mpls/af_mpls.c:2189) + Call Trace: + mpls_dump_routes (net/mpls/af_mpls.c:2236) + netlink_dump (net/netlink/af_netlink.c:2331) + __netlink_dump_start (net/netlink/af_netlink.c:2446) + rtnetlink_rcv_msg (net/core/rtnetlink.c:7033) + netlink_rcv_skb (net/netlink/af_netlink.c:2556) + netlink_unicast (net/netlink/af_netlink.c:1345) + netlink_sendmsg (net/netlink/af_netlink.c:1900) + __sock_sendmsg (net/socket.c:790) + ____sys_sendmsg (net/socket.c:2684) + ___sys_sendmsg (net/socket.c:2738) + __sys_sendmsg (net/socket.c:2770) + do_syscall_64 (arch/x86/entry/syscall_64.c:94) + entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:121) + +Skip unset attributes, as ip_valid_fib_dump_req() does. + +Fixes: 196cfebf8972 ("net/mpls: Handle kernel side filtering of route dumps") +Assisted-by: Claude:claude-opus-4-8 +Reported-by: Xiang Mei +Signed-off-by: Weiming Shi +Reviewed-by: David Ahern +Link: https://patch.msgid.link/20260711114958.1009619-3-bestswngs@gmail.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/mpls/af_mpls.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/net/mpls/af_mpls.c b/net/mpls/af_mpls.c +index 1c70cb26e7ba17..f7f60025d042a4 100644 +--- a/net/mpls/af_mpls.c ++++ b/net/mpls/af_mpls.c +@@ -2123,6 +2123,9 @@ static int mpls_valid_fib_dump_req(struct net *net, const struct nlmsghdr *nlh, + int ifindex; + + if (i == RTA_OIF) { ++ if (!tb[i]) ++ continue; ++ + ifindex = nla_get_u32(tb[i]); + filter->dev = __dev_get_by_index(net, ifindex); + if (!filter->dev) +-- +2.53.0 + diff --git a/queue-6.18/mtd-fix-double-free-and-warn_on-in-add_mtd_device-er.patch b/queue-6.18/mtd-fix-double-free-and-warn_on-in-add_mtd_device-er.patch new file mode 100644 index 0000000000..ceadad7d1b --- /dev/null +++ b/queue-6.18/mtd-fix-double-free-and-warn_on-in-add_mtd_device-er.patch @@ -0,0 +1,102 @@ +From e756d1b2e9182ec68dcb72dde608d71500e3403f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 1 Jul 2026 20:10:42 +0800 +Subject: mtd: fix double free and WARN_ON in add_mtd_device() error paths + +From: Xue Lei + +[ Upstream commit 9d4af746af8ce27eefc2338b2feaa1e01f28b6c3 ] + +When device_register() or mtd_nvmem_add() fails inside +add_mtd_device() for a partition, the error handling triggers +mtd_release() via put_device() or device_unregister(). mtd_release() +calls release_mtd_partition() which frees the mtd_info structure. +However, callers such as mtd_add_partition() and add_mtd_partitions() +also call free_partition() in their error paths, resulting in a double +free. + +Additionally, release_mtd_partition() hits WARN_ON(!list_empty( +&mtd->part.node)) because the partition node is still linked in the +parent's partitions list when the release callback fires from the +add_mtd_device() error path. + +Fix this by overriding dev->type and dev->release before put_device() +in the error paths, so that device_release() invokes a no-op function +instead of mtd_release(). For the mtd_nvmem_add() failure case, +device_unregister() is replaced with device_del() to separate the +device removal from the final kobject reference drop, allowing the +override to take effect before put_device() is called. + +The callers' error paths (list_del + free_partition) remain the sole +owners of mtd_info lifetime on add_mtd_device() failure, which is the +expected contract. + +The normal partition teardown path is not affected: del_mtd_device() +goes through kref_put() -> mtd_device_release() -> device_unregister() +with dev->type still set to &mtd_devtype, so mtd_release() -> +release_mtd_partition() continues to work correctly for the regular +removal case. + +Reported-by: syzbot+e9c76b56dc05023b8117@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=e9c76b56dc05023b8117 +Fixes: 19bfa9ebebb5 ("mtd: use refcount to prevent corruption") +Signed-off-by: Xue Lei +Signed-off-by: Miquel Raynal +Signed-off-by: Sasha Levin +--- + drivers/mtd/mtdcore.c | 23 +++++++++++++++++++---- + 1 file changed, 19 insertions(+), 4 deletions(-) + +diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c +index 64808493b4f5ea..42cabd3c1efad1 100644 +--- a/drivers/mtd/mtdcore.c ++++ b/drivers/mtd/mtdcore.c +@@ -104,6 +104,15 @@ static void mtd_release(struct device *dev) + device_destroy(&mtd_class, index + 1); + } + ++/* ++ * No-op device release used in add_mtd_device() error paths. ++ * Prevents mtd_release() from being called via device_release(), ++ * which would free the mtd_info that the caller still manages. ++ */ ++static void mtd_dev_release_nop(struct device *dev) ++{ ++} ++ + static void mtd_device_release(struct kref *kref) + { + struct mtd_info *mtd = container_of(kref, struct mtd_info, refcnt); +@@ -798,10 +807,8 @@ int add_mtd_device(struct mtd_info *mtd) + mtd_check_of_node(mtd); + of_node_get(mtd_get_of_node(mtd)); + error = device_register(&mtd->dev); +- if (error) { +- put_device(&mtd->dev); ++ if (error) + goto fail_added; +- } + + /* Add the nvmem provider */ + error = mtd_nvmem_add(mtd); +@@ -839,8 +846,16 @@ int add_mtd_device(struct mtd_info *mtd) + return 0; + + fail_nvmem_add: +- device_unregister(&mtd->dev); ++ device_del(&mtd->dev); + fail_added: ++ /* ++ * Clear type and set nop release to prevent mtd_release() -> ++ * release_mtd_partition() -> free_partition() from freeing mtd. ++ * The caller handles cleanup on failure. ++ */ ++ mtd->dev.type = NULL; ++ mtd->dev.release = mtd_dev_release_nop; ++ put_device(&mtd->dev); + of_node_put(mtd_get_of_node(mtd)); + fail_devname: + idr_remove(&mtd_idr, i); +-- +2.53.0 + diff --git a/queue-6.18/mtd-mtdswap-remove-debugfs-stats-file-on-teardown.patch b/queue-6.18/mtd-mtdswap-remove-debugfs-stats-file-on-teardown.patch new file mode 100644 index 0000000000..41371f7d7b --- /dev/null +++ b/queue-6.18/mtd-mtdswap-remove-debugfs-stats-file-on-teardown.patch @@ -0,0 +1,57 @@ +From dc5012153ee7f7c26f2965c9ade4c5143a233feb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 23 Jun 2026 09:53:17 +0800 +Subject: mtd: mtdswap: remove debugfs stats file on teardown + +From: Pengpeng Hou + +[ Upstream commit 66fb31358108d10245b9e4ef0eef3e7d9747055e ] + +mtdswap_add_debugfs() creates an mtdswap_stats debugfs file under the +per-MTD debugfs directory, but mtdswap_remove_dev() never removes it +before freeing the mtdswap_dev. + +Store the returned dentry and remove it during device teardown before the +driver-private state is freed. + +Fixes: a32159024620 ("mtd: Add mtdswap block driver") +Signed-off-by: Pengpeng Hou +Signed-off-by: Miquel Raynal +Signed-off-by: Sasha Levin +--- + drivers/mtd/mtdswap.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/drivers/mtd/mtdswap.c b/drivers/mtd/mtdswap.c +index d8f2e5be2d315e..42ff7deace80c5 100644 +--- a/drivers/mtd/mtdswap.c ++++ b/drivers/mtd/mtdswap.c +@@ -125,6 +125,7 @@ struct mtdswap_dev { + + char *page_buf; + char *oob_buf; ++ struct dentry *debugfs_stats; + }; + + struct mtdswap_oobdata { +@@ -1262,7 +1263,8 @@ static int mtdswap_add_debugfs(struct mtdswap_dev *d) + if (IS_ERR_OR_NULL(root)) + return -1; + +- debugfs_create_file("mtdswap_stats", S_IRUSR, root, d, &mtdswap_fops); ++ d->debugfs_stats = debugfs_create_file("mtdswap_stats", 0400, root, ++ d, &mtdswap_fops); + + return 0; + } +@@ -1463,6 +1465,7 @@ static void mtdswap_remove_dev(struct mtd_blktrans_dev *dev) + { + struct mtdswap_dev *d = MTDSWAP_MBD_TO_MTDSWAP(dev); + ++ debugfs_remove(d->debugfs_stats); + del_mtd_blktrans_dev(dev); + mtdswap_cleanup(d); + kfree(d); +-- +2.53.0 + diff --git a/queue-6.18/mtd-nand-mtk-ecc-stop-on-ecc-idle-timeouts.patch b/queue-6.18/mtd-nand-mtk-ecc-stop-on-ecc-idle-timeouts.patch new file mode 100644 index 0000000000..6250e1e8ab --- /dev/null +++ b/queue-6.18/mtd-nand-mtk-ecc-stop-on-ecc-idle-timeouts.patch @@ -0,0 +1,75 @@ +From 83605e7c140865e08b3862241cde29e0f36b2269 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 23 Jun 2026 21:57:29 +0800 +Subject: mtd: nand: mtk-ecc: stop on ECC idle timeouts + +From: Pengpeng Hou + +[ Upstream commit 16f7ec8d5dc100eafd2c8e06cd30340a30b104a1 ] + +mtk_ecc_wait_idle() logs when the encoder or decoder does not become +idle, but returns void. Callers can therefore configure a non-idle ECC +engine or read parity bytes after an unconfirmed encoder idle state. + +Return the idle poll result and propagate it from the enable and encode +paths that require the engine to be idle before continuing. + +Fixes: 1d6b1e464950 ("mtd: mediatek: driver for MTK Smart Device") +Signed-off-by: Pengpeng Hou +Signed-off-by: Miquel Raynal +Signed-off-by: Sasha Levin +--- + drivers/mtd/nand/ecc-mtk.c | 16 ++++++++++++---- + 1 file changed, 12 insertions(+), 4 deletions(-) + +diff --git a/drivers/mtd/nand/ecc-mtk.c b/drivers/mtd/nand/ecc-mtk.c +index c75bb8b80cc1e1..96703f0a418ea2 100644 +--- a/drivers/mtd/nand/ecc-mtk.c ++++ b/drivers/mtd/nand/ecc-mtk.c +@@ -123,8 +123,8 @@ static int mt7622_ecc_regs[] = { + [ECC_DECIRQ_STA] = 0x144, + }; + +-static inline void mtk_ecc_wait_idle(struct mtk_ecc *ecc, +- enum mtk_ecc_operation op) ++static inline int mtk_ecc_wait_idle(struct mtk_ecc *ecc, ++ enum mtk_ecc_operation op) + { + struct device *dev = ecc->dev; + u32 val; +@@ -136,6 +136,8 @@ static inline void mtk_ecc_wait_idle(struct mtk_ecc *ecc, + if (ret) + dev_warn(dev, "%s NOT idle\n", + op == ECC_ENCODE ? "encoder" : "decoder"); ++ ++ return ret; + } + + static irqreturn_t mtk_ecc_irq(int irq, void *id) +@@ -312,7 +314,11 @@ int mtk_ecc_enable(struct mtk_ecc *ecc, struct mtk_ecc_config *config) + return ret; + } + +- mtk_ecc_wait_idle(ecc, op); ++ ret = mtk_ecc_wait_idle(ecc, op); ++ if (ret) { ++ mutex_unlock(&ecc->lock); ++ return ret; ++ } + + ret = mtk_ecc_config(ecc, config); + if (ret) { +@@ -412,7 +418,9 @@ int mtk_ecc_encode(struct mtk_ecc *ecc, struct mtk_ecc_config *config, + if (ret) + goto timeout; + +- mtk_ecc_wait_idle(ecc, ECC_ENCODE); ++ ret = mtk_ecc_wait_idle(ecc, ECC_ENCODE); ++ if (ret) ++ goto timeout; + + /* Program ECC bytes to OOB: per sector oob = FDM + ECC + SPARE */ + len = (config->strength * ecc->caps->parity_bits + 7) >> 3; +-- +2.53.0 + diff --git a/queue-6.18/net-dropreason-add-skb_drop_reason_recursion_limit.patch b/queue-6.18/net-dropreason-add-skb_drop_reason_recursion_limit.patch new file mode 100644 index 0000000000..65eb8df40c --- /dev/null +++ b/queue-6.18/net-dropreason-add-skb_drop_reason_recursion_limit.patch @@ -0,0 +1,78 @@ +From 3ae064709b65b1e8c74e4524ff8674fb54aff1e5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 12 Mar 2026 20:18:23 +0000 +Subject: net: dropreason: add SKB_DROP_REASON_RECURSION_LIMIT + +From: Eric Dumazet + +[ Upstream commit d15d3de94a4766fb43d7fe7a72ed0479fb268131 ] + +ip[6]tunnel_xmit() can drop packets if a too deep recursion level +is detected. + +Add SKB_DROP_REASON_RECURSION_LIMIT drop reason. + +We will use this reason later in __dev_queue_xmit(). + +Signed-off-by: Eric Dumazet +Reviewed-by: Joe Damato +Link: https://patch.msgid.link/20260312201824.203093-2-edumazet@google.com +Signed-off-by: Jakub Kicinski +Stable-dep-of: 6860b467f569 ("xfrm: propagate -EINPROGRESS from validate_xmit_xfrm()") +Signed-off-by: Sasha Levin +--- + include/net/dropreason-core.h | 3 +++ + include/net/ip6_tunnel.h | 2 +- + net/ipv4/ip_tunnel_core.c | 2 +- + 3 files changed, 5 insertions(+), 2 deletions(-) + +diff --git a/include/net/dropreason-core.h b/include/net/dropreason-core.h +index 58d91ccc56e0b5..de74e537b4ede4 100644 +--- a/include/net/dropreason-core.h ++++ b/include/net/dropreason-core.h +@@ -129,6 +129,7 @@ + FN(DUALPI2_STEP_DROP) \ + FN(PSP_INPUT) \ + FN(PSP_OUTPUT) \ ++ FN(RECURSION_LIMIT) \ + FNe(MAX) + + /** +@@ -616,6 +617,8 @@ enum skb_drop_reason { + SKB_DROP_REASON_PSP_INPUT, + /** @SKB_DROP_REASON_PSP_OUTPUT: PSP output checks failed */ + SKB_DROP_REASON_PSP_OUTPUT, ++ /** @SKB_DROP_REASON_RECURSION_LIMIT: Dead loop on virtual device. */ ++ SKB_DROP_REASON_RECURSION_LIMIT, + /** + * @SKB_DROP_REASON_MAX: the maximum of core drop reasons, which + * shouldn't be used as a real 'reason' - only for tracing code gen +diff --git a/include/net/ip6_tunnel.h b/include/net/ip6_tunnel.h +index 359b595f1df936..b99805ee2fd14b 100644 +--- a/include/net/ip6_tunnel.h ++++ b/include/net/ip6_tunnel.h +@@ -162,7 +162,7 @@ static inline void ip6tunnel_xmit(struct sock *sk, struct sk_buff *skb, + dev->name); + DEV_STATS_INC(dev, tx_errors); + } +- kfree_skb(skb); ++ kfree_skb_reason(skb, SKB_DROP_REASON_RECURSION_LIMIT); + return; + } + +diff --git a/net/ipv4/ip_tunnel_core.c b/net/ipv4/ip_tunnel_core.c +index 4b5fd4b13722ca..fc993c78cbcc5e 100644 +--- a/net/ipv4/ip_tunnel_core.c ++++ b/net/ipv4/ip_tunnel_core.c +@@ -65,7 +65,7 @@ void iptunnel_xmit(struct sock *sk, struct rtable *rt, struct sk_buff *skb, + DEV_STATS_INC(dev, tx_errors); + } + ip_rt_put(rt); +- kfree_skb(skb); ++ kfree_skb_reason(skb, SKB_DROP_REASON_RECURSION_LIMIT); + return; + } + +-- +2.53.0 + diff --git a/queue-6.18/net-iucv-take-a-reference-on-the-socket-found-in-afi.patch b/queue-6.18/net-iucv-take-a-reference-on-the-socket-found-in-afi.patch new file mode 100644 index 0000000000..dc4fca2b21 --- /dev/null +++ b/queue-6.18/net-iucv-take-a-reference-on-the-socket-found-in-afi.patch @@ -0,0 +1,55 @@ +From bd3b68e5cd54d8b476487ae0860661f1f834187b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 5 Jul 2026 22:24:36 -0500 +Subject: net/iucv: take a reference on the socket found in afiucv_hs_rcv() + +From: Bryam Vargas + +[ Upstream commit 4fa349156043dc119721d067329714179f501749 ] + +afiucv_hs_rcv() looks up the destination socket under iucv_sk_list.lock, +drops the lock, and then passes the socket to the afiucv_hs_callback_*() +handlers without holding a reference. AF_IUCV sockets are not +RCU-protected and are freed synchronously by iucv_sock_kill() -> +sock_put(), so a concurrent close can free the socket in the window +between read_unlock() and the handler, which then dereferences freed +memory (for example sk->sk_data_ready() in afiucv_hs_callback_syn()). + +Take a reference with sock_hold() while the socket is still on the list +and release it with sock_put() once the handler has run. + +Fixes: 3881ac441f64 ("af_iucv: add HiperSockets transport") +Signed-off-by: Bryam Vargas +Reviewed-by: Hidayath Khan +Link: https://patch.msgid.link/20260705-b4-disp-fc79c0dc-v1-1-d2cdcb57afa9@proton.me +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/iucv/af_iucv.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c +index c66b90c912e78e..bd0405373c5e97 100644 +--- a/net/iucv/af_iucv.c ++++ b/net/iucv/af_iucv.c +@@ -2089,6 +2089,8 @@ static int afiucv_hs_rcv(struct sk_buff *skb, struct net_device *dev, + } + } + } ++ if (sk) ++ sock_hold(sk); + read_unlock(&iucv_sk_list.lock); + if (!iucv) + sk = NULL; +@@ -2138,6 +2140,8 @@ static int afiucv_hs_rcv(struct sk_buff *skb, struct net_device *dev, + kfree_skb(skb); + } + ++ if (sk) ++ sock_put(sk); + return err; + } + +-- +2.53.0 + diff --git a/queue-6.18/net-plumb-drop-reasons-to-__dev_queue_xmit.patch b/queue-6.18/net-plumb-drop-reasons-to-__dev_queue_xmit.patch new file mode 100644 index 0000000000..797c1ae63b --- /dev/null +++ b/queue-6.18/net-plumb-drop-reasons-to-__dev_queue_xmit.patch @@ -0,0 +1,148 @@ +From 157e30928af00636bab2ea49e0ab9ad66d28d7cb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 12 Mar 2026 20:18:24 +0000 +Subject: net: plumb drop reasons to __dev_queue_xmit() + +From: Eric Dumazet + +[ Upstream commit 045f977dd4ebdd3ad8e96cf684917adfc5805adb ] + +Add drop reasons to __dev_queue_xmit(): + +- SKB_DROP_REASON_DEV_READY : device is not UP. + +- SKB_DROP_REASON_RECURSION_LIMIT : recursion limit on virtual device is hit. + +Also add an unlikely() for the SKB_DROP_REASON_DEV_READY case, +and reduce indentation level. + +Signed-off-by: Eric Dumazet +Reviewed-by: Joe Damato +Link: https://patch.msgid.link/20260312201824.203093-3-edumazet@google.com +Signed-off-by: Jakub Kicinski +Stable-dep-of: 6860b467f569 ("xfrm: propagate -EINPROGRESS from validate_xmit_xfrm()") +Signed-off-by: Sasha Levin +--- + net/core/dev.c | 83 ++++++++++++++++++++++++++------------------------ + 1 file changed, 43 insertions(+), 40 deletions(-) + +diff --git a/net/core/dev.c b/net/core/dev.c +index 8dee703a0916ed..246d654551ae56 100644 +--- a/net/core/dev.c ++++ b/net/core/dev.c +@@ -4702,9 +4702,10 @@ int __dev_queue_xmit(struct sk_buff *skb, struct net_device *sb_dev) + { + struct net_device *dev = skb->dev; + struct netdev_queue *txq = NULL; +- struct Qdisc *q; +- int rc = -ENOMEM; ++ enum skb_drop_reason reason; ++ int cpu, rc = -ENOMEM; + bool again = false; ++ struct Qdisc *q; + + skb_reset_mac_header(skb); + skb_assert_len(skb); +@@ -4773,59 +4774,61 @@ int __dev_queue_xmit(struct sk_buff *skb, struct net_device *sb_dev) + * Check this and shot the lock. It is not prone from deadlocks. + *Either shot noqueue qdisc, it is even simpler 8) + */ +- if (dev->flags & IFF_UP) { +- int cpu = smp_processor_id(); /* ok because BHs are off */ ++ if (unlikely(!(dev->flags & IFF_UP))) { ++ reason = SKB_DROP_REASON_DEV_READY; ++ goto drop; ++ } + +- if (!netif_tx_owned(txq, cpu)) { +- bool is_list = false; ++ cpu = smp_processor_id(); /* ok because BHs are off */ + +- if (dev_xmit_recursion()) +- goto recursion_alert; ++ if (likely(!netif_tx_owned(txq, cpu))) { ++ bool is_list = false; + +- skb = validate_xmit_skb(skb, dev, &again); +- if (!skb) +- goto out; ++ if (dev_xmit_recursion()) ++ goto recursion_alert; + +- HARD_TX_LOCK(dev, txq, cpu); ++ skb = validate_xmit_skb(skb, dev, &again); ++ if (!skb) ++ goto out; + +- if (!netif_xmit_stopped(txq)) { +- is_list = !!skb->next; ++ HARD_TX_LOCK(dev, txq, cpu); + +- dev_xmit_recursion_inc(); +- skb = dev_hard_start_xmit(skb, dev, txq, &rc); +- dev_xmit_recursion_dec(); ++ if (!netif_xmit_stopped(txq)) { ++ is_list = !!skb->next; + +- /* GSO segments a single SKB into +- * a list of frames. TCP expects error +- * to mean none of the data was sent. +- */ +- if (is_list) +- rc = NETDEV_TX_OK; +- } +- HARD_TX_UNLOCK(dev, txq); +- if (!skb) /* xmit completed */ +- goto out; ++ dev_xmit_recursion_inc(); ++ skb = dev_hard_start_xmit(skb, dev, txq, &rc); ++ dev_xmit_recursion_dec(); + +- net_crit_ratelimited("Virtual device %s asks to queue packet!\n", +- dev->name); +- /* NETDEV_TX_BUSY or queue was stopped */ +- if (!is_list) +- rc = -ENETDOWN; +- } else { +- /* Recursion is detected! It is possible, +- * unfortunately ++ /* GSO segments a single SKB into a list of frames. ++ * TCP expects error to mean none of the data was sent. + */ +-recursion_alert: +- net_crit_ratelimited("Dead loop on virtual device %s, fix it urgently!\n", +- dev->name); +- rc = -ENETDOWN; ++ if (is_list) ++ rc = NETDEV_TX_OK; + } ++ HARD_TX_UNLOCK(dev, txq); ++ if (!skb) /* xmit completed */ ++ goto out; ++ ++ net_crit_ratelimited("Virtual device %s asks to queue packet!\n", ++ dev->name); ++ /* NETDEV_TX_BUSY or queue was stopped */ ++ if (!is_list) ++ rc = -ENETDOWN; ++ } else { ++ /* Recursion is detected! It is possible unfortunately. */ ++recursion_alert: ++ net_crit_ratelimited("Dead loop on virtual device %s, fix it urgently!\n", ++ dev->name); ++ rc = -ENETDOWN; + } + ++ reason = SKB_DROP_REASON_RECURSION_LIMIT; ++drop: + rcu_read_unlock_bh(); + + dev_core_stats_tx_dropped_inc(dev); +- kfree_skb_list(skb); ++ kfree_skb_list_reason(skb, reason); + return rc; + out: + rcu_read_unlock_bh(); +-- +2.53.0 + diff --git a/queue-6.18/net-sched-act_tunnel_key-defer-dst_release-to-rcu-ca.patch b/queue-6.18/net-sched-act_tunnel_key-defer-dst_release-to-rcu-ca.patch new file mode 100644 index 0000000000..2300095cd2 --- /dev/null +++ b/queue-6.18/net-sched-act_tunnel_key-defer-dst_release-to-rcu-ca.patch @@ -0,0 +1,176 @@ +From 015647c2c1d27ab2203cf99b27f3f3d619b18890 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 11 Jul 2026 11:05:37 -0400 +Subject: net/sched: act_tunnel_key: Defer dst_release to RCU callback + +From: Jamal Hadi Salim + +[ Upstream commit f1f5c8a3955f8fda3f84ed883ac8daa1847e724c ] + +Fix a race-condition use-after-free in tunnel_key_release_params(). + +The function releases the metadata_dst of the old params synchronously +via dst_release() while deferring the params struct free with +kfree_rcu(). A concurrent tunnel_key_act() reader on the datapath may +still hold the old params pointer (under rcu_read_lock_bh) and proceed +to call dst_clone(¶ms->tcft_enc_metadata->dst) after the writer's +dst_release has already pushed the dst's rcuref to RCUREF_DEAD. + +zdi-disclosures@trendmicro.com produced a poc which i (and Victor) verified +that KASAN reports: + +================================================================== +BUG: KASAN: slab-use-after-free in instrument_atomic_read_write include/linux/instrumented.h:112 +BUG: KASAN: slab-use-after-free in atomic_sub_return_release include/linux/atomic/atomic-instrumented.h:326 +BUG: KASAN: slab-use-after-free in __rcuref_put include/linux/rcuref.h:109 +BUG: KASAN: slab-use-after-free in rcuref_put include/linux/rcuref.h:173 +BUG: KASAN: slab-use-after-free in dst_release+0x5b/0x370 net/core/dst.c:168 +Write of size 4 at addr ffff88806158de40 by task poc/9388 + +CPU: 0 UID: 0 PID: 9388 Comm: poc Tainted: G W 7.1.0-rc7 #7 PREEMPT(lazy) +Tainted: [W]=WARN +Hardware name: QEMU Ubuntu 25.10 PC v2 (i440FX + PIIX, + 10.1 machine, 1996), BIOS 1.16.3-debian-1.16.3-2 04/01/2014 +Call Trace: + + __dump_stack lib/dump_stack.c:94 + dump_stack_lvl+0x100/0x190 lib/dump_stack.c:120 + print_address_description mm/kasan/report.c:378 + print_report+0x139/0x4ad mm/kasan/report.c:482 + kasan_report+0xe4/0x1d0 mm/kasan/report.c:595 + check_region_inline mm/kasan/generic.c:186 + kasan_check_range+0x125/0x200 mm/kasan/generic.c:200 + instrument_atomic_read_write include/linux/instrumented.h:112 + atomic_sub_return_release include/linux/atomic/atomic-instrumented.h:326 + __rcuref_put include/linux/rcuref.h:109 + rcuref_put include/linux/rcuref.h:173 + dst_release+0x5b/0x370 net/core/dst.c:168 + refdst_drop include/net/dst.h:272 + skb_dst_drop include/net/dst.h:284 + skb_release_head_state+0x293/0x400 net/core/skbuff.c:1163 + skb_release_all net/core/skbuff.c:1187 +[..] +Allocated by task 9391: + kasan_save_stack+0x30/0x50 mm/kasan/common.c:57 + kasan_save_track+0x14/0x30 mm/kasan/common.c:78 + poison_kmalloc_redzone mm/kasan/common.c:398 + __kasan_kmalloc+0x9a/0xb0 mm/kasan/common.c:415 + kasan_kmalloc include/linux/kasan.h:263 + __do_kmalloc_node mm/slub.c:5296 + __kmalloc_noprof+0x2f1/0x830 mm/slub.c:5308 + kmalloc_noprof include/linux/slab.h:954 + kzalloc_noprof include/linux/slab.h:1188 + offload_action_alloc+0x2f/0x130 net/core/flow_offload.c:35 + tcf_action_offload_add_ex+0x1ba/0x880 net/sched/act_api.c:258 + tcf_action_offload_add net/sched/act_api.c:293 + tcf_action_init+0x66e/0xa20 net/sched/act_api.c:1547 + tcf_action_add+0xf6/0x5d0 net/sched/act_api.c:2101 +[..] +Freed by task 9391: + kasan_save_stack+0x30/0x50 mm/kasan/common.c:57 + kasan_save_track+0x14/0x30 mm/kasan/common.c:78 + kasan_save_free_info+0x3b/0x70 mm/kasan/generic.c:584 + poison_slab_object mm/kasan/common.c:253 + __kasan_slab_free+0x6b/0x90 mm/kasan/common.c:285 + kasan_slab_free include/linux/kasan.h:235 + slab_free_hook mm/slub.c:2689 + slab_free mm/slub.c:6251 + kfree+0x21f/0x6b0 mm/slub.c:6566 + tcf_action_offload_add_ex+0x4ad/0x880 net/sched/act_api.c:284 + tcf_action_offload_add net/sched/act_api.c:293 + tcf_action_init+0x66e/0xa20 net/sched/act_api.c:1547 + tcf_action_add+0xf6/0x5d0 net/sched/act_api.c:2101 + +The buggy address belongs to the object at ffff88806158de00 + which belongs to the cache kmalloc-256 of size 256 +The buggy address is located 64 bytes inside of + freed 256-byte region [ffff88806158de00, ffff88806158df00) + +The buggy address belongs to the physical page: +page: refcount:0 mapcount:0 mapping:0000000000000000 index:0xffff88806158d600 pfn:0x6158c +head: order:1 mapcount:0 entire_mapcount:0 nr_pages_mapped:0 pincount:0 +flags: 0x4fff00000000240(workingset|head|node=1|zone=1|lastcpupid=0x7ff) +page_type: f5(slab) +raw: 04fff00000000240 ffff88801c841b40 ffffea0001856290 ffffea0001856190 +raw: ffff88806158d600 0000000800100009 00000000f5000000 0000000000000000 +head: 04fff00000000240 ffff88801c841b40 ffffea0001856290 ffffea0001856190 +head: ffff88806158d600 0000000800100009 00000000f5000000 0000000000000000 +head: 04fff00000000001 ffffffffffffff81 00000000ffffffff 00000000ffffffff +head: ffffffffffffffff 0000000000000000 00000000ffffffff 0000000000000002 +page dumped because: kasan: bad access detected +page_owner tracks the page as allocated +page last allocated via order 1, migratetype Unmovable, gfp_mask 0xd2820(GFP_ATOMIC|__GFP_NOWARN|__GFP_NORETRY|__GFP_COMP|__GFP_NOMEMALLOC), pid 9391, tgid 9378 (poc), ts 123227323196, free_ts 0 + set_page_owner include/linux/page_owner.h:32 + post_alloc_hook+0xfe/0x140 mm/page_alloc.c:1853 + prep_new_page mm/page_alloc.c:1861 + get_page_from_freelist+0x110c/0x2fc0 mm/page_alloc.c:3941 + __alloc_frozen_pages_noprof+0x263/0x2bc0 mm/page_alloc.c:5221 + alloc_slab_page mm/slub.c:3278 + allocate_slab mm/slub.c:3467 + new_slab+0xa6/0x690 mm/slub.c:3525 + refill_objects+0x271/0x420 mm/slub.c:7272 + refill_sheaf mm/slub.c:2816 + __pcs_replace_empty_main+0x373/0x630 mm/slub.c:4652 + alloc_from_pcs mm/slub.c:4750 + slab_alloc_node mm/slub.c:4884 + __do_kmalloc_node mm/slub.c:5295 + __kmalloc_noprof+0x66d/0x830 mm/slub.c:5308 + kmalloc_noprof include/linux/slab.h:954 + metadata_dst_alloc+0x26/0x90 net/core/dst.c:298 + tun_rx_dst include/net/dst_metadata.h:144 + __ip_tun_set_dst include/net/dst_metadata.h:208 + tunnel_key_init+0xb01/0x1b90 net/sched/act_tunnel_key.c:451 + tcf_action_init_1+0x46b/0x6c0 net/sched/act_api.c:1428 + tcf_action_init+0x448/0xa20 net/sched/act_api.c:1503 + tcf_action_add+0xf6/0x5d0 net/sched/act_api.c:2101 +[..] +================================================================== + +Fix by moving dst_release() into a custom RCU callback that runs +after the grace period, matching the lifetime of the containing +params struct. Readers in the datapath therefore always find a live +rcuref when calling dst_clone(). + +Fixes: 9174c3df1cd18 ("net/sched: act_tunnel_key: fix memory leak in case of action replace") +Reported-by: zdi-disclosures@trendmicro.com +Tested-by: Victor Nogueira +Signed-off-by: Jamal Hadi Salim +Reviewed-by: Davide Caratti +Link: https://patch.msgid.link/20260711150537.7946-1-jhs@mojatatu.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/sched/act_tunnel_key.c | 14 ++++++++++---- + 1 file changed, 10 insertions(+), 4 deletions(-) + +diff --git a/net/sched/act_tunnel_key.c b/net/sched/act_tunnel_key.c +index 876b30c5709e1f..b14807761d829e 100644 +--- a/net/sched/act_tunnel_key.c ++++ b/net/sched/act_tunnel_key.c +@@ -342,14 +342,20 @@ static const struct nla_policy tunnel_key_policy[TCA_TUNNEL_KEY_MAX + 1] = { + [TCA_TUNNEL_KEY_ENC_TTL] = { .type = NLA_U8 }, + }; + +-static void tunnel_key_release_params(struct tcf_tunnel_key_params *p) ++static void tunnel_key_release_params_rcu(struct rcu_head *head) + { +- if (!p) +- return; ++ struct tcf_tunnel_key_params *p = container_of(head, typeof(*p), rcu); ++ + if (p->tcft_action == TCA_TUNNEL_KEY_ACT_SET) + dst_release(&p->tcft_enc_metadata->dst); ++ kfree(p); ++} + +- kfree_rcu(p, rcu); ++static void tunnel_key_release_params(struct tcf_tunnel_key_params *p) ++{ ++ if (!p) ++ return; ++ call_rcu(&p->rcu, tunnel_key_release_params_rcu); + } + + static int tunnel_key_init(struct net *net, struct nlattr *nla, +-- +2.53.0 + diff --git a/queue-6.18/powerpc-85xx-add-fsl-ifc-to-common-device-ids.patch b/queue-6.18/powerpc-85xx-add-fsl-ifc-to-common-device-ids.patch new file mode 100644 index 0000000000..09363f1192 --- /dev/null +++ b/queue-6.18/powerpc-85xx-add-fsl-ifc-to-common-device-ids.patch @@ -0,0 +1,41 @@ +From 8964512141b9e27fa0f37dd7922121c53b0f6440 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 3 Jun 2026 21:33:09 -0700 +Subject: powerpc/85xx: Add fsl,ifc to common device ids + +From: Rosen Penev + +[ Upstream commit 25957f7c3dac3265332d766b71233e3622f17e14 ] + +Add fsl,ifc to mpc85xx_common_ids so that of_platform_bus_probe +creates a platform device for the IFC node even without 'simple-bus' +in its compatible property. On P1010 and similar platforms the IFC +node is a direct child of the root, so it must be explicitly matched +to be populated. + +Fixes: 0bf51cc9e9e5 ("powerpc: dts: mpc85xx: remove "simple-bus" compatible from ifc node") +Assisted-by: opencode:big-pickle +Signed-off-by: Rosen Penev +Signed-off-by: Madhavan Srinivasan +Link: https://patch.msgid.link/20260604043309.91280-1-rosenp@gmail.com +Signed-off-by: Sasha Levin +--- + arch/powerpc/platforms/85xx/common.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/arch/powerpc/platforms/85xx/common.c b/arch/powerpc/platforms/85xx/common.c +index 757811155587db..c11deb2f50ed45 100644 +--- a/arch/powerpc/platforms/85xx/common.c ++++ b/arch/powerpc/platforms/85xx/common.c +@@ -42,6 +42,8 @@ static const struct of_device_id mpc85xx_common_ids[] __initconst = { + { .compatible = "fsl,qoriq-pcie-v2.3", }, + { .compatible = "fsl,qoriq-pcie-v2.2", }, + { .compatible = "fsl,fman", }, ++ /* IFC NAND and NOR controllers */ ++ { .compatible = "fsl,ifc", }, + {}, + }; + +-- +2.53.0 + diff --git a/queue-6.18/powerpc-time-prepare-to-stop-elapsing-in-dynticks-id.patch b/queue-6.18/powerpc-time-prepare-to-stop-elapsing-in-dynticks-id.patch new file mode 100644 index 0000000000..1323beb836 --- /dev/null +++ b/queue-6.18/powerpc-time-prepare-to-stop-elapsing-in-dynticks-id.patch @@ -0,0 +1,126 @@ +From da45c1a00df585ac0b65434b96e0187dd34ce691 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 8 May 2026 15:16:37 +0200 +Subject: powerpc/time: Prepare to stop elapsing in dynticks-idle + +From: Frederic Weisbecker + +[ Upstream commit c8ba971cf8567d49eb5f43ee90c4e50424331c18 ] + +Currently the tick subsystem stores the idle cputime accounting in +private fields, allowing cohabitation with architecture idle vtime +accounting. The former is fetched on online CPUs, the latter on offline +CPUs. + +For consolidation purpose, architecture vtime accounting will continue +to account the cputime but will make a break when the idle tick is +stopped. The dyntick cputime accounting will then be relayed by the tick +subsystem so that the idle cputime is still seen advancing coherently +even when the tick isn't there to flush the idle vtime. + +Prepare for that and introduce three new APIs which will be used in +subsequent patches: + + - vtime_dynticks_start() is deemed to be called when idle enters in + dyntick mode. The idle cputime that elapsed so far is accumulated. + + - vtime_dynticks_stop() is deemed to be called when idle exits from + dyntick mode. The vtime entry clocks are fast-forward to current time + so that idle accounting restarts elapsing from now. + + - vtime_reset() is deemed to be called from dynticks idle IRQ entry to + fast-forward the clock to current time so that the IRQ time is still + accounted by vtime while nohz cputime is paused. + +Also accumulated vtime won't be flushed from dyntick-idle ticks to avoid +accounting twice the idle cputime, along with nohz accounting. + +Signed-off-by: Frederic Weisbecker +Signed-off-by: Thomas Gleixner +Tested-by: Shrikanth Hegde +Reviewed-by: Shrikanth Hegde +Link: https://patch.msgid.link/20260508131647.43868-6-frederic@kernel.org +Stable-dep-of: c1c1ffa490fc ("powerpc/vtime: Initialize starttime at boot for native accounting") +Signed-off-by: Sasha Levin +--- + arch/powerpc/kernel/time.c | 41 ++++++++++++++++++++++++++++++++++++++ + include/linux/vtime.h | 6 ++++++ + 2 files changed, 47 insertions(+) + +diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c +index b4472288e0d434..3460d1a5a97c2a 100644 +--- a/arch/powerpc/kernel/time.c ++++ b/arch/powerpc/kernel/time.c +@@ -376,6 +376,47 @@ void vtime_task_switch(struct task_struct *prev) + acct->starttime = acct0->starttime; + } + } ++ ++#ifdef CONFIG_NO_HZ_COMMON ++/** ++ * vtime_reset - Fast forward vtime entry clocks ++ * ++ * Called from dynticks idle IRQ entry to fast-forward the clocks to current time ++ * so that the IRQ time is still accounted by vtime while nohz cputime is paused. ++ */ ++void vtime_reset(void) ++{ ++ struct cpu_accounting_data *acct = get_accounting(current); ++ ++ acct->starttime = mftb(); ++#ifdef CONFIG_ARCH_HAS_SCALED_CPUTIME ++ acct->startspurr = read_spurr(acct->starttime); ++#endif ++} ++ ++/** ++ * vtime_dyntick_start - Inform vtime about entry to idle-dynticks ++ * ++ * Called when idle enters in dyntick mode. The idle cputime that elapsed so far ++ * is accumulated and the tick subsystem takes over the idle cputime accounting. ++ */ ++void vtime_dyntick_start(void) ++{ ++ vtime_account_idle(current); ++} ++ ++/** ++ * vtime_dyntick_stop - Inform vtime about exit from idle-dynticks ++ * ++ * Called when idle exits from dyntick mode. The vtime entry clocks are ++ * fast-forward to current time so that idle accounting restarts elapsing from ++ * now. ++ */ ++void vtime_dyntick_stop(void) ++{ ++ vtime_reset(); ++} ++#endif /* CONFIG_NO_HZ_COMMON */ + #endif /* CONFIG_VIRT_CPU_ACCOUNTING_NATIVE */ + + void __no_kcsan __delay(unsigned long loops) +diff --git a/include/linux/vtime.h b/include/linux/vtime.h +index 29dd5b91dd7d66..3fc04b849e4e30 100644 +--- a/include/linux/vtime.h ++++ b/include/linux/vtime.h +@@ -32,11 +32,17 @@ extern void vtime_account_irq(struct task_struct *tsk, unsigned int offset); + extern void vtime_account_softirq(struct task_struct *tsk); + extern void vtime_account_hardirq(struct task_struct *tsk); + extern void vtime_flush(struct task_struct *tsk); ++extern void vtime_reset(void); ++extern void vtime_dyntick_start(void); ++extern void vtime_dyntick_stop(void); + #else /* !CONFIG_VIRT_CPU_ACCOUNTING_NATIVE */ + static inline void vtime_account_irq(struct task_struct *tsk, unsigned int offset) { } + static inline void vtime_account_softirq(struct task_struct *tsk) { } + static inline void vtime_account_hardirq(struct task_struct *tsk) { } + static inline void vtime_flush(struct task_struct *tsk) { } ++static inline void vtime_reset(void) { } ++static inline void vtime_dyntick_start(void) { } ++static inline void vtime_dyntick_stop(void) { } + #endif + + /* +-- +2.53.0 + diff --git a/queue-6.18/powerpc-vtime-initialize-starttime-at-boot-for-nativ.patch b/queue-6.18/powerpc-vtime-initialize-starttime-at-boot-for-nativ.patch new file mode 100644 index 0000000000..c11f586022 --- /dev/null +++ b/queue-6.18/powerpc-vtime-initialize-starttime-at-boot-for-nativ.patch @@ -0,0 +1,90 @@ +From 9629649b7a75a16030b988e53789384f8c1e0f3a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 5 Jun 2026 18:13:29 +0530 +Subject: powerpc/vtime: Initialize starttime at boot for native accounting + +From: Shrikanth Hegde + +[ Upstream commit c1c1ffa490fc33591e90852ed0d38804dd20bc36 ] + +It was observed that /proc/stat had very large value for one ore more +CPUs. It was more visible after recent code simplifications around +cpustats. + +System has 240 CPUs. + +cat /proc/uptime; +194.18 46500.55 +cat /proc/stat +cpu 5966 39 837032887 4650070 164 185 100 0 0 0 +cpu0 108 0 837030890 19109 24 4 23 0 0 0 + +Since uptime is 194s, system time of each CPU can't be more than 19400. +Sum of system time of all CPUs can't be more than 19400*240 4656000. +In fact huge value is close to mftb(). Note mftb doesn't reset on powerVM +when the LPAR restart. It only resets when whole system resets. The same +issue exists for kexec too. + +This happens since starttime is not setup at init time. Once it is set +then subsequent vtime_delta will return the right delta. + +Fix it by initializing the starttime during CPU initialization. This +fixes the large times seen. + +cat /proc/uptime; cat /proc/stat +15.78 3694.63 +cpu 6035 35 1347 369479 23 144 49 0 0 0 +cpu0 19 0 38 1508 0 1 14 0 0 0 + +Now, system time is reported as expected. + +Fixes: cf9efce0ce31 ("powerpc: Account time using timebase rather than PURR") +Reviewed-by: Christophe Leroy (CS GROUP) +Suggested-by: Christophe Leroy (CS GROUP) +Signed-off-by: Shrikanth Hegde +Signed-off-by: Madhavan Srinivasan +Link: https://patch.msgid.link/20260605124329.377533-1-sshegde@linux.ibm.com +Signed-off-by: Sasha Levin +--- + arch/powerpc/kernel/time.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c +index 3460d1a5a97c2a..11145c40183dd1 100644 +--- a/arch/powerpc/kernel/time.c ++++ b/arch/powerpc/kernel/time.c +@@ -377,7 +377,6 @@ void vtime_task_switch(struct task_struct *prev) + } + } + +-#ifdef CONFIG_NO_HZ_COMMON + /** + * vtime_reset - Fast forward vtime entry clocks + * +@@ -394,6 +393,7 @@ void vtime_reset(void) + #endif + } + ++#ifdef CONFIG_NO_HZ_COMMON + /** + * vtime_dyntick_start - Inform vtime about entry to idle-dynticks + * +@@ -933,6 +933,7 @@ static void __init set_decrementer_max(void) + static void __init init_decrementer_clockevent(void) + { + register_decrementer_clockevent(smp_processor_id()); ++ vtime_reset(); + } + + void secondary_cpu_time_init(void) +@@ -948,6 +949,7 @@ void secondary_cpu_time_init(void) + /* FIME: Should make unrelated change to move snapshot_timebase + * call here ! */ + register_decrementer_clockevent(smp_processor_id()); ++ vtime_reset(); + } + + /* +-- +2.53.0 + diff --git a/queue-6.18/ppp-defer-channel-free-to-an-rcu-grace-period-to-fix.patch b/queue-6.18/ppp-defer-channel-free-to-an-rcu-grace-period-to-fix.patch new file mode 100644 index 0000000000..3ae618fe5e --- /dev/null +++ b/queue-6.18/ppp-defer-channel-free-to-an-rcu-grace-period-to-fix.patch @@ -0,0 +1,104 @@ +From 31ae6a218cd9de5471ed2f822577e6a7523964ab Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 6 Jul 2026 11:01:59 +0200 +Subject: ppp: defer channel free to an RCU grace period to fix pppol2tp RX UAF + +From: Norbert Szetei + +[ Upstream commit ec4215683e47424c9c4762fd3c60f552a3119142 ] + +pppol2tp_recv() runs in the L2TP UDP-encap softirq RX path: + + l2tp_udp_encap_recv() -> l2tp_recv_common() -> pppol2tp_recv() + -> ppp_input(&po->chan) + +It runs under rcu_read_lock() holding only an l2tp_session reference and +takes NO reference on the internal PPP channel (struct channel, +chan->ppp) that ppp_input() dereferences. + +The pppox socket is SOCK_RCU_FREE, so 'po' and the embedded ppp_channel +are RCU-safe. But the internal struct channel is a separate allocation +that ppp_release_channel() frees with a plain kfree(): + + close(data socket) -> pppol2tp_release() -> pppox_unbind_sock() + -> ppp_unregister_channel() -> ppp_release_channel() -> kfree(pch) + +For a channel that is bound (PPPIOCGCHAN) but not attached to a ppp unit +(no PPPIOCCONNECT, pch->ppp == NULL) and not bridged, teardown skips +both ppp_disconnect_channel()'s synchronize_net() and +ppp_unbridge_channels()'s synchronize_rcu(), so the kfree() has no grace +period. rcu_read_lock() in pppol2tp_recv() does not protect against a +plain kfree(), so an in-flight ppp_input() on one CPU can dereference +the channel just freed by close() on another CPU. + +The bug is reachable by an unprivileged user. + +Defer the channel free to an RCU callback via call_rcu() so the grace +period fences any in-flight ppp_input(). The disconnect and unbridge +teardown paths already fence with synchronize_net()/synchronize_rcu(); +call_rcu() does the same here without stalling the close() path. + +Fixes: ee40fb2e1eb5 ("l2tp: protect sock pointer of struct pppol2tp_session with RCU") +Assisted-by: Claude:claude-opus-4-8 +Signed-off-by: Norbert Szetei +Reviewed-by: Qingfang Deng +Link: https://patch.msgid.link/E793FCF2-58DE-4387-A983-C7B4BC3158BD@doyensec.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ppp/ppp_generic.c | 18 +++++++++++++++--- + 1 file changed, 15 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c +index 507d216256c0dd..72e98286fba2fe 100644 +--- a/drivers/net/ppp/ppp_generic.c ++++ b/drivers/net/ppp/ppp_generic.c +@@ -185,6 +185,7 @@ struct channel { + struct list_head clist; /* link in list of channels per unit */ + spinlock_t upl; /* protects `ppp' and 'bridge' */ + struct channel __rcu *bridge; /* "bridged" ppp channel */ ++ struct rcu_head rcu; /* for RCU-deferred free of the channel */ + #ifdef CONFIG_PPP_MULTILINK + u8 avail; /* flag used in multilink stuff */ + u8 had_frag; /* >= 1 fragments have been sent */ +@@ -3570,6 +3571,18 @@ ppp_disconnect_channel(struct channel *pch) + return err; + } + ++/* Purge after the grace period: a late ppp_input() may still queue an ++ * skb on pch->file.rq before the last RCU reader drains. ++ */ ++static void ppp_release_channel_free(struct rcu_head *rcu) ++{ ++ struct channel *pch = container_of(rcu, struct channel, rcu); ++ ++ skb_queue_purge(&pch->file.xq); ++ skb_queue_purge(&pch->file.rq); ++ kfree(pch); ++} ++ + /* + * Free up the resources used by a ppp channel. + */ +@@ -3585,9 +3598,7 @@ static void ppp_destroy_channel(struct channel *pch) + pr_err("ppp: destroying undead channel %p !\n", pch); + return; + } +- skb_queue_purge(&pch->file.xq); +- skb_queue_purge(&pch->file.rq); +- kfree(pch); ++ call_rcu(&pch->rcu, ppp_release_channel_free); + } + + static void __exit ppp_cleanup(void) +@@ -3600,6 +3611,7 @@ static void __exit ppp_cleanup(void) + device_destroy(&ppp_class, MKDEV(PPP_MAJOR, 0)); + class_unregister(&ppp_class); + unregister_pernet_device(&ppp_net_ops); ++ rcu_barrier(); /* wait for RCU callbacks before module unload */ + } + + /* +-- +2.53.0 + diff --git a/queue-6.18/rdma-cma-fix-hardware-address-comparison-length-in-n.patch b/queue-6.18/rdma-cma-fix-hardware-address-comparison-length-in-n.patch new file mode 100644 index 0000000000..a288c9c5d3 --- /dev/null +++ b/queue-6.18/rdma-cma-fix-hardware-address-comparison-length-in-n.patch @@ -0,0 +1,43 @@ +From 7ca90ab11374b0f1b7095a046d46f2ee6848367e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 17 Jun 2026 14:21:05 +0300 +Subject: RDMA/cma: Fix hardware address comparison length in netevent callback + +From: Or Gerlitz + +[ Upstream commit 18313833e2c6de222a4f6c072da759d0d5888528 ] + +The cited commit hardcoded the hardware address comparison len to ETH_ALEN. + +This breaks IPoIB, which uses 20-byte addresses. By truncating the +memcmp, the CMA may incorrectly assume the target address is +unchanged and fails to abort the stalled connection. + +Fix this by replacing ETH_ALEN with the dynamic neigh->dev->addr_len +to correctly evaluate the full address regardless of the link layer. + +Fixes: 925d046e7e52 ("RDMA/core: Add a netevent notifier to cma") +Signed-off-by: Or Gerlitz +Link: https://patch.msgid.link/20260617-fix-cma-ipoib-v1-1-03f869344304@ddn.com +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + drivers/infiniband/core/cma.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c +index ce511800b056cf..648acc2222cf54 100644 +--- a/drivers/infiniband/core/cma.c ++++ b/drivers/infiniband/core/cma.c +@@ -5237,7 +5237,7 @@ static int cma_netevent_callback(struct notifier_block *self, + + list_for_each_entry(current_id, &ips_node->id_list, id_list_entry) { + if (!memcmp(current_id->id.route.addr.dev_addr.dst_dev_addr, +- neigh->ha, ETH_ALEN)) ++ neigh->ha, neigh->dev->addr_len)) + continue; + cma_id_get(current_id); + if (!queue_work(cma_wq, ¤t_id->id.net_work)) +-- +2.53.0 + diff --git a/queue-6.18/rdma-erdma-initialize-ret-for-empty-receive-wr-lists.patch b/queue-6.18/rdma-erdma-initialize-ret-for-empty-receive-wr-lists.patch new file mode 100644 index 0000000000..a75814c4ea --- /dev/null +++ b/queue-6.18/rdma-erdma-initialize-ret-for-empty-receive-wr-lists.patch @@ -0,0 +1,42 @@ +From 832adc208d9390b06d28aee20fd51c0e1f904282 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 18 Jun 2026 12:17:51 +0800 +Subject: RDMA/erdma: initialize ret for empty receive WR lists + +From: Ruoyu Wang + +[ Upstream commit 2815a277c53e9a84784d6410cd55a9da5b33068d ] + +erdma_post_recv() returns ret after walking the receive work request list. +If the caller passes an empty list, the loop is skipped and ret is not +assigned. + +Initialize ret to 0 so an empty receive work request list returns success +instead of stack data. + +Fixes: 155055771704 ("RDMA/erdma: Add verbs implementation") +Link: https://patch.msgid.link/r/20260618041752.481193-1-ruoyuw560@gmail.com +Signed-off-by: Ruoyu Wang +Reviewed-by: Cheng Xu +Signed-off-by: Jason Gunthorpe +Signed-off-by: Sasha Levin +--- + drivers/infiniband/hw/erdma/erdma_qp.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/infiniband/hw/erdma/erdma_qp.c b/drivers/infiniband/hw/erdma/erdma_qp.c +index 25f6c49aec7798..e002343832f74d 100644 +--- a/drivers/infiniband/hw/erdma/erdma_qp.c ++++ b/drivers/infiniband/hw/erdma/erdma_qp.c +@@ -734,7 +734,7 @@ int erdma_post_recv(struct ib_qp *ibqp, const struct ib_recv_wr *recv_wr, + const struct ib_recv_wr *wr = recv_wr; + struct erdma_qp *qp = to_eqp(ibqp); + unsigned long flags; +- int ret; ++ int ret = 0; + + spin_lock_irqsave(&qp->lock, flags); + +-- +2.53.0 + diff --git a/queue-6.18/rdma-hns-fix-potential-integer-overflow-in-mhop-hem-.patch b/queue-6.18/rdma-hns-fix-potential-integer-overflow-in-mhop-hem-.patch new file mode 100644 index 0000000000..2b1b3289ea --- /dev/null +++ b/queue-6.18/rdma-hns-fix-potential-integer-overflow-in-mhop-hem-.patch @@ -0,0 +1,52 @@ +From 03c42c521f48d6ac4e3cf4a6f60f144762fe28d2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 27 Jun 2026 09:59:51 +0000 +Subject: RDMA/hns: Fix potential integer overflow in mhop hem cleanup + +From: Danila Chernetsov + +[ Upstream commit 9f0f2d2121f16d420199a82ac5bbc242269133b3 ] + +In hns_roce_cleanup_mhop_hem_table(), the expression: + + obj = i * buf_chunk_size / table->obj_size; + +is evaluated using 32-bit unsigned arithmetic because +'buf_chunk_size' is u32 and the usual arithmetic conversions convert +'i' to unsigned int. The result is assigned to a u64 variable, but the +multiplication may overflow before the assignment. + +For sufficiently large HEM tables, this produces an incorrect object +index passed to hns_roce_table_mhop_put(). + +Cast 'i' to u64 before the multiplication so that the intermediate +calculation is performed with 64-bit arithmetic. + +Found by Linux Verification Center (linuxtesting.org) with SVACE. + +Fixes: a25d13cbe816 ("RDMA/hns: Add the interfaces to support multi hop addressing for the contexts in hip08") +Link: https://patch.msgid.link/r/20260627095951.51378-1-listdansp@mail.ru +Signed-off-by: Danila Chernetsov +Reviewed-by: Junxian Huang +Signed-off-by: Jason Gunthorpe +Signed-off-by: Sasha Levin +--- + drivers/infiniband/hw/hns/hns_roce_hem.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/infiniband/hw/hns/hns_roce_hem.c b/drivers/infiniband/hw/hns/hns_roce_hem.c +index 1680d0ac071ed1..ae7a3939124f23 100644 +--- a/drivers/infiniband/hw/hns/hns_roce_hem.c ++++ b/drivers/infiniband/hw/hns/hns_roce_hem.c +@@ -842,7 +842,7 @@ static void hns_roce_cleanup_mhop_hem_table(struct hns_roce_dev *hr_dev, + mhop.bt_chunk_size; + + for (i = 0; i < table->num_hem; ++i) { +- obj = i * buf_chunk_size / table->obj_size; ++ obj = (u64)i * buf_chunk_size / table->obj_size; + if (table->hem[i]) + hns_roce_table_mhop_put(hr_dev, table, obj, 0); + } +-- +2.53.0 + diff --git a/queue-6.18/rdma-irdma-prevent-overflows-in-memory-contiguity-ch.patch b/queue-6.18/rdma-irdma-prevent-overflows-in-memory-contiguity-ch.patch new file mode 100644 index 0000000000..bafa17419f --- /dev/null +++ b/queue-6.18/rdma-irdma-prevent-overflows-in-memory-contiguity-ch.patch @@ -0,0 +1,64 @@ +From 6702cf7eb4be1928e28d5c255cd5aa4c7959491b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 24 Jun 2026 17:48:46 +0300 +Subject: RDMA/irdma: Prevent overflows in memory contiguity checks + +From: Aleksandrova Alyona + +[ Upstream commit 3cda0dfe8c651dcbb9e38977905d3d3b1750c4ab ] + +irdma_check_mem_contiguous() and irdma_check_mr_contiguous() verify that +PBL entries describe physically contiguous memory ranges. + +Both functions calculate byte offsets using 32-bit operands. For example, +with 4 KiB pages, pg_size * pg_idx overflows 32-bit arithmetic when +pg_idx reaches 1048576. In the level-2 check, PBLE_PER_PAGE is 512, so +i * pg_size * PBLE_PER_PAGE overflows when i reaches 2048. + +These values are reachable in the driver. For MRs, palloc->total_cnt +comes from iwmr->page_cnt, which is calculated by +ib_umem_num_dma_blocks(). The MR size is limited by IRDMA_MAX_MR_SIZE, +so a 4 GiB MR with 4 KiB pages can reach page_cnt of 1048576. PBLE +resources do not exclude this value either: for gen3, the limit is based +on avail_sds * MAX_PBLE_PER_SD, and MAX_PBLE_PER_SD is 0x40000, so 4 SDs +are enough for 1048576 PBLEs. + +Cast one operand to u64 before the multiplications so that the offset +calculations are performed in 64-bit arithmetic. + +Found by Linux Verification Center (linuxtesting.org) with SVACE. + +Fixes: b48c24c2d710 ("RDMA/irdma: Implement device supported verb APIs") +Signed-off-by: Aleksandrova Alyona +Link: https://patch.msgid.link/20260624144846.61242-1-aga@itb.spb.ru +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + drivers/infiniband/hw/irdma/verbs.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/infiniband/hw/irdma/verbs.c b/drivers/infiniband/hw/irdma/verbs.c +index 5f5b79109d5471..4084168d0194fb 100644 +--- a/drivers/infiniband/hw/irdma/verbs.c ++++ b/drivers/infiniband/hw/irdma/verbs.c +@@ -2800,7 +2800,7 @@ static bool irdma_check_mem_contiguous(u64 *arr, u32 npages, u32 pg_size) + u32 pg_idx; + + for (pg_idx = 0; pg_idx < npages; pg_idx++) { +- if ((*arr + (pg_size * pg_idx)) != arr[pg_idx]) ++ if ((*arr + ((u64)pg_size * pg_idx)) != arr[pg_idx]) + return false; + } + +@@ -2833,7 +2833,7 @@ static bool irdma_check_mr_contiguous(struct irdma_pble_alloc *palloc, + + for (i = 0; i < lvl2->leaf_cnt; i++, leaf++) { + arr = leaf->addr; +- if ((*start_addr + (i * pg_size * PBLE_PER_PAGE)) != *arr) ++ if ((*start_addr + ((u64)i * pg_size * PBLE_PER_PAGE)) != *arr) + return false; + ret = irdma_check_mem_contiguous(arr, leaf->cnt, pg_size); + if (!ret) +-- +2.53.0 + diff --git a/queue-6.18/rdma-irdma-prevent-rereg_mr-for-non-mem-regions.patch b/queue-6.18/rdma-irdma-prevent-rereg_mr-for-non-mem-regions.patch new file mode 100644 index 0000000000..e9f76c9d6b --- /dev/null +++ b/queue-6.18/rdma-irdma-prevent-rereg_mr-for-non-mem-regions.patch @@ -0,0 +1,51 @@ +From 62e789ae0408beaa2c9e76773f9d773eeda692ed Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 17 Jun 2026 14:19:36 +0000 +Subject: RDMA/irdma: Prevent rereg_mr for non-mem regions + +From: Jacob Moroni + +[ Upstream commit a846aecb931b4d65d5eafa92a0623545af46d4f2 ] + +When a QP/CQ/SRQ is created, a two step process is used +where the buffer is allocated in userspace and explicitly +registered with the normal reg_mr mechanism prior to creating +the actual QP/CQ/SRQ object. + +These special registrations are indicated via an ABI field +so the driver knows that they do not have a valid mkey and +to skip the actual CQP command submission. + +Since these are real MR objects from the core's perspective, +it is possible for a user application to invoke rereg_mr on them +and cause a real CQP op to be emitted with the zero-initialized +mkey value of 0. + +Fix this by preventing rereg_mr on these special regions. + +Fixes: 5ac388db27c4 ("RDMA/irdma: Add support to re-register a memory region") +Signed-off-by: Jacob Moroni +Reviewed-by: David Hu +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + drivers/infiniband/hw/irdma/verbs.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/infiniband/hw/irdma/verbs.c b/drivers/infiniband/hw/irdma/verbs.c +index 2b85e32134a5b8..c210f9a37fb97b 100644 +--- a/drivers/infiniband/hw/irdma/verbs.c ++++ b/drivers/infiniband/hw/irdma/verbs.c +@@ -3756,6 +3756,9 @@ static struct ib_mr *irdma_rereg_user_mr(struct ib_mr *ib_mr, int flags, + if (flags & ~(IB_MR_REREG_TRANS | IB_MR_REREG_PD | IB_MR_REREG_ACCESS)) + return ERR_PTR(-EOPNOTSUPP); + ++ if (iwmr->type != IRDMA_MEMREG_TYPE_MEM) ++ return ERR_PTR(-EINVAL); ++ + ret = ib_umem_check_rereg(iwmr->region, flags, new_access); + if (ret) + return ERR_PTR(ret); +-- +2.53.0 + diff --git a/queue-6.18/rdma-irdma-prevent-user-triggered-null-deref-on-qp-c.patch b/queue-6.18/rdma-irdma-prevent-user-triggered-null-deref-on-qp-c.patch new file mode 100644 index 0000000000..bf3f553fdf --- /dev/null +++ b/queue-6.18/rdma-irdma-prevent-user-triggered-null-deref-on-qp-c.patch @@ -0,0 +1,66 @@ +From 7573fd775228248bc7ba9361686ad978917f3bb4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 17 Jun 2026 16:40:13 +0000 +Subject: RDMA/irdma: Prevent user-triggered null deref on QP create + +From: Jacob Moroni + +[ Upstream commit b9b0889071569d43623c260074e159cd8f26adb1 ] + +Previously, the user QP creation path would only attempt to +populate iwqp->iwpbl if the user-provided req.user_wqe_bufs +field was non-zero. The problem is that iwqp->iwpbl is +unconditionally dereferenced later on in irdma_setup_virt_qp. + +While there was a check for iwqp->iwpbl != NULL, this check +would only occur if req.user_wqe_bufs was non-zero. The end +result is that a user could send a zero user_wqe_bufs value +and trigger a null ptr deref. + +Fix this by unconditionally calling irdma_get_pbl and bailing +if it fails, similar to the CQ and SRQ paths. + +Fixes: b48c24c2d710 ("RDMA/irdma: Implement device supported verb APIs") +Link: https://patch.msgid.link/r/20260617164013.280790-1-jmoroni@google.com +Signed-off-by: Jacob Moroni +Reviewed-by: David Hu +Signed-off-by: Jason Gunthorpe +Signed-off-by: Sasha Levin +--- + drivers/infiniband/hw/irdma/verbs.c | 19 +++++++++---------- + 1 file changed, 9 insertions(+), 10 deletions(-) + +diff --git a/drivers/infiniband/hw/irdma/verbs.c b/drivers/infiniband/hw/irdma/verbs.c +index dfd5f0caabb878..5f5b79109d5471 100644 +--- a/drivers/infiniband/hw/irdma/verbs.c ++++ b/drivers/infiniband/hw/irdma/verbs.c +@@ -631,17 +631,16 @@ static int irdma_setup_umode_qp(struct ib_udata *udata, + + iwqp->ctx_info.qp_compl_ctx = req.user_compl_ctx; + iwqp->user_mode = 1; +- if (req.user_wqe_bufs) { +- spin_lock_irqsave(&ucontext->qp_reg_mem_list_lock, flags); +- iwqp->iwpbl = irdma_get_pbl((unsigned long)req.user_wqe_bufs, +- &ucontext->qp_reg_mem_list); +- spin_unlock_irqrestore(&ucontext->qp_reg_mem_list_lock, flags); + +- if (!iwqp->iwpbl) { +- ret = -ENODATA; +- ibdev_dbg(&iwdev->ibdev, "VERBS: no pbl info\n"); +- return ret; +- } ++ spin_lock_irqsave(&ucontext->qp_reg_mem_list_lock, flags); ++ iwqp->iwpbl = irdma_get_pbl((unsigned long)req.user_wqe_bufs, ++ &ucontext->qp_reg_mem_list); ++ spin_unlock_irqrestore(&ucontext->qp_reg_mem_list_lock, flags); ++ ++ if (!iwqp->iwpbl) { ++ ret = -ENODATA; ++ ibdev_dbg(&iwdev->ibdev, "VERBS: no pbl info\n"); ++ return ret; + } + + if (!ucontext->use_raw_attrs) { +-- +2.53.0 + diff --git a/queue-6.18/rdma-irdma-remove-redundant-legacy_mode-checks.patch b/queue-6.18/rdma-irdma-remove-redundant-legacy_mode-checks.patch new file mode 100644 index 0000000000..b05128d0a9 --- /dev/null +++ b/queue-6.18/rdma-irdma-remove-redundant-legacy_mode-checks.patch @@ -0,0 +1,110 @@ +From 984124f998cd1af91ed2dd8efc2f3d7a67e4baaa Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 2 Jun 2026 21:44:22 +0000 +Subject: RDMA/irdma: Remove redundant legacy_mode checks + +From: Jacob Moroni + +[ Upstream commit ed8621be482bf18dcd217aa024e95758bf9d28f2 ] + +The driver has the following invariants: + +1. legacy_mode is only allowed on GEN_1 hardware (enforced + in irdma_alloc_ucontext). + +2. GEN_1 hardware does not set IRDMA_FEATURE_CQ_RESIZE or + IRDMA_FEATURE_RTS_AE. These feature flags are only set + for GEN_2 and GEN_3 hardware. + +Therefore, legacy_mode is always false if IRDMA_FEATURE_CQ_RESIZE +or IRDMA_FEATURE_RTS_AE is set, so remove the redundant checks. + +Link: https://patch.msgid.link/r/20260602214423.1315105-1-jmoroni@google.com +Signed-off-by: Jacob Moroni +Signed-off-by: Jason Gunthorpe +Stable-dep-of: b9b088907156 ("RDMA/irdma: Prevent user-triggered null deref on QP create") +Signed-off-by: Sasha Levin +--- + drivers/infiniband/hw/irdma/uk.c | 9 +++------ + drivers/infiniband/hw/irdma/user.h | 1 - + drivers/infiniband/hw/irdma/verbs.c | 7 +------ + 3 files changed, 4 insertions(+), 13 deletions(-) + +diff --git a/drivers/infiniband/hw/irdma/uk.c b/drivers/infiniband/hw/irdma/uk.c +index 4cc81d61be7fad..7aab0076196677 100644 +--- a/drivers/infiniband/hw/irdma/uk.c ++++ b/drivers/infiniband/hw/irdma/uk.c +@@ -1540,15 +1540,12 @@ static const struct irdma_wqe_uk_ops iw_wqe_uk_ops_gen_1 = { + * irdma_setup_connection_wqes - setup WQEs necessary to complete + * connection. + * @qp: hw qp (user and kernel) +- * @info: qp initialization info + */ +-static void irdma_setup_connection_wqes(struct irdma_qp_uk *qp, +- struct irdma_qp_uk_init_info *info) ++static void irdma_setup_connection_wqes(struct irdma_qp_uk *qp) + { + u16 move_cnt = 1; + +- if (!info->legacy_mode && +- (qp->uk_attrs->feature_flags & IRDMA_FEATURE_RTS_AE)) ++ if (qp->uk_attrs->feature_flags & IRDMA_FEATURE_RTS_AE) + move_cnt = 3; + + qp->conn_wqes = move_cnt; +@@ -1699,7 +1696,7 @@ int irdma_uk_qp_init(struct irdma_qp_uk *qp, struct irdma_qp_uk_init_info *info) + sq_ring_size = qp->sq_size << info->sq_shift; + IRDMA_RING_INIT(qp->sq_ring, sq_ring_size); + if (info->first_sq_wq) { +- irdma_setup_connection_wqes(qp, info); ++ irdma_setup_connection_wqes(qp); + qp->swqe_polarity = 1; + qp->first_sq_wq = true; + } else { +diff --git a/drivers/infiniband/hw/irdma/user.h b/drivers/infiniband/hw/irdma/user.h +index aeebf768174abd..a0b409a895f0eb 100644 +--- a/drivers/infiniband/hw/irdma/user.h ++++ b/drivers/infiniband/hw/irdma/user.h +@@ -560,7 +560,6 @@ struct irdma_qp_uk_init_info { + u8 sq_shift; + u8 rq_shift; + int abi_ver; +- bool legacy_mode; + struct irdma_srq_uk *srq_uk; + }; + +diff --git a/drivers/infiniband/hw/irdma/verbs.c b/drivers/infiniband/hw/irdma/verbs.c +index c210f9a37fb97b..dfd5f0caabb878 100644 +--- a/drivers/infiniband/hw/irdma/verbs.c ++++ b/drivers/infiniband/hw/irdma/verbs.c +@@ -632,7 +632,6 @@ static int irdma_setup_umode_qp(struct ib_udata *udata, + iwqp->ctx_info.qp_compl_ctx = req.user_compl_ctx; + iwqp->user_mode = 1; + if (req.user_wqe_bufs) { +- info->qp_uk_init_info.legacy_mode = ucontext->legacy_mode; + spin_lock_irqsave(&ucontext->qp_reg_mem_list_lock, flags); + iwqp->iwpbl = irdma_get_pbl((unsigned long)req.user_wqe_bufs, + &ucontext->qp_reg_mem_list); +@@ -2068,10 +2067,6 @@ static int irdma_resize_cq(struct ib_cq *ibcq, int entries, + rdma_udata_to_drv_context(udata, struct irdma_ucontext, + ibucontext); + +- /* CQ resize not supported with legacy GEN_1 libi40iw */ +- if (ucontext->legacy_mode) +- return -EOPNOTSUPP; +- + if (ib_copy_from_udata(&req, udata, + min(sizeof(req), udata->inlen))) + return -EINVAL; +@@ -2550,7 +2545,7 @@ static int irdma_create_cq(struct ib_cq *ibcq, + cqmr = &iwpbl->cq_mr; + + if (rf->sc_dev.hw_attrs.uk_attrs.feature_flags & +- IRDMA_FEATURE_CQ_RESIZE && !ucontext->legacy_mode) { ++ IRDMA_FEATURE_CQ_RESIZE) { + spin_lock_irqsave(&ucontext->cq_reg_mem_list_lock, flags); + iwpbl_shadow = irdma_get_pbl( + (unsigned long)req.user_shadow_area, +-- +2.53.0 + diff --git a/queue-6.18/rdma-mana_ib-initialize-err-for-empty-send-wr-lists.patch b/queue-6.18/rdma-mana_ib-initialize-err-for-empty-send-wr-lists.patch new file mode 100644 index 0000000000..f3d7633f44 --- /dev/null +++ b/queue-6.18/rdma-mana_ib-initialize-err-for-empty-send-wr-lists.patch @@ -0,0 +1,42 @@ +From 81ff97d6f64d9410b6d08d8158c715c9e905a4c4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 18 Jun 2026 12:17:52 +0800 +Subject: RDMA/mana_ib: initialize err for empty send WR lists + +From: Ruoyu Wang + +[ Upstream commit 155fd5ce2382b0ffbec0d7ee7b3a6818a27a5aed ] + +mana_ib_post_send() returns err after walking the send work request list. +If the caller passes an empty list, the loop is skipped and err is not +assigned. + +Initialize err to 0 so an empty send work request list returns success +instead of stack data. + +Fixes: c8017f5b4856 ("RDMA/mana_ib: UD/GSI work requests") +Link: https://patch.msgid.link/r/20260618041752.481193-2-ruoyuw560@gmail.com +Signed-off-by: Ruoyu Wang +Reviewed-by: Long Li +Signed-off-by: Jason Gunthorpe +Signed-off-by: Sasha Levin +--- + drivers/infiniband/hw/mana/wr.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/infiniband/hw/mana/wr.c b/drivers/infiniband/hw/mana/wr.c +index 1813567d3b16c9..36a1d506f08f65 100644 +--- a/drivers/infiniband/hw/mana/wr.c ++++ b/drivers/infiniband/hw/mana/wr.c +@@ -144,7 +144,7 @@ static int mana_ib_post_send_ud(struct mana_ib_qp *qp, const struct ib_ud_wr *wr + int mana_ib_post_send(struct ib_qp *ibqp, const struct ib_send_wr *wr, + const struct ib_send_wr **bad_wr) + { +- int err; ++ int err = 0; + struct mana_ib_qp *qp = container_of(ibqp, struct mana_ib_qp, ibqp); + + for (; wr; wr = wr->next) { +-- +2.53.0 + diff --git a/queue-6.18/rdma-siw-publish-qp-after-initialization.patch b/queue-6.18/rdma-siw-publish-qp-after-initialization.patch new file mode 100644 index 0000000000..cea32c437f --- /dev/null +++ b/queue-6.18/rdma-siw-publish-qp-after-initialization.patch @@ -0,0 +1,153 @@ +From 662549041c19585df456db3eea891d474b00ea16 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 30 Jun 2026 14:00:40 +0800 +Subject: RDMA/siw: publish QP after initialization + +From: Ruoyu Wang + +[ Upstream commit bb27fcc67c429d97f785c92c35a6c5adebb05d7f ] + +siw_create_qp() currently calls siw_qp_add() before the queues, CQ +pointers, state, completion, and device list entry are ready. A QPN +lookup can therefore reach a QP that is still being constructed. + +Move siw_qp_add() to the end of siw_create_qp(), after QP +initialization and before adding the QP to the siw device list. + +Fixes: f29dd55b0236 ("rdma/siw: queue pair methods") +Link: https://patch.msgid.link/r/20260630060040.966461-1-ruoyuw560@gmail.com +Suggested-by: Bernard Metzler +Signed-off-by: Ruoyu Wang +Acked-by: Bernard Metzler +Signed-off-by: Jason Gunthorpe +Signed-off-by: Sasha Levin +--- + drivers/infiniband/sw/siw/siw_verbs.c | 44 +++++++++++++++------------ + 1 file changed, 24 insertions(+), 20 deletions(-) + +diff --git a/drivers/infiniband/sw/siw/siw_verbs.c b/drivers/infiniband/sw/siw/siw_verbs.c +index efa2f097b58289..9fbade0b85715a 100644 +--- a/drivers/infiniband/sw/siw/siw_verbs.c ++++ b/drivers/infiniband/sw/siw/siw_verbs.c +@@ -316,6 +316,7 @@ int siw_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attrs, + struct siw_ucontext *uctx = + rdma_udata_to_drv_context(udata, struct siw_ucontext, + base_ucontext); ++ struct siw_uresp_create_qp uresp = {}; + unsigned long flags; + int num_sqe, num_rqe, rv = 0; + size_t length; +@@ -369,11 +370,6 @@ int siw_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attrs, + spin_lock_init(&qp->rq_lock); + spin_lock_init(&qp->orq_lock); + +- rv = siw_qp_add(sdev, qp); +- if (rv) +- goto err_atomic; +- +- + /* All queue indices are derived from modulo operations + * on a free running 'get' (consumer) and 'put' (producer) + * unsigned counter. Having queue sizes at power of two +@@ -391,14 +387,14 @@ int siw_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attrs, + + if (qp->sendq == NULL) { + rv = -ENOMEM; +- goto err_out_xa; ++ goto err_out; + } + if (attrs->sq_sig_type != IB_SIGNAL_REQ_WR) { + if (attrs->sq_sig_type == IB_SIGNAL_ALL_WR) + qp->attrs.flags |= SIW_SIGNAL_ALL_WR; + else { + rv = -EINVAL; +- goto err_out_xa; ++ goto err_out; + } + } + qp->pd = pd; +@@ -424,7 +420,7 @@ int siw_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attrs, + + if (qp->recvq == NULL) { + rv = -ENOMEM; +- goto err_out_xa; ++ goto err_out; + } + qp->attrs.rq_size = num_rqe; + } +@@ -439,11 +435,8 @@ int siw_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attrs, + qp->attrs.state = SIW_QP_STATE_IDLE; + + if (udata) { +- struct siw_uresp_create_qp uresp = {}; +- + uresp.num_sqe = num_sqe; + uresp.num_rqe = num_rqe; +- uresp.qp_id = qp_id(qp); + + if (qp->sendq) { + length = num_sqe * sizeof(struct siw_sqe); +@@ -452,7 +445,7 @@ int siw_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attrs, + length, &uresp.sq_key); + if (!qp->sq_entry) { + rv = -ENOMEM; +- goto err_out_xa; ++ goto err_out; + } + } + +@@ -464,9 +457,23 @@ int siw_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attrs, + if (!qp->rq_entry) { + uresp.sq_key = SIW_INVAL_UOBJ_KEY; + rv = -ENOMEM; +- goto err_out_xa; ++ goto err_out; + } + } ++ } ++ qp->tx_cpu = siw_get_tx_cpu(sdev); ++ if (qp->tx_cpu < 0) { ++ rv = -EINVAL; ++ goto err_out; ++ } ++ init_completion(&qp->qp_free); ++ ++ rv = siw_qp_add(sdev, qp); ++ if (rv) ++ goto err_out_tx; ++ ++ if (udata) { ++ uresp.qp_id = qp_id(qp); + + if (udata->outlen < sizeof(uresp)) { + rv = -EINVAL; +@@ -476,22 +483,19 @@ int siw_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attrs, + if (rv) + goto err_out_xa; + } +- qp->tx_cpu = siw_get_tx_cpu(sdev); +- if (qp->tx_cpu < 0) { +- rv = -EINVAL; +- goto err_out_xa; +- } ++ + INIT_LIST_HEAD(&qp->devq); + spin_lock_irqsave(&sdev->lock, flags); + list_add_tail(&qp->devq, &sdev->qp_list); + spin_unlock_irqrestore(&sdev->lock, flags); + +- init_completion(&qp->qp_free); +- + return 0; + + err_out_xa: + xa_erase(&sdev->qp_xa, qp_id(qp)); ++err_out_tx: ++ siw_put_tx_cpu(qp->tx_cpu); ++err_out: + if (uctx) { + rdma_user_mmap_entry_remove(qp->sq_entry); + rdma_user_mmap_entry_remove(qp->rq_entry); +-- +2.53.0 + diff --git a/queue-6.18/rdma-umem-add-pinned-revocable-dmabuf-import-interfa.patch b/queue-6.18/rdma-umem-add-pinned-revocable-dmabuf-import-interfa.patch new file mode 100644 index 0000000000..c04896969e --- /dev/null +++ b/queue-6.18/rdma-umem-add-pinned-revocable-dmabuf-import-interfa.patch @@ -0,0 +1,167 @@ +From fc29c7928cd7a5243546de723ce876bf999326db Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 5 Mar 2026 17:08:24 +0000 +Subject: RDMA/umem: Add pinned revocable dmabuf import interface + +From: Jacob Moroni + +[ Upstream commit ff85a2ebacbdaec9f28c4660c991295ace93cd1c ] + +Added an interface for importing a pinned but revocable dmabuf. +This interface can be used by drivers that are capable of revocation +so that they can import dmabufs from exporters that may require it, +such as VFIO. + +This interface implements a two step process, where drivers will first +call ib_umem_dmabuf_get_pinned_revocable_and_lock() which will pin and +map the dmabuf (and provide a functional move_notify/invalidate_mappings +callback), but will return with the lock still held so that the +driver can then populate the callback via +ib_umem_dmabuf_set_revoke_locked() without races from concurrent +revocations. This scheme also allows for easier integration with drivers +that may not have actually allocated their internal MR objects at the time +of the get_pinned_revocable* call. + +Signed-off-by: Jacob Moroni +Link: https://patch.msgid.link/20260305170826.3803155-4-jmoroni@google.com +Signed-off-by: Leon Romanovsky +Stable-dep-of: a846aecb931b ("RDMA/irdma: Prevent rereg_mr for non-mem regions") +Signed-off-by: Sasha Levin +--- + drivers/infiniband/core/umem_dmabuf.c | 61 +++++++++++++++++++++++++++ + include/rdma/ib_umem.h | 19 +++++++++ + 2 files changed, 80 insertions(+) + +diff --git a/drivers/infiniband/core/umem_dmabuf.c b/drivers/infiniband/core/umem_dmabuf.c +index b239ac09ec2921..4fc73f53342b7e 100644 +--- a/drivers/infiniband/core/umem_dmabuf.c ++++ b/drivers/infiniband/core/umem_dmabuf.c +@@ -206,6 +206,10 @@ static void ib_umem_dmabuf_revoke_locked(struct dma_buf_attachment *attach) + + if (umem_dmabuf->revoked) + return; ++ ++ if (umem_dmabuf->pinned_revoke) ++ umem_dmabuf->pinned_revoke(umem_dmabuf->private); ++ + ib_umem_dmabuf_unmap_pages(umem_dmabuf); + if (umem_dmabuf->pinned) { + dma_buf_unpin(umem_dmabuf->attach); +@@ -214,6 +218,11 @@ static void ib_umem_dmabuf_revoke_locked(struct dma_buf_attachment *attach) + umem_dmabuf->revoked = 1; + } + ++static struct dma_buf_attach_ops ib_umem_dmabuf_attach_pinned_revocable_ops = { ++ .allow_peer2peer = true, ++ .move_notify = ib_umem_dmabuf_revoke_locked, ++}; ++ + static struct ib_umem_dmabuf * + ib_umem_dmabuf_get_pinned_and_lock(struct ib_device *device, + struct device *dma_device, +@@ -266,6 +275,58 @@ ib_umem_dmabuf_get_pinned_with_dma_device(struct ib_device *device, + } + EXPORT_SYMBOL(ib_umem_dmabuf_get_pinned_with_dma_device); + ++/** ++ * ib_umem_dmabuf_get_pinned_revocable_and_lock - Map & pin a revocable dmabuf ++ * @device: IB device. ++ * @offset: Start offset. ++ * @size: Length. ++ * @fd: dmabuf fd. ++ * @access: Access flags. ++ * ++ * Obtains a umem from a dmabuf for drivers/devices that can support revocation. ++ * ++ * Returns with dma_resv_lock held upon success. The driver must set the revoke ++ * callback prior to unlock by calling ib_umem_dmabuf_set_revoke_locked(). ++ * ++ * When a revocation occurs, the revoke callback will be called. The driver must ++ * ensure that the region is no longer accessed when the callback returns. Any ++ * subsequent access attempts should also probably cause an AE for MRs. ++ * ++ * If the umem is used for an MR, the driver must ensure that the key remains in ++ * use such that it cannot be obtained by a new region until this region is ++ * fully deregistered (i.e., ibv_dereg_mr). If a driver needs to serialize with ++ * revoke calls, it can use dma_resv_lock. ++ * ++ * If successful, then the revoke callback may be called at any time and will ++ * also be called automatically upon ib_umem_release (serialized). The revoke ++ * callback will be called one time at most. ++ * ++ * Return: A pointer to ib_umem_dmabuf on success, or an ERR_PTR on failure. ++ */ ++struct ib_umem_dmabuf * ++ib_umem_dmabuf_get_pinned_revocable_and_lock(struct ib_device *device, ++ unsigned long offset, size_t size, ++ int fd, int access) ++{ ++ const struct dma_buf_attach_ops *ops = ++ &ib_umem_dmabuf_attach_pinned_revocable_ops; ++ ++ return ib_umem_dmabuf_get_pinned_and_lock(device, device->dma_device, ++ offset, size, fd, access, ++ ops); ++} ++EXPORT_SYMBOL(ib_umem_dmabuf_get_pinned_revocable_and_lock); ++ ++void ib_umem_dmabuf_set_revoke_locked(struct ib_umem_dmabuf *umem_dmabuf, ++ void (*revoke)(void *priv), void *priv) ++{ ++ dma_resv_assert_held(umem_dmabuf->attach->dmabuf->resv); ++ ++ umem_dmabuf->pinned_revoke = revoke; ++ umem_dmabuf->private = priv; ++} ++EXPORT_SYMBOL(ib_umem_dmabuf_set_revoke_locked); ++ + struct ib_umem_dmabuf *ib_umem_dmabuf_get_pinned(struct ib_device *device, + unsigned long offset, + size_t size, int fd, +diff --git a/include/rdma/ib_umem.h b/include/rdma/ib_umem.h +index 5122f78467675e..90b1ea19a90a0a 100644 +--- a/include/rdma/ib_umem.h ++++ b/include/rdma/ib_umem.h +@@ -36,6 +36,7 @@ struct ib_umem_dmabuf { + struct scatterlist *last_sg; + unsigned long first_sg_offset; + unsigned long last_sg_trim; ++ void (*pinned_revoke)(void *priv); + void *private; + u8 pinned : 1; + u8 revoked : 1; +@@ -141,6 +142,12 @@ struct ib_umem_dmabuf *ib_umem_dmabuf_get_pinned(struct ib_device *device, + size_t size, int fd, + int access); + struct ib_umem_dmabuf * ++ib_umem_dmabuf_get_pinned_revocable_and_lock(struct ib_device *device, ++ unsigned long offset, size_t size, ++ int fd, int access); ++void ib_umem_dmabuf_set_revoke_locked(struct ib_umem_dmabuf *umem_dmabuf, ++ void (*revoke)(void *priv), void *priv); ++struct ib_umem_dmabuf * + ib_umem_dmabuf_get_pinned_with_dma_device(struct ib_device *device, + struct device *dma_device, + unsigned long offset, size_t size, +@@ -201,6 +208,18 @@ ib_umem_dmabuf_get_pinned(struct ib_device *device, unsigned long offset, + return ERR_PTR(-EOPNOTSUPP); + } + ++static inline struct ib_umem_dmabuf * ++ib_umem_dmabuf_get_pinned_revocable_and_lock(struct ib_device *device, ++ unsigned long offset, size_t size, ++ int fd, int access) ++{ ++ return ERR_PTR(-EOPNOTSUPP); ++} ++ ++static inline void ++ib_umem_dmabuf_set_revoke_locked(struct ib_umem_dmabuf *umem_dmabuf, ++ void (*revoke)(void *priv), void *priv) {} ++ + static inline struct ib_umem_dmabuf * + ib_umem_dmabuf_get_pinned_with_dma_device(struct ib_device *device, + struct device *dma_device, +-- +2.53.0 + diff --git a/queue-6.18/riscv-enable-kernel-access-to-shadow-stack-memory-vi.patch b/queue-6.18/riscv-enable-kernel-access-to-shadow-stack-memory-vi.patch new file mode 100644 index 0000000000..2dba401375 --- /dev/null +++ b/queue-6.18/riscv-enable-kernel-access-to-shadow-stack-memory-vi.patch @@ -0,0 +1,105 @@ +From a5ad00dd5f1908fd1a1724c2d45c87edd5326b91 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 25 Jan 2026 21:09:55 -0700 +Subject: riscv: enable kernel access to shadow stack memory via the FWFT SBI + call + +From: Deepak Gupta + +[ Upstream commit 41213bf2ae6c936f51a79986b37f95da9ecbb970 ] + +The kernel has to perform shadow stack operations on the user shadow stack. +During signal delivery and sigreturn, the shadow stack token must be +created and validated respectively. Thus shadow stack access for the kernel +must be enabled. + +In the future, when kernel shadow stacks are enabled, they must be +enabled as early as possible for better coverage and to prevent any +imbalance between the regular stack and the shadow stack. After +'relocate_enable_mmu' has completed, this is the earliest that it can +be enabled. + +Reviewed-by: Zong Li +Signed-off-by: Deepak Gupta +Tested-by: Andreas Korb # QEMU, custom CVA6 +Tested-by: Valentin Haudiquet +Link: https://patch.msgid.link/20251112-v5_user_cfi_series-v23-22-b55691eacf4f@rivosinc.com +[pjw@kernel.org: updated to apply; cleaned up commit message] +Signed-off-by: Paul Walmsley +Stable-dep-of: 3a2694bf6ac8 ("riscv: Gate FUNCTION_ALIGNMENT_4B on DYNAMIC_FTRACE") +Signed-off-by: Sasha Levin +--- + arch/riscv/kernel/asm-offsets.c | 6 ++++++ + arch/riscv/kernel/head.S | 27 +++++++++++++++++++++++++++ + 2 files changed, 33 insertions(+) + +diff --git a/arch/riscv/kernel/asm-offsets.c b/arch/riscv/kernel/asm-offsets.c +index 0a5e3e892c0ea0..739f6c6ed15885 100644 +--- a/arch/riscv/kernel/asm-offsets.c ++++ b/arch/riscv/kernel/asm-offsets.c +@@ -529,4 +529,10 @@ void asm_offsets(void) + DEFINE(FREGS_A6, offsetof(struct __arch_ftrace_regs, a6)); + DEFINE(FREGS_A7, offsetof(struct __arch_ftrace_regs, a7)); + #endif ++#ifdef CONFIG_RISCV_SBI ++ DEFINE(SBI_EXT_FWFT, SBI_EXT_FWFT); ++ DEFINE(SBI_EXT_FWFT_SET, SBI_EXT_FWFT_SET); ++ DEFINE(SBI_FWFT_SHADOW_STACK, SBI_FWFT_SHADOW_STACK); ++ DEFINE(SBI_FWFT_SET_FLAG_LOCK, SBI_FWFT_SET_FLAG_LOCK); ++#endif + } +diff --git a/arch/riscv/kernel/head.S b/arch/riscv/kernel/head.S +index bdf3352acf4cb4..9c99c5ad6fe8a3 100644 +--- a/arch/riscv/kernel/head.S ++++ b/arch/riscv/kernel/head.S +@@ -15,6 +15,7 @@ + #include + #include + #include ++#include + #include "efi-header.S" + + __HEAD +@@ -170,6 +171,19 @@ secondary_start_sbi: + call relocate_enable_mmu + #endif + call .Lsetup_trap_vector ++#if defined(CONFIG_RISCV_SBI) && defined(CONFIG_RISCV_USER_CFI) ++ li a7, SBI_EXT_FWFT ++ li a6, SBI_EXT_FWFT_SET ++ li a0, SBI_FWFT_SHADOW_STACK ++ li a1, 1 /* enable supervisor to access shadow stack access */ ++ li a2, SBI_FWFT_SET_FLAG_LOCK ++ ecall ++ beqz a0, 1f ++ la a1, riscv_nousercfi ++ li a0, CMDLINE_DISABLE_RISCV_USERCFI_BCFI ++ REG_S a0, (a1) ++1: ++#endif + scs_load_current + call smp_callin + #endif /* CONFIG_SMP */ +@@ -330,6 +344,19 @@ SYM_CODE_START(_start_kernel) + la tp, init_task + la sp, init_thread_union + THREAD_SIZE + addi sp, sp, -PT_SIZE_ON_STACK ++#if defined(CONFIG_RISCV_SBI) && defined(CONFIG_RISCV_USER_CFI) ++ li a7, SBI_EXT_FWFT ++ li a6, SBI_EXT_FWFT_SET ++ li a0, SBI_FWFT_SHADOW_STACK ++ li a1, 1 /* enable supervisor to access shadow stack access */ ++ li a2, SBI_FWFT_SET_FLAG_LOCK ++ ecall ++ beqz a0, 1f ++ la a1, riscv_nousercfi ++ li a0, CMDLINE_DISABLE_RISCV_USERCFI_BCFI ++ REG_S a0, (a1) ++1: ++#endif + scs_load_current + + #ifdef CONFIG_KASAN +-- +2.53.0 + diff --git a/queue-6.18/riscv-export-kaslr-offset-and-satp-in-vmcoreinfo-elf.patch b/queue-6.18/riscv-export-kaslr-offset-and-satp-in-vmcoreinfo-elf.patch new file mode 100644 index 0000000000..ff99b227ed --- /dev/null +++ b/queue-6.18/riscv-export-kaslr-offset-and-satp-in-vmcoreinfo-elf.patch @@ -0,0 +1,58 @@ +From 7d1a79d11020d1ec3923d441664f06cf003490a1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 4 Apr 2026 18:42:40 -0600 +Subject: riscv: export kaslr offset and satp in VMCOREINFO ELF notes + +From: Austin Kim + +[ Upstream commit d8e99133eb4a8d09dcbf71f7277dc948d3413227 ] + +The following options are required by the kdump crash utility for RISC-V +based vmcore file: + +- kaslr: If the vmcore is generated from a KASLR-enabled Linux kernel, + the KASLR offset is required for the crash utility to load + the vmcore. Without the proper kaslr option, the crash utility + fails to load the vmcore file. +- satp: The exact root page table address helps determine the correct base + PGD address. + +With this patch, RISC-V VMCOREINFO ELF notes now include both kaslr +and satp information. + +Signed-off-by: Austin Kim +Link: https://patch.msgid.link/aYwKUE3ZzN7/ZY/A@adminpc-PowerEdge-R7525 +Signed-off-by: Paul Walmsley +Stable-dep-of: 3a2694bf6ac8 ("riscv: Gate FUNCTION_ALIGNMENT_4B on DYNAMIC_FTRACE") +Signed-off-by: Sasha Levin +--- + arch/riscv/kernel/vmcore_info.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/arch/riscv/kernel/vmcore_info.c b/arch/riscv/kernel/vmcore_info.c +index d5e448aa90e746..682ba423cf203d 100644 +--- a/arch/riscv/kernel/vmcore_info.c ++++ b/arch/riscv/kernel/vmcore_info.c +@@ -3,6 +3,11 @@ + #include + #include + ++static inline u64 get_satp_value(void) ++{ ++ return csr_read(CSR_SATP); ++} ++ + void arch_crash_save_vmcoreinfo(void) + { + VMCOREINFO_NUMBER(phys_ram_base); +@@ -27,5 +32,7 @@ void arch_crash_save_vmcoreinfo(void) + #else + vmcoreinfo_append_str("NUMBER(va_kernel_pa_offset)=0x%lx\n", + kernel_map.va_kernel_pa_offset); ++ vmcoreinfo_append_str("KERNELOFFSET=%lx\n", kaslr_offset()); ++ vmcoreinfo_append_str("NUMBER(satp)=0x%llx\n", get_satp_value()); + #endif + } +-- +2.53.0 + diff --git a/queue-6.18/riscv-gate-function_alignment_4b-on-dynamic_ftrace.patch b/queue-6.18/riscv-gate-function_alignment_4b-on-dynamic_ftrace.patch new file mode 100644 index 0000000000..75e2b60dc6 --- /dev/null +++ b/queue-6.18/riscv-gate-function_alignment_4b-on-dynamic_ftrace.patch @@ -0,0 +1,53 @@ +From 07e53fd655124537b9b12e767a85526c72df4c14 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 6 Jul 2026 21:04:14 +0800 +Subject: riscv: Gate FUNCTION_ALIGNMENT_4B on DYNAMIC_FTRACE + +From: Rui Qi + +[ Upstream commit 3a2694bf6ac8e47b3814293e80343f58fc72937f ] + +The FUNCTION_ALIGNMENT_4B select forces the whole kernel to be built +with -fmin-function-alignment=4. This alignment is only needed so the +patchable-function-entry NOPs, which arch/riscv/Makefile emits under +CONFIG_DYNAMIC_FTRACE, can be patched reliably on RISCV_ISA_C=y builds +where compressed instructions otherwise allow 2-byte function +alignment. + +The select is currently gated on HAVE_DYNAMIC_FTRACE, a capability bit +that is selected whenever the toolchain supports dynamic ftrace, rather +than on whether tracing is actually enabled. As a result every +RISCV_ISA_C=y build gets 4-byte function alignment across the entire +kernel even when function tracing is disabled, needlessly growing the +kernel image and wasting instruction cache for a feature that is not +in use. + +Gate the select on DYNAMIC_FTRACE instead, matching the condition under +which arch/riscv/Makefile emits -fpatchable-function-entry, so the +alignment is only applied when it is actually needed. + +Fixes: c41bf4326c7b ("riscv: ftrace: align patchable functions to 4 Byte boundary") +Signed-off-by: Rui Qi +Link: https://patch.msgid.link/20260706130415.463682-1-qirui.001@bytedance.com +Signed-off-by: Paul Walmsley +Signed-off-by: Sasha Levin +--- + arch/riscv/Kconfig | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig +index c09dbb89461ddb..17b968321b6679 100644 +--- a/arch/riscv/Kconfig ++++ b/arch/riscv/Kconfig +@@ -153,7 +153,7 @@ config RISCV + select HAVE_DEBUG_KMEMLEAK + select HAVE_DMA_CONTIGUOUS if MMU + select HAVE_DYNAMIC_FTRACE if MMU && (CLANG_SUPPORTS_DYNAMIC_FTRACE || GCC_SUPPORTS_DYNAMIC_FTRACE) +- select FUNCTION_ALIGNMENT_4B if HAVE_DYNAMIC_FTRACE && RISCV_ISA_C ++ select FUNCTION_ALIGNMENT_4B if DYNAMIC_FTRACE && RISCV_ISA_C + select HAVE_DYNAMIC_FTRACE_WITH_DIRECT_CALLS if HAVE_DYNAMIC_FTRACE_WITH_CALL_OPS + select HAVE_DYNAMIC_FTRACE_WITH_CALL_OPS if (DYNAMIC_FTRACE_WITH_ARGS && !CFI) + select HAVE_DYNAMIC_FTRACE_WITH_ARGS if HAVE_DYNAMIC_FTRACE +-- +2.53.0 + diff --git a/queue-6.18/riscv-hwprobe-avoid-uninitialized-read-in-hwprobe_ge.patch b/queue-6.18/riscv-hwprobe-avoid-uninitialized-read-in-hwprobe_ge.patch new file mode 100644 index 0000000000..90f19616b5 --- /dev/null +++ b/queue-6.18/riscv-hwprobe-avoid-uninitialized-read-in-hwprobe_ge.patch @@ -0,0 +1,41 @@ +From e0c01437675c2af560dbf23f79be34cd5085ecd7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 13 Jul 2026 17:30:56 -0700 +Subject: riscv: hwprobe: Avoid uninitialized read in hwprobe_get_cpus() + +From: Mark Harris + +[ Upstream commit 5caae1deee89a6582c761d5dcd4b924b744426cc ] + +When cpusetsize < cpumask_size(), hwprobe_get_cpus() did not fully +initialize its copy of the cpu mask, which could cause non-deterministic +results from the riscv_hwprobe syscall on a system with more than 8 CPUs +when the supplied cpu mask is empty. Address this by fully initializing +the cpu mask. + +Fixes: e178bf146e4b ("RISC-V: hwprobe: Introduce which-cpus flag") +Signed-off-by: Mark Harris +Reviewed-by: Nam Cao +Reviewed-by: Michael Ellerman +Link: https://patch.msgid.link/20260714003056.73707-1-mark.hsj@gmail.com +Signed-off-by: Paul Walmsley +Signed-off-by: Sasha Levin +--- + arch/riscv/kernel/sys_hwprobe.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/arch/riscv/kernel/sys_hwprobe.c b/arch/riscv/kernel/sys_hwprobe.c +index 199d13f86f3135..460fb297672e68 100644 +--- a/arch/riscv/kernel/sys_hwprobe.c ++++ b/arch/riscv/kernel/sys_hwprobe.c +@@ -409,6 +409,7 @@ static int hwprobe_get_cpus(struct riscv_hwprobe __user *pairs, + if (cpusetsize > cpumask_size()) + cpusetsize = cpumask_size(); + ++ cpumask_clear(&cpus); + ret = copy_from_user(&cpus, cpus_user, cpusetsize); + if (ret) + return -EFAULT; +-- +2.53.0 + diff --git a/queue-6.18/riscv-remove-support-for-xip-kernel.patch b/queue-6.18/riscv-remove-support-for-xip-kernel.patch new file mode 100644 index 0000000000..64f6084773 --- /dev/null +++ b/queue-6.18/riscv-remove-support-for-xip-kernel.patch @@ -0,0 +1,979 @@ +From 6d2bb998bb0764d49ef86c981e4d356670186611 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 3 Apr 2026 19:28:48 -0600 +Subject: riscv: Remove support for XIP kernel + +From: Nam Cao + +[ Upstream commit 9b3a2be84803cf18c4b4d1efc695991f0daa153c ] + +XIP has a history of being broken for long periods of time. In 2023, it was +broken for 18 months before getting fixed [1]. In 2024 it was 4 months [2]. + +And now it is broken again since commit a44fb5722199 ("riscv: Add runtime +constant support"), 10 months ago. + +These are clear signs that XIP feature is not being used. + +I occasionally looked after XIP, but mostly because I was bored and had +nothing better to do. + +Remove XIP support. Revert is possible if someone shows up complaining. + +Link: https://lore.kernel.org/linux-riscv/20231212-customary-hardcover-e19462bf8e75@wendy/ [1] +Link: https://lore.kernel.org/linux-riscv/20240526110104.470429-1-namcao@linutronix.de/ [2] +Signed-off-by: Nam Cao +Cc: Frederik Haxel +Cc: Vitaly Wool +Reviewed-by: Jisheng Zhang +Acked-by: Conor Dooley +Link: https://patch.msgid.link/20260202115403.2119218-1-namcao@linutronix.de +[pjw@kernel.org: updated to apply] +Signed-off-by: Paul Walmsley +Stable-dep-of: 3a2694bf6ac8 ("riscv: Gate FUNCTION_ALIGNMENT_4B on DYNAMIC_FTRACE") +Signed-off-by: Sasha Levin +--- + arch/riscv/Kconfig | 86 ++++++--------------- + arch/riscv/Kconfig.socs | 8 +- + arch/riscv/Makefile | 3 - + arch/riscv/boot/Makefile | 11 --- + arch/riscv/include/asm/page.h | 29 -------- + arch/riscv/include/asm/pgtable.h | 20 ----- + arch/riscv/include/asm/scs.h | 1 - + arch/riscv/include/asm/set_memory.h | 2 +- + arch/riscv/include/asm/xip_fixup.h | 49 ------------ + arch/riscv/kernel/head.S | 41 ---------- + arch/riscv/kernel/head.h | 3 - + arch/riscv/kernel/setup.c | 6 +- + arch/riscv/kernel/suspend_entry.S | 2 - + arch/riscv/kernel/traps.c | 4 - + arch/riscv/kernel/vmcore_info.c | 7 -- + arch/riscv/kernel/vmlinux.lds.S | 5 -- + arch/riscv/mm/init.c | 111 ++-------------------------- + 17 files changed, 37 insertions(+), 351 deletions(-) + delete mode 100644 arch/riscv/include/asm/xip_fixup.h + +diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig +index fadec20b87a8e3..c09dbb89461ddb 100644 +--- a/arch/riscv/Kconfig ++++ b/arch/riscv/Kconfig +@@ -48,8 +48,8 @@ config RISCV + select ARCH_HAS_PTE_SPECIAL + select ARCH_HAS_SET_DIRECT_MAP if MMU + select ARCH_HAS_SET_MEMORY if MMU +- select ARCH_HAS_STRICT_KERNEL_RWX if MMU && !XIP_KERNEL +- select ARCH_HAS_STRICT_MODULE_RWX if MMU && !XIP_KERNEL ++ select ARCH_HAS_STRICT_KERNEL_RWX if MMU ++ select ARCH_HAS_STRICT_MODULE_RWX if MMU + select ARCH_HAS_SYNC_CORE_BEFORE_USERMODE + select ARCH_HAS_SYSCALL_WRAPPER + select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST +@@ -85,7 +85,7 @@ config RISCV + select ARCH_WANT_FRAME_POINTERS + select ARCH_WANT_GENERAL_HUGETLB if !RISCV_ISA_SVNAPOT + select ARCH_WANT_HUGE_PMD_SHARE if 64BIT +- select ARCH_WANT_LD_ORPHAN_WARN if !XIP_KERNEL ++ select ARCH_WANT_LD_ORPHAN_WARN + select ARCH_WANT_OPTIMIZE_DAX_VMEMMAP + select ARCH_WANT_OPTIMIZE_HUGETLB_VMEMMAP + select ARCH_WANTS_NO_INSTR +@@ -130,13 +130,13 @@ config RISCV + select HAVE_ARCH_AUDITSYSCALL + select HAVE_ARCH_HUGE_VMALLOC if HAVE_ARCH_HUGE_VMAP + select HAVE_ARCH_HUGE_VMAP if MMU && 64BIT +- select HAVE_ARCH_JUMP_LABEL if !XIP_KERNEL +- select HAVE_ARCH_JUMP_LABEL_RELATIVE if !XIP_KERNEL ++ select HAVE_ARCH_JUMP_LABEL ++ select HAVE_ARCH_JUMP_LABEL_RELATIVE + select HAVE_ARCH_KASAN if MMU && 64BIT + select HAVE_ARCH_KASAN_VMALLOC if MMU && 64BIT + select HAVE_ARCH_KFENCE if MMU && 64BIT + select HAVE_ARCH_KSTACK_ERASE +- select HAVE_ARCH_KGDB if !XIP_KERNEL ++ select HAVE_ARCH_KGDB + select HAVE_ARCH_KGDB_QXFER_PKT + select HAVE_ARCH_MMAP_RND_BITS if MMU + select HAVE_ARCH_MMAP_RND_COMPAT_BITS if COMPAT +@@ -152,7 +152,7 @@ config RISCV + select HAVE_CONTEXT_TRACKING_USER + select HAVE_DEBUG_KMEMLEAK + select HAVE_DMA_CONTIGUOUS if MMU +- select HAVE_DYNAMIC_FTRACE if !XIP_KERNEL && MMU && (CLANG_SUPPORTS_DYNAMIC_FTRACE || GCC_SUPPORTS_DYNAMIC_FTRACE) ++ select HAVE_DYNAMIC_FTRACE if MMU && (CLANG_SUPPORTS_DYNAMIC_FTRACE || GCC_SUPPORTS_DYNAMIC_FTRACE) + select FUNCTION_ALIGNMENT_4B if HAVE_DYNAMIC_FTRACE && RISCV_ISA_C + select HAVE_DYNAMIC_FTRACE_WITH_DIRECT_CALLS if HAVE_DYNAMIC_FTRACE_WITH_CALL_OPS + select HAVE_DYNAMIC_FTRACE_WITH_CALL_OPS if (DYNAMIC_FTRACE_WITH_ARGS && !CFI) +@@ -160,7 +160,7 @@ config RISCV + select HAVE_FTRACE_GRAPH_FUNC + select HAVE_FUNCTION_GRAPH_TRACER if HAVE_DYNAMIC_FTRACE_WITH_ARGS + select HAVE_FUNCTION_GRAPH_FREGS +- select HAVE_FUNCTION_TRACER if !XIP_KERNEL && HAVE_DYNAMIC_FTRACE ++ select HAVE_FUNCTION_TRACER if HAVE_DYNAMIC_FTRACE + select HAVE_EBPF_JIT if MMU + select HAVE_GENERIC_TIF_BITS + select HAVE_GUP_FAST if MMU +@@ -169,16 +169,16 @@ config RISCV + select HAVE_GCC_PLUGINS + select HAVE_GENERIC_VDSO if MMU + select HAVE_IRQ_TIME_ACCOUNTING +- select HAVE_KERNEL_BZIP2 if !XIP_KERNEL && !EFI_ZBOOT +- select HAVE_KERNEL_GZIP if !XIP_KERNEL && !EFI_ZBOOT +- select HAVE_KERNEL_LZ4 if !XIP_KERNEL && !EFI_ZBOOT +- select HAVE_KERNEL_LZMA if !XIP_KERNEL && !EFI_ZBOOT +- select HAVE_KERNEL_LZO if !XIP_KERNEL && !EFI_ZBOOT +- select HAVE_KERNEL_UNCOMPRESSED if !XIP_KERNEL && !EFI_ZBOOT +- select HAVE_KERNEL_ZSTD if !XIP_KERNEL && !EFI_ZBOOT +- select HAVE_KERNEL_XZ if !XIP_KERNEL && !EFI_ZBOOT +- select HAVE_KPROBES if !XIP_KERNEL +- select HAVE_KRETPROBES if !XIP_KERNEL ++ select HAVE_KERNEL_BZIP2 if !EFI_ZBOOT ++ select HAVE_KERNEL_GZIP if !EFI_ZBOOT ++ select HAVE_KERNEL_LZ4 if !EFI_ZBOOT ++ select HAVE_KERNEL_LZMA if !EFI_ZBOOT ++ select HAVE_KERNEL_LZO if !EFI_ZBOOT ++ select HAVE_KERNEL_UNCOMPRESSED if !EFI_ZBOOT ++ select HAVE_KERNEL_ZSTD if !EFI_ZBOOT ++ select HAVE_KERNEL_XZ if !EFI_ZBOOT ++ select HAVE_KPROBES ++ select HAVE_KRETPROBES + # https://github.com/ClangBuiltLinux/linux/issues/1881 + select HAVE_LD_DEAD_CODE_DATA_ELIMINATION if !LD_IS_LLD + select HAVE_MOVE_PMD +@@ -189,9 +189,9 @@ config RISCV + select HAVE_PERF_REGS + select HAVE_PERF_USER_STACK_DUMP + select HAVE_POSIX_CPU_TIMERS_TASK_WORK +- select HAVE_PREEMPT_DYNAMIC_KEY if !XIP_KERNEL ++ select HAVE_PREEMPT_DYNAMIC_KEY + select HAVE_REGS_AND_STACK_ACCESS_API +- select HAVE_RETHOOK if !XIP_KERNEL ++ select HAVE_RETHOOK + select HAVE_RSEQ + select HAVE_RUST if RUSTC_SUPPORTS_RISCV && CC_IS_CLANG + select HAVE_SAMPLE_FTRACE_DIRECT +@@ -212,7 +212,7 @@ config RISCV + select PCI_ECAM if (ACPI && PCI) + select PCI_MSI if PCI + select RELOCATABLE if !MMU && !PHYS_RAM_BASE_FIXED +- select RISCV_ALTERNATIVE if !XIP_KERNEL ++ select RISCV_ALTERNATIVE + select RISCV_APLIC + select RISCV_IMSIC + select RISCV_INTC +@@ -539,7 +539,6 @@ endchoice + + config RISCV_ALTERNATIVE + bool +- depends on !XIP_KERNEL + help + This Kconfig allows the kernel to automatically patch the + erratum or cpufeature required by the execution platform at run +@@ -1113,7 +1112,6 @@ config PARAVIRT_TIME_ACCOUNTING + + config RELOCATABLE + bool "Build a relocatable kernel" +- depends on !XIP_KERNEL + select MODULE_SECTIONS if MODULES + select ARCH_VMLINUX_NEEDS_RELOCS + help +@@ -1130,7 +1128,7 @@ config RELOCATABLE + config RANDOMIZE_BASE + bool "Randomize the address of the kernel image" + select RELOCATABLE +- depends on MMU && 64BIT && !XIP_KERNEL ++ depends on MMU && 64BIT + help + Randomizes the virtual address at which the kernel image is + loaded, as a security feature that deters exploit attempts +@@ -1198,7 +1196,7 @@ config EFI_STUB + + config EFI + bool "UEFI runtime support" +- depends on OF && !XIP_KERNEL ++ depends on OF + depends on MMU + default y + select ARCH_SUPPORTS_ACPI if 64BIT +@@ -1249,44 +1247,6 @@ config PHYS_RAM_BASE + explicitly specified to run early relocations of read-write data + from flash to RAM. + +-config XIP_KERNEL +- bool "Kernel Execute-In-Place from ROM" +- depends on MMU && SPARSEMEM && NONPORTABLE +- # This prevents XIP from being enabled by all{yes,mod}config, which +- # fail to build since XIP doesn't support large kernels. +- depends on !COMPILE_TEST +- select PHYS_RAM_BASE_FIXED +- help +- Execute-In-Place allows the kernel to run from non-volatile storage +- directly addressable by the CPU, such as NOR flash. This saves RAM +- space since the text section of the kernel is not loaded from flash +- to RAM. Read-write sections, such as the data section and stack, +- are still copied to RAM. The XIP kernel is not compressed since +- it has to run directly from flash, so it will take more space to +- store it. The flash address used to link the kernel object files, +- and for storing it, is configuration dependent. Therefore, if you +- say Y here, you must know the proper physical address where to +- store the kernel image depending on your own flash memory usage. +- +- Also note that the make target becomes "make xipImage" rather than +- "make zImage" or "make Image". The final kernel binary to put in +- ROM memory will be arch/riscv/boot/xipImage. +- +- SPARSEMEM is required because the kernel text and rodata that are +- flash resident are not backed by memmap, then any attempt to get +- a struct page on those regions will trigger a fault. +- +- If unsure, say N. +- +-config XIP_PHYS_ADDR +- hex "XIP Kernel Physical Location" +- depends on XIP_KERNEL +- default "0x21000000" +- help +- This is the physical address in your flash memory the kernel will +- be linked for and stored to. This address is dependent on your +- own flash usage. +- + config RISCV_ISA_FALLBACK + bool "Permit falling back to parsing riscv,isa for extension support by default" + default y +diff --git a/arch/riscv/Kconfig.socs b/arch/riscv/Kconfig.socs +index 848e7149e4435a..baed90e6ae4878 100644 +--- a/arch/riscv/Kconfig.socs ++++ b/arch/riscv/Kconfig.socs +@@ -2,7 +2,7 @@ menu "SoC selection" + + config ARCH_ANDES + bool "Andes SoCs" +- depends on MMU && !XIP_KERNEL ++ depends on MMU + select ERRATA_ANDES + help + This enables support for Andes SoC platform hardware. +@@ -28,7 +28,7 @@ config ARCH_RENESAS + + config ARCH_SIFIVE + bool "SiFive SoCs" +- select ERRATA_SIFIVE if !XIP_KERNEL ++ select ERRATA_SIFIVE + help + This enables support for SiFive SoC platform hardware. + +@@ -56,7 +56,7 @@ config SOC_STARFIVE + + config ARCH_SUNXI + bool "Allwinner sun20i SoCs" +- depends on MMU && !XIP_KERNEL ++ depends on MMU + select ERRATA_THEAD + select SUN4I_TIMER + help +@@ -65,7 +65,7 @@ config ARCH_SUNXI + + config ARCH_THEAD + bool "T-HEAD RISC-V SoCs" +- depends on MMU && !XIP_KERNEL ++ depends on MMU + select ERRATA_THEAD + select PM_GENERIC_DOMAINS if PM + help +diff --git a/arch/riscv/Makefile b/arch/riscv/Makefile +index 4c6de57f65ef0e..c7aaa2965a689b 100644 +--- a/arch/riscv/Makefile ++++ b/arch/riscv/Makefile +@@ -147,7 +147,6 @@ ifdef CONFIG_RISCV_M_MODE + boot-image-$(CONFIG_SOC_CANAAN_K210) := loader.bin + endif + boot-image-$(CONFIG_EFI_ZBOOT) := vmlinuz.efi +-boot-image-$(CONFIG_XIP_KERNEL) := xipImage + KBUILD_IMAGE := $(boot)/$(boot-image-y) + + libs-y += arch/riscv/lib/ +@@ -212,8 +211,6 @@ define archhelp + echo ' Image.xz - Compressed kernel image (arch/riscv/boot/Image.xz)' + echo ' vmlinuz.efi - Compressed EFI kernel image (arch/riscv/boot/vmlinuz.efi)' + echo ' Default when CONFIG_EFI_ZBOOT=y' +- echo ' xipImage - Execute-in-place kernel image (arch/riscv/boot/xipImage)' +- echo ' Default when CONFIG_XIP_KERNEL=y' + echo ' install - Install kernel using (your) ~/bin/$(INSTALLKERNEL) or' + echo ' (distribution) /sbin/$(INSTALLKERNEL) or install to ' + echo ' $$(INSTALL_PATH)' +diff --git a/arch/riscv/boot/Makefile b/arch/riscv/boot/Makefile +index 5301adf5f3f5d2..fcfbe3f814d664 100644 +--- a/arch/riscv/boot/Makefile ++++ b/arch/riscv/boot/Makefile +@@ -20,17 +20,6 @@ OBJCOPYFLAGS_xipImage :=-O binary -R .note -R .note.gnu.build-id -R .comment -S + + targets := Image Image.* loader loader.o loader.lds loader.bin xipImage + +-ifeq ($(CONFIG_XIP_KERNEL),y) +- +-quiet_cmd_mkxip = $(quiet_cmd_objcopy) +-cmd_mkxip = $(cmd_objcopy) +- +-$(obj)/xipImage: vmlinux FORCE +- $(call if_changed,mkxip) +- @$(kecho) ' Physical Address of xipImage: $(CONFIG_XIP_PHYS_ADDR)' +- +-endif +- + $(obj)/Image: vmlinux FORCE + $(call if_changed,objcopy) + +diff --git a/arch/riscv/include/asm/page.h b/arch/riscv/include/asm/page.h +index ffe213ad65a4ee..d0e29b52738567 100644 +--- a/arch/riscv/include/asm/page.h ++++ b/arch/riscv/include/asm/page.h +@@ -29,11 +29,7 @@ + #define PAGE_OFFSET_L5 _AC(0xff60000000000000, UL) + #define PAGE_OFFSET_L4 _AC(0xffffaf8000000000, UL) + #define PAGE_OFFSET_L3 _AC(0xffffffd600000000, UL) +-#ifdef CONFIG_XIP_KERNEL +-#define PAGE_OFFSET PAGE_OFFSET_L3 +-#else + #define PAGE_OFFSET kernel_map.page_offset +-#endif /* CONFIG_XIP_KERNEL */ + #else + #define PAGE_OFFSET _AC(0xc0000000, UL) + #endif /* CONFIG_64BIT */ +@@ -106,15 +102,8 @@ struct kernel_mapping { + /* Offset between linear mapping virtual address and kernel load address */ + unsigned long va_pa_offset; + /* Offset between kernel mapping virtual address and kernel load address */ +-#ifdef CONFIG_XIP_KERNEL +- unsigned long va_kernel_xip_text_pa_offset; +- unsigned long va_kernel_xip_data_pa_offset; +- uintptr_t xiprom; +- uintptr_t xiprom_sz; +-#else + unsigned long page_offset; + unsigned long va_kernel_pa_offset; +-#endif + }; + + extern struct kernel_mapping kernel_map; +@@ -133,16 +122,7 @@ extern unsigned long vmemmap_start_pfn; + void *linear_mapping_pa_to_va(unsigned long x); + #endif + +-#ifdef CONFIG_XIP_KERNEL +-#define kernel_mapping_pa_to_va(y) ({ \ +- unsigned long _y = (unsigned long)(y); \ +- (_y < phys_ram_base) ? \ +- (void *)(_y + kernel_map.va_kernel_xip_text_pa_offset) : \ +- (void *)(_y + kernel_map.va_kernel_xip_data_pa_offset); \ +- }) +-#else + #define kernel_mapping_pa_to_va(y) ((void *)((unsigned long)(y) + kernel_map.va_kernel_pa_offset)) +-#endif + + #define __pa_to_va_nodebug(x) linear_mapping_pa_to_va(x) + +@@ -152,16 +132,7 @@ void *linear_mapping_pa_to_va(unsigned long x); + phys_addr_t linear_mapping_va_to_pa(unsigned long x); + #endif + +-#ifdef CONFIG_XIP_KERNEL +-#define kernel_mapping_va_to_pa(y) ({ \ +- unsigned long _y = (unsigned long)(y); \ +- (_y < kernel_map.virt_addr + kernel_map.xiprom_sz) ? \ +- (_y - kernel_map.va_kernel_xip_text_pa_offset) : \ +- (_y - kernel_map.va_kernel_xip_data_pa_offset); \ +- }) +-#else + #define kernel_mapping_va_to_pa(y) ((unsigned long)(y) - kernel_map.va_kernel_pa_offset) +-#endif + + #define __va_to_pa_nodebug(x) ({ \ + unsigned long _x = x; \ +diff --git a/arch/riscv/include/asm/pgtable.h b/arch/riscv/include/asm/pgtable.h +index 9b2e967c9fe080..78bde59498836b 100644 +--- a/arch/riscv/include/asm/pgtable.h ++++ b/arch/riscv/include/asm/pgtable.h +@@ -144,21 +144,6 @@ + + #include + +-#ifdef CONFIG_XIP_KERNEL +-#define XIP_FIXUP(addr) ({ \ +- extern char _sdata[], _start[], _end[]; \ +- uintptr_t __rom_start_data = CONFIG_XIP_PHYS_ADDR \ +- + (uintptr_t)&_sdata - (uintptr_t)&_start; \ +- uintptr_t __rom_end_data = CONFIG_XIP_PHYS_ADDR \ +- + (uintptr_t)&_end - (uintptr_t)&_start; \ +- uintptr_t __a = (uintptr_t)(addr); \ +- (__a >= __rom_start_data && __a < __rom_end_data) ? \ +- __a - __rom_start_data + CONFIG_PHYS_RAM_BASE : __a; \ +- }) +-#else +-#define XIP_FIXUP(addr) (addr) +-#endif /* CONFIG_XIP_KERNEL */ +- + struct pt_alloc_ops { + pte_t *(*get_pte_virt)(phys_addr_t pa); + phys_addr_t (*alloc_pte)(uintptr_t va); +@@ -1106,13 +1091,8 @@ static inline pte_t pte_swp_clear_exclusive(pte_t pte) + extern char _start[]; + extern void *_dtb_early_va; + extern uintptr_t _dtb_early_pa; +-#if defined(CONFIG_XIP_KERNEL) && defined(CONFIG_MMU) +-#define dtb_early_va (*(void **)XIP_FIXUP(&_dtb_early_va)) +-#define dtb_early_pa (*(uintptr_t *)XIP_FIXUP(&_dtb_early_pa)) +-#else + #define dtb_early_va _dtb_early_va + #define dtb_early_pa _dtb_early_pa +-#endif /* CONFIG_XIP_KERNEL */ + extern u64 satp_mode; + + void paging_init(void); +diff --git a/arch/riscv/include/asm/scs.h b/arch/riscv/include/asm/scs.h +index ab7714aa93bdc4..023a412fe38d37 100644 +--- a/arch/riscv/include/asm/scs.h ++++ b/arch/riscv/include/asm/scs.h +@@ -10,7 +10,6 @@ + /* Load init_shadow_call_stack to gp. */ + .macro scs_load_init_stack + la gp, init_shadow_call_stack +- XIP_FIXUP_OFFSET gp + .endm + + /* Load the per-CPU IRQ shadow call stack to gp. */ +diff --git a/arch/riscv/include/asm/set_memory.h b/arch/riscv/include/asm/set_memory.h +index 87389e93325a3b..ef59e1716a2cfd 100644 +--- a/arch/riscv/include/asm/set_memory.h ++++ b/arch/riscv/include/asm/set_memory.h +@@ -47,7 +47,7 @@ bool kernel_page_present(struct page *page); + + #endif /* __ASSEMBLER__ */ + +-#if defined(CONFIG_STRICT_KERNEL_RWX) || defined(CONFIG_XIP_KERNEL) ++#if defined(CONFIG_STRICT_KERNEL_RWX) + #ifdef CONFIG_64BIT + #define SECTION_ALIGN (1 << 21) + #else +diff --git a/arch/riscv/include/asm/xip_fixup.h b/arch/riscv/include/asm/xip_fixup.h +deleted file mode 100644 +index f3d56299bc22c5..00000000000000 +--- a/arch/riscv/include/asm/xip_fixup.h ++++ /dev/null +@@ -1,49 +0,0 @@ +-/* SPDX-License-Identifier: GPL-2.0-only */ +-/* +- * XIP fixup macros, only useful in assembly. +- */ +-#ifndef _ASM_RISCV_XIP_FIXUP_H +-#define _ASM_RISCV_XIP_FIXUP_H +- +-#include +- +-#ifdef CONFIG_XIP_KERNEL +-.macro XIP_FIXUP_OFFSET reg +- /* Fix-up address in Flash into address in RAM early during boot before +- * MMU is up. Because generated code "thinks" data is in Flash, but it +- * is actually in RAM (actually data is also in Flash, but Flash is +- * read-only, thus we need to use the data residing in RAM). +- * +- * The start of data in Flash is _sdata and the start of data in RAM is +- * CONFIG_PHYS_RAM_BASE. So this fix-up essentially does this: +- * reg += CONFIG_PHYS_RAM_BASE - _start +- */ +- li t0, CONFIG_PHYS_RAM_BASE +- add \reg, \reg, t0 +- la t0, _sdata +- sub \reg, \reg, t0 +-.endm +-.macro XIP_FIXUP_FLASH_OFFSET reg +- /* In linker script, at the transition from read-only section to +- * writable section, the VMA is increased while LMA remains the same. +- * (See in linker script how _sdata, __data_loc and LOAD_OFFSET is +- * changed) +- * +- * Consequently, early during boot before MMU is up, the generated code +- * reads the "writable" section at wrong addresses, because VMA is used +- * by compiler to generate code, but the data is located in Flash using +- * LMA. +- */ +- la t0, _sdata +- sub \reg, \reg, t0 +- la t0, __data_loc +- add \reg, \reg, t0 +-.endm +-#else +-.macro XIP_FIXUP_OFFSET reg +-.endm +-.macro XIP_FIXUP_FLASH_OFFSET reg +-.endm +-#endif /* CONFIG_XIP_KERNEL */ +- +-#endif +diff --git a/arch/riscv/kernel/head.S b/arch/riscv/kernel/head.S +index 9c99c5ad6fe8a3..65039904436892 100644 +--- a/arch/riscv/kernel/head.S ++++ b/arch/riscv/kernel/head.S +@@ -14,7 +14,6 @@ + #include + #include + #include +-#include + #include + #include "efi-header.S" + +@@ -75,7 +74,6 @@ pe_head_start: + relocate_enable_mmu: + /* Relocate return address */ + la a1, kernel_map +- XIP_FIXUP_OFFSET a1 + REG_L a1, KERNEL_MAP_VIRT_ADDR(a1) + la a2, _start + sub a1, a1, a2 +@@ -89,7 +87,6 @@ relocate_enable_mmu: + /* Compute satp for kernel page tables, but don't load it yet */ + srl a2, a0, PAGE_SHIFT + la a1, satp_mode +- XIP_FIXUP_OFFSET a1 + REG_L a1, 0(a1) + or a2, a2, a1 + +@@ -100,7 +97,6 @@ relocate_enable_mmu: + * to ensure the new translations are in use. + */ + la a0, trampoline_pg_dir +- XIP_FIXUP_OFFSET a0 + srl a0, a0, PAGE_SHIFT + or a0, a0, a1 + sfence.vma +@@ -154,11 +150,9 @@ secondary_start_sbi: + + /* a0 contains the hartid & a1 contains boot data */ + li a2, SBI_HART_BOOT_TASK_PTR_OFFSET +- XIP_FIXUP_OFFSET a2 + add a2, a2, a1 + REG_L tp, (a2) + li a3, SBI_HART_BOOT_STACK_PTR_OFFSET +- XIP_FIXUP_OFFSET a3 + add a3, a3, a1 + REG_L sp, (a3) + +@@ -167,7 +161,6 @@ secondary_start_sbi: + #ifdef CONFIG_MMU + /* Enable virtual memory and relocate to virtual address */ + la a0, swapper_pg_dir +- XIP_FIXUP_OFFSET a0 + call relocate_enable_mmu + #endif + call .Lsetup_trap_vector +@@ -269,40 +262,13 @@ SYM_CODE_START(_start_kernel) + .Lgood_cores: + + /* The lottery system is only required for spinwait booting method */ +-#ifndef CONFIG_XIP_KERNEL + /* Pick one hart to run the main boot sequence */ + la a3, hart_lottery + li a2, 1 + amoadd.w a3, a2, (a3) + bnez a3, .Lsecondary_start +- +-#else +- /* hart_lottery in flash contains a magic number */ +- la a3, hart_lottery +- mv a2, a3 +- XIP_FIXUP_OFFSET a2 +- XIP_FIXUP_FLASH_OFFSET a3 +- lw t1, (a3) +- amoswap.w t0, t1, (a2) +- /* first time here if hart_lottery in RAM is not set */ +- beq t0, t1, .Lsecondary_start +- +-#endif /* CONFIG_XIP */ + #endif /* CONFIG_RISCV_BOOT_SPINWAIT */ + +-#ifdef CONFIG_XIP_KERNEL +- la sp, _end + THREAD_SIZE +- XIP_FIXUP_OFFSET sp +- mv s0, a0 +- mv s1, a1 +- call __copy_data +- +- /* Restore a0 & a1 copy */ +- mv a0, s0 +- mv a1, s1 +-#endif +- +-#ifndef CONFIG_XIP_KERNEL + /* Clear BSS for flat non-ELF images */ + la a3, __bss_start + la a4, __bss_stop +@@ -312,20 +278,16 @@ SYM_CODE_START(_start_kernel) + add a3, a3, RISCV_SZPTR + blt a3, a4, .Lclear_bss + .Lclear_bss_done: +-#endif + la a2, boot_cpu_hartid +- XIP_FIXUP_OFFSET a2 + REG_S a0, (a2) + + /* Initialize page tables and relocate to virtual addresses */ + la tp, init_task + la sp, init_thread_union + THREAD_SIZE +- XIP_FIXUP_OFFSET sp + addi sp, sp, -PT_SIZE_ON_STACK + scs_load_init_stack + #ifdef CONFIG_BUILTIN_DTB + la a0, __dtb_start +- XIP_FIXUP_OFFSET a0 + #else + mv a0, a1 + #endif /* CONFIG_BUILTIN_DTB */ +@@ -335,7 +297,6 @@ SYM_CODE_START(_start_kernel) + call setup_vm + #ifdef CONFIG_MMU + la a0, early_pg_dir +- XIP_FIXUP_OFFSET a0 + call relocate_enable_mmu + #endif /* CONFIG_MMU */ + +@@ -374,9 +335,7 @@ SYM_CODE_START(_start_kernel) + + slli a3, a0, LGREG + la a1, __cpu_spinwait_stack_pointer +- XIP_FIXUP_OFFSET a1 + la a2, __cpu_spinwait_task_pointer +- XIP_FIXUP_OFFSET a2 + add a1, a3, a1 + add a2, a3, a2 + +diff --git a/arch/riscv/kernel/head.h b/arch/riscv/kernel/head.h +index a556fdaafed943..05a04bef442b1b 100644 +--- a/arch/riscv/kernel/head.h ++++ b/arch/riscv/kernel/head.h +@@ -11,9 +11,6 @@ + extern atomic_t hart_lottery; + + asmlinkage void __init setup_vm(uintptr_t dtb_pa); +-#ifdef CONFIG_XIP_KERNEL +-asmlinkage void __init __copy_data(void); +-#endif + + #ifdef CONFIG_RISCV_BOOT_SPINWAIT + extern void *__cpu_spinwait_stack_pointer[]; +diff --git a/arch/riscv/kernel/setup.c b/arch/riscv/kernel/setup.c +index b5bc5fc65cea65..c89cc272440b9f 100644 +--- a/arch/riscv/kernel/setup.c ++++ b/arch/riscv/kernel/setup.c +@@ -46,11 +46,7 @@ + * This is used before the kernel initializes the BSS so it can't be in the + * BSS. + */ +-atomic_t hart_lottery __section(".sdata") +-#ifdef CONFIG_XIP_KERNEL +-= ATOMIC_INIT(0xC001BEEF) +-#endif +-; ++atomic_t hart_lottery __section(".sdata"); + unsigned long boot_cpu_hartid; + EXPORT_SYMBOL_GPL(boot_cpu_hartid); + +diff --git a/arch/riscv/kernel/suspend_entry.S b/arch/riscv/kernel/suspend_entry.S +index 2d54f309c14059..d71b55fd6259f3 100644 +--- a/arch/riscv/kernel/suspend_entry.S ++++ b/arch/riscv/kernel/suspend_entry.S +@@ -10,7 +10,6 @@ + #include + #include + #include +-#include + + .text + .altmacro +@@ -70,7 +69,6 @@ SYM_TYPED_FUNC_START(__cpu_resume_enter) + + /* Enable MMU */ + la a0, swapper_pg_dir +- XIP_FIXUP_OFFSET a0 + call relocate_enable_mmu + + /* Restore A0 and A1 */ +diff --git a/arch/riscv/kernel/traps.c b/arch/riscv/kernel/traps.c +index 47afea4ff1a8d2..3d24a4697bd915 100644 +--- a/arch/riscv/kernel/traps.c ++++ b/arch/riscv/kernel/traps.c +@@ -142,11 +142,7 @@ static void do_trap_error(struct pt_regs *regs, int signo, int code, + } + } + +-#if defined(CONFIG_XIP_KERNEL) && defined(CONFIG_RISCV_ALTERNATIVE) +-#define __trap_section __noinstr_section(".xip.traps") +-#else + #define __trap_section noinstr +-#endif + #define DO_ERROR_INFO(name, signo, code, str) \ + asmlinkage __visible __trap_section void name(struct pt_regs *regs) \ + { \ +diff --git a/arch/riscv/kernel/vmcore_info.c b/arch/riscv/kernel/vmcore_info.c +index 682ba423cf203d..c27efceec3cc3a 100644 +--- a/arch/riscv/kernel/vmcore_info.c ++++ b/arch/riscv/kernel/vmcore_info.c +@@ -24,15 +24,8 @@ void arch_crash_save_vmcoreinfo(void) + #endif + #endif + vmcoreinfo_append_str("NUMBER(KERNEL_LINK_ADDR)=0x%lx\n", KERNEL_LINK_ADDR); +-#ifdef CONFIG_XIP_KERNEL +- /* TODO: Communicate with crash-utility developers on the information to +- * export. The XIP case is more complicated, because the virtual-physical +- * address offset depends on whether the address is in ROM or in RAM. +- */ +-#else + vmcoreinfo_append_str("NUMBER(va_kernel_pa_offset)=0x%lx\n", + kernel_map.va_kernel_pa_offset); + vmcoreinfo_append_str("KERNELOFFSET=%lx\n", kaslr_offset()); + vmcoreinfo_append_str("NUMBER(satp)=0x%llx\n", get_satp_value()); +-#endif + } +diff --git a/arch/riscv/kernel/vmlinux.lds.S b/arch/riscv/kernel/vmlinux.lds.S +index 997f9eb3b22b13..1f4f8496941aef 100644 +--- a/arch/riscv/kernel/vmlinux.lds.S ++++ b/arch/riscv/kernel/vmlinux.lds.S +@@ -7,10 +7,6 @@ + #define RO_EXCEPTION_TABLE_ALIGN 4 + #define RUNTIME_DISCARD_EXIT + +-#ifdef CONFIG_XIP_KERNEL +-#include "vmlinux-xip.lds.S" +-#else +- + #include + #define LOAD_OFFSET KERNEL_LINK_ADDR + +@@ -176,4 +172,3 @@ SECTIONS + + DISCARDS + } +-#endif /* CONFIG_XIP_KERNEL */ +diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c +index ee40ca01ac6636..4994df8dc92618 100644 +--- a/arch/riscv/mm/init.c ++++ b/arch/riscv/mm/init.c +@@ -41,20 +41,17 @@ u64 new_vmalloc[NR_CPUS / sizeof(u64) + 1]; + + struct kernel_mapping kernel_map __ro_after_init; + EXPORT_SYMBOL(kernel_map); +-#ifdef CONFIG_XIP_KERNEL +-#define kernel_map (*(struct kernel_mapping *)XIP_FIXUP(&kernel_map)) +-#endif + + #ifdef CONFIG_64BIT +-u64 satp_mode __ro_after_init = !IS_ENABLED(CONFIG_XIP_KERNEL) ? SATP_MODE_57 : SATP_MODE_39; ++u64 satp_mode __ro_after_init = SATP_MODE_57; + #else + u64 satp_mode __ro_after_init = SATP_MODE_32; + #endif + EXPORT_SYMBOL(satp_mode); + + #ifdef CONFIG_64BIT +-bool pgtable_l4_enabled __ro_after_init = !IS_ENABLED(CONFIG_XIP_KERNEL); +-bool pgtable_l5_enabled __ro_after_init = !IS_ENABLED(CONFIG_XIP_KERNEL); ++bool pgtable_l4_enabled __ro_after_init = true; ++bool pgtable_l5_enabled __ro_after_init = true; + EXPORT_SYMBOL(pgtable_l4_enabled); + EXPORT_SYMBOL(pgtable_l5_enabled); + #endif +@@ -197,9 +194,6 @@ void __init arch_mm_preinit(void) + + /* Limit the memory size via mem. */ + static phys_addr_t memory_limit; +-#ifdef CONFIG_XIP_KERNEL +-#define memory_limit (*(phys_addr_t *)XIP_FIXUP(&memory_limit)) +-#endif /* CONFIG_XIP_KERNEL */ + + static int __init early_mem(char *p) + { +@@ -223,10 +217,7 @@ static void __init setup_bootmem(void) + phys_addr_t max_mapped_addr; + phys_addr_t phys_ram_end, vmlinux_start; + +- if (IS_ENABLED(CONFIG_XIP_KERNEL)) +- vmlinux_start = __pa_symbol(&_sdata); +- else +- vmlinux_start = __pa_symbol(&_start); ++ vmlinux_start = __pa_symbol(&_start); + + memblock_enforce_memory_limit(memory_limit); + +@@ -246,12 +237,10 @@ static void __init setup_bootmem(void) + * Make sure we align the start of the memory on a PMD boundary so that + * at worst, we map the linear mapping with PMD mappings. + */ +- if (!IS_ENABLED(CONFIG_XIP_KERNEL)) { +- phys_ram_base = memblock_start_of_DRAM() & PMD_MASK; ++ phys_ram_base = memblock_start_of_DRAM() & PMD_MASK; + #ifdef CONFIG_SPARSEMEM_VMEMMAP +- vmemmap_start_pfn = round_down(phys_ram_base, VMEMMAP_ADDR_ALIGN) >> PAGE_SHIFT; ++ vmemmap_start_pfn = round_down(phys_ram_base, VMEMMAP_ADDR_ALIGN) >> PAGE_SHIFT; + #endif +- } + + /* + * In 64-bit, any use of __va/__pa before this point is wrong as we +@@ -366,13 +355,6 @@ static pte_t fixmap_pte[PTRS_PER_PTE] __page_aligned_bss; + + pgd_t early_pg_dir[PTRS_PER_PGD] __initdata __aligned(PAGE_SIZE); + +-#ifdef CONFIG_XIP_KERNEL +-#define pt_ops (*(struct pt_alloc_ops *)XIP_FIXUP(&pt_ops)) +-#define trampoline_pg_dir ((pgd_t *)XIP_FIXUP(trampoline_pg_dir)) +-#define fixmap_pte ((pte_t *)XIP_FIXUP(fixmap_pte)) +-#define early_pg_dir ((pgd_t *)XIP_FIXUP(early_pg_dir)) +-#endif /* CONFIG_XIP_KERNEL */ +- + static const pgprot_t protection_map[16] = { + [VM_NONE] = PAGE_NONE, + [VM_READ] = PAGE_READ, +@@ -469,32 +451,14 @@ static pmd_t trampoline_pmd[PTRS_PER_PMD] __page_aligned_bss; + static pmd_t fixmap_pmd[PTRS_PER_PMD] __page_aligned_bss; + static pmd_t early_pmd[PTRS_PER_PMD] __initdata __aligned(PAGE_SIZE); + +-#ifdef CONFIG_XIP_KERNEL +-#define trampoline_pmd ((pmd_t *)XIP_FIXUP(trampoline_pmd)) +-#define fixmap_pmd ((pmd_t *)XIP_FIXUP(fixmap_pmd)) +-#define early_pmd ((pmd_t *)XIP_FIXUP(early_pmd)) +-#endif /* CONFIG_XIP_KERNEL */ +- + static p4d_t trampoline_p4d[PTRS_PER_P4D] __page_aligned_bss; + static p4d_t fixmap_p4d[PTRS_PER_P4D] __page_aligned_bss; + static p4d_t early_p4d[PTRS_PER_P4D] __initdata __aligned(PAGE_SIZE); + +-#ifdef CONFIG_XIP_KERNEL +-#define trampoline_p4d ((p4d_t *)XIP_FIXUP(trampoline_p4d)) +-#define fixmap_p4d ((p4d_t *)XIP_FIXUP(fixmap_p4d)) +-#define early_p4d ((p4d_t *)XIP_FIXUP(early_p4d)) +-#endif /* CONFIG_XIP_KERNEL */ +- + static pud_t trampoline_pud[PTRS_PER_PUD] __page_aligned_bss; + static pud_t fixmap_pud[PTRS_PER_PUD] __page_aligned_bss; + static pud_t early_pud[PTRS_PER_PUD] __initdata __aligned(PAGE_SIZE); + +-#ifdef CONFIG_XIP_KERNEL +-#define trampoline_pud ((pud_t *)XIP_FIXUP(trampoline_pud)) +-#define fixmap_pud ((pud_t *)XIP_FIXUP(fixmap_pud)) +-#define early_pud ((pud_t *)XIP_FIXUP(early_pud)) +-#endif /* CONFIG_XIP_KERNEL */ +- + static pmd_t *__init get_pmd_virt_early(phys_addr_t pa) + { + /* Before MMU is enabled */ +@@ -765,21 +729,6 @@ static uintptr_t __meminit best_map_size(phys_addr_t pa, uintptr_t va, phys_addr + return PAGE_SIZE; + } + +-#ifdef CONFIG_XIP_KERNEL +-#define phys_ram_base (*(phys_addr_t *)XIP_FIXUP(&phys_ram_base)) +-extern char _xiprom[], _exiprom[], __data_loc; +- +-/* called from head.S with MMU off */ +-asmlinkage void __init __copy_data(void) +-{ +- void *from = (void *)(&__data_loc); +- void *to = (void *)CONFIG_PHYS_RAM_BASE; +- size_t sz = (size_t)((uintptr_t)(&_end) - (uintptr_t)(&_sdata)); +- +- memcpy(to, from, sz); +-} +-#endif +- + #ifdef CONFIG_STRICT_KERNEL_RWX + static __meminit pgprot_t pgprot_from_va(uintptr_t va) + { +@@ -815,7 +764,7 @@ static __meminit pgprot_t pgprot_from_va(uintptr_t va) + } + #endif /* CONFIG_STRICT_KERNEL_RWX */ + +-#if defined(CONFIG_64BIT) && !defined(CONFIG_XIP_KERNEL) ++#if defined(CONFIG_64BIT) + u64 __pi_set_satp_mode_from_cmdline(uintptr_t dtb_pa); + u64 __pi_set_satp_mode_from_fdt(uintptr_t dtb_pa); + +@@ -965,28 +914,6 @@ static __init void set_satp_mode(uintptr_t dtb_pa) + #error "setup_vm() is called from head.S before relocate so it should not use absolute addressing." + #endif + +-#ifdef CONFIG_XIP_KERNEL +-static void __init create_kernel_page_table(pgd_t *pgdir, +- __always_unused bool early) +-{ +- uintptr_t va, start_va, end_va; +- +- /* Map the flash resident part */ +- end_va = kernel_map.virt_addr + kernel_map.xiprom_sz; +- for (va = kernel_map.virt_addr; va < end_va; va += PMD_SIZE) +- create_pgd_mapping(pgdir, va, +- kernel_map.xiprom + (va - kernel_map.virt_addr), +- PMD_SIZE, PAGE_KERNEL_EXEC); +- +- /* Map the data in RAM */ +- start_va = kernel_map.virt_addr + (uintptr_t)&_sdata - (uintptr_t)&_start; +- end_va = kernel_map.virt_addr + kernel_map.size; +- for (va = start_va; va < end_va; va += PMD_SIZE) +- create_pgd_mapping(pgdir, va, +- kernel_map.phys_addr + (va - start_va), +- PMD_SIZE, PAGE_KERNEL); +-} +-#else + static void __init create_kernel_page_table(pgd_t *pgdir, bool early) + { + uintptr_t va, end_va; +@@ -999,7 +926,6 @@ static void __init create_kernel_page_table(pgd_t *pgdir, bool early) + early ? + PAGE_KERNEL_EXEC : pgprot_from_va(va)); + } +-#endif + + /* + * Setup a 4MB mapping that encompasses the device tree: for 64-bit kernel, +@@ -1141,27 +1067,11 @@ asmlinkage void __init setup_vm(uintptr_t dtb_pa) + + kernel_map.virt_addr = KERNEL_LINK_ADDR + kernel_map.virt_offset; + +-#ifdef CONFIG_XIP_KERNEL +- kernel_map.xiprom = (uintptr_t)CONFIG_XIP_PHYS_ADDR; +- kernel_map.xiprom_sz = (uintptr_t)(&_exiprom) - (uintptr_t)(&_xiprom); +- +- phys_ram_base = CONFIG_PHYS_RAM_BASE; +-#ifdef CONFIG_SPARSEMEM_VMEMMAP +- vmemmap_start_pfn = round_down(phys_ram_base, VMEMMAP_ADDR_ALIGN) >> PAGE_SHIFT; +-#endif +- kernel_map.phys_addr = (uintptr_t)CONFIG_PHYS_RAM_BASE; +- kernel_map.size = (uintptr_t)(&_end) - (uintptr_t)(&_start); +- +- kernel_map.va_kernel_xip_text_pa_offset = kernel_map.virt_addr - kernel_map.xiprom; +- kernel_map.va_kernel_xip_data_pa_offset = kernel_map.virt_addr - kernel_map.phys_addr +- + (uintptr_t)&_sdata - (uintptr_t)&_start; +-#else + kernel_map.phys_addr = (uintptr_t)(&_start); + kernel_map.size = (uintptr_t)(&_end) - kernel_map.phys_addr; + kernel_map.va_kernel_pa_offset = kernel_map.virt_addr - kernel_map.phys_addr; +-#endif + +-#if defined(CONFIG_64BIT) && !defined(CONFIG_XIP_KERNEL) ++#if defined(CONFIG_64BIT) + set_satp_mode(dtb_pa); + set_mmap_rnd_bits_max(); + #endif +@@ -1234,13 +1144,8 @@ asmlinkage void __init setup_vm(uintptr_t dtb_pa) + if (pgtable_l4_enabled) + create_pud_mapping(trampoline_pud, kernel_map.virt_addr, + (uintptr_t)trampoline_pmd, PUD_SIZE, PAGE_TABLE); +-#ifdef CONFIG_XIP_KERNEL +- create_pmd_mapping(trampoline_pmd, kernel_map.virt_addr, +- kernel_map.xiprom, PMD_SIZE, PAGE_KERNEL_EXEC); +-#else + create_pmd_mapping(trampoline_pmd, kernel_map.virt_addr, + kernel_map.phys_addr, PMD_SIZE, PAGE_KERNEL_EXEC); +-#endif + #else + /* Setup trampoline PGD */ + create_pgd_mapping(trampoline_pg_dir, kernel_map.virt_addr, +-- +2.53.0 + diff --git a/queue-6.18/s390-checksum-fix-csum_partial-without-vector-facili.patch b/queue-6.18/s390-checksum-fix-csum_partial-without-vector-facili.patch new file mode 100644 index 0000000000..4e24624a1a --- /dev/null +++ b/queue-6.18/s390-checksum-fix-csum_partial-without-vector-facili.patch @@ -0,0 +1,41 @@ +From 998350d98a4bb5c984015934dcae3f387033d6c4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 8 Jul 2026 12:02:14 +0200 +Subject: s390/checksum: Fix csum_partial() without vector facility + +From: Vasily Gorbik + +[ Upstream commit 4bb06b60d982355e22647b3d12d6619419f8c1fa ] + +Currently csum_partial() calls csum_copy() with copy=false and dst=NULL. +On machines without the vector facility, csum_copy() falls back to +cksm(dst, ...), causing the checksum to be calculated from address zero +instead of the source buffer. + +The VX implementation already checksums data loaded from src. Make the +fallback do the same by passing src to cksm(). + +Fixes: dcd3e1de9d17 ("s390/checksum: provide csum_partial_copy_nocheck()") +Reviewed-by: Heiko Carstens +Signed-off-by: Vasily Gorbik +Signed-off-by: Sasha Levin +--- + arch/s390/lib/csum-partial.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/s390/lib/csum-partial.c b/arch/s390/lib/csum-partial.c +index 458abd9bac7025..9d74ceff136c54 100644 +--- a/arch/s390/lib/csum-partial.c ++++ b/arch/s390/lib/csum-partial.c +@@ -23,7 +23,7 @@ static __always_inline __wsum csum_copy(void *dst, const void *src, int len, __w + if (!cpu_has_vx()) { + if (copy) + memcpy(dst, src, len); +- return cksm(dst, len, sum); ++ return cksm(src, len, sum); + } + kernel_fpu_begin(&vxstate, KERNEL_VXR_V16V23); + fpu_vlvgf(16, (__force u32)sum, 1); +-- +2.53.0 + diff --git a/queue-6.18/sched-ext-avoid-null-ptr-traversal-when-put_prev_tas.patch b/queue-6.18/sched-ext-avoid-null-ptr-traversal-when-put_prev_tas.patch new file mode 100644 index 0000000000..a5ad532cd2 --- /dev/null +++ b/queue-6.18/sched-ext-avoid-null-ptr-traversal-when-put_prev_tas.patch @@ -0,0 +1,61 @@ +From 58de3631610a2f09047fd9789edfd3369c5125a3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 6 Dec 2025 02:22:03 +0000 +Subject: sched/ext: Avoid null ptr traversal when ->put_prev_task() is called + with NULL next + +From: John Stultz + +[ Upstream commit 12b5cd99a05f7cbc2ceb88b3b9601d404ef2236a ] + +Early when trying to get sched_ext and proxy-exe working together, +I kept tripping over NULL ptr in put_prev_task_scx() on the line: + if (sched_class_above(&ext_sched_class, next->sched_class)) { + +Which was due to put_prev_task() passes a NULL next, calling: + prev->sched_class->put_prev_task(rq, prev, NULL); + +put_prev_task_scx() already guards for a NULL next in the +switch_class case, but doesn't seem to have a guard for +sched_class_above() check. + +I can't say I understand why this doesn't trip usually without +proxy-exec. And in newer kernels there are way fewer +put_prev_task(), and I can't easily reproduce the issue now +even with proxy-exec. + +But we still have one put_prev_task() call left in core.c that +seems like it could trip this, so I wanted to send this out for +consideration. + +tj: put_prev_task() can be called with NULL @next; however, when @p is +queued, that doesn't happen, so this condition shouldn't currently be +triggerable. The connection isn't straightforward or necessarily reliable, +so add the NULL check even if it can't currently be triggered. + +Link: http://lkml.kernel.org/r/20251206022218.1541878-1-jstultz@google.com +Signed-off-by: John Stultz +Reviewed-by: Andrea Righi +Signed-off-by: Tejun Heo +Stable-dep-of: b7d9c359e5cf ("sched_ext: Don't warn on core-sched forced idle in put_prev_task_scx()") +Signed-off-by: Sasha Levin +--- + kernel/sched/ext.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/kernel/sched/ext.c b/kernel/sched/ext.c +index d8280f87443310..d399494364c0a3 100644 +--- a/kernel/sched/ext.c ++++ b/kernel/sched/ext.c +@@ -2396,7 +2396,7 @@ static void put_prev_task_scx(struct rq *rq, struct task_struct *p, + * ops.enqueue() that @p is the only one available for this cpu, + * which should trigger an explicit follow-up scheduling event. + */ +- if (sched_class_above(&ext_sched_class, next->sched_class)) { ++ if (next && sched_class_above(&ext_sched_class, next->sched_class)) { + WARN_ON_ONCE(!(sch->ops.flags & SCX_OPS_ENQ_LAST)); + do_enqueue_task(rq, p, SCX_ENQ_LAST, -1); + } else { +-- +2.53.0 + diff --git a/queue-6.18/sched_ext-don-t-warn-on-core-sched-forced-idle-in-pu.patch b/queue-6.18/sched_ext-don-t-warn-on-core-sched-forced-idle-in-pu.patch new file mode 100644 index 0000000000..e9e00e0e21 --- /dev/null +++ b/queue-6.18/sched_ext-don-t-warn-on-core-sched-forced-idle-in-pu.patch @@ -0,0 +1,52 @@ +From cc160a64fc58eca600ed8c19c2e6c514acdff58e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 29 Jun 2026 12:55:48 -1000 +Subject: sched_ext: Don't warn on core-sched forced idle in + put_prev_task_scx() + +From: Tejun Heo + +[ Upstream commit b7d9c359e5cf867f7eb23df3bb1c6b9e58af24da ] + +put_prev_task_scx() warns when a runnable task drops to a lower sched_class +without SCX_OPS_ENQ_LAST, on the assumption that balance_one() would have +kept it running. Core scheduling breaks that: a forced-idle SMT sibling +reschedules through the core_pick fast path in pick_next_task(), which skips +pick_task_scx() and thus balance_one(), so a runnable task can drop to idle +with ENQ_LAST unset. + +Gate the warning on sched_cpu_cookie_match(): a cookie mismatch means core +scheduling forced the idle, while a match (or core scheduling off) still +catches a genuine missing-ENQ_LAST drop. + +Fixes: 7c65ae81ea86 ("sched_ext: Don't call put_prev_task_scx() before picking the next task") +Signed-off-by: Tejun Heo +Reviewed-by: Andrea Righi +Signed-off-by: Sasha Levin +--- + kernel/sched/ext.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/kernel/sched/ext.c b/kernel/sched/ext.c +index d399494364c0a3..83baf270888882 100644 +--- a/kernel/sched/ext.c ++++ b/kernel/sched/ext.c +@@ -2395,9 +2395,14 @@ static void put_prev_task_scx(struct rq *rq, struct task_struct *p, + * sched_class, %SCX_OPS_ENQ_LAST must be set. Tell + * ops.enqueue() that @p is the only one available for this cpu, + * which should trigger an explicit follow-up scheduling event. ++ * ++ * Core scheduling can force this CPU idle while @p stays ++ * runnable. @p's cookie then won't match the core's, so skip ++ * the warning in that case. + */ + if (next && sched_class_above(&ext_sched_class, next->sched_class)) { +- WARN_ON_ONCE(!(sch->ops.flags & SCX_OPS_ENQ_LAST)); ++ WARN_ON_ONCE(sched_cpu_cookie_match(rq, p) && ++ !(sch->ops.flags & SCX_OPS_ENQ_LAST)); + do_enqueue_task(rq, p, SCX_ENQ_LAST, -1); + } else { + do_enqueue_task(rq, p, 0, -1); +-- +2.53.0 + diff --git a/queue-6.18/scsi-core-wake-eh-reliably-when-using-scsi_schedule_.patch b/queue-6.18/scsi-core-wake-eh-reliably-when-using-scsi_schedule_.patch new file mode 100644 index 0000000000..29ddb777de --- /dev/null +++ b/queue-6.18/scsi-core-wake-eh-reliably-when-using-scsi_schedule_.patch @@ -0,0 +1,123 @@ +From 1ff88d3291818e5cf10ecea0d61d338f4ed2695e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 15 Jun 2026 13:46:30 -0400 +Subject: scsi: core: wake eh reliably when using scsi_schedule_eh + +From: David Jeffery + +[ Upstream commit dccf3b1798b70f94e958b3d00b83010399e6fb05 ] + +Drivers which use the scsi_schedule_eh function to run the error handler +currently risk the error handler thread never waking once all commands are +timed out or inactive. There is no enforced memory order between setting +the host into error recovery state and counting busy commands. This can +result in a race with scsi_dec_host_busy where neither CPU sees both +conditions of all commands inactive and the host error state to request +waking the error handler. + +To fix this, run the scsi_schedule_eh's scsi_eh_wakeup from a new work item +which will use rcu to ensure scsi_schedule_eh's call to scsi_host_busy will +occur after the error state is globally visible and will be seen by any +current scsi_dec_host_busy callers. + +Fixes: 6eb045e092ef ("scsi: core: avoid host-wide host_busy counter for scsi_mq") +Signed-off-by: David Jeffery +Link: https://patch.msgid.link/20260615174630.11492-1-djeffery@redhat.com +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +--- + drivers/scsi/hosts.c | 2 ++ + drivers/scsi/scsi_error.c | 22 +++++++++++++++++++++- + drivers/scsi/scsi_priv.h | 1 + + include/scsi/scsi_host.h | 3 +++ + 4 files changed, 27 insertions(+), 1 deletion(-) + +diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c +index 17173239301e61..a1055fe4922f64 100644 +--- a/drivers/scsi/hosts.c ++++ b/drivers/scsi/hosts.c +@@ -343,6 +343,7 @@ static void scsi_host_dev_release(struct device *dev) + /* Wait for functions invoked through call_rcu(&scmd->rcu, ...) */ + rcu_barrier(); + ++ cancel_work_sync(&shost->eh_work); + if (shost->tmf_work_q) + destroy_workqueue(shost->tmf_work_q); + if (shost->ehandler) +@@ -408,6 +409,7 @@ struct Scsi_Host *scsi_host_alloc(const struct scsi_host_template *sht, int priv + INIT_LIST_HEAD(&shost->starved_list); + init_waitqueue_head(&shost->host_wait); + mutex_init(&shost->scan_mutex); ++ INIT_WORK(&shost->eh_work, scsi_rcu_eh_wakeup); + + index = ida_alloc(&host_index_ida, GFP_KERNEL); + if (index < 0) { +diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c +index 2fd4ca96b3089d..13d46b6e0359e2 100644 +--- a/drivers/scsi/scsi_error.c ++++ b/drivers/scsi/scsi_error.c +@@ -73,6 +73,26 @@ void scsi_eh_wakeup(struct Scsi_Host *shost, unsigned int busy) + } + } + ++void scsi_rcu_eh_wakeup(struct work_struct *work) ++{ ++ struct Scsi_Host *shost = container_of(work, struct Scsi_Host, eh_work); ++ unsigned long flags; ++ unsigned int busy; ++ ++ /* ++ * Ensure any running scsi_dec_host_busy has completed its rcu section ++ * so changes to host state and host_eh_scheduled are visible to all ++ * future calls of scsi_dec_host_busy ++ */ ++ synchronize_rcu(); ++ ++ busy = scsi_host_busy(shost); ++ ++ spin_lock_irqsave(shost->host_lock, flags); ++ scsi_eh_wakeup(shost, busy); ++ spin_unlock_irqrestore(shost->host_lock, flags); ++} ++ + /** + * scsi_schedule_eh - schedule EH for SCSI host + * @shost: SCSI host to invoke error handling on. +@@ -88,7 +108,7 @@ void scsi_schedule_eh(struct Scsi_Host *shost) + if (scsi_host_set_state(shost, SHOST_RECOVERY) == 0 || + scsi_host_set_state(shost, SHOST_CANCEL_RECOVERY) == 0) { + shost->host_eh_scheduled++; +- scsi_eh_wakeup(shost, scsi_host_busy(shost)); ++ queue_work(shost->tmf_work_q, &shost->eh_work); + } + + spin_unlock_irqrestore(shost->host_lock, flags); +diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h +index 5b2b19f5e8ec8a..68866b18a60058 100644 +--- a/drivers/scsi/scsi_priv.h ++++ b/drivers/scsi/scsi_priv.h +@@ -91,6 +91,7 @@ extern enum blk_eh_timer_return scsi_timeout(struct request *req); + extern int scsi_error_handler(void *host); + extern enum scsi_disposition scsi_decide_disposition(struct scsi_cmnd *cmd); + extern void scsi_eh_wakeup(struct Scsi_Host *shost, unsigned int busy); ++extern void scsi_rcu_eh_wakeup(struct work_struct *work); + extern void scsi_eh_scmd_add(struct scsi_cmnd *); + void scsi_eh_ready_devs(struct Scsi_Host *shost, + struct list_head *work_q, +diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h +index f5a24326123605..936403c15e53d3 100644 +--- a/include/scsi/scsi_host.h ++++ b/include/scsi/scsi_host.h +@@ -714,6 +714,9 @@ struct Scsi_Host { + */ + struct device *dma_dev; + ++ /* Used for an rcu-synchronizing eh wakeup */ ++ struct work_struct eh_work; ++ + /* Delay for runtime autosuspend */ + int rpm_autosuspend_delay; + +-- +2.53.0 + diff --git a/queue-6.18/sctp-fix-auth_hmacs-array-size-in-struct-sctp_cookie.patch b/queue-6.18/sctp-fix-auth_hmacs-array-size-in-struct-sctp_cookie.patch new file mode 100644 index 0000000000..cf83adec84 --- /dev/null +++ b/queue-6.18/sctp-fix-auth_hmacs-array-size-in-struct-sctp_cookie.patch @@ -0,0 +1,56 @@ +From d691c900016dba20728097018f0e72793251a8eb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 10 Jul 2026 14:12:35 -0400 +Subject: sctp: fix auth_hmacs array size in struct sctp_cookie + +From: Xin Long + +[ Upstream commit e0b5252a59383b77d1b8dbeda00b7184dd95f4d3 ] + +The auth_hmacs array in struct sctp_cookie is supposed to store a complete +SCTP_AUTH_HMAC_ALGO parameter, which consists of a struct sctp_paramhdr +followed by N HMAC identifiers. + +However, the array size was calculated using an extra 2 bytes instead of +sizeof(struct sctp_paramhdr), which is 4 bytes. When four HMAC identifiers +are configured, the HMAC-ALGO parameter stored in the endpoint is larger +than the auth_hmacs buffer in the cookie. + +As a result, sctp_association_init() copies beyond the end of auth_hmacs +when initializing the association, corrupting the adjacent auth_chunks +field. This can lead to an invalid HMAC identifier being accepted and later +cause an out-of-bounds read in sctp_auth_get_hmac(). + +Fix the array size calculation by including the full SCTP parameter header +size. + +Fixes: 1f485649f529 ("[SCTP]: Implement SCTP-AUTH internals") +Reported-by: Yuan Tan +Reported-by: Xin Liu +Reported-by: Zihan Xi +Reported-by: Ren Wei +Signed-off-by: Xin Long +Link: https://patch.msgid.link/634a0de0d5de29532915e6d47c92a0cbc206e03f.1783707155.git.lucien.xin@gmail.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + include/net/sctp/structs.h | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h +index 2ae390219efdd3..4bbba29f7341ee 100644 +--- a/include/net/sctp/structs.h ++++ b/include/net/sctp/structs.h +@@ -316,7 +316,8 @@ struct sctp_cookie { + + __u8 auth_random[sizeof(struct sctp_paramhdr) + + SCTP_AUTH_RANDOM_LENGTH]; +- __u8 auth_hmacs[SCTP_AUTH_NUM_HMACS * sizeof(__u16) + 2]; ++ __u8 auth_hmacs[sizeof(struct sctp_paramhdr) + ++ SCTP_AUTH_NUM_HMACS * sizeof(__u16)]; + __u8 auth_chunks[sizeof(struct sctp_paramhdr) + SCTP_AUTH_MAX_CHUNKS]; + + /* This is a shim for my peer's INIT packet, followed by +-- +2.53.0 + diff --git a/queue-6.18/selftests-alsa-fix-memory-leak-in-find_controls-erro.patch b/queue-6.18/selftests-alsa-fix-memory-leak-in-find_controls-erro.patch new file mode 100644 index 0000000000..1f6dd89c35 --- /dev/null +++ b/queue-6.18/selftests-alsa-fix-memory-leak-in-find_controls-erro.patch @@ -0,0 +1,41 @@ +From dca872c32386ede5a6542d06907aedb185da24c3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 4 Jul 2026 16:27:36 +0530 +Subject: selftests/alsa: Fix memory leak in find_controls error path + +From: Malaya Kumar Rout + +[ Upstream commit cb89f0c1aed02eb233c4271f76f830b37e222ff6 ] + +In find_controls(), card_data is allocated with malloc() but when +snd_ctl_open_lconf() fails, the code jumps to next_card without +freeing the allocated memory. This results in a memory leak for +each card where snd_ctl_open_lconf() fails. + +Add free(card_data) before goto next_card to ensure proper cleanup +of the allocated memory in the error path. + +Fixes: 5aaf9efffc57 ("kselftest: alsa: Add simplistic test for ALSA mixer controls kselftest") +Signed-off-by: Malaya Kumar Rout +Link: https://patch.msgid.link/20260704105736.94874-1-malayarout91@gmail.com +Signed-off-by: Takashi Iwai +Signed-off-by: Sasha Levin +--- + tools/testing/selftests/alsa/mixer-test.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/tools/testing/selftests/alsa/mixer-test.c b/tools/testing/selftests/alsa/mixer-test.c +index e113dafa5c2464..cfb7968fbac075 100644 +--- a/tools/testing/selftests/alsa/mixer-test.c ++++ b/tools/testing/selftests/alsa/mixer-test.c +@@ -84,6 +84,7 @@ static void find_controls(void) + if (err < 0) { + ksft_print_msg("Failed to get hctl for card %d: %s\n", + card, snd_strerror(err)); ++ free(card_data); + goto next_card; + } + +-- +2.53.0 + diff --git a/queue-6.18/series b/queue-6.18/series index 05c7a67a5a..5bd94d2e63 100644 --- a/queue-6.18/series +++ b/queue-6.18/series @@ -30,3 +30,115 @@ xprtrdma-clear-receive-side-ownership-pointers-on-re.patch input-ims-pcu-fix-heap-buffer-overflow-in-ims_pcu_pr.patch input-ims-pcu-fix-logic-error-in-packet-reset.patch fuse-fix-writeback-array-overflow-when-max_pages-is-.patch +arm64-tegra-remove-fallback-compatible-for-gpcdma.patch +arm64-tegra-fix-cpu-compatible-string-to-cortex-a78a.patch +net-dropreason-add-skb_drop_reason_recursion_limit.patch +net-plumb-drop-reasons-to-__dev_queue_xmit.patch +xfrm-propagate-einprogress-from-validate_xmit_xfrm.patch +xfrm-fix-stale-skb-prev-after-async-crypto-steals-a-.patch +firmware-arm_ffa-respect-firmware-advertised-rx-tx-b.patch +ib-mad-drop-unmatched-rmpp-responses-before-reassemb.patch +mtd-mtdswap-remove-debugfs-stats-file-on-teardown.patch +mtd-nand-mtk-ecc-stop-on-ecc-idle-timeouts.patch +btrfs-reject-free-space-cache-with-more-entries-than.patch +btrfs-fix-root-leak-if-its-reloc-root-is-unexpected-.patch +btrfs-use-bool-type-for-btrfs_path-members-used-as-b.patch +btrfs-fallback-to-transaction-csum-tree-on-a-commit-.patch +firmware-arm_ffa-fix-null-dereference-in-ffa_partiti.patch +sched-ext-avoid-null-ptr-traversal-when-put_prev_tas.patch +sched_ext-don-t-warn-on-core-sched-forced-idle-in-pu.patch +xfrm-reject-optional-iptfs-templates-in-outbound-pol.patch +rdma-cma-fix-hardware-address-comparison-length-in-n.patch +rdma-umem-add-pinned-revocable-dmabuf-import-interfa.patch +rdma-irdma-prevent-rereg_mr-for-non-mem-regions.patch +rdma-irdma-remove-redundant-legacy_mode-checks.patch +rdma-irdma-prevent-user-triggered-null-deref-on-qp-c.patch +rdma-erdma-initialize-ret-for-empty-receive-wr-lists.patch +rdma-mana_ib-initialize-err-for-empty-send-wr-lists.patch +rdma-hns-fix-potential-integer-overflow-in-mhop-hem-.patch +rdma-siw-publish-qp-after-initialization.patch +mtd-fix-double-free-and-warn_on-in-add_mtd_device-er.patch +selftests-alsa-fix-memory-leak-in-find_controls-erro.patch +rdma-irdma-prevent-overflows-in-memory-contiguity-ch.patch +xfrm-clear-mode-callbacks-after-failed-mode-setup.patch +xfrm-iptfs-propagate-skbfl_shared_frag-in-iptfs_skb_.patch +xfrm6-clear-dst.dev-on-error-to-avoid-double-netdev_.patch +xfrm-policy-preallocate-inexact-bins-before-xfrm_has.patch +wifi-cfg80211-cancel-sched-scan-results-work-on-unre.patch +wifi-ipw2100-fix-potential-memory-leak-in-ipw2100_pc.patch +wifi-cfg80211-fix-an-error-handling-path-in-cfg80211.patch +wifi-mac80211_hwsim-clamp-virtio-rx-length-before-sk.patch +wifi-mac80211-fix-unsol_bcast_probe_resp-double-free.patch +wifi-mac80211-fix-fils_discovery-double-free-on-allo.patch +wifi-libertas-fix-memory-leak-in-helper_firmware_cb.patch +wifi-mac80211-defer-link-rx-stats-percpu-free-to-rcu.patch +wifi-p54-validate-rx-frame-length-in-p54_rx_eeprom_r.patch +wifi-cfg80211-convert-pmsr_free_wk-to-wiphy_work-to-.patch +wifi-nl80211-free-rnr-data-on-mbssid-mismatch.patch +wifi-cfg80211-derive-s1g-beacon-tsf-from-s1g-fields.patch +wifi-nl80211-validate-nested-mbssid-ie-blobs.patch +wifi-nl80211-constrain-mbssid-tx-link-id-range.patch +wifi-cfg80211-validate-pmsr-measurement-type-data.patch +wifi-cfg80211-validate-pmsr-ftm-preamble-range.patch +wifi-cfg80211-reject-unsupported-pmsr-ftm-location-r.patch +wifi-mac80211-avoid-non-s1g-aid-fallback-for-s1g-ass.patch +wifi-mac80211-free-ap_vlan-bc_buf-skbs-outside-irq-l.patch +wifi-brcmfmac-initialize-sdio-data-work-before-clean.patch +wifi-cfg80211-bound-element-id-read-when-checking-no.patch +firmware-arm_ffa-fix-out-of-bound-writes-in-ffa_setu.patch +firmware-arm_ffa-fix-endpoint-memory-access-descript.patch +asoc-meson-aiu-fifo-spdif-soft-reset-the-s-pdif-data.patch +asoc-amd-ps-disable-msi-on-resume-in-acp-pci-driver.patch +asoc-amd-ps-fix-wrong-acp-version-string-in-pci_requ.patch +asoc-amd-ps-replace-bitwise-or-with-logical-or-in-ir.patch +asoc-cs42l43-correct-report-for-forced-microphone-ja.patch +asoc-tas2562-fix-deprecated-shut-down-gpio-always-cl.patch +firmware-arm_scmi-rate-limit-queue-full-warnings-in-.patch +cpufreq-make-cpufreq_update_pressure-fall-back-to-cp.patch +ppp-defer-channel-free-to-an-rcu-grace-period-to-fix.patch +ipv4-fib-free-fib_alias-with-kfree_rcu-on-insert-err.patch +net-iucv-take-a-reference-on-the-socket-found-in-afi.patch +udmabuf-ensure-to-perform-cache-synchronisation-in-b.patch +scsi-core-wake-eh-reliably-when-using-scsi_schedule_.patch +ata-sata_dwc_460ex-enable-sata-interrupts-only-after.patch +ata-sata_dwc_460ex-use-platform_get_irq.patch +ata-sata_dwc_460ex-fix-clear_interrupt_bit-clearing-.patch +ata-sata_dwc_460ex-fix-infinite-loop-in-ncq-tag-comp.patch +accel-ivpu-fix-wrong-register-read-in-lnl-failure-di.patch +alsa-usb-audio-skip-dsd-quirk-for-musical-fidelity-m.patch +bluetooth-qca-fix-nvm-tag-length-underflow-in-tlv-pa.patch +bluetooth-mgmt-revalidate-load_conn_param-queued-upd.patch +bluetooth-hci_sync-extend-conn_hash-lookup-critical-.patch +bluetooth-mgmt-fix-locking-in-unpair_device-disconne.patch +bluetooth-mgmt-hold-reference-for-hci_conn-in-mgmt_p.patch +bluetooth-hci_qca-clear-memdump-state-on-invalid-dum.patch +smb-client-handle-overlapping-allocated-ranges-in-fa.patch +riscv-enable-kernel-access-to-shadow-stack-memory-vi.patch +riscv-export-kaslr-offset-and-satp-in-vmcoreinfo-elf.patch +riscv-remove-support-for-xip-kernel.patch +riscv-gate-function_alignment_4b-on-dynamic_ftrace.patch +drm-i915-gt-use-correct-selftest-config-symbol.patch +can-raw-add-locking-for-raw-flags-bitfield.patch +powerpc-85xx-add-fsl-ifc-to-common-device-ids.patch +powerpc-time-prepare-to-stop-elapsing-in-dynticks-id.patch +powerpc-vtime-initialize-starttime-at-boot-for-nativ.patch +bpf-sockmap-reject-unhashed-udp-sockets-on-sockmap-u.patch +drm-panthor-check-debugfs-gem-lock-initialization.patch +s390-checksum-fix-csum_partial-without-vector-facili.patch +riscv-hwprobe-avoid-uninitialized-read-in-hwprobe_ge.patch +can-j1939-fix-lockless-local-destination-check.patch +drm-xe-allow-the-caller-to-pass-guc_buf_cache-size.patch +drm-xe-sa-shadow-buffer-support-in-the-sub-allocator.patch +drm-xe-vf-shadow-buffer-management-for-ccs-read-writ.patch +drm-xe-vf-fix-vf-ccs-attach-detach-race-with-in-flig.patch +drm-xe-wopcm-fix-wopcm-size-for-lnl.patch +ksmbd-pin-conn-during-async-oplock-break-notificatio.patch +ksmbd-validate-compound-request-size-before-reading-.patch +drm-i915-wm-clear-the-plane-ddb_y-entries-on-plane-d.patch +drm-i915-selftests-fix-gt-pm-sort-comparators.patch +accel-amdxdna-fix-use-after-free-of-mm_struct-in-job.patch +tcp-fix-time_wait-socket-reference-leak-on-psp-polic.patch +dpll-fix-null-pointer-dereference-in-dpll_msg_add_pi.patch +net-sched-act_tunnel_key-defer-dst_release-to-rcu-ca.patch +sctp-fix-auth_hmacs-array-size-in-struct-sctp_cookie.patch +mpls-fix-null-deref-in-mpls_valid_fib_dump_req-on-co.patch diff --git a/queue-6.18/smb-client-handle-overlapping-allocated-ranges-in-fa.patch b/queue-6.18/smb-client-handle-overlapping-allocated-ranges-in-fa.patch new file mode 100644 index 0000000000..7f3823a8ac --- /dev/null +++ b/queue-6.18/smb-client-handle-overlapping-allocated-ranges-in-fa.patch @@ -0,0 +1,110 @@ +From 858f8c41f18865f7a79fdf9353d296b976abe900 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 3 Jul 2026 13:32:56 +0800 +Subject: smb/client: handle overlapping allocated ranges in fallocate + +From: Huiwen He + +[ Upstream commit b09ae45d85dc816987a71db9eebc54b0ae288e94 ] + +smb3_simple_fallocate_range() can skip holes when an allocated range +returned by the server starts before the current fallocate offset. The +skipped hole is not zero-filled, but fallocate still returns success. A +later write to that hole may therefore fail with ENOSPC. + +The function queries allocated ranges so that it can preserve existing +contents and write zeroes only into holes. However, the server may return +a range that starts before the current fallocate offset. + +For example, assume the fallocate request is [100, 400) and the only +allocated range returned by the server is [0, 200): + + Request: [100, 400) + Server range: [ 0, 200) allocated + + Correct: + [100, 200) allocated data, skip + [200, 400) hole, zero-fill + + Current: + [100, 300) skipped + [300, 400) zero-filled afterwards + +The current code adds the full server range length, 200, to the current +offset 100 and moves to 300. As a result, the hole in [200, 300) is +skipped without being zero-filled. + +Fix this by advancing only over the part of the allocated range that +overlaps the current fallocate offset. Ignore ranges that end before the +current offset and reject ranges whose end offset overflows. + +This also prevents a malformed range length from causing an out-of-bounds +zero-buffer read. + +Fixes: 966a3cb7c7db ("cifs: improve fallocate emulation") +Signed-off-by: Huiwen He +Reviewed-by: ChenXiaoSong +Signed-off-by: Steve French +Signed-off-by: Sasha Levin +--- + fs/smb/client/smb2ops.c | 25 ++++++++++++++++++------- + 1 file changed, 18 insertions(+), 7 deletions(-) + +diff --git a/fs/smb/client/smb2ops.c b/fs/smb/client/smb2ops.c +index 786a7e963f1ff4..5bbe98dc0529b9 100644 +--- a/fs/smb/client/smb2ops.c ++++ b/fs/smb/client/smb2ops.c +@@ -3546,6 +3546,7 @@ static int smb3_simple_fallocate_range(unsigned int xid, + struct file_allocated_range_buffer in_data, *out_data = NULL, *tmp_data; + u32 out_data_len; + char *buf = NULL; ++ u64 range_start, range_len, range_end; + loff_t l; + int rc; + +@@ -3582,13 +3583,21 @@ static int smb3_simple_fallocate_range(unsigned int xid, + goto out; + } + +- if (off < le64_to_cpu(tmp_data->file_offset)) { ++ range_start = le64_to_cpu(tmp_data->file_offset); ++ range_len = le64_to_cpu(tmp_data->length); ++ if (check_add_overflow(range_start, range_len, &range_end) || ++ range_end > S64_MAX) { ++ rc = -EINVAL; ++ goto out; ++ } ++ ++ if (off < range_start) { + /* + * We are at a hole. Write until the end of the region + * or until the next allocated data, + * whichever comes next. + */ +- l = le64_to_cpu(tmp_data->file_offset) - off; ++ l = range_start - off; + if (len < l) + l = len; + rc = smb3_simple_fallocate_write_range(xid, tcon, +@@ -3605,11 +3614,13 @@ static int smb3_simple_fallocate_range(unsigned int xid, + * until the end of the data or the end of the region + * we are supposed to fallocate, whichever comes first. + */ +- l = le64_to_cpu(tmp_data->length); +- if (len < l) +- l = len; +- off += l; +- len -= l; ++ if (off < range_end) { ++ l = range_end - off; ++ if (len < l) ++ l = len; ++ off += l; ++ len -= l; ++ } + + tmp_data = &tmp_data[1]; + out_data_len -= sizeof(struct file_allocated_range_buffer); +-- +2.53.0 + diff --git a/queue-6.18/tcp-fix-time_wait-socket-reference-leak-on-psp-polic.patch b/queue-6.18/tcp-fix-time_wait-socket-reference-leak-on-psp-polic.patch new file mode 100644 index 0000000000..753ba6a8d5 --- /dev/null +++ b/queue-6.18/tcp-fix-time_wait-socket-reference-leak-on-psp-polic.patch @@ -0,0 +1,62 @@ +From 47031beac7caa02b94056aea285f72ad21da5d5f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 10 Jul 2026 18:13:17 +0000 +Subject: tcp: fix TIME_WAIT socket reference leak on PSP policy failure + +From: Eric Dumazet + +[ Upstream commit 2c1931a81122c3cdc4c89448fe0442c69e21c0d5 ] + +Release the TIME_WAIT socket reference and jump to discard_it +upon PSP policy failure in both IPv4 and IPv6 receive paths. +This prevents a memory leak of tcp_tw_bucket structures. + +Fixes: 659a2899a57d ("tcp: add datapath logic for PSP with inline key exchange") +Signed-off-by: Eric Dumazet +Reviewed-by: Kuniyuki Iwashima +Reviewed-by: Daniel Zahka +Link: https://patch.msgid.link/20260710181317.4060230-1-edumazet@google.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/ipv4/tcp_ipv4.c | 6 ++++-- + net/ipv6/tcp_ipv6.c | 6 ++++-- + 2 files changed, 8 insertions(+), 4 deletions(-) + +diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c +index f0106c2be1cf23..a1ed4fa264836d 100644 +--- a/net/ipv4/tcp_ipv4.c ++++ b/net/ipv4/tcp_ipv4.c +@@ -2452,8 +2452,10 @@ int tcp_v4_rcv(struct sk_buff *skb) + } + + drop_reason = psp_twsk_rx_policy_check(inet_twsk(sk), skb); +- if (drop_reason) +- break; ++ if (drop_reason) { ++ inet_twsk_put(inet_twsk(sk)); ++ goto discard_it; ++ } + } + /* to ACK */ + fallthrough; +diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c +index 59b5900dd42bd6..ad9f69d49f2e3d 100644 +--- a/net/ipv6/tcp_ipv6.c ++++ b/net/ipv6/tcp_ipv6.c +@@ -1984,8 +1984,10 @@ INDIRECT_CALLABLE_SCOPE int tcp_v6_rcv(struct sk_buff *skb) + } + + drop_reason = psp_twsk_rx_policy_check(inet_twsk(sk), skb); +- if (drop_reason) +- break; ++ if (drop_reason) { ++ inet_twsk_put(inet_twsk(sk)); ++ goto discard_it; ++ } + } + /* to ACK */ + fallthrough; +-- +2.53.0 + diff --git a/queue-6.18/udmabuf-ensure-to-perform-cache-synchronisation-in-b.patch b/queue-6.18/udmabuf-ensure-to-perform-cache-synchronisation-in-b.patch new file mode 100644 index 0000000000..57f0d328ff --- /dev/null +++ b/queue-6.18/udmabuf-ensure-to-perform-cache-synchronisation-in-b.patch @@ -0,0 +1,68 @@ +From eddc2266bc4c0b8221f4d2b3d504b9903fa1c8d1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 27 Jun 2026 12:57:25 +0200 +Subject: udmabuf: Ensure to perform cache synchronisation in + begin_cpu_udmabuf() + +From: Robert Mader + +[ Upstream commit 1d0e25c1ddf2063c499264fb2ba0fa6a3e4f8a00 ] + +The message of commit 504e2b4ab97a ("dma-buf/udmabuf: skip redundant cpu sync to +fix cacheline EEXIST warning") says: + +> The CPU sync at map/unmap time is also redundant for udmabuf: +> begin_cpu_udmabuf() and end_cpu_udmabuf() already perform explicit +> cache synchronization via dma_sync_sgtable_for_cpu/device() when CPU +> access is requested through the dma-buf interface. + +This, however, does not apply to the first time begin_cpu_udmabuf() is +called on an udmabuf, in which case the implementation previously relied on +get_sg_table() to perform the cache synchronisation. + +Ensure to call dma_sync_sgtable_for_cpu() in that case as well. + +Fixes: 504e2b4ab97a ("dma-buf/udmabuf: skip redundant cpu sync to fix cacheline EEXIST warning") +Signed-off-by: Robert Mader +Reviewed-by: Mikhail Gavrilov +Signed-off-by: Vivek Kasireddy +Link: https://patch.msgid.link/20260627105725.9083-1-robert.mader@collabora.com +Signed-off-by: Sasha Levin +--- + drivers/dma-buf/udmabuf.c | 9 +++++---- + 1 file changed, 5 insertions(+), 4 deletions(-) + +diff --git a/drivers/dma-buf/udmabuf.c b/drivers/dma-buf/udmabuf.c +index be47d1ff6c508b..30b0f0c72e928c 100644 +--- a/drivers/dma-buf/udmabuf.c ++++ b/drivers/dma-buf/udmabuf.c +@@ -249,21 +249,22 @@ static int begin_cpu_udmabuf(struct dma_buf *buf, + { + struct udmabuf *ubuf = buf->priv; + struct device *dev = ubuf->device->this_device; +- int ret = 0; + + if (!ubuf->sg) { + ubuf->sg = get_sg_table(dev, buf, direction); + if (IS_ERR(ubuf->sg)) { ++ int ret; ++ + ret = PTR_ERR(ubuf->sg); + ubuf->sg = NULL; ++ return ret; + } else { + ubuf->sg_dir = direction; + } +- } else { +- dma_sync_sgtable_for_cpu(dev, ubuf->sg, direction); + } + +- return ret; ++ dma_sync_sgtable_for_cpu(dev, ubuf->sg, direction); ++ return 0; + } + + static int end_cpu_udmabuf(struct dma_buf *buf, +-- +2.53.0 + diff --git a/queue-6.18/wifi-brcmfmac-initialize-sdio-data-work-before-clean.patch b/queue-6.18/wifi-brcmfmac-initialize-sdio-data-work-before-clean.patch new file mode 100644 index 0000000000..bd93b6fa13 --- /dev/null +++ b/queue-6.18/wifi-brcmfmac-initialize-sdio-data-work-before-clean.patch @@ -0,0 +1,61 @@ +From 87467d11d656e2b12af6f971b6b9a243bcf713fd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 19 Jun 2026 14:44:01 +0800 +Subject: wifi: brcmfmac: initialize SDIO data work before cleanup + +From: Runyu Xiao + +[ Upstream commit 2a665946e0407a05a3f81bd56a08553c446498e0 ] + +brcmf_sdio_probe() stores the newly allocated bus in sdiodev->bus before +allocating the ordered workqueue. If that allocation fails, the function +jumps to fail and calls brcmf_sdio_remove(). + +brcmf_sdio_remove() unconditionally cancels bus->datawork. Initialize the +work item before the first failure path that can reach brcmf_sdio_remove(), +so the cleanup path always observes a valid work object. + +This issue was found by our static analysis tool and then confirmed by +manual review of the probe error path and the remove-time work drain. The +problem pattern is an early setup failure that reaches a cleanup helper +which cancels an embedded work item before its initializer has run. + +A QEMU PoC forced alloc_ordered_workqueue() to fail at the same point in +brcmf_sdio_probe(), before INIT_WORK(&bus->datawork) is reached. The +resulting fail path calls brcmf_sdio_remove(), and DEBUG_OBJECTS reports +the invalid work drain with brcmf_sdio_probe() and brcmf_sdio_remove() in +the stack. + +Fixes: 9982464379e8 ("brcmfmac: make sdio suspend wait for threads to freeze") +Signed-off-by: Runyu Xiao +Acked-by: Arend van Spriel +Link: https://patch.msgid.link/20260619064401.1048976-1-runyu.xiao@seu.edu.cn +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c +index a0e88dbaaebe67..9ab62a2667c7b6 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c +@@ -4465,6 +4465,7 @@ int brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev) + bus->sdiodev = sdiodev; + sdiodev->bus = bus; + skb_queue_head_init(&bus->glom); ++ INIT_WORK(&bus->datawork, brcmf_sdio_dataworker); + bus->txbound = BRCMF_TXBOUND; + bus->rxbound = BRCMF_RXBOUND; + bus->txminmax = BRCMF_TXMINMAX; +@@ -4479,7 +4480,6 @@ int brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev) + goto fail; + } + brcmf_sdiod_freezer_count(sdiodev); +- INIT_WORK(&bus->datawork, brcmf_sdio_dataworker); + bus->brcmf_wq = wq; + + /* attempt to attach to the dongle */ +-- +2.53.0 + diff --git a/queue-6.18/wifi-cfg80211-bound-element-id-read-when-checking-no.patch b/queue-6.18/wifi-cfg80211-bound-element-id-read-when-checking-no.patch new file mode 100644 index 0000000000..3073a6f980 --- /dev/null +++ b/queue-6.18/wifi-cfg80211-bound-element-id-read-when-checking-no.patch @@ -0,0 +1,58 @@ +From c5d19719dae4fff34ae3dcf48f518c5063431a4c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 7 Jul 2026 18:48:28 +0900 +Subject: wifi: cfg80211: bound element ID read when checking non-inheritance +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: HE WEI (ギカク) + +[ Upstream commit cb8afea4655ff004fa7feee825d5c79783525383 ] + +cfg80211_is_element_inherited() reads the first data octet of the +candidate element (id = elem->data[0]) to look it up in an extension +non-inheritance list. It does so after testing elem->id, but without +verifying that the element actually has a data octet. A zero-length +extension element (WLAN_EID_EXTENSION with length 0) therefore makes it +read one octet past the end of the element. + +_ieee802_11_parse_elems_full() runs this check for every element of a +frame once a non-inheritance context exists -- e.g. while parsing a +per-STA profile of a Multi-Link element in a (re)association response, +or a non-transmitted BSS profile -- so a crafted frame from an AP can +trigger a one-octet slab-out-of-bounds read during element parsing: + + BUG: KASAN: slab-out-of-bounds in cfg80211_is_element_inherited + Read of size 1 ... in net/wireless/scan.c + +Return early (treat the element as inherited) when an extension element +carries no data, mirroring the existing handling of empty ID lists. + +The bug was found by fuzzing ieee802_11_parse_elems_full() under KASAN. + +Fixes: f7dacfb11475 ("cfg80211: support non-inheritance element") +Signed-off-by: HE WEI (ギカク) +Link: https://patch.msgid.link/20260707094828.16465-1-skyexpoc@gmail.com +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + net/wireless/scan.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/wireless/scan.c b/net/wireless/scan.c +index af1e2ce1628dae..11f7a27bb7046c 100644 +--- a/net/wireless/scan.c ++++ b/net/wireless/scan.c +@@ -205,7 +205,7 @@ bool cfg80211_is_element_inherited(const struct element *elem, + return true; + + if (elem->id == WLAN_EID_EXTENSION) { +- if (!ext_id_len) ++ if (!ext_id_len || !elem->datalen) + return true; + loop_len = ext_id_len; + list = &non_inherit_elem->data[3 + id_len]; +-- +2.53.0 + diff --git a/queue-6.18/wifi-cfg80211-cancel-sched-scan-results-work-on-unre.patch b/queue-6.18/wifi-cfg80211-cancel-sched-scan-results-work-on-unre.patch new file mode 100644 index 0000000000..006463f295 --- /dev/null +++ b/queue-6.18/wifi-cfg80211-cancel-sched-scan-results-work-on-unre.patch @@ -0,0 +1,83 @@ +From 217b282593ec1d1e345374e3c6cc4a8f563c6cb5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 20 Jun 2026 00:25:42 +0800 +Subject: wifi: cfg80211: cancel sched scan results work on unregister + +From: Cen Zhang + +[ Upstream commit edf0730be33696a1bd142792830d392129e495cc ] + +cfg80211_sched_scan_results() can queue rdev->sched_scan_res_wk from a +driver result notification while a scheduled scan request is present. The +work callback recovers the containing cfg80211_registered_device and then +locks the wiphy and walks the scheduled-scan request list. + +wiphy_unregister() already makes the wiphy unreachable and drains rdev work +items before cfg80211_dev_free() can release the object, but it does not +drain sched_scan_res_wk. A queued or running result work item can therefore +cross the unregister/free boundary and access freed rdev state. + +The buggy scenario involves two paths, with each column showing the order +within that path: + +scheduled-scan result path: unregister/free path: +1. cfg80211_sched_scan_results() 1. interface teardown stops and + queues rdev->sched_scan_res_wk. removes the scheduled scan request. +2. cfg80211_wq starts the work 2. wiphy_unregister() drains other + item and recovers rdev. rdev work items. +3. The worker locks rdev->wiphy 3. cfg80211_dev_free() destroys and + and walks rdev state. frees rdev. + +Cancel sched_scan_res_wk in wiphy_unregister() alongside the other rdev +work items. cancel_work_sync() removes a pending result notification and +waits for an already running callback, so cfg80211_dev_free() cannot free +rdev while this work item is still active. + +Validation reproduced this kernel report: +BUG: KASAN: use-after-free in cfg80211_sched_scan_results_wk+0x4a6/0x530 +Workqueue: cfg80211 cfg80211_sched_scan_results_wk [cfg80211] +Read of size 8 +Call trace: + dump_stack_lvl+0x66/0xa0 + print_report+0xce/0x630 + cfg80211_sched_scan_results_wk+0x4a6/0x530 + srso_alias_return_thunk+0x5/0xfbef5 + __virt_addr_valid+0x224/0x430 + kasan_report+0xac/0xe0 + lockdep_hardirqs_on_prepare+0xea/0x1a0 + process_one_work+0x8d0/0x18f0 (kernel/workqueue.c:3212) + lock_is_held_type+0x8f/0x100 + worker_thread+0x5ad/0xfd0 + __kthread_parkme+0xc6/0x200 + kthread+0x31e/0x410 + trace_hardirqs_on+0x1a/0x170 + ret_from_fork+0x576/0x810 + __switch_to+0x57e/0xe20 + __switch_to_asm+0x33/0x70 + ret_from_fork_asm+0x1a/0x30 + +Fixes: 807f8a8c3004 ("cfg80211/nl80211: add support for scheduled scans") +Assisted-by: Codex:gpt-5.5 +Signed-off-by: Cen Zhang +Link: https://patch.msgid.link/20260619162542.3878296-1-zzzccc427@gmail.com +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + net/wireless/core.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/net/wireless/core.c b/net/wireless/core.c +index 6b204ca91a140b..34b76479f888bf 100644 +--- a/net/wireless/core.c ++++ b/net/wireless/core.c +@@ -1195,6 +1195,7 @@ void wiphy_unregister(struct wiphy *wiphy) + /* this has nothing to do now but make sure it's gone */ + cancel_work_sync(&rdev->wiphy_work); + ++ cancel_work_sync(&rdev->sched_scan_res_wk); + cancel_work_sync(&rdev->rfkill_block); + cancel_work_sync(&rdev->conn_work); + flush_work(&rdev->event_work); +-- +2.53.0 + diff --git a/queue-6.18/wifi-cfg80211-convert-pmsr_free_wk-to-wiphy_work-to-.patch b/queue-6.18/wifi-cfg80211-convert-pmsr_free_wk-to-wiphy_work-to-.patch new file mode 100644 index 0000000000..dbe2b98ec0 --- /dev/null +++ b/queue-6.18/wifi-cfg80211-convert-pmsr_free_wk-to-wiphy_work-to-.patch @@ -0,0 +1,138 @@ +From cb25d64896bb51dbad8a252ecaadd06b8cf401bd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 3 Jul 2026 13:55:23 +0530 +Subject: wifi: cfg80211: convert pmsr_free_wk to wiphy_work to fix deadlock + +From: Peddolla Harshavardhan Reddy + +[ Upstream commit 2b0eab425e1f658d8fe1df7590e3b9af5959505e ] + +When a netlink socket that owns a PMSR session is closed, +cfg80211_release_pmsr() clears the request's nl_portid and queues +pmsr_free_wk to call cfg80211_pmsr_process_abort() asynchronously. + +If the interface tears down concurrently, cfg80211_pmsr_wdev_down() +is called under wiphy_lock and calls cancel_work_sync(&pmsr_free_wk) +to wait for any running work. The work function acquires wiphy_lock +via guard(wiphy) before calling process_abort. + +This is a deadlock: wdev_down holds wiphy_lock and blocks inside +cancel_work_sync(); pmsr_free_wk blocks trying to acquire that same +wiphy_lock. Neither thread can proceed. + +The same deadlock is reachable from cfg80211_leave_locked(), which +calls cfg80211_pmsr_wdev_down() for all interface types under +wiphy_lock. + +Fix this by converting pmsr_free_wk from a plain work_struct to a +wiphy_work. The wiphy_work dispatcher holds wiphy_lock when running +work items, so the explicit guard(wiphy) in the work function is no +longer needed. wiphy_work_cancel() can be called safely while holding +wiphy_lock - since wiphy_lock prevents the work from running +concurrently, wiphy_work_cancel() never blocks, eliminating the +deadlock. + +Remove the cancel_work_sync() for pmsr_free_wk from the +NETDEV_GOING_DOWN handler. cfg80211_leave(), called unconditionally +just before it, already cancels any pending work under wiphy_lock +via wiphy_work_cancel() inside cfg80211_pmsr_wdev_down(). + +Fixes: 6dccbc9f3e1d ("wifi: cfg80211: cancel pmsr_free_wk in cfg80211_pmsr_wdev_down") +Signed-off-by: Peddolla Harshavardhan Reddy +Link: https://patch.msgid.link/20260703082523.2629324-1-peddolla.reddy@oss.qualcomm.com +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + include/net/cfg80211.h | 2 +- + net/wireless/core.c | 3 +-- + net/wireless/core.h | 2 +- + net/wireless/pmsr.c | 8 +++----- + 4 files changed, 6 insertions(+), 9 deletions(-) + +diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h +index 820e299f06b5ee..1509be85139ecf 100644 +--- a/include/net/cfg80211.h ++++ b/include/net/cfg80211.h +@@ -6740,7 +6740,7 @@ struct wireless_dev { + + struct list_head pmsr_list; + spinlock_t pmsr_lock; +- struct work_struct pmsr_free_wk; ++ struct wiphy_work pmsr_free_wk; + + unsigned long unprot_beacon_reported; + +diff --git a/net/wireless/core.c b/net/wireless/core.c +index 34b76479f888bf..efbf7b3046342e 100644 +--- a/net/wireless/core.c ++++ b/net/wireless/core.c +@@ -1444,7 +1444,7 @@ void cfg80211_init_wdev(struct wireless_dev *wdev) + INIT_LIST_HEAD(&wdev->mgmt_registrations); + INIT_LIST_HEAD(&wdev->pmsr_list); + spin_lock_init(&wdev->pmsr_lock); +- INIT_WORK(&wdev->pmsr_free_wk, cfg80211_pmsr_free_wk); ++ wiphy_work_init(&wdev->pmsr_free_wk, cfg80211_pmsr_free_wk); + + #ifdef CONFIG_CFG80211_WEXT + wdev->wext.default_key = -1; +@@ -1579,7 +1579,6 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb, + } + /* since we just did cfg80211_leave() nothing to do there */ + cancel_work_sync(&wdev->disconnect_wk); +- cancel_work_sync(&wdev->pmsr_free_wk); + break; + case NETDEV_DOWN: + wiphy_lock(&rdev->wiphy); +diff --git a/net/wireless/core.h b/net/wireless/core.h +index d5d78752227af9..9bfd39af1742e1 100644 +--- a/net/wireless/core.h ++++ b/net/wireless/core.h +@@ -566,7 +566,7 @@ cfg80211_get_6ghz_power_type(const u8 *elems, size_t elems_len); + + void cfg80211_release_pmsr(struct wireless_dev *wdev, u32 portid); + void cfg80211_pmsr_wdev_down(struct wireless_dev *wdev); +-void cfg80211_pmsr_free_wk(struct work_struct *work); ++void cfg80211_pmsr_free_wk(struct wiphy *wiphy, struct wiphy_work *work); + + void cfg80211_remove_link(struct wireless_dev *wdev, unsigned int link_id); + void cfg80211_remove_links(struct wireless_dev *wdev); +diff --git a/net/wireless/pmsr.c b/net/wireless/pmsr.c +index 13801cf35e9fca..d2546c27879fa4 100644 +--- a/net/wireless/pmsr.c ++++ b/net/wireless/pmsr.c +@@ -625,13 +625,11 @@ static void cfg80211_pmsr_process_abort(struct wireless_dev *wdev) + } + } + +-void cfg80211_pmsr_free_wk(struct work_struct *work) ++void cfg80211_pmsr_free_wk(struct wiphy *wiphy, struct wiphy_work *work) + { + struct wireless_dev *wdev = container_of(work, struct wireless_dev, + pmsr_free_wk); + +- guard(wiphy)(wdev->wiphy); +- + cfg80211_pmsr_process_abort(wdev); + } + +@@ -647,7 +645,7 @@ void cfg80211_pmsr_wdev_down(struct wireless_dev *wdev) + } + spin_unlock_bh(&wdev->pmsr_lock); + +- cancel_work_sync(&wdev->pmsr_free_wk); ++ wiphy_work_cancel(wdev->wiphy, &wdev->pmsr_free_wk); + if (found) + cfg80211_pmsr_process_abort(wdev); + +@@ -662,7 +660,7 @@ void cfg80211_release_pmsr(struct wireless_dev *wdev, u32 portid) + list_for_each_entry(req, &wdev->pmsr_list, list) { + if (req->nl_portid == portid) { + req->nl_portid = 0; +- schedule_work(&wdev->pmsr_free_wk); ++ wiphy_work_queue(wdev->wiphy, &wdev->pmsr_free_wk); + } + } + spin_unlock_bh(&wdev->pmsr_lock); +-- +2.53.0 + diff --git a/queue-6.18/wifi-cfg80211-derive-s1g-beacon-tsf-from-s1g-fields.patch b/queue-6.18/wifi-cfg80211-derive-s1g-beacon-tsf-from-s1g-fields.patch new file mode 100644 index 0000000000..6cafb93225 --- /dev/null +++ b/queue-6.18/wifi-cfg80211-derive-s1g-beacon-tsf-from-s1g-fields.patch @@ -0,0 +1,54 @@ +From e58aa203d89963bb3a37816299f3ab4b8abe0eca Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 12 Jun 2026 00:19:46 +0800 +Subject: wifi: cfg80211: derive S1G beacon TSF from S1G fields + +From: Zhao Li + +[ Upstream commit 4e5a4641e7b4763656336b7891d01359aaf363cd ] + +cfg80211_inform_bss_frame_data() parses S1G beacons with the extension +frame layout, but still reads the TSF from the regular probe response +layout after the S1G branch. For S1G beacons that reads bytes at the +regular management-frame timestamp offset instead of the S1G timestamp. + +Use the 32-bit S1G beacon timestamp and the S1G Beacon Compatibility +element's TSF completion field when informing an S1G BSS. Keep the +regular management-frame timestamp read in the non-S1G branch. + +Fixes: 9eaffe5078ca ("cfg80211: convert S1G beacon to scan results") +Signed-off-by: Zhao Li +Tested-by: Lachlan Hodges +Reviewed-by: Lachlan Hodges +Link: https://patch.msgid.link/20260611161943.91069-6-enderaoelyther@gmail.com +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + net/wireless/scan.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/net/wireless/scan.c b/net/wireless/scan.c +index 27d5f99dbb2289..af1e2ce1628dae 100644 +--- a/net/wireless/scan.c ++++ b/net/wireless/scan.c +@@ -3326,14 +3326,15 @@ cfg80211_inform_bss_frame_data(struct wiphy *wiphy, + bssid = ext->u.s1g_beacon.sa; + capability = le16_to_cpu(compat->compat_info); + beacon_interval = le16_to_cpu(compat->beacon_int); ++ tsf = le32_to_cpu(ext->u.s1g_beacon.timestamp); ++ tsf |= (u64)le32_to_cpu(compat->tsf_completion) << 32; + } else { + bssid = mgmt->bssid; + beacon_interval = le16_to_cpu(mgmt->u.probe_resp.beacon_int); + capability = le16_to_cpu(mgmt->u.probe_resp.capab_info); ++ tsf = le64_to_cpu(mgmt->u.probe_resp.timestamp); + } + +- tsf = le64_to_cpu(mgmt->u.probe_resp.timestamp); +- + if (ieee80211_is_probe_resp(mgmt->frame_control)) + ftype = CFG80211_BSS_FTYPE_PRESP; + else if (ext) +-- +2.53.0 + diff --git a/queue-6.18/wifi-cfg80211-fix-an-error-handling-path-in-cfg80211.patch b/queue-6.18/wifi-cfg80211-fix-an-error-handling-path-in-cfg80211.patch new file mode 100644 index 0000000000..7f4b1a1cea --- /dev/null +++ b/queue-6.18/wifi-cfg80211-fix-an-error-handling-path-in-cfg80211.patch @@ -0,0 +1,41 @@ +From 06ccde9e54ccfe49ed663639f90063c207d034c6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 20 Jun 2026 21:48:56 +0200 +Subject: wifi: cfg80211: Fix an error handling path in cfg80211_wext_siwscan() + +From: Christophe JAILLET + +[ Upstream commit c6659f66d4ee4841aafae5659d2ef5e4c5c63cb6 ] + +If the test against IEEE80211_MAX_SSID_LEN fails, then 'creq' leaks. +Use the existing error handling path to fix it. + +Fixes: 2a5193119269 ("cfg80211/nl80211: scanning (and mac80211 update to use it)") +Signed-off-by: Christophe JAILLET +Link: https://patch.msgid.link/a1be7eea4da0da18f90589af252bb76a18a61978.1781984889.git.christophe.jaillet@wanadoo.fr +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + net/wireless/scan.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/net/wireless/scan.c b/net/wireless/scan.c +index 2f2104bb0d52ff..27d5f99dbb2289 100644 +--- a/net/wireless/scan.c ++++ b/net/wireless/scan.c +@@ -3627,8 +3627,10 @@ int cfg80211_wext_siwscan(struct net_device *dev, + /* translate "Scan for SSID" request */ + if (wreq) { + if (wrqu->data.flags & IW_SCAN_THIS_ESSID) { +- if (wreq->essid_len > IEEE80211_MAX_SSID_LEN) +- return -EINVAL; ++ if (wreq->essid_len > IEEE80211_MAX_SSID_LEN) { ++ err = -EINVAL; ++ goto out; ++ } + memcpy(creq->req.ssids[0].ssid, wreq->essid, + wreq->essid_len); + creq->req.ssids[0].ssid_len = wreq->essid_len; +-- +2.53.0 + diff --git a/queue-6.18/wifi-cfg80211-reject-unsupported-pmsr-ftm-location-r.patch b/queue-6.18/wifi-cfg80211-reject-unsupported-pmsr-ftm-location-r.patch new file mode 100644 index 0000000000..20776f51b3 --- /dev/null +++ b/queue-6.18/wifi-cfg80211-reject-unsupported-pmsr-ftm-location-r.patch @@ -0,0 +1,50 @@ +From 829c68ca26346639aa1a707b25f54604d4886c93 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 12 Jun 2026 21:37:11 +0800 +Subject: wifi: cfg80211: reject unsupported PMSR FTM location requests + +From: Zhao Li + +[ Upstream commit 69ef6a7ec277f16d216be8da2b3cbe872786c999 ] + +PMSR FTM location request flags are syntactically valid, but they must +be rejected when the device capability does not advertise support for +them. + +Return an error immediately after rejecting unsupported LCI or civic +location request bits so the request cannot reach the driver. + +Fixes: 9bb7e0f24e7e7 ("cfg80211: add peer measurement with FTM initiator API") +Assisted-by: Codex:gpt-5.5 +Assisted-by: Claude:claude-opus-4.8 +Signed-off-by: Zhao Li +Link: https://patch.msgid.link/20260612133710.93544-2-enderaoelyther@gmail.com +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + net/wireless/pmsr.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/net/wireless/pmsr.c b/net/wireless/pmsr.c +index fd14a3c2eab45b..06563f60848705 100644 +--- a/net/wireless/pmsr.c ++++ b/net/wireless/pmsr.c +@@ -114,6 +114,7 @@ static int pmsr_parse_ftm(struct cfg80211_registered_device *rdev, + NL_SET_ERR_MSG_ATTR(info->extack, + tb[NL80211_PMSR_FTM_REQ_ATTR_REQUEST_LCI], + "FTM: LCI request not supported"); ++ return -EOPNOTSUPP; + } + + out->ftm.request_civicloc = +@@ -122,6 +123,7 @@ static int pmsr_parse_ftm(struct cfg80211_registered_device *rdev, + NL_SET_ERR_MSG_ATTR(info->extack, + tb[NL80211_PMSR_FTM_REQ_ATTR_REQUEST_CIVICLOC], + "FTM: civic location request not supported"); ++ return -EOPNOTSUPP; + } + + out->ftm.trigger_based = +-- +2.53.0 + diff --git a/queue-6.18/wifi-cfg80211-validate-pmsr-ftm-preamble-range.patch b/queue-6.18/wifi-cfg80211-validate-pmsr-ftm-preamble-range.patch new file mode 100644 index 0000000000..2f11957931 --- /dev/null +++ b/queue-6.18/wifi-cfg80211-validate-pmsr-ftm-preamble-range.patch @@ -0,0 +1,45 @@ +From 5f0d9677a99c4fc6f298ec9e3e3a7e669d3a7eda Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 12 Jun 2026 21:37:04 +0800 +Subject: wifi: cfg80211: validate PMSR FTM preamble range + +From: Zhao Li + +[ Upstream commit 36230936468f0ba4930e94aef496fc229d4bb951 ] + +PMSR FTM request parsing accepts preamble values outside the +enumerated nl80211 preamble range. + +Reject out-of-range values before using them in the parser capability +bit test using the policy. + +Fixes: 9bb7e0f24e7e7 ("cfg80211: add peer measurement with FTM initiator API") +Assisted-by: Codex:gpt-5.5 +Assisted-by: Claude:claude-opus-4.8 +Signed-off-by: Zhao Li +Link: https://patch.msgid.link/20260612133703.93274-2-enderaoelyther@gmail.com +[drop unnecessary check] +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + net/wireless/nl80211.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c +index 237e5d7eeb47c3..776dcf8835d715 100644 +--- a/net/wireless/nl80211.c ++++ b/net/wireless/nl80211.c +@@ -347,7 +347,9 @@ nl80211_ftm_responder_policy[NL80211_FTM_RESP_ATTR_MAX + 1] = { + static const struct nla_policy + nl80211_pmsr_ftm_req_attr_policy[NL80211_PMSR_FTM_REQ_ATTR_MAX + 1] = { + [NL80211_PMSR_FTM_REQ_ATTR_ASAP] = { .type = NLA_FLAG }, +- [NL80211_PMSR_FTM_REQ_ATTR_PREAMBLE] = { .type = NLA_U32 }, ++ [NL80211_PMSR_FTM_REQ_ATTR_PREAMBLE] = ++ NLA_POLICY_RANGE(NLA_U32, NL80211_PREAMBLE_LEGACY, ++ NL80211_PREAMBLE_HE), + [NL80211_PMSR_FTM_REQ_ATTR_NUM_BURSTS_EXP] = + NLA_POLICY_MAX(NLA_U8, 15), + [NL80211_PMSR_FTM_REQ_ATTR_BURST_PERIOD] = { .type = NLA_U16 }, +-- +2.53.0 + diff --git a/queue-6.18/wifi-cfg80211-validate-pmsr-measurement-type-data.patch b/queue-6.18/wifi-cfg80211-validate-pmsr-measurement-type-data.patch new file mode 100644 index 0000000000..3e53f09bea --- /dev/null +++ b/queue-6.18/wifi-cfg80211-validate-pmsr-measurement-type-data.patch @@ -0,0 +1,76 @@ +From b2abf7c1394e2fd8fa1c1b3060310142d393d5b4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 12 Jun 2026 21:36:57 +0800 +Subject: wifi: cfg80211: validate PMSR measurement type data + +From: Zhao Li + +[ Upstream commit 41aa973eb05922848dded26875c55ef982ac1c49 ] + +PMSR request parsing accepts missing or duplicated measurement type +entries in NL80211_PMSR_REQ_ATTR_DATA. + +Track whether one measurement type was already provided, reject a +second one immediately, and return an error if the request data block +contains no measurement type at all. + +Fixes: 9bb7e0f24e7e7 ("cfg80211: add peer measurement with FTM initiator API") +Assisted-by: Codex:gpt-5.5 +Assisted-by: Claude:claude-opus-4.8 +Signed-off-by: Zhao Li +Link: https://patch.msgid.link/20260612133656.92900-2-enderaoelyther@gmail.com +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + net/wireless/pmsr.c | 19 +++++++++++++++++-- + 1 file changed, 17 insertions(+), 2 deletions(-) + +diff --git a/net/wireless/pmsr.c b/net/wireless/pmsr.c +index d2546c27879fa4..fd14a3c2eab45b 100644 +--- a/net/wireless/pmsr.c ++++ b/net/wireless/pmsr.c +@@ -196,6 +196,7 @@ static int pmsr_parse_peer(struct cfg80211_registered_device *rdev, + { + struct nlattr *tb[NL80211_PMSR_PEER_ATTR_MAX + 1]; + struct nlattr *req[NL80211_PMSR_REQ_ATTR_MAX + 1]; ++ bool have_measurement_type = false; + struct nlattr *treq; + int err, rem; + +@@ -248,6 +249,14 @@ static int pmsr_parse_peer(struct cfg80211_registered_device *rdev, + } + + nla_for_each_nested(treq, req[NL80211_PMSR_REQ_ATTR_DATA], rem) { ++ if (have_measurement_type) { ++ NL_SET_ERR_MSG_ATTR(info->extack, treq, ++ "multiple measurement types in request data"); ++ return -EINVAL; ++ } ++ ++ have_measurement_type = true; ++ + switch (nla_type(treq)) { + case NL80211_PMSR_TYPE_FTM: + err = pmsr_parse_ftm(rdev, treq, out, info); +@@ -257,10 +266,16 @@ static int pmsr_parse_peer(struct cfg80211_registered_device *rdev, + "unsupported measurement type"); + err = -EINVAL; + } ++ if (err) ++ return err; + } + +- if (err) +- return err; ++ if (!have_measurement_type) { ++ NL_SET_ERR_MSG_ATTR(info->extack, ++ req[NL80211_PMSR_REQ_ATTR_DATA], ++ "missing measurement type in request data"); ++ return -EINVAL; ++ } + + return 0; + } +-- +2.53.0 + diff --git a/queue-6.18/wifi-ipw2100-fix-potential-memory-leak-in-ipw2100_pc.patch b/queue-6.18/wifi-ipw2100-fix-potential-memory-leak-in-ipw2100_pc.patch new file mode 100644 index 0000000000..e0328a6da2 --- /dev/null +++ b/queue-6.18/wifi-ipw2100-fix-potential-memory-leak-in-ipw2100_pc.patch @@ -0,0 +1,60 @@ +From fb8b855b52b8b224a2bed6bf8fb93996a5cb0eb8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 20 Jun 2026 12:22:39 +0530 +Subject: wifi: ipw2100: fix potential memory leak in ipw2100_pci_init_one() + +From: Abdun Nihaal + +[ Upstream commit 0d388f62031dbabcba0f44bb91b59f10e88cac17 ] + +The memory allocated in the ipw2100_alloc_device() function is not freed +in some of the error paths in ipw2100_pci_init_one(). Fix that by +converting the direct return into a goto to the error path return. + +The error path when pci_enable_device() fails cannot jump to fail, since +at this point priv is not set, so perform error handling inline. + +Fixes: 2c86c275015c ("Add ipw2100 wireless driver.") +Signed-off-by: Abdun Nihaal +Link: https://patch.msgid.link/20260620065242.93798-1-nihaal@cse.iitm.ac.in +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/intel/ipw2x00/ipw2100.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/drivers/net/wireless/intel/ipw2x00/ipw2100.c b/drivers/net/wireless/intel/ipw2x00/ipw2100.c +index 215814861cbda5..0808e69c3c1786 100644 +--- a/drivers/net/wireless/intel/ipw2x00/ipw2100.c ++++ b/drivers/net/wireless/intel/ipw2x00/ipw2100.c +@@ -6162,6 +6162,8 @@ static int ipw2100_pci_init_one(struct pci_dev *pci_dev, + if (err) { + printk(KERN_WARNING DRV_NAME + "Error calling pci_enable_device.\n"); ++ free_libipw(dev, 0); ++ pci_iounmap(pci_dev, ioaddr); + return err; + } + +@@ -6174,16 +6176,14 @@ static int ipw2100_pci_init_one(struct pci_dev *pci_dev, + if (err) { + printk(KERN_WARNING DRV_NAME + "Error calling pci_set_dma_mask.\n"); +- pci_disable_device(pci_dev); +- return err; ++ goto fail; + } + + err = pci_request_regions(pci_dev, DRV_NAME); + if (err) { + printk(KERN_WARNING DRV_NAME + "Error calling pci_request_regions.\n"); +- pci_disable_device(pci_dev); +- return err; ++ goto fail; + } + + /* We disable the RETRY_TIMEOUT register (0x41) to keep +-- +2.53.0 + diff --git a/queue-6.18/wifi-libertas-fix-memory-leak-in-helper_firmware_cb.patch b/queue-6.18/wifi-libertas-fix-memory-leak-in-helper_firmware_cb.patch new file mode 100644 index 0000000000..6d716ee696 --- /dev/null +++ b/queue-6.18/wifi-libertas-fix-memory-leak-in-helper_firmware_cb.patch @@ -0,0 +1,50 @@ +From 09b2b0cf2bfe5f18db155c09a1696dd3bac39364 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 24 Jun 2026 16:53:43 +0800 +Subject: wifi: libertas: fix memory leak in helper_firmware_cb() + +From: Dawei Feng + +[ Upstream commit 63c2391deefb31e1b801b7f32bd502ca4808639b ] + +helper_firmware_cb() neglects to free the single-stage firmware image +after a successful async load, leading to a memory leak in the USB +firmware-download path. + +Fix this memory leak by calling release_firmware() immediately after +lbs_fw_loaded() returns. + +The bug was first flagged by an experimental analysis tool we are +developing for kernel memory-management bugs while analyzing +v6.13-rc1. The tool is still under development and is not yet publicly +available. Manual inspection confirms that the bug is still present in +the current wireless tree. + +An x86_64 allyesconfig build showed no new warnings. As we do not have +compatible Libertas USB hardware for exercising this firmware-download +path, no runtime testing was able to be performed. + +Fixes: 1dfba3060fe7 ("libertas: move firmware lifetime handling to firmware.c") +Signed-off-by: Dawei Feng +Link: https://patch.msgid.link/20260624085343.575508-1-dawei.feng@seu.edu.cn +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/marvell/libertas/firmware.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/net/wireless/marvell/libertas/firmware.c b/drivers/net/wireless/marvell/libertas/firmware.c +index f124110944b7e9..9bf7d4c207b9ed 100644 +--- a/drivers/net/wireless/marvell/libertas/firmware.c ++++ b/drivers/net/wireless/marvell/libertas/firmware.c +@@ -78,6 +78,7 @@ static void helper_firmware_cb(const struct firmware *firmware, void *context) + } else { + /* No main firmware needed for this helper --> success! */ + lbs_fw_loaded(priv, 0, firmware, NULL); ++ release_firmware(firmware); + } + } + +-- +2.53.0 + diff --git a/queue-6.18/wifi-mac80211-avoid-non-s1g-aid-fallback-for-s1g-ass.patch b/queue-6.18/wifi-mac80211-avoid-non-s1g-aid-fallback-for-s1g-ass.patch new file mode 100644 index 0000000000..4782eda660 --- /dev/null +++ b/queue-6.18/wifi-mac80211-avoid-non-s1g-aid-fallback-for-s1g-ass.patch @@ -0,0 +1,58 @@ +From be5d1a130db68d8c0d2aeef1c4ec6631df006095 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 12 Jun 2026 23:24:41 +0800 +Subject: wifi: mac80211: avoid non-S1G AID fallback for S1G assoc + +From: Zhao Li + +[ Upstream commit 035ed430ce6a2c35b01e211844a9f0a7643e57a4 ] + +When assoc_data->s1g is set and no AID Response element is present, +falling back to mgmt->u.assoc_resp.aid reads the non-S1G +association-response layout. + +Keep the fallback for non-S1G only. If a successful S1G association +response omits the AID Response element, abandon the association +instead of proceeding with AID 0. Initialize aid to 0 for other S1G +responses so the later mask and logging flow keeps a defined value +without reading the non-S1G layout. + +Fixes: 2a8a6b7c4cb0 ("wifi: mac80211: handle station association response with S1G") +Assisted-by: Codex:gpt-5.5 +Assisted-by: Claude:claude-opus-4.8 +Signed-off-by: Zhao Li +Link: https://patch.msgid.link/20260612152440.25955-2-enderaoelyther@gmail.com +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + net/mac80211/mlme.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c +index 8854e47b056721..9ec4125c06d193 100644 +--- a/net/mac80211/mlme.c ++++ b/net/mac80211/mlme.c +@@ -6476,7 +6476,7 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, + { + struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; + struct ieee80211_mgd_assoc_data *assoc_data = ifmgd->assoc_data; +- u16 capab_info, status_code, aid; ++ u16 capab_info, status_code, aid = 0; + struct ieee80211_elems_parse_params parse_params = { + .bss = NULL, + .link_id = -1, +@@ -6553,8 +6553,10 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, + + if (elems->aid_resp) + aid = le16_to_cpu(elems->aid_resp->aid); +- else ++ else if (!assoc_data->s1g) + aid = le16_to_cpu(mgmt->u.assoc_resp.aid); ++ else if (status_code == WLAN_STATUS_SUCCESS) ++ goto abandon_assoc; + + /* + * The 5 MSB of the AID field are reserved for a non-S1G STA. For +-- +2.53.0 + diff --git a/queue-6.18/wifi-mac80211-defer-link-rx-stats-percpu-free-to-rcu.patch b/queue-6.18/wifi-mac80211-defer-link-rx-stats-percpu-free-to-rcu.patch new file mode 100644 index 0000000000..d7c88c6a6d --- /dev/null +++ b/queue-6.18/wifi-mac80211-defer-link-rx-stats-percpu-free-to-rcu.patch @@ -0,0 +1,77 @@ +From 317659041812361a2ed34cfde85999d92ffbdb90 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 27 Jun 2026 16:30:28 +0800 +Subject: wifi: mac80211: defer link RX stats percpu free to RCU + +From: Maoyi Xie + +[ Upstream commit aa2eb62525188269cdd402a583b9a8ed94657ff0 ] + +sta_remove_link() frees a removed MLO link's RX stats percpu buffer right +away, but defers only the link container to RCU: + + sta_info_free_link(&alloc->info); + kfree_rcu(alloc, rcu_head); + +The RX fast path reads link_sta under rcu_read_lock and writes the percpu +stats. A reader that resolved link_sta before the removal keeps the +pointer. The container stays alive from the kfree_rcu, so the read still +works. But the percpu block it points to is already freed. This needs +uses_rss. That is when pcpu_rx_stats exists. + +The full STA teardown frees the deflink stats only after +synchronize_net(). The link removal path had no such barrier. The race is +hard to win in practice, but the free should still wait for RCU. + +Free the link together with its data from a single RCU callback, so the +percpu block is reclaimed only after readers drain. + +Fixes: c71420db653a ("wifi: mac80211: RCU-ify link STA pointers") +Link: https://lore.kernel.org/r/20260626080158.3589711-1-maoyixie.tju@gmail.com +Suggested-by: Johannes Berg +Co-developed-by: Kaixuan Li +Signed-off-by: Kaixuan Li +Signed-off-by: Maoyi Xie +Link: https://patch.msgid.link/20260627083028.3826810-1-maoyixie.tju@gmail.com +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + net/mac80211/sta_info.c | 15 +++++++++++---- + 1 file changed, 11 insertions(+), 4 deletions(-) + +diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c +index b0d9bb830f2931..54a6b20a4c5cd5 100644 +--- a/net/mac80211/sta_info.c ++++ b/net/mac80211/sta_info.c +@@ -355,6 +355,15 @@ static void sta_info_free_link(struct link_sta_info *link_sta) + free_percpu(link_sta->pcpu_rx_stats); + } + ++static void sta_link_free_rcu(struct rcu_head *head) ++{ ++ struct sta_link_alloc *alloc = ++ container_of(head, struct sta_link_alloc, rcu_head); ++ ++ sta_info_free_link(&alloc->info); ++ kfree(alloc); ++} ++ + static void sta_accumulate_removed_link_stats(struct sta_info *sta, int link_id) + { + struct link_sta_info *link_sta = wiphy_dereference(sta->local->hw.wiphy, +@@ -427,10 +436,8 @@ static void sta_remove_link(struct sta_info *sta, unsigned int link_id, + + RCU_INIT_POINTER(sta->link[link_id], NULL); + RCU_INIT_POINTER(sta->sta.link[link_id], NULL); +- if (alloc) { +- sta_info_free_link(&alloc->info); +- kfree_rcu(alloc, rcu_head); +- } ++ if (alloc) ++ call_rcu(&alloc->rcu_head, sta_link_free_rcu); + + ieee80211_sta_recalc_aggregates(&sta->sta); + } +-- +2.53.0 + diff --git a/queue-6.18/wifi-mac80211-fix-fils_discovery-double-free-on-allo.patch b/queue-6.18/wifi-mac80211-fix-fils_discovery-double-free-on-allo.patch new file mode 100644 index 0000000000..59287c293e --- /dev/null +++ b/queue-6.18/wifi-mac80211-fix-fils_discovery-double-free-on-allo.patch @@ -0,0 +1,66 @@ +From fcc90eefedcfe83fa5f7b5bd862a2616f91a1992 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 21 Jun 2026 02:35:32 -0700 +Subject: wifi: mac80211: fix fils_discovery double free on alloc failure + +From: Xiang Mei + +[ Upstream commit 286e52a799fa158bdbd77da1426c4d93f9a6e7ad ] + +ieee80211_set_fils_discovery() calls kfree_rcu() on the old template +before allocating the replacement. If the kzalloc() then fails, it +returns -ENOMEM while link->u.ap.fils_discovery still points at the +object already queued for freeing. A later update or AP teardown +(ieee80211_stop_ap()) re-queues that same rcu_head; the second free is +caught by KASAN when the RCU sheaf is processed in softirq: + + BUG: KASAN: double-free in rcu_free_sheaf (mm/slub.c:5850) + Free of addr ffff88800c065280 by task swapper/0/0 + ... + __rcu_free_sheaf_prepare (mm/slub.c:2634 mm/slub.c:2940) + rcu_free_sheaf (mm/slub.c:5850) + rcu_core (kernel/rcu/tree.c:2617 kernel/rcu/tree.c:2869) + handle_softirqs (kernel/softirq.c:622) + The buggy address belongs to the cache kmalloc-96 of size 96 + +Queue the old object for kfree_rcu() only after the new one is published, +matching ieee80211_set_probe_resp() and ieee80211_set_s1g_short_beacon(). + +Fixes: 3b1c256eb4ae ("wifi: mac80211: fixes in FILS discovery updates") +Reported-by: Weiming Shi +Assisted-by: Claude:claude-opus-4-8 +Signed-off-by: Xiang Mei +Link: https://patch.msgid.link/20260621093532.884188-2-xmei5@asu.edu +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + net/mac80211/cfg.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c +index 001e4bb55b6199..f6232948bc0f4a 100644 +--- a/net/mac80211/cfg.c ++++ b/net/mac80211/cfg.c +@@ -1124,9 +1124,6 @@ static int ieee80211_set_fils_discovery(struct ieee80211_sub_if_data *sdata, + fd->max_interval = params->max_interval; + + old = sdata_dereference(link->u.ap.fils_discovery, sdata); +- if (old) +- kfree_rcu(old, rcu_head); +- + if (params->tmpl && params->tmpl_len) { + new = kzalloc(sizeof(*new) + params->tmpl_len, GFP_KERNEL); + if (!new) +@@ -1138,6 +1135,9 @@ static int ieee80211_set_fils_discovery(struct ieee80211_sub_if_data *sdata, + RCU_INIT_POINTER(link->u.ap.fils_discovery, NULL); + } + ++ if (old) ++ kfree_rcu(old, rcu_head); ++ + *changed |= BSS_CHANGED_FILS_DISCOVERY; + return 0; + } +-- +2.53.0 + diff --git a/queue-6.18/wifi-mac80211-fix-unsol_bcast_probe_resp-double-free.patch b/queue-6.18/wifi-mac80211-fix-unsol_bcast_probe_resp-double-free.patch new file mode 100644 index 0000000000..d7df531f65 --- /dev/null +++ b/queue-6.18/wifi-mac80211-fix-unsol_bcast_probe_resp-double-free.patch @@ -0,0 +1,66 @@ +From f16702730b4c70a69ab47966e27885c5d91379b8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 21 Jun 2026 02:35:31 -0700 +Subject: wifi: mac80211: fix unsol_bcast_probe_resp double free on alloc + failure + +From: Xiang Mei + +[ Upstream commit 1d067abcd37062426c59ec73dbc4e87a63f33fea ] + +ieee80211_set_unsol_bcast_probe_resp() calls kfree_rcu() on the old +template before allocating the replacement. If the kzalloc() then fails, +it returns -ENOMEM while link->u.ap.unsol_bcast_probe_resp still points +at the object already queued for freeing. A later update or AP teardown +re-queues that same rcu_head; the second free is caught by KASAN when the +RCU sheaf is processed in softirq: + + BUG: KASAN: double-free in rcu_free_sheaf (mm/slub.c:5850) + Free of addr ffff88800d06f300 by task exploit/145 + ... + __rcu_free_sheaf_prepare (mm/slub.c:2634 mm/slub.c:2940) + rcu_free_sheaf (mm/slub.c:5850) + rcu_core (kernel/rcu/tree.c:2617 kernel/rcu/tree.c:2869) + handle_softirqs (kernel/softirq.c:622) + The buggy address belongs to the cache kmalloc-128 of size 128 + +Queue the old object for kfree_rcu() only after the new one is published, +matching ieee80211_set_probe_resp() and ieee80211_set_s1g_short_beacon(). + +Fixes: 3b1c256eb4ae ("wifi: mac80211: fixes in FILS discovery updates") +Reported-by: Weiming Shi +Assisted-by: Claude:claude-opus-4-8 +Signed-off-by: Xiang Mei +Link: https://patch.msgid.link/20260621093532.884188-1-xmei5@asu.edu +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + net/mac80211/cfg.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c +index d32eacbb7517d7..001e4bb55b6199 100644 +--- a/net/mac80211/cfg.c ++++ b/net/mac80211/cfg.c +@@ -1157,8 +1157,6 @@ ieee80211_set_unsol_bcast_probe_resp(struct ieee80211_sub_if_data *sdata, + link_conf->unsol_bcast_probe_resp_interval = params->interval; + + old = sdata_dereference(link->u.ap.unsol_bcast_probe_resp, sdata); +- if (old) +- kfree_rcu(old, rcu_head); + + if (params->tmpl && params->tmpl_len) { + new = kzalloc(sizeof(*new) + params->tmpl_len, GFP_KERNEL); +@@ -1171,6 +1169,9 @@ ieee80211_set_unsol_bcast_probe_resp(struct ieee80211_sub_if_data *sdata, + RCU_INIT_POINTER(link->u.ap.unsol_bcast_probe_resp, NULL); + } + ++ if (old) ++ kfree_rcu(old, rcu_head); ++ + *changed |= BSS_CHANGED_UNSOL_BCAST_PROBE_RESP; + return 0; + } +-- +2.53.0 + diff --git a/queue-6.18/wifi-mac80211-free-ap_vlan-bc_buf-skbs-outside-irq-l.patch b/queue-6.18/wifi-mac80211-free-ap_vlan-bc_buf-skbs-outside-irq-l.patch new file mode 100644 index 0000000000..49fb75b9f1 --- /dev/null +++ b/queue-6.18/wifi-mac80211-free-ap_vlan-bc_buf-skbs-outside-irq-l.patch @@ -0,0 +1,77 @@ +From 0961e2844b4de1174fe918becdbe1c0dda0721c8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 6 Jul 2026 22:08:41 +0800 +Subject: wifi: mac80211: free AP_VLAN bc_buf SKBs outside IRQ lock + +From: Cen Zhang + +[ Upstream commit f3858d5b1432098c1936e03d6e03dd0e33facf60 ] + +ieee80211_do_stop() removes AP_VLAN packets from the parent AP +ps->bc_buf while holding ps->bc_buf.lock with IRQs disabled. It then +calls ieee80211_free_txskb() before dropping the lock. + +ieee80211_free_txskb() is not just a passive SKB release. For SKBs with +TX status state it can report a dropped frame through cfg80211/nl80211, +and that path can reach netlink tap transmit. This is the same reason +the pending queue cleanup in ieee80211_do_stop() already unlinks SKBs +under the queue lock and frees them after IRQ state is restored. + +The buggy scenario involves two paths, with each column showing the +order within that path: + +AP_VLAN management TX: AP_VLAN stop: +1. attach ACK-status state 1. clear the running state +2. queue a multicast SKB on 2. take ps->bc_buf.lock with IRQs + parent ps->bc_buf disabled + 3. unlink the AP_VLAN SKB + 4. call ieee80211_free_txskb() + +Unlink matching AP_VLAN SKBs from ps->bc_buf under the existing lock, +but move them to a local free queue. Drop the lock and restore IRQ state +before calling ieee80211_free_txskb(). + +WARNING: kernel/softirq.c:430 at __local_bh_enable_ip + +Fixes: 397a7a24ef8c ("mac80211: free ps->bc_buf skbs on vlan device stop") +Assisted-by: Codex:gpt-5.5 +Signed-off-by: Cen Zhang +Link: https://patch.msgid.link/20260706140841.581566-1-zzzccc427@gmail.com +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + net/mac80211/iface.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c +index 72c129478da088..499126317a914c 100644 +--- a/net/mac80211/iface.c ++++ b/net/mac80211/iface.c +@@ -581,6 +581,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, bool going_do + WARN_ON(!list_empty(&sdata->u.ap.vlans)); + } else if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) { + /* remove all packets in parent bc_buf pointing to this dev */ ++ __skb_queue_head_init(&freeq); + ps = &sdata->bss->ps; + + spin_lock_irqsave(&ps->bc_buf.lock, flags); +@@ -588,10 +589,15 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, bool going_do + if (skb->dev == sdata->dev) { + __skb_unlink(skb, &ps->bc_buf); + local->total_ps_buffered--; +- ieee80211_free_txskb(&local->hw, skb); ++ __skb_queue_tail(&freeq, skb); + } + } + spin_unlock_irqrestore(&ps->bc_buf.lock, flags); ++ ++ skb_queue_walk_safe(&freeq, skb, tmp) { ++ __skb_unlink(skb, &freeq); ++ ieee80211_free_txskb(&local->hw, skb); ++ } + } + + if (going_down) +-- +2.53.0 + diff --git a/queue-6.18/wifi-mac80211_hwsim-clamp-virtio-rx-length-before-sk.patch b/queue-6.18/wifi-mac80211_hwsim-clamp-virtio-rx-length-before-sk.patch new file mode 100644 index 0000000000..f49ede9ab3 --- /dev/null +++ b/queue-6.18/wifi-mac80211_hwsim-clamp-virtio-rx-length-before-sk.patch @@ -0,0 +1,46 @@ +From adb861c677b9ed82b74afead6239a4aac0d6fe13 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 20 Jun 2026 21:45:18 -0500 +Subject: wifi: mac80211_hwsim: clamp virtio RX length before skb_put + +From: Bryam Vargas + +[ Upstream commit 10a2b430f8f06ae14b9590b6f6faa6b588ef0654 ] + +hwsim_virtio_rx_work() passes the virtqueue used-ring length reported by +the device straight to skb_put() on a fixed-size receive skb. A backend +reporting a length larger than the skb tailroom drives skb_put() past the +buffer end and hits skb_over_panic() -- a host-triggerable guest panic +(denial of service). + +Clamp the length to the skb's available room before skb_put(). A +conforming device never reports more than the posted buffer size, so valid +frames are unaffected; a truncated over-report then fails the +length/header checks in hwsim_virtio_handle_cmd() and is dropped, so +truncating rather than dropping here cannot be turned into a parsing +problem. + +Fixes: 5d44fe7c9808 ("mac80211_hwsim: add frame transmission support over virtio") +Signed-off-by: Bryam Vargas +Link: https://patch.msgid.link/20260620-b4-disp-474bee37-v1-1-1a4d37f3e2d4@proton.me +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/virtual/mac80211_hwsim.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/net/wireless/virtual/mac80211_hwsim.c b/drivers/net/wireless/virtual/mac80211_hwsim.c +index 20815fdc9d3764..a0724e1c530709 100644 +--- a/drivers/net/wireless/virtual/mac80211_hwsim.c ++++ b/drivers/net/wireless/virtual/mac80211_hwsim.c +@@ -6898,6 +6898,7 @@ static void hwsim_virtio_rx_work(struct work_struct *work) + + skb->data = skb->head; + skb_reset_tail_pointer(skb); ++ len = min(len, skb_end_offset(skb)); + skb_put(skb, len); + hwsim_virtio_handle_cmd(skb); + +-- +2.53.0 + diff --git a/queue-6.18/wifi-nl80211-constrain-mbssid-tx-link-id-range.patch b/queue-6.18/wifi-nl80211-constrain-mbssid-tx-link-id-range.patch new file mode 100644 index 0000000000..a7fb796494 --- /dev/null +++ b/queue-6.18/wifi-nl80211-constrain-mbssid-tx-link-id-range.patch @@ -0,0 +1,40 @@ +From da859bdc32bb3e2c76d0d2c6330c47e9e91c4e7d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 12 Jun 2026 21:18:56 +0800 +Subject: wifi: nl80211: constrain MBSSID TX link ID range + +From: Zhao Li + +[ Upstream commit 172f06023669f0a96d32511669ff45c600731380 ] + +MBSSID transmitted-profile link IDs are valid only in the range +0..IEEE80211_MLD_MAX_NUM_LINKS - 1. Constrain the nl80211 policy to +reject out-of-range values during attribute validation. + +Fixes: 37523c3c47b3 ("wifi: nl80211: add link id of transmitted profile for MLO MBSSID") +Assisted-by: Codex:gpt-5.5 +Assisted-by: Claude:claude-opus-4.8 +Signed-off-by: Zhao Li +Link: https://patch.msgid.link/20260612131854.43575-4-enderaoelyther@gmail.com +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + net/wireless/nl80211.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c +index 5583edf4852775..237e5d7eeb47c3 100644 +--- a/net/wireless/nl80211.c ++++ b/net/wireless/nl80211.c +@@ -501,7 +501,7 @@ nl80211_mbssid_config_policy[NL80211_MBSSID_CONFIG_ATTR_MAX + 1] = { + [NL80211_MBSSID_CONFIG_ATTR_TX_IFINDEX] = { .type = NLA_U32 }, + [NL80211_MBSSID_CONFIG_ATTR_EMA] = { .type = NLA_FLAG }, + [NL80211_MBSSID_CONFIG_ATTR_TX_LINK_ID] = +- NLA_POLICY_MAX(NLA_U8, IEEE80211_MLD_MAX_NUM_LINKS), ++ NLA_POLICY_RANGE(NLA_U8, 0, IEEE80211_MLD_MAX_NUM_LINKS - 1), + }; + + static const struct nla_policy +-- +2.53.0 + diff --git a/queue-6.18/wifi-nl80211-free-rnr-data-on-mbssid-mismatch.patch b/queue-6.18/wifi-nl80211-free-rnr-data-on-mbssid-mismatch.patch new file mode 100644 index 0000000000..66ad33756d --- /dev/null +++ b/queue-6.18/wifi-nl80211-free-rnr-data-on-mbssid-mismatch.patch @@ -0,0 +1,43 @@ +From 303f1846a7ff8f35a0ec458add0544b8b0c6d8da Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 10 Jun 2026 19:22:09 +0800 +Subject: wifi: nl80211: free RNR data on MBSSID mismatch + +From: Zhao Li + +[ Upstream commit 07a95ec2b54774201fdf4ef7ffb0ca2ab19ed29c ] + +nl80211_parse_beacon() rejects EMA RNR data when there are fewer RNR +entries than MBSSID entries. + +The rejected RNR allocation has not been attached to the beacon data yet, +so free it before returning the error. + +Fixes: dbbb27e183b1 ("cfg80211: support RNR for EMA AP") +Signed-off-by: Zhao Li +Link: https://patch.msgid.link/20260610112208.1308-2-enderaoelyther@gmail.com +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + net/wireless/nl80211.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c +index 6e41a4269e1c57..e765c992eb20e4 100644 +--- a/net/wireless/nl80211.c ++++ b/net/wireless/nl80211.c +@@ -6232,8 +6232,10 @@ static int nl80211_parse_beacon(struct cfg80211_registered_device *rdev, + if (IS_ERR(rnr)) + return PTR_ERR(rnr); + +- if (rnr && rnr->cnt < bcn->mbssid_ies->cnt) ++ if (rnr && rnr->cnt < bcn->mbssid_ies->cnt) { ++ kfree(rnr); + return -EINVAL; ++ } + + bcn->rnr_ies = rnr; + } +-- +2.53.0 + diff --git a/queue-6.18/wifi-nl80211-validate-nested-mbssid-ie-blobs.patch b/queue-6.18/wifi-nl80211-validate-nested-mbssid-ie-blobs.patch new file mode 100644 index 0000000000..e755739904 --- /dev/null +++ b/queue-6.18/wifi-nl80211-validate-nested-mbssid-ie-blobs.patch @@ -0,0 +1,67 @@ +From 4299bd357c046b0e694f77f11986ba38128209ff Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 12 Jun 2026 21:18:55 +0800 +Subject: wifi: nl80211: validate nested MBSSID IE blobs + +From: Zhao Li + +[ Upstream commit 7f4b01812323443b55e4c65381c9dc851ff009e3 ] + +Validate each nested NL80211_ATTR_MBSSID_ELEMS entry as a well-formed +information-element stream before storing it for beacon construction. + +RNR parsing already validates each nested blob with validate_ie_attr() +before storing it. Apply the same syntactic IE validation to MBSSID +entries before counting and copying their data and length pointers. + +Fixes: dc1e3cb8da8b ("nl80211: MBSSID and EMA support in AP mode") +Assisted-by: Codex:gpt-5.5 +Assisted-by: Claude:claude-opus-4.8 +Signed-off-by: Zhao Li +Link: https://patch.msgid.link/20260612131854.43575-3-enderaoelyther@gmail.com +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + net/wireless/nl80211.c | 12 ++++++++++-- + 1 file changed, 10 insertions(+), 2 deletions(-) + +diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c +index e765c992eb20e4..5583edf4852775 100644 +--- a/net/wireless/nl80211.c ++++ b/net/wireless/nl80211.c +@@ -6034,7 +6034,8 @@ static int nl80211_parse_mbssid_config(struct wiphy *wiphy, + } + + static struct cfg80211_mbssid_elems * +-nl80211_parse_mbssid_elems(struct wiphy *wiphy, struct nlattr *attrs) ++nl80211_parse_mbssid_elems(struct wiphy *wiphy, struct nlattr *attrs, ++ struct netlink_ext_ack *extack) + { + struct nlattr *nl_elems; + struct cfg80211_mbssid_elems *elems; +@@ -6045,6 +6046,12 @@ nl80211_parse_mbssid_elems(struct wiphy *wiphy, struct nlattr *attrs) + return ERR_PTR(-EINVAL); + + nla_for_each_nested(nl_elems, attrs, rem_elems) { ++ int ret; ++ ++ ret = validate_ie_attr(nl_elems, extack); ++ if (ret) ++ return ERR_PTR(ret); ++ + if (num_elems >= 255) + return ERR_PTR(-EINVAL); + num_elems++; +@@ -6216,7 +6223,8 @@ static int nl80211_parse_beacon(struct cfg80211_registered_device *rdev, + if (attrs[NL80211_ATTR_MBSSID_ELEMS]) { + struct cfg80211_mbssid_elems *mbssid = + nl80211_parse_mbssid_elems(&rdev->wiphy, +- attrs[NL80211_ATTR_MBSSID_ELEMS]); ++ attrs[NL80211_ATTR_MBSSID_ELEMS], ++ extack); + + if (IS_ERR(mbssid)) + return PTR_ERR(mbssid); +-- +2.53.0 + diff --git a/queue-6.18/wifi-p54-validate-rx-frame-length-in-p54_rx_eeprom_r.patch b/queue-6.18/wifi-p54-validate-rx-frame-length-in-p54_rx_eeprom_r.patch new file mode 100644 index 0000000000..4ba6dcc529 --- /dev/null +++ b/queue-6.18/wifi-p54-validate-rx-frame-length-in-p54_rx_eeprom_r.patch @@ -0,0 +1,80 @@ +From 15c6bc3621a82ef7774c11e775080282a8a4ed4e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 27 Jun 2026 17:05:10 -0700 +Subject: wifi: p54: validate RX frame length in p54_rx_eeprom_readback() + +From: Xiang Mei + +[ Upstream commit ebd6d37fa94bee929e0b4c9ca19fdf9b1dcf6cea ] + +p54_rx_eeprom_readback() copies the requested EEPROM slice out of a +device-supplied readback frame without checking that the skb actually holds +that many bytes. Commit da1b9a55ff11 ("wifi: p54: prevent buffer-overflow in +p54_rx_eeprom_readback()") closed the destination overflow by copying a +fixed priv->eeprom_slice_size (and rejecting a mismatched advertised len), +but the source side is still unbounded: nothing verifies the frame is long +enough to supply that many bytes. + +A malicious USB device can send a short frame whose advertised len matches +priv->eeprom_slice_size while the payload is truncated. The equality check +passes and memcpy() reads past the end of the skb, leaking adjacent heap: + + BUG: KASAN: slab-out-of-bounds in p54_rx (drivers/net/wireless/intersil/p54/txrx.c:507) + Read of size 1016 at addr ffff88800f077114 by task swapper/0/0 + Call Trace: + + ... + __asan_memcpy (mm/kasan/shadow.c:105) + p54_rx (drivers/net/wireless/intersil/p54/txrx.c:507) + p54u_rx_cb (drivers/net/wireless/intersil/p54/p54usb.c:163) + __usb_hcd_giveback_urb (drivers/usb/core/hcd.c:1657) + dummy_timer (drivers/usb/gadget/udc/dummy_hcd.c:2005) + ... + + + The buggy address belongs to the object at ffff88800f0770c0 + which belongs to the cache skbuff_small_head of size 704 + The buggy address is located 84 bytes inside of + allocated 704-byte region [ffff88800f0770c0, ffff88800f077380) + +Check that the slice fits in the skb before copying. + +Fixes: 7cb770729ba8 ("p54: move eeprom code into common library") +Reported-by: Weiming Shi +Assisted-by: Claude:claude-opus-4-8 +Signed-off-by: Xiang Mei +Acked-by: Christian Lamparter +Link: https://patch.msgid.link/20260628000510.4152481-1-xmei5@asu.edu +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/intersil/p54/txrx.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/drivers/net/wireless/intersil/p54/txrx.c b/drivers/net/wireless/intersil/p54/txrx.c +index 1294a1d6528e2c..9f491334c8d043 100644 +--- a/drivers/net/wireless/intersil/p54/txrx.c ++++ b/drivers/net/wireless/intersil/p54/txrx.c +@@ -499,11 +499,19 @@ static void p54_rx_eeprom_readback(struct p54_common *priv, + if (le16_to_cpu(eeprom->v2.len) != priv->eeprom_slice_size) + return; + ++ if (eeprom->v2.data + priv->eeprom_slice_size > ++ skb_tail_pointer(skb)) ++ return; ++ + memcpy(priv->eeprom, eeprom->v2.data, priv->eeprom_slice_size); + } else { + if (le16_to_cpu(eeprom->v1.len) != priv->eeprom_slice_size) + return; + ++ if (eeprom->v1.data + priv->eeprom_slice_size > ++ skb_tail_pointer(skb)) ++ return; ++ + memcpy(priv->eeprom, eeprom->v1.data, priv->eeprom_slice_size); + } + +-- +2.53.0 + diff --git a/queue-6.18/xfrm-clear-mode-callbacks-after-failed-mode-setup.patch b/queue-6.18/xfrm-clear-mode-callbacks-after-failed-mode-setup.patch new file mode 100644 index 0000000000..b59b14abc5 --- /dev/null +++ b/queue-6.18/xfrm-clear-mode-callbacks-after-failed-mode-setup.patch @@ -0,0 +1,90 @@ +From 1cbf50199d1e9e0975575046587ee703c963bac7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 27 Jun 2026 11:01:17 +0800 +Subject: xfrm: clear mode callbacks after failed mode setup + +From: Cen Zhang + +[ Upstream commit 2538bd3cd1ff5af655908469544ac7b7ae259386 ] + +xfrm_state_gc_task can run long after a failed IPTFS state setup. In the +reproduced case, __xfrm_init_state() cached x->mode_cbs, IPTFS setup +returned -ENOMEM before publishing mode_data, and the temporary module +reference from xfrm_get_mode_cbs() was dropped immediately. The dead state +then kept x->mode_cbs until deferred GC ran after xfrm_iptfs had been +unloaded. + +Clear x->mode_cbs when mode init or clone fails before publishing +mode_data. Those states never installed mode-specific state or the +long-term IPTFS module pin, so deferred GC has nothing mode-specific to +destroy and must not retain a callback table pointer past the temporary +lookup reference. + +The buggy scenario involves two paths, with each column showing the order +within that path: + +failed setup path: +1. cache x->mode_cbs +2. mode setup fails before mode_data +3. drop the temporary module ref +4. dead state keeps x->mode_cbs cached + +GC/unload path: +1. xfrm_state_put() queues GC work +2. xfrm_iptfs unloads later +3. xfrm_state_gc_task runs +4. GC dereferences stale x->mode_cbs + +This also covers the failed clone path where clone_state() returns before +publishing mode_data. + +Validation reproduced this kernel report: +Kernel panic - not syncing: Fatal exception +CONFIG_FAULT_INJECTION_STACKTRACE_FILTER=y +failslab_stacktrace_filter matched xfrm_iptfs frames +ack_error=-12 +FAULT_INJECTION: forcing a failure +BUG: unable to handle page fault +Workqueue: events xfrm_state_gc_task +RIP: xfrm_state_gc_task+0x142/0x650 +Modules linked in: esp4_offload xfrm_user [last unloaded: xfrm_iptfs] +Kernel panic - not syncing: Fatal exception + +Fixes: 4b3faf610cc6 ("xfrm: iptfs: add new iptfs xfrm mode impl") +Assisted-by: Codex:gpt-5.5 +Signed-off-by: Cen Zhang +Signed-off-by: Steffen Klassert +Signed-off-by: Sasha Levin +--- + net/xfrm/xfrm_state.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c +index 89daad5db10c9d..b9049c2297bd5a 100644 +--- a/net/xfrm/xfrm_state.c ++++ b/net/xfrm/xfrm_state.c +@@ -2070,8 +2070,11 @@ static struct xfrm_state *xfrm_state_clone_and_setup(struct xfrm_state *orig, + + x->mode_cbs = orig->mode_cbs; + if (x->mode_cbs && x->mode_cbs->clone_state) { +- if (x->mode_cbs->clone_state(x, orig)) ++ if (x->mode_cbs->clone_state(x, orig)) { ++ if (!x->mode_data) ++ x->mode_cbs = NULL; + goto error; ++ } + } + + +@@ -3253,6 +3256,8 @@ int __xfrm_init_state(struct xfrm_state *x, struct netlink_ext_ack *extack) + if (x->mode_cbs->init_state) + err = x->mode_cbs->init_state(x); + module_put(x->mode_cbs->owner); ++ if (err && !x->mode_data) ++ x->mode_cbs = NULL; + } + error: + return err; +-- +2.53.0 + diff --git a/queue-6.18/xfrm-fix-stale-skb-prev-after-async-crypto-steals-a-.patch b/queue-6.18/xfrm-fix-stale-skb-prev-after-async-crypto-steals-a-.patch new file mode 100644 index 0000000000..775be3325b --- /dev/null +++ b/queue-6.18/xfrm-fix-stale-skb-prev-after-async-crypto-steals-a-.patch @@ -0,0 +1,53 @@ +From 29d89ce66ca226883dede338eafe4fe9709dbd25 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 21 Jun 2026 12:03:27 +0200 +Subject: xfrm: fix stale skb->prev after async crypto steals a GSO segment + +From: Petr Wozniak + +[ Upstream commit 3f4c3919baf0944ad96580467c302bc6c7758b00 ] + +skb_gso_segment() leaves the segment list head with ->prev pointing at +the last segment, an invariant validate_xmit_skb_list() relies on when +it sets its tail pointer (tail = skb->prev). + +When validate_xmit_xfrm() walks a GSO list and some segments are stolen +by async crypto (->xmit() returns -EINPROGRESS), those segments are +unlinked from the list but the head ->prev is never updated. If the +last segment is the one stolen, the returned head still has ->prev +pointing at it, even though it is now owned by the crypto engine and may +be freed. validate_xmit_skb_list() later does tail->next = skb, writing +through that stale pointer -- a use-after-free. + +Repoint skb->prev at the last retained segment before returning. + +Fixes: f53c723902d1 ("net: Add asynchronous callbacks for xfrm on layer 2.") +Signed-off-by: Petr Wozniak +Signed-off-by: Steffen Klassert +Signed-off-by: Sasha Levin +--- + net/xfrm/xfrm_device.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/net/xfrm/xfrm_device.c b/net/xfrm/xfrm_device.c +index 8b526e3676389a..4719aba331cd66 100644 +--- a/net/xfrm/xfrm_device.c ++++ b/net/xfrm/xfrm_device.c +@@ -224,6 +224,14 @@ struct sk_buff *validate_xmit_xfrm(struct sk_buff *skb, netdev_features_t featur + pskb = skb2; + } + ++ /* skb_gso_segment() set skb->prev to the last segment, but async ++ * crypto may have stolen it above without updating ->prev. Repoint ++ * it at the last retained segment so validate_xmit_skb_list() does ++ * not chain onto a segment now owned by the crypto engine. ++ */ ++ if (skb) ++ skb->prev = pskb; ++ + return skb ? skb : ERR_PTR(-EINPROGRESS); + } + EXPORT_SYMBOL_GPL(validate_xmit_xfrm); +-- +2.53.0 + diff --git a/queue-6.18/xfrm-iptfs-propagate-skbfl_shared_frag-in-iptfs_skb_.patch b/queue-6.18/xfrm-iptfs-propagate-skbfl_shared_frag-in-iptfs_skb_.patch new file mode 100644 index 0000000000..6c84ff90f8 --- /dev/null +++ b/queue-6.18/xfrm-iptfs-propagate-skbfl_shared_frag-in-iptfs_skb_.patch @@ -0,0 +1,51 @@ +From b944177ffcca7a2571dc0b92bf7d1d4bf84d185d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 1 Jul 2026 11:31:52 +0800 +Subject: xfrm: iptfs: propagate SKBFL_SHARED_FRAG in iptfs_skb_add_frags() + +From: Chen YanJun + +[ Upstream commit 430ea57d6daf765e88f90046afbfd1e071cb7200 ] + +When iptfs_skb_add_frags() copies frag references from the source +frag walk into a new SKB, it increments the page reference count via +__skb_frag_ref() but does not propagate SKBFL_SHARED_FRAG to the +destination SKB's skb_shinfo->flags. + +If the source SKB carries shared frags (e.g. from a page-pool backed +receive path), the new inner SKB will appear to ESP as having privately +owned frags. A subsequent esp_input() call for a nested transport-mode +SA then takes the no-COW fast path and decrypts in place, writing over +pages that are still referenced by the outer IPTFS SKB. This causes +kernel-visible memory corruption and can trigger a panic. + +All other frag-transfer helpers in the kernel (skb_try_coalesce, +skb_gro_receive, __pskb_copy_fclone, skb_shift, skb_segment) correctly +propagate SKBFL_SHARED_FRAG; align iptfs_skb_add_frags() with this +convention by setting the flag inside the loop immediately after +__skb_frag_ref() and nr_frags++, so every exit path that attaches a frag +unconditionally propagates SKBFL_SHARED_FRAG. + +Fixes: 5f2b6a909574 ("xfrm: iptfs: add skb-fragment sharing code") +Signed-off-by: Chen YanJun +Signed-off-by: Steffen Klassert +Signed-off-by: Sasha Levin +--- + net/xfrm/xfrm_iptfs.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/net/xfrm/xfrm_iptfs.c b/net/xfrm/xfrm_iptfs.c +index fe8e4f21b32819..d39253b06c4efd 100644 +--- a/net/xfrm/xfrm_iptfs.c ++++ b/net/xfrm/xfrm_iptfs.c +@@ -480,6 +480,7 @@ static int iptfs_skb_add_frags(struct sk_buff *skb, + } + __skb_frag_ref(tofrag); + shinfo->nr_frags++; ++ shinfo->flags |= SKBFL_SHARED_FRAG; + + /* see if we are done */ + fraglen = tofrag->len; +-- +2.53.0 + diff --git a/queue-6.18/xfrm-policy-preallocate-inexact-bins-before-xfrm_has.patch b/queue-6.18/xfrm-policy-preallocate-inexact-bins-before-xfrm_has.patch new file mode 100644 index 0000000000..3ebff3d200 --- /dev/null +++ b/queue-6.18/xfrm-policy-preallocate-inexact-bins-before-xfrm_has.patch @@ -0,0 +1,75 @@ +From 00e79f8efe45f129ecc6bcab9e29dfea73ef0b17 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 3 Jul 2026 05:19:32 +0000 +Subject: xfrm: policy: preallocate inexact bins before xfrm_hash_rebuild + reinsert + +From: Xiang Mei (Microsoft) + +[ Upstream commit f38f8cce2f7e79775b3db7e8a5eacda04ac908e4 ] + +xfrm_hash_rebuild()'s first loop preallocates the bins/chains the reinsert +loop needs, so the reinsert (after hlist_del_rcu()) cannot allocate or +fail. But its guard is inverted: it skips policies with prefixlen < +threshold and preallocates for the rest. + +prefixlen < threshold is exactly when policy_hash_bysel() returns NULL and +the reinsert takes the allocating xfrm_policy_inexact_insert() path. So the +loop preallocates for the exact policies (which never allocate) and skips +the inexact ones, whose bin/node is then allocated GFP_ATOMIC during +reinsert. On failure the error path only WARN_ONCE()s and continues, +leaving a poisoned bydst node; the next rebuild's hlist_del_rcu() +dereferences LIST_POISON2 and takes a GPF. Reachable under memory pressure, +deterministic via failslab. + +Invert the guard so preallocation covers exactly the reinserted policies; +the reinsert then allocates nothing and cannot fail. + +Crash: + Oops: general protection fault, probably for non-canonical address + 0xfbd59c0000000024: 0000 [#1] SMP KASAN NOPTI + KASAN: maybe wild-memory-access in range [0xdead...] + ... + Workqueue: events xfrm_hash_rebuild + RIP: 0010:xfrm_hash_rebuild+0x5b3/0x1190 + RAX: dead000000000122 (LIST_POISON2 + offset) + ... + Call Trace: + hlist_del_rcu (include/linux/rculist.h:599) + xfrm_hash_rebuild (net/xfrm/xfrm_policy.c:1365) + process_one_work (kernel/workqueue.c:3322) + worker_thread (kernel/workqueue.c:3486) + kthread (kernel/kthread.c:436) + ret_from_fork (arch/x86/kernel/process.c:158) + ret_from_fork_asm (arch/x86/entry/entry_64.S:245) + ... + Kernel panic - not syncing: Fatal exception in interrupt + +Fixes: 24969facd704 ("xfrm: policy: store inexact policies in an rhashtable") +Reported-by: AutonomousCodeSecurity@microsoft.com +Signed-off-by: Xiang Mei (Microsoft) +Reviewed-by: Florian Westphal +Signed-off-by: Steffen Klassert +Signed-off-by: Sasha Levin +--- + net/xfrm/xfrm_policy.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c +index 4dad1f8172286a..25f9cbd3ce6a4f 100644 +--- a/net/xfrm/xfrm_policy.c ++++ b/net/xfrm/xfrm_policy.c +@@ -1329,8 +1329,8 @@ static void xfrm_hash_rebuild(struct work_struct *work) + } + } + +- if (policy->selector.prefixlen_d < dbits || +- policy->selector.prefixlen_s < sbits) ++ if (policy->selector.prefixlen_d >= dbits && ++ policy->selector.prefixlen_s >= sbits) + continue; + + bin = xfrm_policy_inexact_alloc_bin(policy, dir); +-- +2.53.0 + diff --git a/queue-6.18/xfrm-propagate-einprogress-from-validate_xmit_xfrm.patch b/queue-6.18/xfrm-propagate-einprogress-from-validate_xmit_xfrm.patch new file mode 100644 index 0000000000..7c2ceefc41 --- /dev/null +++ b/queue-6.18/xfrm-propagate-einprogress-from-validate_xmit_xfrm.patch @@ -0,0 +1,98 @@ +From 369d2e389cd5a90eae6df7f2ab42f639aa0b8f56 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 21 Jun 2026 12:03:26 +0200 +Subject: xfrm: propagate -EINPROGRESS from validate_xmit_xfrm() + +From: Petr Wozniak + +[ Upstream commit 6860b467f569f732b11cbc588ae7e195e90e7e23 ] + +validate_xmit_xfrm() returns NULL both when a packet is dropped and +when it is stolen by async crypto (-EINPROGRESS from ->xmit()). +Callers cannot distinguish the two cases. + +f53c723902d1 ("net: Add asynchronous callbacks for xfrm on layer 2.") +changed the semantics of a NULL return from "dropped" to "stolen or +dropped", but __dev_queue_xmit() was not updated. On virtual/bridge +interfaces (noqueue qdisc) __dev_queue_xmit() initialises rc=-ENOMEM +and jumps to out: when skb is NULL, returning -ENOMEM to the caller +even though the packet will be delivered correctly via xfrm_dev_resume(). + +Return ERR_PTR(-EINPROGRESS) from validate_xmit_xfrm() for the async +case so callers can tell it apart from a real drop. Update +__dev_queue_xmit() to handle ERR_PTR(-EINPROGRESS) from +validate_xmit_skb() correctly. Update validate_xmit_skb_list() to +use IS_ERR_OR_NULL() so that ERR_PTR(-EINPROGRESS) is not mistakenly +added to the transmitted list. + +Fixes: f53c723902d1 ("net: Add asynchronous callbacks for xfrm on layer 2.") +Suggested-by: Sabrina Dubroca +Signed-off-by: Petr Wozniak +Signed-off-by: Steffen Klassert +Signed-off-by: Sasha Levin +--- + net/core/dev.c | 10 ++++++++-- + net/xfrm/xfrm_device.c | 4 ++-- + 2 files changed, 10 insertions(+), 4 deletions(-) + +diff --git a/net/core/dev.c b/net/core/dev.c +index 246d654551ae56..a83083e8761b1b 100644 +--- a/net/core/dev.c ++++ b/net/core/dev.c +@@ -4005,6 +4005,9 @@ static struct sk_buff *validate_xmit_unreadable_skb(struct sk_buff *skb, + return NULL; + } + ++/* Returns the skb on success, NULL if dropped, or ERR_PTR(-EINPROGRESS) ++ * if stolen by async xfrm crypto (delivered via xfrm_dev_resume()). ++ */ + static struct sk_buff *validate_xmit_skb(struct sk_buff *skb, struct net_device *dev, bool *again) + { + netdev_features_t features; +@@ -4076,7 +4079,7 @@ struct sk_buff *validate_xmit_skb_list(struct sk_buff *skb, struct net_device *d + skb->prev = skb; + + skb = validate_xmit_skb(skb, dev, again); +- if (!skb) ++ if (IS_ERR_OR_NULL(skb)) + continue; + + if (!head) +@@ -4788,8 +4791,11 @@ int __dev_queue_xmit(struct sk_buff *skb, struct net_device *sb_dev) + goto recursion_alert; + + skb = validate_xmit_skb(skb, dev, &again); +- if (!skb) ++ if (IS_ERR_OR_NULL(skb)) { ++ if (PTR_ERR(skb) == -EINPROGRESS) ++ rc = NET_XMIT_SUCCESS; + goto out; ++ } + + HARD_TX_LOCK(dev, txq, cpu); + +diff --git a/net/xfrm/xfrm_device.c b/net/xfrm/xfrm_device.c +index 550457e4c4f01d..8b526e3676389a 100644 +--- a/net/xfrm/xfrm_device.c ++++ b/net/xfrm/xfrm_device.c +@@ -182,7 +182,7 @@ struct sk_buff *validate_xmit_xfrm(struct sk_buff *skb, netdev_features_t featur + err = x->type_offload->xmit(x, skb, esp_features); + if (err) { + if (err == -EINPROGRESS) +- return NULL; ++ return ERR_PTR(-EINPROGRESS); + + XFRM_INC_STATS(xs_net(x), LINUX_MIB_XFRMOUTSTATEPROTOERROR); + kfree_skb(skb); +@@ -224,7 +224,7 @@ struct sk_buff *validate_xmit_xfrm(struct sk_buff *skb, netdev_features_t featur + pskb = skb2; + } + +- return skb; ++ return skb ? skb : ERR_PTR(-EINPROGRESS); + } + EXPORT_SYMBOL_GPL(validate_xmit_xfrm); + +-- +2.53.0 + diff --git a/queue-6.18/xfrm-reject-optional-iptfs-templates-in-outbound-pol.patch b/queue-6.18/xfrm-reject-optional-iptfs-templates-in-outbound-pol.patch new file mode 100644 index 0000000000..41b25271ae --- /dev/null +++ b/queue-6.18/xfrm-reject-optional-iptfs-templates-in-outbound-pol.patch @@ -0,0 +1,173 @@ +From be31820820c21ea4fb8c646223eb4bf6268babd5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 27 Jun 2026 10:23:43 +0200 +Subject: xfrm: reject optional IPTFS templates in outbound policies + +From: Antony Antony + +[ Upstream commit ea528f18231ec0f33317be57f8866913b19aba6e ] + +syzbot reported a stack-out-of-bounds read in xfrm_state_find() +which flows from xfrm_tmpl_resolve_one(). + +Commit 3d776e31c841 ("xfrm: Reject optional tunnel/BEET mode +templates in outbound policies") disallowed optional tunnel and +BEET in outbound policies to prevent this. Later when IPTFS +added, it was not covered by that fix and can still trigger +the out-of-bounds read; + +Extend the check to disallow optional IPTFS in outbound policies +as well. IPTFS should be identical to tunnel mode. +IN and FWD policies are not affected: xfrm_tmpl_resolve_one() +is only reachable via the outbound path. + +Reproducer, before: + +ip link add dummy0 type dummy +ip link set dummy0 up +ip addr add 10.1.1.1/24 dev dummy0 +ip xfrm policy add src 10.1.1.1/32 dst 10.1.1.2/32 dir out tmpl + src fc00::dead:1 dst fc00::dead:2 proto esp reqid 1 mode iptfs + level use tmpl src fc00::dead:1 dst fc00::dead:2 proto esp reqid + 2 mode transport +ping -W 1 -c 1 10.1.1.2 +PING 10.1.1.2 (10.1.1.2) 56(84) bytes of data. + +[ 64.168420] ================================================================== +[ 64.169977] BUG: KASAN: stack-out-of-bounds in __xfrm6_addr_hash+0x11e/0x170 +[ 64.169977] Read of size 4 at addr ffff88800e1ffd20 by task ping/2844 + +[ 64.169977] CPU: 2 UID: 0 PID: 2844 Comm: ping Not tainted 7.1.0-rc7-00180-geb23b588430a #98 PREEMPT(full) +[ 64.169977] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.16.3-debian-1.16.3-2 04/01/2014 +[ 64.169977] Call Trace: +[ 64.169977] +[ 64.169977] dump_stack_lvl+0x47/0x70 +[ 64.169977] ? __xfrm6_addr_hash+0x11e/0x170 +[ 64.169977] print_report+0x152/0x4b0 +[ 64.169977] ? ksys_mmap_pgoff+0x6d/0xa0 +[ 64.169977] ? entry_SYSCALL_64_after_hwframe+0x76/0x7e +[ 64.169977] ? rcu_read_unlock_sched+0xa/0x20 +[ 64.169977] ? __virt_addr_valid+0x21b/0x230 +[ 64.169977] ? __xfrm6_addr_hash+0x11e/0x170 +[ 64.169977] kasan_report+0xa8/0xd0 +[ 64.169977] ? __xfrm6_addr_hash+0x11e/0x170 +[ 64.169977] __xfrm6_addr_hash+0x11e/0x170 +[ 64.169977] __xfrm_dst_hash+0x24/0xc0 +[ 64.169977] xfrm_state_find+0xa2d/0x2f90 +[ 64.169977] ? __pfx_xfrm_state_find+0x10/0x10 +[ 64.169977] ? __pfx_ftrace_graph_ret_addr+0x10/0x10 +[ 64.169977] ? __pfx_ftrace_graph_ret_addr+0x10/0x10 +[ 64.169977] xfrm_tmpl_resolve_one+0x210/0x570 +[ 64.169977] ? __pfx_xfrm_tmpl_resolve_one+0x10/0x10 +[ 64.169977] ? __pfx_stack_trace_consume_entry+0x10/0x10 +[ 64.169977] ? kernel_text_address+0x5b/0x80 +[ 64.169977] ? __kernel_text_address+0xe/0x30 +[ 64.169977] ? unwind_get_return_address+0x5e/0x90 +[ 64.169977] ? arch_stack_walk+0x8c/0xe0 +[ 64.169977] xfrm_tmpl_resolve+0x130/0x200 +[ 64.169977] ? __pfx_xfrm_tmpl_resolve+0x10/0x10 +[ 64.169977] ? __pfx_xfrm_policy_inexact_lookup_rcu+0x10/0x10 +[ 64.169977] ? __refcount_add_not_zero.constprop.0+0xb2/0x110 +[ 64.169977] ? __pfx___refcount_add_not_zero.constprop.0+0x10/0x10 +[ 64.169977] xfrm_resolve_and_create_bundle+0xd5/0x310 +[ 64.169977] ? __pfx_xfrm_resolve_and_create_bundle+0x10/0x10 +[ 64.169977] ? __pfx_xfrm_policy_lookup_bytype+0x10/0x10 +[ 64.169977] ? __pfx_xfrm_policy_lookup_bytype+0x10/0x10 +[ 64.169977] xfrm_lookup_with_ifid+0x3d8/0xb80 +[ 64.169977] ? __pfx_xfrm_lookup_with_ifid+0x10/0x10 +[ 64.169977] ? ip_route_output_key_hash+0xc6/0x110 +[ 64.169977] ? kasan_save_track+0x10/0x30 +[ 64.169977] xfrm_lookup_route+0x18/0xe0 +[ 64.169977] ip4_datagram_release_cb+0x4c9/0x530 +[ 64.169977] ? __pfx_ip4_datagram_release_cb+0x10/0x10 +[ 64.169977] ? do_raw_spin_lock+0x71/0xc0 +[ 64.169977] ? __pfx_do_raw_spin_lock+0x10/0x10 +[ 64.169977] release_sock+0xb0/0x170 +[ 64.169977] udp_connect+0x43/0x50 +[ 64.169977] __sys_connect+0xa6/0x100 +[ 64.169977] ? alloc_fd+0x2e9/0x300 +[ 64.169977] ? __pfx___sys_connect+0x10/0x10 +[ 64.169977] ? preempt_latency_start+0x1f/0x70 +[ 64.169977] ? fd_install+0x7e/0x150 +[ 64.169977] ? rcu_read_unlock_sched+0xa/0x20 +[ 64.169977] ? __sys_socket+0xdf/0x130 +[ 64.169977] ? __pfx___sys_socket+0x10/0x10 +[ 64.169977] ? vma_refcount_put+0x43/0xa0 +[ 64.169977] __x64_sys_connect+0x7e/0x90 +[ 64.169977] do_syscall_64+0x11b/0x2b0 +[ 64.169977] entry_SYSCALL_64_after_hwframe+0x76/0x7e +[ 64.169977] RIP: 0033:0x7f4851ecb570 +[ 64.169977] Code: 00 f7 d8 64 89 01 48 83 c8 ff c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 44 00 00 80 3d f9 ca 0d 00 00 74 17 b8 2a 00 00 00 0f 05 <48> 3d 00 f0 ff ff 77 58 c3 0f 1f 80 00 00 00 00 48 83 ec 18 89 54 +[ 64.169977] RSP: 002b:00007ffc830e3498 EFLAGS: 00000202 ORIG_RAX: 000000000000002a +[ 64.169977] RAX: ffffffffffffffda RBX: 00007ffc830e34d0 RCX: 00007f4851ecb570 +[ 64.169977] RDX: 0000000000000010 RSI: 00007ffc830e34d0 RDI: 0000000000000005 +[ 64.169977] RBP: 0000000000000000 R08: 0000000000000003 R09: 0000000000000000 +[ 64.169977] R10: 0000000000000006 R11: 0000000000000202 R12: 0000000000000005 +[ 64.169977] R13: 0000000000000000 R14: 00005619a863f340 R15: 0000000000000000 +[ 64.169977] + +[ 64.169977] The buggy address belongs to stack of task ping/2844 +[ 64.169977] and is located at offset 88 in frame: +[ 64.169977] ip4_datagram_release_cb+0x0/0x530 + +[ 64.169977] This frame has 1 object: +[ 64.169977] [32, 88) 'fl4' + +[ 64.169977] The buggy address belongs to the physical page: +[ 64.169977] page: refcount:0 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0xe1ff +[ 64.169977] flags: 0x4000000000000000(zone=1) +[ 64.169977] raw: 4000000000000000 0000000000000000 ffffea0000387fc8 0000000000000000 +[ 64.169977] raw: 0000000000000000 0000000000000000 00000000ffffffff 0000000000000000 +[ 64.169977] page dumped because: kasan: bad access detected + +[ 64.169977] Memory state around the buggy address: +[ 64.169977] ffff88800e1ffc00: f2 f2 00 00 f3 f3 00 00 00 00 00 00 00 00 00 00 +[ 64.169977] ffff88800e1ffc80: 00 00 00 00 00 00 00 00 00 f1 f1 f1 f1 00 00 00 +[ 64.169977] >ffff88800e1ffd00: 00 00 00 00 f3 f3 f3 f3 f3 00 00 00 00 00 00 00 +[ 64.169977] ^ +[ 64.169977] ffff88800e1ffd80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 f1 f1 +[ 64.169977] ffff88800e1ffe00: f1 f1 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +[ 64.169977] ================================================================== +[ 64.245153] Disabling lock debugging due to kernel taint + +After the fix: + +ip xfrm policy add src 10.1.1.1/32 dst 10.1.1.2/32 dir out tmpl \ + src fc00::dead:1 dst fc00::dead:2 proto esp reqid 1 mode iptfs \ + level use tmpl src fc00::dead:1 dst fc00::dead:2 proto esp reqid 2 \ + mode transport + +Error: Mode in optional template not allowed in outbound policy. + +Fixes: d1716d5a44c3 ("xfrm: add generic iptfs defines and functionality") +Reported-by: syzbot+0ac4d84afe1066a1f3e9@syzkaller.appspotmail.com +Closes: https://lore.kernel.org/all/6a3ceb94.43b4ff68.30a095.0004.GAE@google.com/T/ +Signed-off-by: Antony Antony +Signed-off-by: Steffen Klassert +Signed-off-by: Sasha Levin +--- + net/xfrm/xfrm_user.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c +index 9ad6619888c738..3641ccccbc4153 100644 +--- a/net/xfrm/xfrm_user.c ++++ b/net/xfrm/xfrm_user.c +@@ -2068,13 +2068,12 @@ static int validate_tmpl(int nr, struct xfrm_user_tmpl *ut, u16 family, + switch (ut[i].mode) { + case XFRM_MODE_TUNNEL: + case XFRM_MODE_BEET: ++ case XFRM_MODE_IPTFS: + if (ut[i].optional && dir == XFRM_POLICY_OUT) { + NL_SET_ERR_MSG(extack, "Mode in optional template not allowed in outbound policy"); + return -EINVAL; + } + break; +- case XFRM_MODE_IPTFS: +- break; + default: + if (ut[i].family != prev_family) { + NL_SET_ERR_MSG(extack, "Mode in template doesn't support a family change"); +-- +2.53.0 + diff --git a/queue-6.18/xfrm6-clear-dst.dev-on-error-to-avoid-double-netdev_.patch b/queue-6.18/xfrm6-clear-dst.dev-on-error-to-avoid-double-netdev_.patch new file mode 100644 index 0000000000..4c1549b806 --- /dev/null +++ b/queue-6.18/xfrm6-clear-dst.dev-on-error-to-avoid-double-netdev_.patch @@ -0,0 +1,60 @@ +From d12616259b7271d16f66ca6cfba379f0fe59ccb6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 2 Jul 2026 01:05:16 +0000 +Subject: xfrm6: clear dst.dev on error to avoid double netdev_put in + xfrm6_fill_dst() + +From: Xiang Mei (Microsoft) + +[ Upstream commit 136992de9bb91871084ae52d172610541c76e4d2 ] + +On the error path where in6_dev_get(dev) returns NULL, xfrm6_fill_dst() +releases the device reference with netdev_put() but leaves +xdst->u.dst.dev set. dst_destroy() later calls netdev_put(dst->dev) +again, so the same net_device reference is released twice, underflowing +its refcount (ref_tracker WARNING + "unregister_netdevice: waiting for + to become free"). + +Clear xdst->u.dst.dev after the netdev_put(), the same way the XFRM +device-offload paths xfrm_dev_state_add() and xfrm_dev_policy_add() in +net/xfrm/xfrm_device.c NULL ->dev when releasing the reference on error. + + ref_tracker: reference already released. + ref_tracker: allocated in: + xfrm6_fill_dst (net/ipv6/xfrm6_policy.c:86) + ... + udpv6_sendmsg (net/ipv6/udp.c:1696) + ... + ref_tracker: freed in: + xfrm6_fill_dst (net/ipv6/xfrm6_policy.c:90) + ... + WARNING: lib/ref_tracker.c:322 at ref_tracker_free+0x58b/0x780 + dst_destroy (net/core/dst.c:115) + rcu_core + handle_softirqs + ... + +Fixes: 84c4a9dfbf43 ("xfrm6: release dev before returning error") +Reported-by: AutonomousCodeSecurity@microsoft.com +Signed-off-by: Xiang Mei (Microsoft) +Signed-off-by: Steffen Klassert +Signed-off-by: Sasha Levin +--- + net/ipv6/xfrm6_policy.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c +index 125ea9a5b8a082..3b749475f6ed65 100644 +--- a/net/ipv6/xfrm6_policy.c ++++ b/net/ipv6/xfrm6_policy.c +@@ -88,6 +88,7 @@ static int xfrm6_fill_dst(struct xfrm_dst *xdst, struct net_device *dev, + xdst->u.rt6.rt6i_idev = in6_dev_get(dev); + if (!xdst->u.rt6.rt6i_idev) { + netdev_put(dev, &xdst->u.dst.dev_tracker); ++ xdst->u.dst.dev = NULL; + return -ENODEV; + } + +-- +2.53.0 + diff --git a/queue-6.6/alsa-usb-audio-skip-dsd-quirk-for-musical-fidelity-m.patch b/queue-6.6/alsa-usb-audio-skip-dsd-quirk-for-musical-fidelity-m.patch new file mode 100644 index 0000000000..55a48c8567 --- /dev/null +++ b/queue-6.6/alsa-usb-audio-skip-dsd-quirk-for-musical-fidelity-m.patch @@ -0,0 +1,47 @@ +From f49bf28572a05a3275e16f233dd9461017b26886 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 9 Jul 2026 11:56:06 +0200 +Subject: ALSA: usb-audio: Skip DSD quirk for Musical Fidelity M6s DAC + +From: Takashi Iwai + +[ Upstream commit 93b47e66cc6d6c6382d44b44f5e7f6fc3a7b38c3 ] + +Salvador reported that the recent fix for applying the DSD quirk to +Musical Fidelity devices broke for his M6s DAC model (2772:0502). + +Although this is basically a firmware bug, the model in question is +fairly old, and no further firmware update can be expected, so it'd be +better to address in the driver side. + +As an ad hoc workaround, skip the DSD quirk for this device by adding +an empty quirk entry of 2772:0502; this essentially skips the later +DSD quirk entry by the match with the vendor 2772. + +Fixes: da3a7efff64e ("ALSA: usb-audio: Update for native DSD support quirks") +Reported-by: Salvador Blaya +Closes: https://lore.kernel.org/CAOdyq+qFaqCh=tK_wNnA64hv5pQuA1Y09ANxQ=xK8yR-t4mf9Q@mail.gmail.com +Tested-by: Salvador Blaya +Signed-off-by: Takashi Iwai +Link: https://patch.msgid.link/20260709095614.1418838-1-tiwai@suse.de +Signed-off-by: Sasha Levin +--- + sound/usb/quirks.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c +index ed625d5bbe9ab0..8d77662d344f79 100644 +--- a/sound/usb/quirks.c ++++ b/sound/usb/quirks.c +@@ -2269,6 +2269,8 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = { + QUIRK_FLAG_DSD_RAW), + DEVICE_FLG(0x2708, 0x0002, /* Audient iD14 */ + QUIRK_FLAG_IGNORE_CTL_ERROR), ++ DEVICE_FLG(0x2772, 0x0502, /* Musical Fidelity M6s DAC */ ++ 0), /* for avoiding QUIRK_FLAG_DSD_RAW with vendor match */ + DEVICE_FLG(0x2912, 0x30c8, /* Audioengine D1 */ + QUIRK_FLAG_GET_SAMPLE_RATE), + DEVICE_FLG(0x2a70, 0x1881, /* OnePlus Technology (Shenzhen) Co., Ltd. BE02T */ +-- +2.53.0 + diff --git a/queue-6.6/arm64-tegra-fix-cpu-compatible-string-to-cortex-a78a.patch b/queue-6.6/arm64-tegra-fix-cpu-compatible-string-to-cortex-a78a.patch new file mode 100644 index 0000000000..bf931ebf57 --- /dev/null +++ b/queue-6.6/arm64-tegra-fix-cpu-compatible-string-to-cortex-a78a.patch @@ -0,0 +1,144 @@ +From c3ce16e7b3cb2190b0c3dabcd6f9fffaf63a66ab Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 21 Jan 2026 16:15:34 +0530 +Subject: arm64: tegra: Fix CPU compatible string to cortex-a78ae on Tegra234 + +From: Sumit Gupta + +[ Upstream commit 0dfa1e960f86e032007882b032c5cc7d14ebe73e ] + +The Tegra234 SoC uses Cortex-A78AE cores, not Cortex-A78. Update the +compatible string for all CPU nodes to match the actual hardware. + +Tegra234 hardware reports: + # head /proc/cpuinfo | egrep 'implementer|part' + CPU implementer : 0x41 + CPU part : 0xd42 + +Which maps to (from arch/arm64/include/asm/cputype.h): + #define ARM_CPU_IMP_ARM 0x41 + #define ARM_CPU_PART_CORTEX_A78AE 0xD42 + +Fixes: a12cf5c339b08 ("arm64: tegra: Describe Tegra234 CPU hierarchy") +Signed-off-by: Sumit Gupta +Signed-off-by: Thierry Reding +Signed-off-by: Sasha Levin +--- + arch/arm64/boot/dts/nvidia/tegra234.dtsi | 24 ++++++++++++------------ + 1 file changed, 12 insertions(+), 12 deletions(-) + +diff --git a/arch/arm64/boot/dts/nvidia/tegra234.dtsi b/arch/arm64/boot/dts/nvidia/tegra234.dtsi +index d1d7f6a50e11f2..6decf99af5f089 100644 +--- a/arch/arm64/boot/dts/nvidia/tegra234.dtsi ++++ b/arch/arm64/boot/dts/nvidia/tegra234.dtsi +@@ -3109,7 +3109,7 @@ cpus { + #size-cells = <0>; + + cpu0_0: cpu@0 { +- compatible = "arm,cortex-a78"; ++ compatible = "arm,cortex-a78ae"; + device_type = "cpu"; + reg = <0x00000>; + +@@ -3128,7 +3128,7 @@ cpu0_0: cpu@0 { + }; + + cpu0_1: cpu@100 { +- compatible = "arm,cortex-a78"; ++ compatible = "arm,cortex-a78ae"; + device_type = "cpu"; + reg = <0x00100>; + +@@ -3147,7 +3147,7 @@ cpu0_1: cpu@100 { + }; + + cpu0_2: cpu@200 { +- compatible = "arm,cortex-a78"; ++ compatible = "arm,cortex-a78ae"; + device_type = "cpu"; + reg = <0x00200>; + +@@ -3166,7 +3166,7 @@ cpu0_2: cpu@200 { + }; + + cpu0_3: cpu@300 { +- compatible = "arm,cortex-a78"; ++ compatible = "arm,cortex-a78ae"; + device_type = "cpu"; + reg = <0x00300>; + +@@ -3185,7 +3185,7 @@ cpu0_3: cpu@300 { + }; + + cpu1_0: cpu@10000 { +- compatible = "arm,cortex-a78"; ++ compatible = "arm,cortex-a78ae"; + device_type = "cpu"; + reg = <0x10000>; + +@@ -3204,7 +3204,7 @@ cpu1_0: cpu@10000 { + }; + + cpu1_1: cpu@10100 { +- compatible = "arm,cortex-a78"; ++ compatible = "arm,cortex-a78ae"; + device_type = "cpu"; + reg = <0x10100>; + +@@ -3223,7 +3223,7 @@ cpu1_1: cpu@10100 { + }; + + cpu1_2: cpu@10200 { +- compatible = "arm,cortex-a78"; ++ compatible = "arm,cortex-a78ae"; + device_type = "cpu"; + reg = <0x10200>; + +@@ -3242,7 +3242,7 @@ cpu1_2: cpu@10200 { + }; + + cpu1_3: cpu@10300 { +- compatible = "arm,cortex-a78"; ++ compatible = "arm,cortex-a78ae"; + device_type = "cpu"; + reg = <0x10300>; + +@@ -3261,7 +3261,7 @@ cpu1_3: cpu@10300 { + }; + + cpu2_0: cpu@20000 { +- compatible = "arm,cortex-a78"; ++ compatible = "arm,cortex-a78ae"; + device_type = "cpu"; + reg = <0x20000>; + +@@ -3280,7 +3280,7 @@ cpu2_0: cpu@20000 { + }; + + cpu2_1: cpu@20100 { +- compatible = "arm,cortex-a78"; ++ compatible = "arm,cortex-a78ae"; + device_type = "cpu"; + reg = <0x20100>; + +@@ -3299,7 +3299,7 @@ cpu2_1: cpu@20100 { + }; + + cpu2_2: cpu@20200 { +- compatible = "arm,cortex-a78"; ++ compatible = "arm,cortex-a78ae"; + device_type = "cpu"; + reg = <0x20200>; + +@@ -3318,7 +3318,7 @@ cpu2_2: cpu@20200 { + }; + + cpu2_3: cpu@20300 { +- compatible = "arm,cortex-a78"; ++ compatible = "arm,cortex-a78ae"; + device_type = "cpu"; + reg = <0x20300>; + +-- +2.53.0 + diff --git a/queue-6.6/asoc-amd-ps-fix-wrong-acp-version-string-in-pci_requ.patch b/queue-6.6/asoc-amd-ps-fix-wrong-acp-version-string-in-pci_requ.patch new file mode 100644 index 0000000000..37f4c0ed38 --- /dev/null +++ b/queue-6.6/asoc-amd-ps-fix-wrong-acp-version-string-in-pci_requ.patch @@ -0,0 +1,39 @@ +From 77e4a3a713a6eb34288f83be2ef3d3acd4164f52 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 7 Jul 2026 11:29:37 +0530 +Subject: ASoC: amd: ps: fix wrong ACP version string in pci_request_regions() + +From: Vijendar Mukunda + +[ Upstream commit f7697ecf6eab9d4887dd731038b3dc405c7e755e ] + +The driver handles ACP6.3/7.0/7.1/7.2 platforms but the region was +claimed with the stale name "AMD ACP6.2 audio" left over from the +original ACP6.2 driver. Correct it to "AMD ACP6.3 audio". + +Fixes: 95e43a170bb1 ("ASoC: amd: add Pink Sardine ACP PCI driver") +Signed-off-by: Vijendar Mukunda +Reviewed-by: Mario Limonciello (AMD) +Link: https://patch.msgid.link/20260707060130.2514138-3-Vijendar.Mukunda@amd.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/amd/ps/pci-ps.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/sound/soc/amd/ps/pci-ps.c b/sound/soc/amd/ps/pci-ps.c +index 4af3c3665387db..8fe602c0b690cc 100644 +--- a/sound/soc/amd/ps/pci-ps.c ++++ b/sound/soc/amd/ps/pci-ps.c +@@ -599,7 +599,7 @@ static int snd_acp63_probe(struct pci_dev *pci, + return -ENODEV; + } + +- ret = pci_request_regions(pci, "AMD ACP6.2 audio"); ++ ret = pci_request_regions(pci, "AMD ACP6.3 audio"); + if (ret < 0) { + dev_err(&pci->dev, "pci_request_regions failed\n"); + goto disable_pci; +-- +2.53.0 + diff --git a/queue-6.6/asoc-cs42l43-correct-report-for-forced-microphone-ja.patch b/queue-6.6/asoc-cs42l43-correct-report-for-forced-microphone-ja.patch new file mode 100644 index 0000000000..82dfbbdc9f --- /dev/null +++ b/queue-6.6/asoc-cs42l43-correct-report-for-forced-microphone-ja.patch @@ -0,0 +1,45 @@ +From 0a684363e549e554efa8e873d0b0f7b12cf0bec0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 8 Jul 2026 11:34:30 +0100 +Subject: ASoC: cs42l43: Correct report for forced microphone jack + +From: Charles Keepax + +[ Upstream commit f74e6e15485b68b92b2807071e822db6309b7e38 ] + +Currently if the jack is forced to the microphone mode, it will report +as line in. Correct the report to microphone. + +Fixes: fc918cbe874e ("ASoC: cs42l43: Add support for the cs42l43") +Signed-off-by: Charles Keepax +Link: https://patch.msgid.link/20260708103430.1395207-1-ckeepax@opensource.cirrus.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/codecs/cs42l43-jack.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/sound/soc/codecs/cs42l43-jack.c b/sound/soc/codecs/cs42l43-jack.c +index ba60acc4b2f094..d0f424d2e32650 100644 +--- a/sound/soc/codecs/cs42l43-jack.c ++++ b/sound/soc/codecs/cs42l43-jack.c +@@ -283,6 +283,7 @@ irqreturn_t cs42l43_bias_detect_clamp(int irq, void *data) + #define CS42L43_JACK_ABSENT 0x0 + + #define CS42L43_JACK_OPTICAL (SND_JACK_MECHANICAL | SND_JACK_AVOUT) ++#define CS42L43_JACK_MICROPHONE (SND_JACK_MECHANICAL | SND_JACK_MICROPHONE) + #define CS42L43_JACK_HEADPHONE (SND_JACK_MECHANICAL | SND_JACK_HEADPHONE) + #define CS42L43_JACK_HEADSET (SND_JACK_MECHANICAL | SND_JACK_HEADSET) + #define CS42L43_JACK_LINEOUT (SND_JACK_MECHANICAL | SND_JACK_LINEOUT) +@@ -867,7 +868,7 @@ static const struct cs42l43_jack_override_mode { + .hsdet_mode = CS42L43_JACK_3_POLE_SWITCHES, + .mic_ctrl = (0x3 << CS42L43_JACK_STEREO_CONFIG_SHIFT) | + CS42L43_HS1_BIAS_EN_MASK | CS42L43_HS2_BIAS_EN_MASK, +- .report = CS42L43_JACK_LINEIN, ++ .report = CS42L43_JACK_MICROPHONE, + }, + [CS42L43_JACK_RAW_OPTICAL] = { + .hsdet_mode = CS42L43_JACK_3_POLE_SWITCHES, +-- +2.53.0 + diff --git a/queue-6.6/asoc-meson-aiu-fifo-spdif-soft-reset-the-s-pdif-data.patch b/queue-6.6/asoc-meson-aiu-fifo-spdif-soft-reset-the-s-pdif-data.patch new file mode 100644 index 0000000000..091b1019f0 --- /dev/null +++ b/queue-6.6/asoc-meson-aiu-fifo-spdif-soft-reset-the-s-pdif-data.patch @@ -0,0 +1,64 @@ +From 4672804fd825170db46d3225e5eb0e30d9cbb751 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 27 Jun 2026 13:12:05 +0000 +Subject: ASoC: meson: aiu: fifo-spdif: soft reset the S/PDIF datapath on + start/stop + +From: Christian Hewitt + +[ Upstream commit 6b59c53c8adc2b522327407af5e1793a65b67e4b ] + +The I2S FIFO soft-resets its fast domain on start (AIU_RST_SOFT bit 0 + +AIU_I2S_SYNC read in aiu_fifo_i2s_trigger), mirroring the downstream +vendor driver's audio_out_i2s_enable(). The S/PDIF FIFO has no equivalent: +it only toggles the IEC958 DCU, so a stale datapath FIFO can be replayed, +producing the "machine gun noise" buffer underrun - on start when switching +outputs, and on stop when playback ends. The latter is audible on devices +with an always-on S/PDIF-fed DAC (e.g. the ES7144 on the WeTek Play2). + +The vendor driver resets the IEC958 fast domain (AIU_RST_SOFT bit 2) on +both enable and disable (audio_hw_958_enable), and when reconfiguring +(audio_hw_958_reset clears AIU_958_DCU_FF_CTRL then resets). Do the same: +reset before enabling the DCU on start, and before disabling on stop. + +Fixes: 6ae9ca9ce986bf ("ASoC: meson: aiu: add i2s and spdif support") +Signed-off-by: Christian Hewitt +Reviewed-by: Martin Blumenstingl +Link: https://patch.msgid.link/20260627131205.808800-1-christianshewitt@gmail.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/meson/aiu-fifo-spdif.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/sound/soc/meson/aiu-fifo-spdif.c b/sound/soc/meson/aiu-fifo-spdif.c +index fa91f3c53fa462..fe75deafdb69fd 100644 +--- a/sound/soc/meson/aiu-fifo-spdif.c ++++ b/sound/soc/meson/aiu-fifo-spdif.c +@@ -24,6 +24,7 @@ + #define AIU_MEM_IEC958_CONTROL_MODE_16BIT BIT(7) + #define AIU_MEM_IEC958_CONTROL_MODE_LINEAR BIT(8) + #define AIU_MEM_IEC958_BUF_CNTL_INIT BIT(0) ++#define AIU_RST_SOFT_958_FAST BIT(2) + + #define AIU_FIFO_SPDIF_BLOCK 8 + +@@ -68,11 +69,15 @@ static int fifo_spdif_trigger(struct snd_pcm_substream *substream, int cmd, + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: ++ snd_soc_component_write(component, AIU_RST_SOFT, ++ AIU_RST_SOFT_958_FAST); + fifo_spdif_dcu_enable(component, true); + break; + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + case SNDRV_PCM_TRIGGER_STOP: ++ snd_soc_component_write(component, AIU_RST_SOFT, ++ AIU_RST_SOFT_958_FAST); + fifo_spdif_dcu_enable(component, false); + break; + default: +-- +2.53.0 + diff --git a/queue-6.6/asoc-tas2562-fix-deprecated-shut-down-gpio-always-cl.patch b/queue-6.6/asoc-tas2562-fix-deprecated-shut-down-gpio-always-cl.patch new file mode 100644 index 0000000000..23edfd6818 --- /dev/null +++ b/queue-6.6/asoc-tas2562-fix-deprecated-shut-down-gpio-always-cl.patch @@ -0,0 +1,62 @@ +From 55d735ce73149d2e700f6a7723f17ab3081a79b8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 6 Jul 2026 21:01:09 +0530 +Subject: ASoC: tas2562: fix deprecated 'shut-down' GPIO always cleared after + lookup + +From: Uday Khare + +[ Upstream commit 3238c634725afbb2a137fdda762208510828f71d ] + +In tas2562_parse_dt(), the fallback lookup for the deprecated +"shut-down" GPIO property is broken due to a missing pair of braces. + +The code intends to reset sdz_gpio to NULL only when the lookup +returns an error that is not -EPROBE_DEFER (so the driver gracefully +continues without a GPIO). However, without braces the statement: + + tas2562->sdz_gpio = NULL; + +falls outside the IS_ERR() check and is executed unconditionally +for every path through the if block, including a successful GPIO +lookup. + +This means any device using the deprecated 'shut-down' DT property +will always have sdz_gpio == NULL after probe, making the GPIO +completely non-functional. + +Fix this by adding the missing braces to scope the NULL assignment +inside the IS_ERR() branch, matching the pattern already used for +the primary 'shutdown' GPIO lookup above. + +Fixes: f78a97003b8b ("ASoC: tas2562: Update shutdown GPIO property") +Signed-off-by: Uday Khare +Link: https://patch.msgid.link/20260706153109.10953-1-udaykhare77@gmail.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/codecs/tas2562.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/sound/soc/codecs/tas2562.c b/sound/soc/codecs/tas2562.c +index 962c2cdfa01744..a109315a8c0533 100644 +--- a/sound/soc/codecs/tas2562.c ++++ b/sound/soc/codecs/tas2562.c +@@ -684,11 +684,12 @@ static int tas2562_parse_dt(struct tas2562_data *tas2562) + if (tas2562->sdz_gpio == NULL) { + tas2562->sdz_gpio = devm_gpiod_get_optional(dev, "shut-down", + GPIOD_OUT_HIGH); +- if (IS_ERR(tas2562->sdz_gpio)) ++ if (IS_ERR(tas2562->sdz_gpio)) { + if (PTR_ERR(tas2562->sdz_gpio) == -EPROBE_DEFER) + return -EPROBE_DEFER; + +- tas2562->sdz_gpio = NULL; ++ tas2562->sdz_gpio = NULL; ++ } + } + + if (tas2562->model_id == TAS2110) +-- +2.53.0 + diff --git a/queue-6.6/ata-sata_dwc_460ex-enable-sata-interrupts-only-after.patch b/queue-6.6/ata-sata_dwc_460ex-enable-sata-interrupts-only-after.patch new file mode 100644 index 0000000000..0a3a04b791 --- /dev/null +++ b/queue-6.6/ata-sata_dwc_460ex-enable-sata-interrupts-only-after.patch @@ -0,0 +1,56 @@ +From bc4ba3c230ac97bac03c92eb84782d402bd5b1be Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 12 Jul 2026 14:37:26 -0700 +Subject: ata: sata_dwc_460ex: enable SATA interrupts only after IRQ handler is + registered + +From: Rosen Penev + +[ Upstream commit 4bbc16a353a98023e5ddfca7c1fc0e49971cf4d0 ] + +sata_dwc_enable_interrupts() is called before platform_get_irq() and +ata_host_activate(), leaving the SATA controller's interrupt mask +enabled without a registered handler. If a later step fails (irq +request, phy init, etc.) or if the controller asserts an interrupt +during probe, the irq line may fire with no handler, causing a +spurious interrupt storm. + +Move sata_dwc_enable_interrupts() after ata_host_activate() so that +interrupts are only unmasked once the handler is registered and the +core is fully initialized. + +Fixes: 62936009f35a ("[libata] Add 460EX on-chip SATA driver, sata_dwc_460ex") +Assisted-by: opencode:big-pickle +Signed-off-by: Rosen Penev +Signed-off-by: Damien Le Moal +Signed-off-by: Sasha Levin +--- + drivers/ata/sata_dwc_460ex.c | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c +index 52f5168e4db542..16c1deef389d10 100644 +--- a/drivers/ata/sata_dwc_460ex.c ++++ b/drivers/ata/sata_dwc_460ex.c +@@ -1168,9 +1168,6 @@ static int sata_dwc_probe(struct platform_device *ofdev) + /* Save dev for later use in dev_xxx() routines */ + hsdev->dev = dev; + +- /* Enable SATA Interrupts */ +- sata_dwc_enable_interrupts(hsdev); +- + /* Get SATA interrupt number */ + irq = irq_of_parse_and_map(np, 0); + if (!irq) { +@@ -1203,6 +1200,8 @@ static int sata_dwc_probe(struct platform_device *ofdev) + if (err) + dev_err(dev, "failed to activate host"); + ++ /* Enable SATA Interrupts */ ++ sata_dwc_enable_interrupts(hsdev); + return 0; + + error_out: +-- +2.53.0 + diff --git a/queue-6.6/ata-sata_dwc_460ex-fix-clear_interrupt_bit-clearing-.patch b/queue-6.6/ata-sata_dwc_460ex-fix-clear_interrupt_bit-clearing-.patch new file mode 100644 index 0000000000..39c9baf2df --- /dev/null +++ b/queue-6.6/ata-sata_dwc_460ex-fix-clear_interrupt_bit-clearing-.patch @@ -0,0 +1,45 @@ +From e5ca5ec0990e73d23296779a8595150ea10decf9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 12 Jul 2026 14:37:27 -0700 +Subject: ata: sata_dwc_460ex: fix clear_interrupt_bit() clearing all pending + interrupts + +From: Rosen Penev + +[ Upstream commit 66c4e310ad71f41e41736d33dd8a1fb5eaaec7f3 ] + +clear_interrupt_bit() ignores the bit argument and performs a +read-write-back of the entire INTPR register. If INTPR uses standard +Write-1-to-Clear semantics, this clears every pending interrupt bit, +not just the intended one. Coalesced interrupts (e.g. DMAT + NEWFP) +would be cleared together, silently losing the second event. + +Write only the specific bit to clear so that other pending interrupts +are preserved. + +Fixes: 62936009f35a ("[libata] Add 460EX on-chip SATA driver, sata_dwc_460ex") +Assisted-by: opencode:big-pickle +Signed-off-by: Rosen Penev +Signed-off-by: Damien Le Moal +Signed-off-by: Sasha Levin +--- + drivers/ata/sata_dwc_460ex.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c +index 97b934fa116e26..74514608a7fada 100644 +--- a/drivers/ata/sata_dwc_460ex.c ++++ b/drivers/ata/sata_dwc_460ex.c +@@ -394,8 +394,7 @@ static void clear_serror(struct ata_port *ap) + + static void clear_interrupt_bit(struct sata_dwc_device *hsdev, u32 bit) + { +- sata_dwc_writel(&hsdev->sata_dwc_regs->intpr, +- sata_dwc_readl(&hsdev->sata_dwc_regs->intpr)); ++ sata_dwc_writel(&hsdev->sata_dwc_regs->intpr, bit); + } + + static u32 qcmd_tag_to_mask(u8 tag) +-- +2.53.0 + diff --git a/queue-6.6/ata-sata_dwc_460ex-fix-infinite-loop-in-ncq-tag-comp.patch b/queue-6.6/ata-sata_dwc_460ex-fix-infinite-loop-in-ncq-tag-comp.patch new file mode 100644 index 0000000000..d09cee8335 --- /dev/null +++ b/queue-6.6/ata-sata_dwc_460ex-fix-infinite-loop-in-ncq-tag-comp.patch @@ -0,0 +1,54 @@ +From 16c28ef0055eb0651dfd619ace0db575df7957a5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 12 Jul 2026 14:37:28 -0700 +Subject: ata: sata_dwc_460ex: fix infinite loop in NCQ tag completion + bit-scanning + +From: Rosen Penev + +[ Upstream commit c2130f6553f4a5cbdc259de069600117a995f197 ] + +The hand-rolled bit-scanning loop in the NCQ completion path has an +infinite loop bug. When tag_mask has only high bits set (e.g. +0x80000000), the inner while loop left-shifts tag_mask until it +overflows to 0. At that point !(0 & 1) is always true and 0 <<= 1 +stays 0, causing an infinite loop in hardirq context with a spinlock +held. + +Replace the open-coded bit-scanning with __ffs() which correctly +finds the least significant set bit and is bounded by the width of +the argument. + +Fixes: 62936009f35a ("[libata] Add 460EX on-chip SATA driver, sata_dwc_460ex") +Assisted-by: opencode:big-pickle +Signed-off-by: Rosen Penev +Signed-off-by: Damien Le Moal +Signed-off-by: Sasha Levin +--- + drivers/ata/sata_dwc_460ex.c | 9 ++------- + 1 file changed, 2 insertions(+), 7 deletions(-) + +diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c +index 74514608a7fada..66db8dd8ec2670 100644 +--- a/drivers/ata/sata_dwc_460ex.c ++++ b/drivers/ata/sata_dwc_460ex.c +@@ -607,14 +607,9 @@ static irqreturn_t sata_dwc_isr(int irq, void *dev_instance) + status = ap->ops->sff_check_status(ap); + dev_dbg(ap->dev, "%s ATA status register=0x%x\n", __func__, status); + +- tag = 0; + while (tag_mask) { +- while (!(tag_mask & 0x00000001)) { +- tag++; +- tag_mask <<= 1; +- } +- +- tag_mask &= (~0x00000001); ++ tag = __ffs(tag_mask); ++ tag_mask &= ~(1U << tag); + qc = ata_qc_from_tag(ap, tag); + if (unlikely(!qc)) { + dev_err(ap->dev, "failed to get qc"); +-- +2.53.0 + diff --git a/queue-6.6/ata-sata_dwc_460ex-use-platform_get_irq.patch b/queue-6.6/ata-sata_dwc_460ex-use-platform_get_irq.patch new file mode 100644 index 0000000000..2fd8810077 --- /dev/null +++ b/queue-6.6/ata-sata_dwc_460ex-use-platform_get_irq.patch @@ -0,0 +1,92 @@ +From d6b13a1e3db9e498cf8eb90e88b4ccc8d0add612 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 12 Jul 2026 14:37:25 -0700 +Subject: ata: sata_dwc_460ex: use platform_get_irq() + +From: Rosen Penev + +[ Upstream commit a4af122106f73ea510bb35a9ea1dedd980fc0db7 ] + +Replace irq_of_parse_and_map() with platform_get_irq() in both +sata_dwc_dma_init_old() and sata_dwc_probe(). This is the preferred +way to obtain IRQs for platform devices and provides better error +reporting. Remove the now-unnecessary #include . + +irq_of_parse_and_map() requires irq_dispose_mapping(), which is missing. + +Also fix unused variable when CONFIG_SATA_DWC_OLD_DMA is disabled. + +Fixes: 62936009f35a ("[libata] Add 460EX on-chip SATA driver, sata_dwc_460ex") +Assisted-by: opencode:big-pickle +Signed-off-by: Rosen Penev +Signed-off-by: Damien Le Moal +Signed-off-by: Sasha Levin +--- + drivers/ata/sata_dwc_460ex.c | 21 +++++++-------------- + 1 file changed, 7 insertions(+), 14 deletions(-) + +diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c +index 16c1deef389d10..97b934fa116e26 100644 +--- a/drivers/ata/sata_dwc_460ex.c ++++ b/drivers/ata/sata_dwc_460ex.c +@@ -19,7 +19,6 @@ + #include + #include + #include +-#include + #include + #include + #include +@@ -226,7 +225,6 @@ static int sata_dwc_dma_init_old(struct platform_device *pdev, + struct sata_dwc_device *hsdev) + { + struct device *dev = &pdev->dev; +- struct device_node *np = dev->of_node; + + hsdev->dma = devm_kzalloc(dev, sizeof(*hsdev->dma), GFP_KERNEL); + if (!hsdev->dma) +@@ -236,11 +234,9 @@ static int sata_dwc_dma_init_old(struct platform_device *pdev, + hsdev->dma->id = pdev->id; + + /* Get SATA DMA interrupt number */ +- hsdev->dma->irq = irq_of_parse_and_map(np, 1); +- if (!hsdev->dma->irq) { +- dev_err(dev, "no SATA DMA irq\n"); +- return -ENODEV; +- } ++ hsdev->dma->irq = platform_get_irq(pdev, 1); ++ if (hsdev->dma->irq < 0) ++ return hsdev->dma->irq; + + /* Get physical SATA DMA register base address */ + hsdev->dma->regs = devm_platform_ioremap_resource(pdev, 1); +@@ -1125,7 +1121,6 @@ static const struct ata_port_info sata_dwc_port_info[] = { + static int sata_dwc_probe(struct platform_device *ofdev) + { + struct device *dev = &ofdev->dev; +- struct device_node *np = dev->of_node; + struct sata_dwc_device *hsdev; + u32 idr, versionr; + char *ver = (char *)&versionr; +@@ -1169,14 +1164,12 @@ static int sata_dwc_probe(struct platform_device *ofdev) + hsdev->dev = dev; + + /* Get SATA interrupt number */ +- irq = irq_of_parse_and_map(np, 0); +- if (!irq) { +- dev_err(dev, "no SATA DMA irq\n"); +- return -ENODEV; +- } ++ irq = platform_get_irq(ofdev, 0); ++ if (irq < 0) ++ return irq; + + #ifdef CONFIG_SATA_DWC_OLD_DMA +- if (!of_property_present(np, "dmas")) { ++ if (!of_property_present(dev->of_node, "dmas")) { + err = sata_dwc_dma_init_old(ofdev, hsdev); + if (err) + return err; +-- +2.53.0 + diff --git a/queue-6.6/bluetooth-hci_qca-clear-memdump-state-on-invalid-dum.patch b/queue-6.6/bluetooth-hci_qca-clear-memdump-state-on-invalid-dum.patch new file mode 100644 index 0000000000..bff6fab0b8 --- /dev/null +++ b/queue-6.6/bluetooth-hci_qca-clear-memdump-state-on-invalid-dum.patch @@ -0,0 +1,55 @@ +From a1e3cf309950a1a015a5290dbcb650a3ea6e6350 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 9 Jul 2026 14:22:50 +0800 +Subject: Bluetooth: hci_qca: Clear memdump state on invalid dump size + +From: Ruoyu Wang + +[ Upstream commit bf587a10c33e5571a299742e45bc18960b9912e7 ] + +qca_controller_memdump() allocates qca->qca_memdump before processing +the first dump packet. For a sequence-zero packet it then disables IBS, +marks memdump collection active, and reads the advertised dump size. + +If the controller reports a zero dump size, the error path frees the +local qca_memdump object and returns without clearing qca->qca_memdump +or undoing the collection state. A later memdump work item initializes +its local pointer from qca->qca_memdump and skips allocation when that +pointer is non-NULL, so it can operate on freed memory. The stale +collection and IBS-disabled flags can also leave waiters or later +transmit handling blocked behind an aborted dump. + +Clear the saved pointer and memdump state before returning from the +invalid-size path, matching the cleanup used when hci_devcd_init() fails. + +A static analysis checker reported the stale memdump state, and manual +source review confirmed the invalid-size failure path. + +Fixes: 06d3fdfcdf5c ("Bluetooth: hci_qca: Add qcom devcoredump support") +Signed-off-by: Ruoyu Wang +Reviewed-by: Paul Menzel +Reviewed-by: Zijun Hu +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + drivers/bluetooth/hci_qca.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c +index 2986b18655a150..47c50a43db0232 100644 +--- a/drivers/bluetooth/hci_qca.c ++++ b/drivers/bluetooth/hci_qca.c +@@ -1069,6 +1069,10 @@ static void qca_controller_memdump(struct work_struct *work) + if (!(qca_memdump->ram_dump_size)) { + bt_dev_err(hu->hdev, "Rx invalid memdump size"); + kfree(qca_memdump); ++ qca->qca_memdump = NULL; ++ qca->memdump_state = QCA_MEMDUMP_COLLECTED; ++ clear_and_wake_up_bit(QCA_MEMDUMP_COLLECTION, &qca->flags); ++ clear_bit(QCA_IBS_DISABLED, &qca->flags); + kfree_skb(skb); + mutex_unlock(&qca->hci_memdump_lock); + return; +-- +2.53.0 + diff --git a/queue-6.6/bluetooth-mgmt-fix-locking-in-unpair_device-disconne.patch b/queue-6.6/bluetooth-mgmt-fix-locking-in-unpair_device-disconne.patch new file mode 100644 index 0000000000..b4bee2c896 --- /dev/null +++ b/queue-6.6/bluetooth-mgmt-fix-locking-in-unpair_device-disconne.patch @@ -0,0 +1,88 @@ +From bf17a794933e787e75eaca81489671269e25c214 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 10 Jul 2026 11:23:41 +0300 +Subject: Bluetooth: mgmt: fix locking in unpair_device/disconnect_sync + +From: Pauli Virtanen + +[ Upstream commit 16cd66443957e4ad42155c6fec401012f600c6f8 ] + +Dereferencing RCU-protected pointers outside critical sections is +invalid and may lead to UAF. + +Take hdev->lock for hci_conn lookup and hci_abort_conn(). Don't use RCU +to ensure the conn is fully initialized at this point. + +Fixes: 227a0cdf4a028 ("Bluetooth: MGMT: Fix not generating command complete for MGMT_OP_DISCONNECT") +Signed-off-by: Pauli Virtanen +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/mgmt.c | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + +diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c +index 20fe7f011b75c2..2d9781668cb74a 100644 +--- a/net/bluetooth/mgmt.c ++++ b/net/bluetooth/mgmt.c +@@ -3005,6 +3005,8 @@ static int unpair_device_sync(struct hci_dev *hdev, void *data) + struct mgmt_cp_unpair_device *cp = cmd->param; + struct hci_conn *conn; + ++ hci_dev_lock(hdev); ++ + if (cp->addr.type == BDADDR_BREDR) + conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, + &cp->addr.bdaddr); +@@ -3012,6 +3014,11 @@ static int unpair_device_sync(struct hci_dev *hdev, void *data) + conn = hci_conn_hash_lookup_le(hdev, &cp->addr.bdaddr, + le_addr_type(cp->addr.type)); + ++ if (conn) ++ hci_conn_get(conn); ++ ++ hci_dev_unlock(hdev); ++ + if (!conn) + return 0; + +@@ -3019,6 +3026,7 @@ static int unpair_device_sync(struct hci_dev *hdev, void *data) + * will clean up the connection no matter the error. + */ + hci_abort_conn(conn, HCI_ERROR_REMOTE_USER_TERM); ++ hci_conn_put(conn); + + return 0; + } +@@ -3166,6 +3174,8 @@ static int disconnect_sync(struct hci_dev *hdev, void *data) + struct mgmt_cp_disconnect *cp = cmd->param; + struct hci_conn *conn; + ++ hci_dev_lock(hdev); ++ + if (cp->addr.type == BDADDR_BREDR) + conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, + &cp->addr.bdaddr); +@@ -3173,6 +3183,11 @@ static int disconnect_sync(struct hci_dev *hdev, void *data) + conn = hci_conn_hash_lookup_le(hdev, &cp->addr.bdaddr, + le_addr_type(cp->addr.type)); + ++ if (conn) ++ hci_conn_get(conn); ++ ++ hci_dev_unlock(hdev); ++ + if (!conn) + return -ENOTCONN; + +@@ -3180,6 +3195,7 @@ static int disconnect_sync(struct hci_dev *hdev, void *data) + * will clean up the connection no matter the error. + */ + hci_abort_conn(conn, HCI_ERROR_REMOTE_USER_TERM); ++ hci_conn_put(conn); + + return 0; + } +-- +2.53.0 + diff --git a/queue-6.6/bluetooth-mgmt-hold-reference-for-hci_conn-in-mgmt_p.patch b/queue-6.6/bluetooth-mgmt-hold-reference-for-hci_conn-in-mgmt_p.patch new file mode 100644 index 0000000000..6a13a049bf --- /dev/null +++ b/queue-6.6/bluetooth-mgmt-hold-reference-for-hci_conn-in-mgmt_p.patch @@ -0,0 +1,107 @@ +From bc548702fd1de53bd541fecba1505aaaf8bb77b2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 10 Jul 2026 11:23:42 +0300 +Subject: Bluetooth: mgmt: hold reference for hci_conn in mgmt_pending_cmds + +From: Pauli Virtanen + +[ Upstream commit da55f570191d5d72f10c607a7043b947eb05ea46 ] + +Dereferencing RCU-protected pointers outside critical sections is +invalid and may lead to UAF. Use of hci_conn in hci_sync callbacks also +needs to hold refcount to avoid UAF. + +Take appropriate locks for hci_conn lookups, and take refcount for +hci_conn pointers stored in mgmt_pending_cmd so that the pointer stays +valid. + +When accessing conn->state, ensure hdev->lock is held to avoid data +race. + +Fixes: 7b445e220db9 ("Bluetooth: MGMT: Fix holding hci_conn reference while command is queued") +Signed-off-by: Pauli Virtanen +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/mgmt.c | 26 ++++++++++++++++++++++---- + 1 file changed, 22 insertions(+), 4 deletions(-) + +diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c +index 2d9781668cb74a..979caeb85a42c7 100644 +--- a/net/bluetooth/mgmt.c ++++ b/net/bluetooth/mgmt.c +@@ -7417,6 +7417,9 @@ static void get_conn_info_complete(struct hci_dev *hdev, void *data, int err) + rp.max_tx_power = HCI_TX_POWER_INVALID; + } + ++ if (conn) ++ hci_conn_put(conn); ++ + mgmt_cmd_complete(cmd->sk, cmd->hdev->id, MGMT_OP_GET_CONN_INFO, status, + &rp, sizeof(rp)); + +@@ -7431,6 +7434,8 @@ static int get_conn_info_sync(struct hci_dev *hdev, void *data) + int err; + __le16 handle; + ++ hci_dev_lock(hdev); ++ + /* Make sure we are still connected */ + if (cp->addr.type == BDADDR_BREDR) + conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, +@@ -7438,12 +7443,16 @@ static int get_conn_info_sync(struct hci_dev *hdev, void *data) + else + conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr); + +- if (!conn || conn->state != BT_CONNECTED) ++ if (!conn || conn->state != BT_CONNECTED) { ++ hci_dev_unlock(hdev); + return MGMT_STATUS_NOT_CONNECTED; ++ } + +- cmd->user_data = conn; ++ cmd->user_data = hci_conn_get(conn); + handle = cpu_to_le16(conn->handle); + ++ hci_dev_unlock(hdev); ++ + /* Refresh RSSI each time */ + err = hci_read_rssi_sync(hdev, handle); + +@@ -7577,6 +7586,9 @@ static void get_clock_info_complete(struct hci_dev *hdev, void *data, int err) + } + + complete: ++ if (conn) ++ hci_conn_put(conn); ++ + mgmt_cmd_complete(cmd->sk, cmd->hdev->id, cmd->opcode, status, &rp, + sizeof(rp)); + +@@ -7593,15 +7605,21 @@ static int get_clock_info_sync(struct hci_dev *hdev, void *data) + memset(&hci_cp, 0, sizeof(hci_cp)); + hci_read_clock_sync(hdev, &hci_cp); + ++ hci_dev_lock(hdev); ++ + /* Make sure connection still exists */ + conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->addr.bdaddr); +- if (!conn || conn->state != BT_CONNECTED) ++ if (!conn || conn->state != BT_CONNECTED) { ++ hci_dev_unlock(hdev); + return MGMT_STATUS_NOT_CONNECTED; ++ } + +- cmd->user_data = conn; ++ cmd->user_data = hci_conn_get(conn); + hci_cp.handle = cpu_to_le16(conn->handle); + hci_cp.which = 0x01; /* Piconet clock */ + ++ hci_dev_unlock(hdev); ++ + return hci_read_clock_sync(hdev, &hci_cp); + } + +-- +2.53.0 + diff --git a/queue-6.6/bluetooth-qca-fix-nvm-tag-length-underflow-in-tlv-pa.patch b/queue-6.6/bluetooth-qca-fix-nvm-tag-length-underflow-in-tlv-pa.patch new file mode 100644 index 0000000000..8cdbc0920f --- /dev/null +++ b/queue-6.6/bluetooth-qca-fix-nvm-tag-length-underflow-in-tlv-pa.patch @@ -0,0 +1,68 @@ +From f985439a532e8a7c9c50e9346fdffc72af23625c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 4 Jul 2026 16:10:30 -0700 +Subject: Bluetooth: qca: fix NVM tag length underflow in TLV parser + +From: Xiang Mei + +[ Upstream commit c90164ca0f7036942ba088eb7ea8d3f6c2352020 ] + +In the TLV_TYPE_NVM branch of qca_tlv_check_data() the tag loop bound is +"while (idx < length - sizeof(struct tlv_type_nvm))". "length" is a signed +int from the firmware TLV header and sizeof(struct tlv_type_nvm) is a +size_t (12), so "length" is converted to size_t and any firmware-supplied +"length" < 12 makes the subtraction wrap to a huge value. The loop body +then reads a 12-byte struct tlv_type_nvm past the end of the short +vmalloc'd firmware buffer (and the EDL_TAG_ID_* handlers can write past it). + +Rewrite the bound as "idx + sizeof(struct tlv_type_nvm) <= length"; both +operands are non-negative, so it no longer underflows and a "length" too +small for one record correctly skips the loop. + + BUG: KASAN: vmalloc-out-of-bounds in qca_download_firmware.isra.0 (drivers/bluetooth/btqca.c:421) + Read of size 2 at addr ffffc900000e5004 by task kworker/u9:0/52 + Workqueue: hci0 hci_power_on + Call Trace: + ... + kasan_report (mm/kasan/report.c:595) + qca_download_firmware.isra.0 (drivers/bluetooth/btqca.c:421 drivers/bluetooth/btqca.c:617) + qca_uart_setup (drivers/bluetooth/btqca.c:948) + qca_setup (drivers/bluetooth/hci_qca.c:2029) + hci_uart_setup (drivers/bluetooth/hci_ldisc.c:438) + hci_dev_open_sync (net/bluetooth/hci_sync.c:5227) + hci_power_on (net/bluetooth/hci_core.c:920) + process_one_work (kernel/workqueue.c:3322) + worker_thread (kernel/workqueue.c:3486) + kthread (kernel/kthread.c:436) + ret_from_fork (arch/x86/kernel/process.c:158) + ret_from_fork_asm (arch/x86/entry/entry_64.S:245) + +Fixes: 2e4edfa1e2bd ("Bluetooth: qca: add missing firmware sanity checks") +Reported-by: Weiming Shi +Assisted-by: Claude:claude-opus-4-8 +Signed-off-by: Xiang Mei +Reported-by: Weiming Shi +Reviewed-by: Johan Hovold +Acked-by: Bartosz Golaszewski +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + drivers/bluetooth/btqca.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/bluetooth/btqca.c b/drivers/bluetooth/btqca.c +index 5b34da23adce7c..09ef7df5c231bf 100644 +--- a/drivers/bluetooth/btqca.c ++++ b/drivers/bluetooth/btqca.c +@@ -430,7 +430,7 @@ static int qca_tlv_check_data(struct hci_dev *hdev, + + idx = 0; + data = tlv->data; +- while (idx < length - sizeof(struct tlv_type_nvm)) { ++ while (idx + sizeof(struct tlv_type_nvm) <= length) { + tlv_nvm = (struct tlv_type_nvm *)(data + idx); + + tag_id = le16_to_cpu(tlv_nvm->tag_id); +-- +2.53.0 + diff --git a/queue-6.6/bpf-sockmap-reject-unhashed-udp-sockets-on-sockmap-u.patch b/queue-6.6/bpf-sockmap-reject-unhashed-udp-sockets-on-sockmap-u.patch new file mode 100644 index 0000000000..3bab107c56 --- /dev/null +++ b/queue-6.6/bpf-sockmap-reject-unhashed-udp-sockets-on-sockmap-u.patch @@ -0,0 +1,74 @@ +From b54ac57221e3a728cc23301e5e7de8866cea4dea Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 7 Jul 2026 06:23:57 +0200 +Subject: bpf, sockmap: Reject unhashed UDP sockets on sockmap update + +From: Michal Luczaj + +[ Upstream commit 66efd3368ae10d05e08fbe6425b50fdec7186ac7 ] + +UDP sockets get SOCK_RCU_FREE set when (auto-)bound. This means +sk_is_refcounted(unbound) = true, while sk_is_refcounted(bound) = false. + +Because sockmap accepts unbound UDP sockets, a BPF program can increment a +socket's refcount via lookup. If the socket is subsequently bound, the +transition from unbound to bound causes bpf_sk_release() to skip the +decrement of the refcount, causing a memory leak. + +unreferenced object 0xffff88810bc2eb40 (size 1984): + comm "test_progs", pid 2451, jiffies 4295320596 + hex dump (first 32 bytes): + 7f 00 00 01 7f 00 00 01 d2 04 1b b7 04 d2 00 00 ................ + 02 00 01 40 00 00 00 00 00 00 00 00 00 00 00 00 ...@............ + backtrace (crc bdee079d): + kmem_cache_alloc_noprof+0x557/0x660 + sk_prot_alloc+0x69/0x240 + sk_alloc+0x30/0x460 + inet_create+0x2ce/0xf80 + __sock_create+0x25b/0x5c0 + __sys_socket+0x119/0x1d0 + __x64_sys_socket+0x72/0xd0 + do_syscall_64+0xa1/0x5f0 + entry_SYSCALL_64_after_hwframe+0x76/0x7e + +Instead of special-casing for refcounted sockets, reject unhashed UDP +sockets during sockmap updates, as there is no benefit to supporting those. +This effectively reverts the commit under Fixes, with two exceptions: + +1. sock_map_sk_state_allowed() maintains a fall-through `return true`. +2. In the spirit of commit b8b8315e39ff ("bpf, sockmap: Remove unhash + handler for BPF sockmap usage"), the proto::unhash BPF handler is not + reintroduced. + +Historical note: this issue is related to commit 67312adc96b5 ("bpf: reject +unhashed sockets in bpf_sk_assign"). + +Fixes: 0c48eefae712 ("sock_map: Lift socket state restriction for datagram sockets") +Suggested-by: Kuniyuki Iwashima +Signed-off-by: Michal Luczaj +Reviewed-by: Kuniyuki Iwashima +Reviewed-by: Jakub Sitnicki +Reviewed-by: John Fastabend +Link: https://lore.kernel.org/bpf/20260707-sockmap-lookup-udp-leak-v4-2-f878346f27ab@rbox.co +Signed-off-by: Kumar Kartikeya Dwivedi +Signed-off-by: Sasha Levin +--- + net/core/sock_map.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/net/core/sock_map.c b/net/core/sock_map.c +index 3a53b6a0e76e2b..052057303cff11 100644 +--- a/net/core/sock_map.c ++++ b/net/core/sock_map.c +@@ -539,6 +539,8 @@ static bool sock_map_sk_state_allowed(const struct sock *sk) + { + if (sk_is_tcp(sk)) + return (1 << sk->sk_state) & (TCPF_ESTABLISHED | TCPF_LISTEN); ++ if (sk_is_udp(sk)) ++ return sk_hashed(sk); + if (sk_is_stream_unix(sk)) + return (1 << sk->sk_state) & TCPF_ESTABLISHED; + if (sk_is_vsock(sk) && +-- +2.53.0 + diff --git a/queue-6.6/btrfs-fix-root-leak-if-its-reloc-root-is-unexpected-.patch b/queue-6.6/btrfs-fix-root-leak-if-its-reloc-root-is-unexpected-.patch new file mode 100644 index 0000000000..156a692dab --- /dev/null +++ b/queue-6.6/btrfs-fix-root-leak-if-its-reloc-root-is-unexpected-.patch @@ -0,0 +1,40 @@ +From f0b4983acccece1380927134dde9c89363defe42 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 11 Jun 2026 15:16:21 +0100 +Subject: btrfs: fix root leak if its reloc root is unexpected in + merge_reloc_roots() + +From: Filipe Manana + +[ Upstream commit ce6050bafb4e33377dc17fcc357736bfc351180c ] + +If we have an unexpected reloc_root for our root, we jump to the out label +but never drop the reference we obtained for root, resulting in a leak. +Add a missing btrfs_put_root() call. + +Fixes: 24213fa46c70 ("btrfs: do proper error handling in merge_reloc_roots") +Reviewed-by: Qu Wenruo +Reviewed-by: Johannes Thumshirn +Signed-off-by: Filipe Manana +Reviewed-by: David Sterba +Signed-off-by: David Sterba +Signed-off-by: Sasha Levin +--- + fs/btrfs/relocation.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c +index 0f05eb97925fdd..90aacda2523eb5 100644 +--- a/fs/btrfs/relocation.c ++++ b/fs/btrfs/relocation.c +@@ -1991,6 +1991,7 @@ void merge_reloc_roots(struct reloc_control *rc) + * corruption, e.g. bad reloc tree key offset. + */ + ret = -EINVAL; ++ btrfs_put_root(root); + goto out; + } + ret = merge_reloc_root(rc, root); +-- +2.53.0 + diff --git a/queue-6.6/btrfs-reject-free-space-cache-with-more-entries-than.patch b/queue-6.6/btrfs-reject-free-space-cache-with-more-entries-than.patch new file mode 100644 index 0000000000..b2ca70f9ab --- /dev/null +++ b/queue-6.6/btrfs-reject-free-space-cache-with-more-entries-than.patch @@ -0,0 +1,88 @@ +From fb06b5ea70e89228bd02433f2959afe47e3a15f1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 10 Jun 2026 10:29:26 -0700 +Subject: btrfs: reject free space cache with more entries than pages + +From: Xiang Mei + +[ Upstream commit a2d8d5647ed854e38f941741aea45b9eb15a6350 ] + +When loading a v1 free space cache, __load_free_space_cache() takes +num_entries and num_bitmaps straight from the on-disk +btrfs_free_space_header. That header is stored in the tree_root under a key +with type 0, which the tree-checker has no case for, so neither count is +validated before the load trusts it. + +The load loops num_entries times and maps the next page whenever the current +one runs out, going through io_ctl_check_crc() -> io_ctl_map_page(), which +does io_ctl->pages[io_ctl->index++]. But pages[] is allocated in +io_ctl_init() from the cache inode's i_size, not from num_entries: + + num_pages = DIV_ROUND_UP(i_size_read(inode), PAGE_SIZE); + io_ctl->pages = kcalloc(num_pages, sizeof(struct page *), GFP_NOFS); + +So if num_entries claims more records than the pages can hold, io_ctl->index +runs off the end of pages[]. The write side never hits this because +io_ctl_add_entry() and io_ctl_add_bitmap() both stop once +io_ctl->index >= io_ctl->num_pages; the read side just never had the same +check. + +To trigger it, take a clean cache (num_entries = here), set num_entries +in the header to 0x10000, and fix up the leaf checksum so it still passes +the tree-checker. The cache inode has i_size = 65536, so num_pages is 16 and +pages[] is a 16-pointer (kmalloc-128) array. The load now tries to read +65536 entries, io_ctl->index walks up to 16, and pages[16] is read past the +array: + + BUG: KASAN: slab-out-of-bounds in io_ctl_check_crc (fs/btrfs/free-space-cache.c:420 fs/btrfs/free-space-cache.c:565) + Read of size 8 at addr ffff88800c833a80 by task kworker/u8:3/58 + io_ctl_check_crc (fs/btrfs/free-space-cache.c:420 fs/btrfs/free-space-cache.c:565) + __load_free_space_cache (fs/btrfs/free-space-cache.c:655 fs/btrfs/free-space-cache.c:820) + load_free_space_cache (fs/btrfs/free-space-cache.c:1017) + caching_thread (fs/btrfs/block-group.c:880) + btrfs_work_helper (fs/btrfs/async-thread.c:312) + process_one_work + worker_thread + kthread + ret_from_fork + +free-space-cache.c:420 is io_ctl_map_page(), inlined into io_ctl_check_crc() +at line 565, which is why that is the frame KASAN names. The out-of-bounds +slot is then treated as a struct page and handed to crc32c(), so the bad +read turns into a GP fault. + +Add the missing check to io_ctl_check_crc(), which is where both the entry +loop and the bitmap loop end up. When num_entries is too large the load now +fails like any corrupt cache: __load_free_space_cache() drops it and rebuilds +the free space from the extent tree, so a valid cache is never rejected. + +Reported-by: Weiming Shi +Fixes: 5b0e95bf607d ("Btrfs: inline checksums into the disk free space cache") +Link: https://lore.kernel.org/linux-btrfs/CAPpSM+RMPByMCKXvM5QFKToxsyNccfuFLWMdD0mfd0wh2Ja62w@mail.gmail.com/ +Assisted-by: Claude:claude-opus-4-8 +Reviewed-by: Qu Wenruo +Signed-off-by: Xiang Mei +Reviewed-by: David Sterba +Signed-off-by: David Sterba +Signed-off-by: Sasha Levin +--- + fs/btrfs/free-space-cache.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c +index c6e3b9a2921ab1..8be5614ae9b620 100644 +--- a/fs/btrfs/free-space-cache.c ++++ b/fs/btrfs/free-space-cache.c +@@ -559,6 +559,9 @@ static int io_ctl_check_crc(struct btrfs_io_ctl *io_ctl, int index) + u32 crc = ~(u32)0; + unsigned offset = 0; + ++ if (index >= io_ctl->num_pages) ++ return -EIO; ++ + if (index == 0) + offset = sizeof(u32) * io_ctl->num_pages; + +-- +2.53.0 + diff --git a/queue-6.6/can-j1939-fix-lockless-local-destination-check.patch b/queue-6.6/can-j1939-fix-lockless-local-destination-check.patch new file mode 100644 index 0000000000..216ab6c15d --- /dev/null +++ b/queue-6.6/can-j1939-fix-lockless-local-destination-check.patch @@ -0,0 +1,81 @@ +From 71531bd2ca42e5635894c250ff1044742337fe3d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 7 May 2026 10:22:26 +0200 +Subject: can: j1939: fix lockless local-destination check + +From: Shuhao Fu + +[ Upstream commit e4e8af62adab2fdcca230006f829407a953070cd ] + +j1939_priv.ents[].nusers is documented as protected by priv->lock, and +its updates already happen under that lock. j1939_can_recv() also reads +it under read_lock_bh(). However, j1939_session_skb_queue() and +j1939_tp_send() still read priv->ents[da].nusers without taking the +lock. + +Those transport-side checks decide whether to set J1939_ECU_LOCAL_DST, so +they can race with j1939_local_ecu_get() and j1939_local_ecu_put() while +userspace is binding or releasing sockets concurrently with TP traffic. +This can misclassify TP/ETP sessions as local or remote and take the wrong +transport path. + +Fix both transport paths by routing the destination-locality check through +a helper that reads ents[].nusers under read_lock_bh(&priv->lock). + +Fixes: 9d71dd0c7009 ("can: add support of SAE J1939 protocol") +Signed-off-by: Shuhao Fu +Tested-by: Oleksij Rempel +Acked-by: Oleksij Rempel +Link: https://patch.msgid.link/20260419140614.GA4041240@chcpu16 +Signed-off-by: Marc Kleine-Budde +Signed-off-by: Sasha Levin +--- + net/can/j1939/transport.c | 18 ++++++++++++++---- + 1 file changed, 14 insertions(+), 4 deletions(-) + +diff --git a/net/can/j1939/transport.c b/net/can/j1939/transport.c +index 6c37562a50f72e..d8dada03b3cd12 100644 +--- a/net/can/j1939/transport.c ++++ b/net/can/j1939/transport.c +@@ -350,6 +350,18 @@ static void j1939_session_skb_drop_old(struct j1939_session *session) + } + } + ++static bool j1939_address_is_local(struct j1939_priv *priv, u8 addr) ++{ ++ bool local = false; ++ ++ read_lock_bh(&priv->lock); ++ if (j1939_address_is_unicast(addr) && priv->ents[addr].nusers) ++ local = true; ++ read_unlock_bh(&priv->lock); ++ ++ return local; ++} ++ + void j1939_session_skb_queue(struct j1939_session *session, + struct sk_buff *skb) + { +@@ -358,8 +370,7 @@ void j1939_session_skb_queue(struct j1939_session *session, + + j1939_ac_fixup(priv, skb); + +- if (j1939_address_is_unicast(skcb->addr.da) && +- priv->ents[skcb->addr.da].nusers) ++ if (j1939_address_is_local(priv, skcb->addr.da)) + skcb->flags |= J1939_ECU_LOCAL_DST; + + skcb->flags |= J1939_ECU_LOCAL_SRC; +@@ -2021,8 +2032,7 @@ struct j1939_session *j1939_tp_send(struct j1939_priv *priv, + return ERR_PTR(ret); + + /* fix DST flags, it may be used there soon */ +- if (j1939_address_is_unicast(skcb->addr.da) && +- priv->ents[skcb->addr.da].nusers) ++ if (j1939_address_is_local(priv, skcb->addr.da)) + skcb->flags |= J1939_ECU_LOCAL_DST; + + /* src is always local, I'm sending ... */ +-- +2.53.0 + diff --git a/queue-6.6/drm-i915-gt-use-correct-selftest-config-symbol.patch b/queue-6.6/drm-i915-gt-use-correct-selftest-config-symbol.patch new file mode 100644 index 0000000000..e9b5ccf1b4 --- /dev/null +++ b/queue-6.6/drm-i915-gt-use-correct-selftest-config-symbol.patch @@ -0,0 +1,50 @@ +From 735966ebdde72beb6fa06343f3069c8db3040f9e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 5 Jul 2026 16:02:25 +0800 +Subject: drm/i915/gt: use correct selftest config symbol + +From: Pengpeng Hou + +[ Upstream commit a82f1bb8191aec98a971a2196136016ef70c0880 ] + +intel_engine_user.c checks CONFIG_DRM_I915_SELFTESTS before running +the engine UABI isolation check. Kconfig defines DRM_I915_SELFTEST, +without the trailing "S", and the rest of i915 uses +CONFIG_DRM_I915_SELFTEST. + +Because CONFIG_DRM_I915_SELFTESTS is not backed by any Kconfig symbol, +the IS_ENABLED() test is always false. Use the existing selftest symbol +so the debug/selftest guarded path can be reached when selftests are +enabled. + +This is a source-level fix. It does not claim dynamic hardware +reproduction; the evidence is the Kconfig definition and the inconsistent +guard in intel_engine_user.c. + +Fixes: 750e76b4f9f6 ("drm/i915/gt: Move the [class][inst] lookup for engines onto the GT") +Signed-off-by: Pengpeng Hou +Signed-off-by: Tvrtko Ursulin +Link: https://lore.kernel.org/r/20260705080225.436-1-pengpeng@iscas.ac.cn +(cherry picked from commit 14a2012a490258f3f93857bc4f1b203405964be7) +Signed-off-by: Rodrigo Vivi +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/i915/gt/intel_engine_user.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/i915/gt/intel_engine_user.c b/drivers/gpu/drm/i915/gt/intel_engine_user.c +index d304e0a948f0d1..13b27ee9e7bef2 100644 +--- a/drivers/gpu/drm/i915/gt/intel_engine_user.c ++++ b/drivers/gpu/drm/i915/gt/intel_engine_user.c +@@ -260,7 +260,7 @@ void intel_engines_driver_register(struct drm_i915_private *i915) + p = &prev->rb_right; + } + +- if (IS_ENABLED(CONFIG_DRM_I915_SELFTESTS) && ++ if (IS_ENABLED(CONFIG_DRM_I915_SELFTEST) && + IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM)) { + struct intel_engine_cs *engine; + unsigned int isolation; +-- +2.53.0 + diff --git a/queue-6.6/drm-i915-selftests-fix-gt-pm-sort-comparators.patch b/queue-6.6/drm-i915-selftests-fix-gt-pm-sort-comparators.patch new file mode 100644 index 0000000000..c5bcd17747 --- /dev/null +++ b/queue-6.6/drm-i915-selftests-fix-gt-pm-sort-comparators.patch @@ -0,0 +1,55 @@ +From 4e64b88750d16f37967b76e0e8a9981226de64f4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 15 Jul 2026 01:04:30 +0300 +Subject: drm/i915/selftests: Fix GT PM sort comparators + +From: Emre Cecanpunar + +[ Upstream commit 612978b83f45bf7018815209db5395d759db6f26 ] + +Compare the sampled clock values instead of their addresses. Comparing +addresses leaves the samples unsorted, preventing the code from discarding +the minimum and maximum samples. + +Fixes: 1a5392479207 ("drm/i915/selftests: Measure CS_TIMESTAMP") +Signed-off-by: Emre Cecanpunar +Signed-off-by: Tvrtko Ursulin +Link: https://lore.kernel.org/r/20260714220430.238433-1-emreleno@gmail.com +(cherry picked from commit 682ea2d28d18bb06f9fc663cb5ab7e80dc0e606a) +Signed-off-by: Rodrigo Vivi +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/i915/gt/selftest_gt_pm.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/drivers/gpu/drm/i915/gt/selftest_gt_pm.c b/drivers/gpu/drm/i915/gt/selftest_gt_pm.c +index 0971241707ce83..d396fbd55b740b 100644 +--- a/drivers/gpu/drm/i915/gt/selftest_gt_pm.c ++++ b/drivers/gpu/drm/i915/gt/selftest_gt_pm.c +@@ -16,9 +16,9 @@ static int cmp_u64(const void *A, const void *B) + { + const u64 *a = A, *b = B; + +- if (a < b) ++ if (*a < *b) + return -1; +- else if (a > b) ++ else if (*a > *b) + return 1; + else + return 0; +@@ -28,9 +28,9 @@ static int cmp_u32(const void *A, const void *B) + { + const u32 *a = A, *b = B; + +- if (a < b) ++ if (*a < *b) + return -1; +- else if (a > b) ++ else if (*a > *b) + return 1; + else + return 0; +-- +2.53.0 + diff --git a/queue-6.6/firmware-arm_ffa-fix-null-dereference-in-ffa_partiti.patch b/queue-6.6/firmware-arm_ffa-fix-null-dereference-in-ffa_partiti.patch new file mode 100644 index 0000000000..9d6ed4295b --- /dev/null +++ b/queue-6.6/firmware-arm_ffa-fix-null-dereference-in-ffa_partiti.patch @@ -0,0 +1,48 @@ +From c1c76ef67b595de535ef503708b058408c57fa17 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 17 Jun 2026 16:35:00 -0700 +Subject: firmware: arm_ffa: Fix NULL dereference in ffa_partition_info_get() + +From: Unnathi Chalicheemala + +[ Upstream commit 8ae5f8e4836667fcaffdf2e3c6068b0a8b364dd8 ] + +ffa_partition_info_get() passes uuid_str directly to uuid_parse() +without a NULL check. When a caller passes NULL, uuid_parse() -> +__uuid_parse() -> uuid_is_valid() dereferences the pointer, causing +a kernel panic: + + | Unable to handle kernel NULL pointer dereference at virtual address + | 0000000000000040 + | pc : uuid_parse+0x40/0xac + | lr : ffa_partition_info_get+0x1c/0x94 [arm_ffa] + +Add a NULL guard before uuid_parse() so a NULL argument returns +-ENODEV instead of crashing. Callers are expected to always supply +a valid partition UUID, so NULL is not a supported input. + +Fixes: d0c0bce83122 ("firmware: arm_ffa: Setup in-kernel users of FFA partitions") +Signed-off-by: Unnathi Chalicheemala +Link: https://patch.msgid.link/20260617-ffa_partition_nullptr_fix-v2-1-bc801b4ce34c@oss.qualcomm.com +Signed-off-by: Sudeep Holla +Signed-off-by: Sasha Levin +--- + drivers/firmware/arm_ffa/driver.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/firmware/arm_ffa/driver.c b/drivers/firmware/arm_ffa/driver.c +index ece91d8d820b51..2309a31549e25a 100644 +--- a/drivers/firmware/arm_ffa/driver.c ++++ b/drivers/firmware/arm_ffa/driver.c +@@ -582,7 +582,7 @@ static int ffa_partition_info_get(const char *uuid_str, + uuid_t uuid; + struct ffa_partition_info *pbuf; + +- if (uuid_parse(uuid_str, &uuid)) { ++ if (!uuid_str || uuid_parse(uuid_str, &uuid)) { + pr_err("invalid uuid (%s)\n", uuid_str); + return -ENODEV; + } +-- +2.53.0 + diff --git a/queue-6.6/firmware-arm_scmi-rate-limit-queue-full-warnings-in-.patch b/queue-6.6/firmware-arm_scmi-rate-limit-queue-full-warnings-in-.patch new file mode 100644 index 0000000000..e62b43f133 --- /dev/null +++ b/queue-6.6/firmware-arm_scmi-rate-limit-queue-full-warnings-in-.patch @@ -0,0 +1,54 @@ +From 429e0a9ec869f466a8c9e44079424e254dffc82c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 8 Jul 2026 12:53:39 +0530 +Subject: firmware: arm_scmi: Rate-limit queue-full warnings in IRQ context + +From: Pushpendra Singh + +[ Upstream commit a4447c0693830d5ecadd6e755cb7fdc55d86aacc ] + +The scmi_notify() function is called from interrupt context to queue +received notification events onto a per-protocol kfifo. When the kfifo +is full, it logs a warning via dev_warn() for every dropped event. + +Under conditions where the platform sends a burst of SCMI notifications +faster than the deferred worker can drain the queue, this results in a +flood of dev_warn() calls from IRQ context. Each call acquires the +console lock and may execute blocking console writes, causing the CPU +to be held in interrupt context for an extended period and leading to +observable system stalls. + +Fix this by switching to dev_warn_ratelimited() to limit the frequency +of log messages when the notification queue is full. This reduces +console overhead in interrupt context and prevents CPU stalls caused by +excessive logging, while still preserving diagnostic visibility. + +Fixes: bd31b249692e ("firmware: arm_scmi: Add notification dispatch and delivery") +Signed-off-by: Pushpendra Singh +Link: https://patch.msgid.link/20260708072339.3021140-1-pushpendra.singh@oss.qualcomm.com +Signed-off-by: Sudeep Holla +Signed-off-by: Sasha Levin +--- + drivers/firmware/arm_scmi/notify.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/firmware/arm_scmi/notify.c b/drivers/firmware/arm_scmi/notify.c +index 4782b115e6ec51..1bc715fe3968c3 100644 +--- a/drivers/firmware/arm_scmi/notify.c ++++ b/drivers/firmware/arm_scmi/notify.c +@@ -595,9 +595,9 @@ int scmi_notify(const struct scmi_handle *handle, u8 proto_id, u8 evt_id, + return -EINVAL; + } + if (kfifo_avail(&r_evt->proto->equeue.kfifo) < sizeof(eh) + len) { +- dev_warn(handle->dev, +- "queue full, dropping proto_id:%d evt_id:%d ts:%lld\n", +- proto_id, evt_id, ktime_to_ns(ts)); ++ dev_warn_ratelimited(handle->dev, ++ "queue full, dropping proto_id:%d evt_id:%d ts:%lld\n", ++ proto_id, evt_id, ktime_to_ns(ts)); + return -ENOMEM; + } + +-- +2.53.0 + diff --git a/queue-6.6/ib-mad-drop-unmatched-rmpp-responses-before-reassemb.patch b/queue-6.6/ib-mad-drop-unmatched-rmpp-responses-before-reassemb.patch new file mode 100644 index 0000000000..8e833d2e43 --- /dev/null +++ b/queue-6.6/ib-mad-drop-unmatched-rmpp-responses-before-reassemb.patch @@ -0,0 +1,90 @@ +From 4701b6916689bc938628639a8d799a90184f81dd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 6 Jun 2026 16:01:55 -0400 +Subject: IB/mad: Drop unmatched RMPP responses before reassembly + +From: Michael Bommarito + +[ Upstream commit d2e52d610b9b09694261632340b801a421e0b0c5 ] + +Kernel-handled RMPP receive processing starts reassembly for active +DATA responses before the response is matched to an outstanding send. +The normal match happens later, after ib_process_rmpp_recv_wc() has +either assembled a complete message or consumed the segment. + +That ordering lets an unsolicited response that routes to a kernel +RMPP agent by the high TID bits allocate or extend RMPP receive state +before the full TID and source address are checked against a real +request. A reordered burst can therefore reach the receive-side +insertion path even though the response would not match any send. + +For kernel-handled RMPP DATA responses, require the existing +ib_find_send_mad() match before entering RMPP reassembly. The matcher +already checks the full TID, management class and source address/GID +against the agent wait, backlog and in-flight send lists. If there is +no match, drop the response without creating RMPP state. + +This leaves the RMPP window behavior unchanged and only rejects +responses that have no corresponding request. + +Fixes: fa619a77046b ("[PATCH] IB: Add RMPP implementation") +Assisted-by: Codex:gpt-5-5-xhigh +Signed-off-by: Michael Bommarito +Link: https://patch.msgid.link/3170ff3bc389a930bb1641f2caa394a0b2241579.1780774907.git.michael.bommarito@gmail.com +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + drivers/infiniband/core/mad.c | 30 ++++++++++++++++++++++++++++++ + 1 file changed, 30 insertions(+) + +diff --git a/drivers/infiniband/core/mad.c b/drivers/infiniband/core/mad.c +index 242434c09e8d8f..bddb1c607aff62 100644 +--- a/drivers/infiniband/core/mad.c ++++ b/drivers/infiniband/core/mad.c +@@ -1778,6 +1778,24 @@ void ib_mark_mad_done(struct ib_mad_send_wr_private *mad_send_wr) + &mad_send_wr->mad_agent_priv->done_list); + } + ++static bool is_kernel_rmpp_data_response(struct ib_mad_agent_private *agent, ++ struct ib_mad_recv_wc *mad_recv_wc) ++{ ++ const struct ib_mad_hdr *mad_hdr = &mad_recv_wc->recv_buf.mad->mad_hdr; ++ struct ib_rmpp_mad *rmpp_mad; ++ ++ if (!ib_mad_kernel_rmpp_agent(&agent->agent) || ++ !ib_response_mad(mad_hdr) || ++ !ib_is_mad_class_rmpp(mad_hdr->mgmt_class)) ++ return false; ++ ++ rmpp_mad = (struct ib_rmpp_mad *)mad_recv_wc->recv_buf.mad; ++ ++ return (ib_get_rmpp_flags(&rmpp_mad->rmpp_hdr) & ++ IB_MGMT_RMPP_FLAG_ACTIVE) && ++ rmpp_mad->rmpp_hdr.rmpp_type == IB_MGMT_RMPP_TYPE_DATA; ++} ++ + static void ib_mad_complete_recv(struct ib_mad_agent_private *mad_agent_priv, + struct ib_mad_recv_wc *mad_recv_wc) + { +@@ -1796,6 +1814,18 @@ static void ib_mad_complete_recv(struct ib_mad_agent_private *mad_agent_priv, + } + + list_add(&mad_recv_wc->recv_buf.list, &mad_recv_wc->rmpp_list); ++ if (is_kernel_rmpp_data_response(mad_agent_priv, mad_recv_wc)) { ++ spin_lock_irqsave(&mad_agent_priv->lock, flags); ++ mad_send_wr = ib_find_send_mad(mad_agent_priv, mad_recv_wc); ++ spin_unlock_irqrestore(&mad_agent_priv->lock, flags); ++ ++ if (!mad_send_wr) { ++ ib_free_recv_mad(mad_recv_wc); ++ deref_mad_agent(mad_agent_priv); ++ return; ++ } ++ } ++ + if (ib_mad_kernel_rmpp_agent(&mad_agent_priv->agent)) { + mad_recv_wc = ib_process_rmpp_recv_wc(mad_agent_priv, + mad_recv_wc); +-- +2.53.0 + diff --git a/queue-6.6/ipv4-fib-free-fib_alias-with-kfree_rcu-on-insert-err.patch b/queue-6.6/ipv4-fib-free-fib_alias-with-kfree_rcu-on-insert-err.patch new file mode 100644 index 0000000000..a145b6ba71 --- /dev/null +++ b/queue-6.6/ipv4-fib-free-fib_alias-with-kfree_rcu-on-insert-err.patch @@ -0,0 +1,67 @@ +From 50c2f63ea3e7504935fdd663a4c6f34f753beb5c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 4 Jul 2026 10:14:21 -0700 +Subject: ipv4: fib: free fib_alias with kfree_rcu() on insert error path + +From: Weiming Shi + +[ Upstream commit f2f152e94a67bc746afaf05a1b2702c195553112 ] + +fib_table_insert() publishes new_fa into the leaf's fa_list with +fib_insert_alias() before calling the fib entry notifiers. When a +notifier fails, the error path removes new_fa with fib_remove_alias() +(hlist_del_rcu) and frees it right away with kmem_cache_free(). + +fib_table_lookup() walks that list under rcu_read_lock() only, so a +concurrent lookup that already reached new_fa keeps reading it after the +free: + + BUG: KASAN: slab-use-after-free in fib_table_lookup (net/ipv4/fib_trie.c:1601) + Read of size 1 at addr ffff88810676d4eb by task exploit/297 + Call Trace: + fib_table_lookup (net/ipv4/fib_trie.c:1601) + ip_route_output_key_hash_rcu (net/ipv4/route.c:2814) + ip_route_output_key_hash (net/ipv4/route.c:2705) + __ip4_datagram_connect (net/ipv4/datagram.c:49) + udp_connect (net/ipv4/udp.c:2144) + __sys_connect (net/socket.c:2167) + __x64_sys_connect (net/socket.c:2173) + do_syscall_64 + entry_SYSCALL_64_after_hwframe + which belongs to the cache ip_fib_alias of size 56 + +Triggering the error path needs CAP_NET_ADMIN and a registered fib +notifier that can reject a route; a netdevsim device whose IPv4 FIB +resource is exhausted is enough. + +Free new_fa with alias_free_mem_rcu(), as fib_table_delete() already +does for a fib_alias removed from the trie. + +Fixes: a6c76c17df02 ("ipv4: Notify route after insertion to the routing table") +Reported-by: Xiang Mei +Assisted-by: Claude:claude-opus-4-8 +Signed-off-by: Weiming Shi +Reviewed-by: Ido Schimmel +Link: https://patch.msgid.link/20260704171421.1786806-1-bestswngs@gmail.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/ipv4/fib_trie.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c +index c9e1526e749b2b..53e7664eeb0a2a 100644 +--- a/net/ipv4/fib_trie.c ++++ b/net/ipv4/fib_trie.c +@@ -1390,7 +1390,7 @@ int fib_table_insert(struct net *net, struct fib_table *tb, + out_remove_new_fa: + fib_remove_alias(t, tp, l, new_fa); + out_free_new_fa: +- kmem_cache_free(fn_alias_kmem, new_fa); ++ alias_free_mem_rcu(new_fa); + out: + fib_release_info(fi); + err: +-- +2.53.0 + diff --git a/queue-6.6/ksmbd-pin-conn-during-async-oplock-break-notificatio.patch b/queue-6.6/ksmbd-pin-conn-during-async-oplock-break-notificatio.patch new file mode 100644 index 0000000000..2e49393940 --- /dev/null +++ b/queue-6.6/ksmbd-pin-conn-during-async-oplock-break-notificatio.patch @@ -0,0 +1,75 @@ +From 0e53619c02fb79c9145174ebc9d07440d7861baa Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 9 Jul 2026 22:49:55 +0800 +Subject: ksmbd: pin conn during async oplock break notification + +From: Qihang + +[ Upstream commit aa5d8f3f96aa11a4a54ce993c11ce8af11c546f9 ] + +smb2_oplock_break_noti() and smb2_lease_break_noti() store a ksmbd_conn +pointer in an async ksmbd_work and then queue that work on ksmbd-io. The +work only increments conn->r_count, which prevents teardown from passing +the pending-request wait after the increment, but it does not pin the +struct ksmbd_conn object. + +If connection teardown races with an oplock break notification, the last +conn reference can be dropped before the queued worker finishes. The +worker then uses the freed conn in ksmbd_conn_write() and +ksmbd_conn_r_count_dec(). + +Take a real conn reference when publishing the conn pointer to the async +work item, and drop it after the notification work has decremented +r_count. Apply the same lifetime rule to lease break notification, which +uses the same work->conn pattern. + +Fixes: 3aa660c05924 ("ksmbd: prevent connection release during oplock break notification") +Signed-off-by: Qihang +Acked-by: Namjae Jeon +Signed-off-by: Steve French +Signed-off-by: Sasha Levin +--- + fs/smb/server/oplock.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/fs/smb/server/oplock.c b/fs/smb/server/oplock.c +index 82a7709b3e9ac8..109bb71d06adff 100644 +--- a/fs/smb/server/oplock.c ++++ b/fs/smb/server/oplock.c +@@ -705,6 +705,7 @@ static void __smb2_oplock_break_noti(struct work_struct *wk) + out: + ksmbd_free_work_struct(work); + ksmbd_conn_r_count_dec(conn); ++ ksmbd_conn_put(conn); + } + + /** +@@ -740,7 +741,7 @@ static int smb2_oplock_break_noti(struct oplock_info *opinfo) + br_info->open_trunc = opinfo->open_trunc; + + work->request_buf = (char *)br_info; +- work->conn = conn; ++ work->conn = ksmbd_conn_get(conn); + work->sess = opinfo->sess; + + ksmbd_conn_r_count_inc(conn); +@@ -814,6 +815,7 @@ static void __smb2_lease_break_noti(struct work_struct *wk) + out: + ksmbd_free_work_struct(work); + ksmbd_conn_r_count_dec(conn); ++ ksmbd_conn_put(conn); + } + + /** +@@ -853,7 +855,7 @@ static int smb2_lease_break_noti(struct oplock_info *opinfo) + memcpy(br_info->lease_key, lease->lease_key, SMB2_LEASE_KEY_SIZE); + + work->request_buf = (char *)br_info; +- work->conn = conn; ++ work->conn = ksmbd_conn_get(conn); + work->sess = opinfo->sess; + + ksmbd_conn_r_count_inc(conn); +-- +2.53.0 + diff --git a/queue-6.6/ksmbd-validate-compound-request-size-before-reading-.patch b/queue-6.6/ksmbd-validate-compound-request-size-before-reading-.patch new file mode 100644 index 0000000000..d79bd3650d --- /dev/null +++ b/queue-6.6/ksmbd-validate-compound-request-size-before-reading-.patch @@ -0,0 +1,69 @@ +From baeb0952b39688fdc919a805c9d1cca476c59378 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 13 Jul 2026 21:55:10 +0000 +Subject: ksmbd: validate compound request size before reading StructureSize2 + +From: Xiang Mei (Microsoft) + +[ Upstream commit 15b38176fd1530372905c602fde51fe89ec8c877 ] + +When ksmbd validates a compound (chained) SMB2 request, +ksmbd_smb2_check_message() reads pdu->StructureSize2 without first +checking that the compound element is large enough to contain it. +StructureSize2 is a 2-byte field at offset 64 +(__SMB2_HEADER_STRUCTURE_SIZE) from the start of each element. + +The compound-walking logic only guarantees that a full 64-byte SMB2 +header is present for the trailing element: when NextCommand is 0, len is +reduced to the number of bytes remaining after next_smb2_rcv_hdr_off. A +remote client can craft a compound request whose last element has exactly +64 bytes, so the 2-byte StructureSize2 read at offset 64 extends one byte +past the receive buffer, producing a slab-out-of-bounds read. + + BUG: KASAN: slab-out-of-bounds in ksmbd_smb2_check_message (fs/smb/server/smb2misc.c:402) + Read of size 2 at addr ffff888012ae31ac by task kworker/0:1/14 + The buggy address is located 172 bytes inside of allocated 173-byte region + Workqueue: ksmbd-io handle_ksmbd_work + Call Trace: + ... + kasan_report (mm/kasan/report.c:595) + ksmbd_smb2_check_message (fs/smb/server/smb2misc.c:402) + handle_ksmbd_work (fs/smb/server/server.c:119) + process_one_work (kernel/workqueue.c:3314) + worker_thread (kernel/workqueue.c:3397) + kthread (kernel/kthread.c:436) + ret_from_fork (arch/x86/kernel/process.c:158) + ret_from_fork_asm (arch/x86/entry/entry_64.S:245) + +Reject any compound element that is too small to hold StructureSize2 +before dereferencing it. + +Fixes: e2f34481b24d ("cifsd: add server-side procedures for SMB3") +Reported-by: AutonomousCodeSecurity@microsoft.com +Signed-off-by: Xiang Mei (Microsoft) +Acked-by: Namjae Jeon +Signed-off-by: Steve French +Signed-off-by: Sasha Levin +--- + fs/smb/server/smb2misc.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/fs/smb/server/smb2misc.c b/fs/smb/server/smb2misc.c +index 727cb49926ee52..ffbddf00d24e95 100644 +--- a/fs/smb/server/smb2misc.c ++++ b/fs/smb/server/smb2misc.c +@@ -400,6 +400,11 @@ int ksmbd_smb2_check_message(struct ksmbd_work *work) + return 1; + } + ++ if (len < __SMB2_HEADER_STRUCTURE_SIZE + sizeof(__le16)) { ++ ksmbd_debug(SMB, "Message is too small for StructureSize2\n"); ++ return 1; ++ } ++ + if (smb2_req_struct_sizes[command] != pdu->StructureSize2) { + if (!(command == SMB2_OPLOCK_BREAK_HE && + (le16_to_cpu(pdu->StructureSize2) == OP_BREAK_STRUCT_SIZE_20 || +-- +2.53.0 + diff --git a/queue-6.6/mpls-fix-null-deref-in-mpls_valid_fib_dump_req-on-co.patch b/queue-6.6/mpls-fix-null-deref-in-mpls_valid_fib_dump_req-on-co.patch new file mode 100644 index 0000000000..c4b5fbb1b5 --- /dev/null +++ b/queue-6.6/mpls-fix-null-deref-in-mpls_valid_fib_dump_req-on-co.patch @@ -0,0 +1,68 @@ +From 5df6f66914760a65857caa8fb2bd47f92f3ec5ea Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 11 Jul 2026 04:50:00 -0700 +Subject: mpls: fix NULL deref in mpls_valid_fib_dump_req() on CONFIG_INET=n + +From: Weiming Shi + +[ Upstream commit 56d96fededd61192cd7cc8d2b0f36adfd59036c3 ] + +On CONFIG_INET=n builds, mpls_valid_fib_dump_req() walks the parsed +attribute table itself instead of calling ip_valid_fib_dump_req(). The +RTA_OIF arm passes tb[RTA_OIF] to nla_get_u32() without checking it is +present, so an RTM_GETROUTE dump for AF_MPLS with strict checking and no +RTA_OIF hits a NULL dereference. + +RTM_GETROUTE is RTNL_KIND_GET, which rtnetlink_rcv_msg() permits without +CAP_NET_ADMIN, so an unprivileged user can trigger it. + + Oops: general protection fault, probably for non-canonical address + 0xdffffc0000000000: 0000 [#1] SMP KASAN NOPTI + KASAN: null-ptr-deref in range [0x0000000000000000-0x0000000000000007] + RIP: 0010:mpls_valid_fib_dump_req (net/mpls/af_mpls.c:2189) + Call Trace: + mpls_dump_routes (net/mpls/af_mpls.c:2236) + netlink_dump (net/netlink/af_netlink.c:2331) + __netlink_dump_start (net/netlink/af_netlink.c:2446) + rtnetlink_rcv_msg (net/core/rtnetlink.c:7033) + netlink_rcv_skb (net/netlink/af_netlink.c:2556) + netlink_unicast (net/netlink/af_netlink.c:1345) + netlink_sendmsg (net/netlink/af_netlink.c:1900) + __sock_sendmsg (net/socket.c:790) + ____sys_sendmsg (net/socket.c:2684) + ___sys_sendmsg (net/socket.c:2738) + __sys_sendmsg (net/socket.c:2770) + do_syscall_64 (arch/x86/entry/syscall_64.c:94) + entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:121) + +Skip unset attributes, as ip_valid_fib_dump_req() does. + +Fixes: 196cfebf8972 ("net/mpls: Handle kernel side filtering of route dumps") +Assisted-by: Claude:claude-opus-4-8 +Reported-by: Xiang Mei +Signed-off-by: Weiming Shi +Reviewed-by: David Ahern +Link: https://patch.msgid.link/20260711114958.1009619-3-bestswngs@gmail.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/mpls/af_mpls.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/net/mpls/af_mpls.c b/net/mpls/af_mpls.c +index 0561a530ecf0d9..2099ce095edc8e 100644 +--- a/net/mpls/af_mpls.c ++++ b/net/mpls/af_mpls.c +@@ -2125,6 +2125,9 @@ static int mpls_valid_fib_dump_req(struct net *net, const struct nlmsghdr *nlh, + int ifindex; + + if (i == RTA_OIF) { ++ if (!tb[i]) ++ continue; ++ + ifindex = nla_get_u32(tb[i]); + filter->dev = __dev_get_by_index(net, ifindex); + if (!filter->dev) +-- +2.53.0 + diff --git a/queue-6.6/mtd-fix-double-free-and-warn_on-in-add_mtd_device-er.patch b/queue-6.6/mtd-fix-double-free-and-warn_on-in-add_mtd_device-er.patch new file mode 100644 index 0000000000..d778431898 --- /dev/null +++ b/queue-6.6/mtd-fix-double-free-and-warn_on-in-add_mtd_device-er.patch @@ -0,0 +1,102 @@ +From e23ae0ea5cd3d6845d8c4d1b5c073b06391e76f2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 1 Jul 2026 20:10:42 +0800 +Subject: mtd: fix double free and WARN_ON in add_mtd_device() error paths + +From: Xue Lei + +[ Upstream commit 9d4af746af8ce27eefc2338b2feaa1e01f28b6c3 ] + +When device_register() or mtd_nvmem_add() fails inside +add_mtd_device() for a partition, the error handling triggers +mtd_release() via put_device() or device_unregister(). mtd_release() +calls release_mtd_partition() which frees the mtd_info structure. +However, callers such as mtd_add_partition() and add_mtd_partitions() +also call free_partition() in their error paths, resulting in a double +free. + +Additionally, release_mtd_partition() hits WARN_ON(!list_empty( +&mtd->part.node)) because the partition node is still linked in the +parent's partitions list when the release callback fires from the +add_mtd_device() error path. + +Fix this by overriding dev->type and dev->release before put_device() +in the error paths, so that device_release() invokes a no-op function +instead of mtd_release(). For the mtd_nvmem_add() failure case, +device_unregister() is replaced with device_del() to separate the +device removal from the final kobject reference drop, allowing the +override to take effect before put_device() is called. + +The callers' error paths (list_del + free_partition) remain the sole +owners of mtd_info lifetime on add_mtd_device() failure, which is the +expected contract. + +The normal partition teardown path is not affected: del_mtd_device() +goes through kref_put() -> mtd_device_release() -> device_unregister() +with dev->type still set to &mtd_devtype, so mtd_release() -> +release_mtd_partition() continues to work correctly for the regular +removal case. + +Reported-by: syzbot+e9c76b56dc05023b8117@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=e9c76b56dc05023b8117 +Fixes: 19bfa9ebebb5 ("mtd: use refcount to prevent corruption") +Signed-off-by: Xue Lei +Signed-off-by: Miquel Raynal +Signed-off-by: Sasha Levin +--- + drivers/mtd/mtdcore.c | 23 +++++++++++++++++++---- + 1 file changed, 19 insertions(+), 4 deletions(-) + +diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c +index 97ca2a897f1d49..506ebd4ba1b458 100644 +--- a/drivers/mtd/mtdcore.c ++++ b/drivers/mtd/mtdcore.c +@@ -103,6 +103,15 @@ static void mtd_release(struct device *dev) + device_destroy(&mtd_class, index + 1); + } + ++/* ++ * No-op device release used in add_mtd_device() error paths. ++ * Prevents mtd_release() from being called via device_release(), ++ * which would free the mtd_info that the caller still manages. ++ */ ++static void mtd_dev_release_nop(struct device *dev) ++{ ++} ++ + static void mtd_device_release(struct kref *kref) + { + struct mtd_info *mtd = container_of(kref, struct mtd_info, refcnt); +@@ -745,10 +754,8 @@ int add_mtd_device(struct mtd_info *mtd) + mtd_check_of_node(mtd); + of_node_get(mtd_get_of_node(mtd)); + error = device_register(&mtd->dev); +- if (error) { +- put_device(&mtd->dev); ++ if (error) + goto fail_added; +- } + + /* Add the nvmem provider */ + error = mtd_nvmem_add(mtd); +@@ -786,8 +793,16 @@ int add_mtd_device(struct mtd_info *mtd) + return 0; + + fail_nvmem_add: +- device_unregister(&mtd->dev); ++ device_del(&mtd->dev); + fail_added: ++ /* ++ * Clear type and set nop release to prevent mtd_release() -> ++ * release_mtd_partition() -> free_partition() from freeing mtd. ++ * The caller handles cleanup on failure. ++ */ ++ mtd->dev.type = NULL; ++ mtd->dev.release = mtd_dev_release_nop; ++ put_device(&mtd->dev); + of_node_put(mtd_get_of_node(mtd)); + idr_remove(&mtd_idr, i); + fail_locked: +-- +2.53.0 + diff --git a/queue-6.6/mtd-mtdswap-remove-debugfs-stats-file-on-teardown.patch b/queue-6.6/mtd-mtdswap-remove-debugfs-stats-file-on-teardown.patch new file mode 100644 index 0000000000..d5a866c5e8 --- /dev/null +++ b/queue-6.6/mtd-mtdswap-remove-debugfs-stats-file-on-teardown.patch @@ -0,0 +1,57 @@ +From bfc22a57c7ddf543462126cd612d13d26037b2ca Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 23 Jun 2026 09:53:17 +0800 +Subject: mtd: mtdswap: remove debugfs stats file on teardown + +From: Pengpeng Hou + +[ Upstream commit 66fb31358108d10245b9e4ef0eef3e7d9747055e ] + +mtdswap_add_debugfs() creates an mtdswap_stats debugfs file under the +per-MTD debugfs directory, but mtdswap_remove_dev() never removes it +before freeing the mtdswap_dev. + +Store the returned dentry and remove it during device teardown before the +driver-private state is freed. + +Fixes: a32159024620 ("mtd: Add mtdswap block driver") +Signed-off-by: Pengpeng Hou +Signed-off-by: Miquel Raynal +Signed-off-by: Sasha Levin +--- + drivers/mtd/mtdswap.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/drivers/mtd/mtdswap.c b/drivers/mtd/mtdswap.c +index 680366616da240..4d695875ea1b23 100644 +--- a/drivers/mtd/mtdswap.c ++++ b/drivers/mtd/mtdswap.c +@@ -125,6 +125,7 @@ struct mtdswap_dev { + + char *page_buf; + char *oob_buf; ++ struct dentry *debugfs_stats; + }; + + struct mtdswap_oobdata { +@@ -1262,7 +1263,8 @@ static int mtdswap_add_debugfs(struct mtdswap_dev *d) + if (IS_ERR_OR_NULL(root)) + return -1; + +- debugfs_create_file("mtdswap_stats", S_IRUSR, root, d, &mtdswap_fops); ++ d->debugfs_stats = debugfs_create_file("mtdswap_stats", 0400, root, ++ d, &mtdswap_fops); + + return 0; + } +@@ -1463,6 +1465,7 @@ static void mtdswap_remove_dev(struct mtd_blktrans_dev *dev) + { + struct mtdswap_dev *d = MTDSWAP_MBD_TO_MTDSWAP(dev); + ++ debugfs_remove(d->debugfs_stats); + del_mtd_blktrans_dev(dev); + mtdswap_cleanup(d); + kfree(d); +-- +2.53.0 + diff --git a/queue-6.6/mtd-nand-mtk-ecc-stop-on-ecc-idle-timeouts.patch b/queue-6.6/mtd-nand-mtk-ecc-stop-on-ecc-idle-timeouts.patch new file mode 100644 index 0000000000..9dd4120a76 --- /dev/null +++ b/queue-6.6/mtd-nand-mtk-ecc-stop-on-ecc-idle-timeouts.patch @@ -0,0 +1,75 @@ +From 04237dc10029c01d84808bc978fbddc2f33ecf31 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 23 Jun 2026 21:57:29 +0800 +Subject: mtd: nand: mtk-ecc: stop on ECC idle timeouts + +From: Pengpeng Hou + +[ Upstream commit 16f7ec8d5dc100eafd2c8e06cd30340a30b104a1 ] + +mtk_ecc_wait_idle() logs when the encoder or decoder does not become +idle, but returns void. Callers can therefore configure a non-idle ECC +engine or read parity bytes after an unconfirmed encoder idle state. + +Return the idle poll result and propagate it from the enable and encode +paths that require the engine to be idle before continuing. + +Fixes: 1d6b1e464950 ("mtd: mediatek: driver for MTK Smart Device") +Signed-off-by: Pengpeng Hou +Signed-off-by: Miquel Raynal +Signed-off-by: Sasha Levin +--- + drivers/mtd/nand/ecc-mtk.c | 16 ++++++++++++---- + 1 file changed, 12 insertions(+), 4 deletions(-) + +diff --git a/drivers/mtd/nand/ecc-mtk.c b/drivers/mtd/nand/ecc-mtk.c +index c75bb8b80cc1e1..96703f0a418ea2 100644 +--- a/drivers/mtd/nand/ecc-mtk.c ++++ b/drivers/mtd/nand/ecc-mtk.c +@@ -123,8 +123,8 @@ static int mt7622_ecc_regs[] = { + [ECC_DECIRQ_STA] = 0x144, + }; + +-static inline void mtk_ecc_wait_idle(struct mtk_ecc *ecc, +- enum mtk_ecc_operation op) ++static inline int mtk_ecc_wait_idle(struct mtk_ecc *ecc, ++ enum mtk_ecc_operation op) + { + struct device *dev = ecc->dev; + u32 val; +@@ -136,6 +136,8 @@ static inline void mtk_ecc_wait_idle(struct mtk_ecc *ecc, + if (ret) + dev_warn(dev, "%s NOT idle\n", + op == ECC_ENCODE ? "encoder" : "decoder"); ++ ++ return ret; + } + + static irqreturn_t mtk_ecc_irq(int irq, void *id) +@@ -312,7 +314,11 @@ int mtk_ecc_enable(struct mtk_ecc *ecc, struct mtk_ecc_config *config) + return ret; + } + +- mtk_ecc_wait_idle(ecc, op); ++ ret = mtk_ecc_wait_idle(ecc, op); ++ if (ret) { ++ mutex_unlock(&ecc->lock); ++ return ret; ++ } + + ret = mtk_ecc_config(ecc, config); + if (ret) { +@@ -412,7 +418,9 @@ int mtk_ecc_encode(struct mtk_ecc *ecc, struct mtk_ecc_config *config, + if (ret) + goto timeout; + +- mtk_ecc_wait_idle(ecc, ECC_ENCODE); ++ ret = mtk_ecc_wait_idle(ecc, ECC_ENCODE); ++ if (ret) ++ goto timeout; + + /* Program ECC bytes to OOB: per sector oob = FDM + ECC + SPARE */ + len = (config->strength * ecc->caps->parity_bits + 7) >> 3; +-- +2.53.0 + diff --git a/queue-6.6/net-iucv-take-a-reference-on-the-socket-found-in-afi.patch b/queue-6.6/net-iucv-take-a-reference-on-the-socket-found-in-afi.patch new file mode 100644 index 0000000000..2269488f5d --- /dev/null +++ b/queue-6.6/net-iucv-take-a-reference-on-the-socket-found-in-afi.patch @@ -0,0 +1,55 @@ +From ae5f5693138c94b6eae630935068afe776c45f21 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 5 Jul 2026 22:24:36 -0500 +Subject: net/iucv: take a reference on the socket found in afiucv_hs_rcv() + +From: Bryam Vargas + +[ Upstream commit 4fa349156043dc119721d067329714179f501749 ] + +afiucv_hs_rcv() looks up the destination socket under iucv_sk_list.lock, +drops the lock, and then passes the socket to the afiucv_hs_callback_*() +handlers without holding a reference. AF_IUCV sockets are not +RCU-protected and are freed synchronously by iucv_sock_kill() -> +sock_put(), so a concurrent close can free the socket in the window +between read_unlock() and the handler, which then dereferences freed +memory (for example sk->sk_data_ready() in afiucv_hs_callback_syn()). + +Take a reference with sock_hold() while the socket is still on the list +and release it with sock_put() once the handler has run. + +Fixes: 3881ac441f64 ("af_iucv: add HiperSockets transport") +Signed-off-by: Bryam Vargas +Reviewed-by: Hidayath Khan +Link: https://patch.msgid.link/20260705-b4-disp-fc79c0dc-v1-1-d2cdcb57afa9@proton.me +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/iucv/af_iucv.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c +index e9a9bb0dee065a..a7b95590f6c96c 100644 +--- a/net/iucv/af_iucv.c ++++ b/net/iucv/af_iucv.c +@@ -2090,6 +2090,8 @@ static int afiucv_hs_rcv(struct sk_buff *skb, struct net_device *dev, + } + } + } ++ if (sk) ++ sock_hold(sk); + read_unlock(&iucv_sk_list.lock); + if (!iucv) + sk = NULL; +@@ -2139,6 +2141,8 @@ static int afiucv_hs_rcv(struct sk_buff *skb, struct net_device *dev, + kfree_skb(skb); + } + ++ if (sk) ++ sock_put(sk); + return err; + } + +-- +2.53.0 + diff --git a/queue-6.6/net-sched-act_tunnel_key-defer-dst_release-to-rcu-ca.patch b/queue-6.6/net-sched-act_tunnel_key-defer-dst_release-to-rcu-ca.patch new file mode 100644 index 0000000000..b1df1df7d9 --- /dev/null +++ b/queue-6.6/net-sched-act_tunnel_key-defer-dst_release-to-rcu-ca.patch @@ -0,0 +1,176 @@ +From f6f40cd903b73cc252fe4e476961c04b5b424c86 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 11 Jul 2026 11:05:37 -0400 +Subject: net/sched: act_tunnel_key: Defer dst_release to RCU callback + +From: Jamal Hadi Salim + +[ Upstream commit f1f5c8a3955f8fda3f84ed883ac8daa1847e724c ] + +Fix a race-condition use-after-free in tunnel_key_release_params(). + +The function releases the metadata_dst of the old params synchronously +via dst_release() while deferring the params struct free with +kfree_rcu(). A concurrent tunnel_key_act() reader on the datapath may +still hold the old params pointer (under rcu_read_lock_bh) and proceed +to call dst_clone(¶ms->tcft_enc_metadata->dst) after the writer's +dst_release has already pushed the dst's rcuref to RCUREF_DEAD. + +zdi-disclosures@trendmicro.com produced a poc which i (and Victor) verified +that KASAN reports: + +================================================================== +BUG: KASAN: slab-use-after-free in instrument_atomic_read_write include/linux/instrumented.h:112 +BUG: KASAN: slab-use-after-free in atomic_sub_return_release include/linux/atomic/atomic-instrumented.h:326 +BUG: KASAN: slab-use-after-free in __rcuref_put include/linux/rcuref.h:109 +BUG: KASAN: slab-use-after-free in rcuref_put include/linux/rcuref.h:173 +BUG: KASAN: slab-use-after-free in dst_release+0x5b/0x370 net/core/dst.c:168 +Write of size 4 at addr ffff88806158de40 by task poc/9388 + +CPU: 0 UID: 0 PID: 9388 Comm: poc Tainted: G W 7.1.0-rc7 #7 PREEMPT(lazy) +Tainted: [W]=WARN +Hardware name: QEMU Ubuntu 25.10 PC v2 (i440FX + PIIX, + 10.1 machine, 1996), BIOS 1.16.3-debian-1.16.3-2 04/01/2014 +Call Trace: + + __dump_stack lib/dump_stack.c:94 + dump_stack_lvl+0x100/0x190 lib/dump_stack.c:120 + print_address_description mm/kasan/report.c:378 + print_report+0x139/0x4ad mm/kasan/report.c:482 + kasan_report+0xe4/0x1d0 mm/kasan/report.c:595 + check_region_inline mm/kasan/generic.c:186 + kasan_check_range+0x125/0x200 mm/kasan/generic.c:200 + instrument_atomic_read_write include/linux/instrumented.h:112 + atomic_sub_return_release include/linux/atomic/atomic-instrumented.h:326 + __rcuref_put include/linux/rcuref.h:109 + rcuref_put include/linux/rcuref.h:173 + dst_release+0x5b/0x370 net/core/dst.c:168 + refdst_drop include/net/dst.h:272 + skb_dst_drop include/net/dst.h:284 + skb_release_head_state+0x293/0x400 net/core/skbuff.c:1163 + skb_release_all net/core/skbuff.c:1187 +[..] +Allocated by task 9391: + kasan_save_stack+0x30/0x50 mm/kasan/common.c:57 + kasan_save_track+0x14/0x30 mm/kasan/common.c:78 + poison_kmalloc_redzone mm/kasan/common.c:398 + __kasan_kmalloc+0x9a/0xb0 mm/kasan/common.c:415 + kasan_kmalloc include/linux/kasan.h:263 + __do_kmalloc_node mm/slub.c:5296 + __kmalloc_noprof+0x2f1/0x830 mm/slub.c:5308 + kmalloc_noprof include/linux/slab.h:954 + kzalloc_noprof include/linux/slab.h:1188 + offload_action_alloc+0x2f/0x130 net/core/flow_offload.c:35 + tcf_action_offload_add_ex+0x1ba/0x880 net/sched/act_api.c:258 + tcf_action_offload_add net/sched/act_api.c:293 + tcf_action_init+0x66e/0xa20 net/sched/act_api.c:1547 + tcf_action_add+0xf6/0x5d0 net/sched/act_api.c:2101 +[..] +Freed by task 9391: + kasan_save_stack+0x30/0x50 mm/kasan/common.c:57 + kasan_save_track+0x14/0x30 mm/kasan/common.c:78 + kasan_save_free_info+0x3b/0x70 mm/kasan/generic.c:584 + poison_slab_object mm/kasan/common.c:253 + __kasan_slab_free+0x6b/0x90 mm/kasan/common.c:285 + kasan_slab_free include/linux/kasan.h:235 + slab_free_hook mm/slub.c:2689 + slab_free mm/slub.c:6251 + kfree+0x21f/0x6b0 mm/slub.c:6566 + tcf_action_offload_add_ex+0x4ad/0x880 net/sched/act_api.c:284 + tcf_action_offload_add net/sched/act_api.c:293 + tcf_action_init+0x66e/0xa20 net/sched/act_api.c:1547 + tcf_action_add+0xf6/0x5d0 net/sched/act_api.c:2101 + +The buggy address belongs to the object at ffff88806158de00 + which belongs to the cache kmalloc-256 of size 256 +The buggy address is located 64 bytes inside of + freed 256-byte region [ffff88806158de00, ffff88806158df00) + +The buggy address belongs to the physical page: +page: refcount:0 mapcount:0 mapping:0000000000000000 index:0xffff88806158d600 pfn:0x6158c +head: order:1 mapcount:0 entire_mapcount:0 nr_pages_mapped:0 pincount:0 +flags: 0x4fff00000000240(workingset|head|node=1|zone=1|lastcpupid=0x7ff) +page_type: f5(slab) +raw: 04fff00000000240 ffff88801c841b40 ffffea0001856290 ffffea0001856190 +raw: ffff88806158d600 0000000800100009 00000000f5000000 0000000000000000 +head: 04fff00000000240 ffff88801c841b40 ffffea0001856290 ffffea0001856190 +head: ffff88806158d600 0000000800100009 00000000f5000000 0000000000000000 +head: 04fff00000000001 ffffffffffffff81 00000000ffffffff 00000000ffffffff +head: ffffffffffffffff 0000000000000000 00000000ffffffff 0000000000000002 +page dumped because: kasan: bad access detected +page_owner tracks the page as allocated +page last allocated via order 1, migratetype Unmovable, gfp_mask 0xd2820(GFP_ATOMIC|__GFP_NOWARN|__GFP_NORETRY|__GFP_COMP|__GFP_NOMEMALLOC), pid 9391, tgid 9378 (poc), ts 123227323196, free_ts 0 + set_page_owner include/linux/page_owner.h:32 + post_alloc_hook+0xfe/0x140 mm/page_alloc.c:1853 + prep_new_page mm/page_alloc.c:1861 + get_page_from_freelist+0x110c/0x2fc0 mm/page_alloc.c:3941 + __alloc_frozen_pages_noprof+0x263/0x2bc0 mm/page_alloc.c:5221 + alloc_slab_page mm/slub.c:3278 + allocate_slab mm/slub.c:3467 + new_slab+0xa6/0x690 mm/slub.c:3525 + refill_objects+0x271/0x420 mm/slub.c:7272 + refill_sheaf mm/slub.c:2816 + __pcs_replace_empty_main+0x373/0x630 mm/slub.c:4652 + alloc_from_pcs mm/slub.c:4750 + slab_alloc_node mm/slub.c:4884 + __do_kmalloc_node mm/slub.c:5295 + __kmalloc_noprof+0x66d/0x830 mm/slub.c:5308 + kmalloc_noprof include/linux/slab.h:954 + metadata_dst_alloc+0x26/0x90 net/core/dst.c:298 + tun_rx_dst include/net/dst_metadata.h:144 + __ip_tun_set_dst include/net/dst_metadata.h:208 + tunnel_key_init+0xb01/0x1b90 net/sched/act_tunnel_key.c:451 + tcf_action_init_1+0x46b/0x6c0 net/sched/act_api.c:1428 + tcf_action_init+0x448/0xa20 net/sched/act_api.c:1503 + tcf_action_add+0xf6/0x5d0 net/sched/act_api.c:2101 +[..] +================================================================== + +Fix by moving dst_release() into a custom RCU callback that runs +after the grace period, matching the lifetime of the containing +params struct. Readers in the datapath therefore always find a live +rcuref when calling dst_clone(). + +Fixes: 9174c3df1cd18 ("net/sched: act_tunnel_key: fix memory leak in case of action replace") +Reported-by: zdi-disclosures@trendmicro.com +Tested-by: Victor Nogueira +Signed-off-by: Jamal Hadi Salim +Reviewed-by: Davide Caratti +Link: https://patch.msgid.link/20260711150537.7946-1-jhs@mojatatu.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/sched/act_tunnel_key.c | 14 ++++++++++---- + 1 file changed, 10 insertions(+), 4 deletions(-) + +diff --git a/net/sched/act_tunnel_key.c b/net/sched/act_tunnel_key.c +index 99fb869aee91b7..65664e530c73b5 100644 +--- a/net/sched/act_tunnel_key.c ++++ b/net/sched/act_tunnel_key.c +@@ -344,14 +344,20 @@ static const struct nla_policy tunnel_key_policy[TCA_TUNNEL_KEY_MAX + 1] = { + [TCA_TUNNEL_KEY_ENC_TTL] = { .type = NLA_U8 }, + }; + +-static void tunnel_key_release_params(struct tcf_tunnel_key_params *p) ++static void tunnel_key_release_params_rcu(struct rcu_head *head) + { +- if (!p) +- return; ++ struct tcf_tunnel_key_params *p = container_of(head, typeof(*p), rcu); ++ + if (p->tcft_action == TCA_TUNNEL_KEY_ACT_SET) + dst_release(&p->tcft_enc_metadata->dst); ++ kfree(p); ++} + +- kfree_rcu(p, rcu); ++static void tunnel_key_release_params(struct tcf_tunnel_key_params *p) ++{ ++ if (!p) ++ return; ++ call_rcu(&p->rcu, tunnel_key_release_params_rcu); + } + + static int tunnel_key_init(struct net *net, struct nlattr *nla, +-- +2.53.0 + diff --git a/queue-6.6/powerpc-time-prepare-to-stop-elapsing-in-dynticks-id.patch b/queue-6.6/powerpc-time-prepare-to-stop-elapsing-in-dynticks-id.patch new file mode 100644 index 0000000000..75b8516115 --- /dev/null +++ b/queue-6.6/powerpc-time-prepare-to-stop-elapsing-in-dynticks-id.patch @@ -0,0 +1,126 @@ +From 3ee02603e5e21fe6047a9aceb0de8157211593f3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 8 May 2026 15:16:37 +0200 +Subject: powerpc/time: Prepare to stop elapsing in dynticks-idle + +From: Frederic Weisbecker + +[ Upstream commit c8ba971cf8567d49eb5f43ee90c4e50424331c18 ] + +Currently the tick subsystem stores the idle cputime accounting in +private fields, allowing cohabitation with architecture idle vtime +accounting. The former is fetched on online CPUs, the latter on offline +CPUs. + +For consolidation purpose, architecture vtime accounting will continue +to account the cputime but will make a break when the idle tick is +stopped. The dyntick cputime accounting will then be relayed by the tick +subsystem so that the idle cputime is still seen advancing coherently +even when the tick isn't there to flush the idle vtime. + +Prepare for that and introduce three new APIs which will be used in +subsequent patches: + + - vtime_dynticks_start() is deemed to be called when idle enters in + dyntick mode. The idle cputime that elapsed so far is accumulated. + + - vtime_dynticks_stop() is deemed to be called when idle exits from + dyntick mode. The vtime entry clocks are fast-forward to current time + so that idle accounting restarts elapsing from now. + + - vtime_reset() is deemed to be called from dynticks idle IRQ entry to + fast-forward the clock to current time so that the IRQ time is still + accounted by vtime while nohz cputime is paused. + +Also accumulated vtime won't be flushed from dyntick-idle ticks to avoid +accounting twice the idle cputime, along with nohz accounting. + +Signed-off-by: Frederic Weisbecker +Signed-off-by: Thomas Gleixner +Tested-by: Shrikanth Hegde +Reviewed-by: Shrikanth Hegde +Link: https://patch.msgid.link/20260508131647.43868-6-frederic@kernel.org +Stable-dep-of: c1c1ffa490fc ("powerpc/vtime: Initialize starttime at boot for native accounting") +Signed-off-by: Sasha Levin +--- + arch/powerpc/kernel/time.c | 41 ++++++++++++++++++++++++++++++++++++++ + include/linux/vtime.h | 6 ++++++ + 2 files changed, 47 insertions(+) + +diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c +index 7fce6adb6f05fd..4287f2bd5450c1 100644 +--- a/arch/powerpc/kernel/time.c ++++ b/arch/powerpc/kernel/time.c +@@ -376,6 +376,47 @@ void vtime_task_switch(struct task_struct *prev) + acct->starttime = acct0->starttime; + } + } ++ ++#ifdef CONFIG_NO_HZ_COMMON ++/** ++ * vtime_reset - Fast forward vtime entry clocks ++ * ++ * Called from dynticks idle IRQ entry to fast-forward the clocks to current time ++ * so that the IRQ time is still accounted by vtime while nohz cputime is paused. ++ */ ++void vtime_reset(void) ++{ ++ struct cpu_accounting_data *acct = get_accounting(current); ++ ++ acct->starttime = mftb(); ++#ifdef CONFIG_ARCH_HAS_SCALED_CPUTIME ++ acct->startspurr = read_spurr(acct->starttime); ++#endif ++} ++ ++/** ++ * vtime_dyntick_start - Inform vtime about entry to idle-dynticks ++ * ++ * Called when idle enters in dyntick mode. The idle cputime that elapsed so far ++ * is accumulated and the tick subsystem takes over the idle cputime accounting. ++ */ ++void vtime_dyntick_start(void) ++{ ++ vtime_account_idle(current); ++} ++ ++/** ++ * vtime_dyntick_stop - Inform vtime about exit from idle-dynticks ++ * ++ * Called when idle exits from dyntick mode. The vtime entry clocks are ++ * fast-forward to current time so that idle accounting restarts elapsing from ++ * now. ++ */ ++void vtime_dyntick_stop(void) ++{ ++ vtime_reset(); ++} ++#endif /* CONFIG_NO_HZ_COMMON */ + #endif /* CONFIG_VIRT_CPU_ACCOUNTING_NATIVE */ + + void __no_kcsan __delay(unsigned long loops) +diff --git a/include/linux/vtime.h b/include/linux/vtime.h +index 3684487d01e1c6..7cee518fde3a24 100644 +--- a/include/linux/vtime.h ++++ b/include/linux/vtime.h +@@ -37,11 +37,17 @@ extern void vtime_account_irq(struct task_struct *tsk, unsigned int offset); + extern void vtime_account_softirq(struct task_struct *tsk); + extern void vtime_account_hardirq(struct task_struct *tsk); + extern void vtime_flush(struct task_struct *tsk); ++extern void vtime_reset(void); ++extern void vtime_dyntick_start(void); ++extern void vtime_dyntick_stop(void); + #else /* !CONFIG_VIRT_CPU_ACCOUNTING_NATIVE */ + static inline void vtime_account_irq(struct task_struct *tsk, unsigned int offset) { } + static inline void vtime_account_softirq(struct task_struct *tsk) { } + static inline void vtime_account_hardirq(struct task_struct *tsk) { } + static inline void vtime_flush(struct task_struct *tsk) { } ++static inline void vtime_reset(void) { } ++static inline void vtime_dyntick_start(void) { } ++static inline void vtime_dyntick_stop(void) { } + #endif + + /* +-- +2.53.0 + diff --git a/queue-6.6/powerpc-vtime-initialize-starttime-at-boot-for-nativ.patch b/queue-6.6/powerpc-vtime-initialize-starttime-at-boot-for-nativ.patch new file mode 100644 index 0000000000..4573e9373f --- /dev/null +++ b/queue-6.6/powerpc-vtime-initialize-starttime-at-boot-for-nativ.patch @@ -0,0 +1,90 @@ +From 664fe818fd32ff55cd938a71c7658b147aee7dc0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 5 Jun 2026 18:13:29 +0530 +Subject: powerpc/vtime: Initialize starttime at boot for native accounting + +From: Shrikanth Hegde + +[ Upstream commit c1c1ffa490fc33591e90852ed0d38804dd20bc36 ] + +It was observed that /proc/stat had very large value for one ore more +CPUs. It was more visible after recent code simplifications around +cpustats. + +System has 240 CPUs. + +cat /proc/uptime; +194.18 46500.55 +cat /proc/stat +cpu 5966 39 837032887 4650070 164 185 100 0 0 0 +cpu0 108 0 837030890 19109 24 4 23 0 0 0 + +Since uptime is 194s, system time of each CPU can't be more than 19400. +Sum of system time of all CPUs can't be more than 19400*240 4656000. +In fact huge value is close to mftb(). Note mftb doesn't reset on powerVM +when the LPAR restart. It only resets when whole system resets. The same +issue exists for kexec too. + +This happens since starttime is not setup at init time. Once it is set +then subsequent vtime_delta will return the right delta. + +Fix it by initializing the starttime during CPU initialization. This +fixes the large times seen. + +cat /proc/uptime; cat /proc/stat +15.78 3694.63 +cpu 6035 35 1347 369479 23 144 49 0 0 0 +cpu0 19 0 38 1508 0 1 14 0 0 0 + +Now, system time is reported as expected. + +Fixes: cf9efce0ce31 ("powerpc: Account time using timebase rather than PURR") +Reviewed-by: Christophe Leroy (CS GROUP) +Suggested-by: Christophe Leroy (CS GROUP) +Signed-off-by: Shrikanth Hegde +Signed-off-by: Madhavan Srinivasan +Link: https://patch.msgid.link/20260605124329.377533-1-sshegde@linux.ibm.com +Signed-off-by: Sasha Levin +--- + arch/powerpc/kernel/time.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c +index 4287f2bd5450c1..dce831af31662e 100644 +--- a/arch/powerpc/kernel/time.c ++++ b/arch/powerpc/kernel/time.c +@@ -377,7 +377,6 @@ void vtime_task_switch(struct task_struct *prev) + } + } + +-#ifdef CONFIG_NO_HZ_COMMON + /** + * vtime_reset - Fast forward vtime entry clocks + * +@@ -394,6 +393,7 @@ void vtime_reset(void) + #endif + } + ++#ifdef CONFIG_NO_HZ_COMMON + /** + * vtime_dyntick_start - Inform vtime about entry to idle-dynticks + * +@@ -927,6 +927,7 @@ static void __init set_decrementer_max(void) + static void __init init_decrementer_clockevent(void) + { + register_decrementer_clockevent(smp_processor_id()); ++ vtime_reset(); + } + + void secondary_cpu_time_init(void) +@@ -942,6 +943,7 @@ void secondary_cpu_time_init(void) + /* FIME: Should make unrelated change to move snapshot_timebase + * call here ! */ + register_decrementer_clockevent(smp_processor_id()); ++ vtime_reset(); + } + + /* This function is only called on the boot processor */ +-- +2.53.0 + diff --git a/queue-6.6/ppp-defer-channel-free-to-an-rcu-grace-period-to-fix.patch b/queue-6.6/ppp-defer-channel-free-to-an-rcu-grace-period-to-fix.patch new file mode 100644 index 0000000000..cbc5cae81f --- /dev/null +++ b/queue-6.6/ppp-defer-channel-free-to-an-rcu-grace-period-to-fix.patch @@ -0,0 +1,104 @@ +From 0949947b1e83d9da594240e3f4dfb6182439df24 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 6 Jul 2026 11:01:59 +0200 +Subject: ppp: defer channel free to an RCU grace period to fix pppol2tp RX UAF + +From: Norbert Szetei + +[ Upstream commit ec4215683e47424c9c4762fd3c60f552a3119142 ] + +pppol2tp_recv() runs in the L2TP UDP-encap softirq RX path: + + l2tp_udp_encap_recv() -> l2tp_recv_common() -> pppol2tp_recv() + -> ppp_input(&po->chan) + +It runs under rcu_read_lock() holding only an l2tp_session reference and +takes NO reference on the internal PPP channel (struct channel, +chan->ppp) that ppp_input() dereferences. + +The pppox socket is SOCK_RCU_FREE, so 'po' and the embedded ppp_channel +are RCU-safe. But the internal struct channel is a separate allocation +that ppp_release_channel() frees with a plain kfree(): + + close(data socket) -> pppol2tp_release() -> pppox_unbind_sock() + -> ppp_unregister_channel() -> ppp_release_channel() -> kfree(pch) + +For a channel that is bound (PPPIOCGCHAN) but not attached to a ppp unit +(no PPPIOCCONNECT, pch->ppp == NULL) and not bridged, teardown skips +both ppp_disconnect_channel()'s synchronize_net() and +ppp_unbridge_channels()'s synchronize_rcu(), so the kfree() has no grace +period. rcu_read_lock() in pppol2tp_recv() does not protect against a +plain kfree(), so an in-flight ppp_input() on one CPU can dereference +the channel just freed by close() on another CPU. + +The bug is reachable by an unprivileged user. + +Defer the channel free to an RCU callback via call_rcu() so the grace +period fences any in-flight ppp_input(). The disconnect and unbridge +teardown paths already fence with synchronize_net()/synchronize_rcu(); +call_rcu() does the same here without stalling the close() path. + +Fixes: ee40fb2e1eb5 ("l2tp: protect sock pointer of struct pppol2tp_session with RCU") +Assisted-by: Claude:claude-opus-4-8 +Signed-off-by: Norbert Szetei +Reviewed-by: Qingfang Deng +Link: https://patch.msgid.link/E793FCF2-58DE-4387-A983-C7B4BC3158BD@doyensec.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ppp/ppp_generic.c | 18 +++++++++++++++--- + 1 file changed, 15 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c +index 2b5843d14cbb84..53e96a8740397c 100644 +--- a/drivers/net/ppp/ppp_generic.c ++++ b/drivers/net/ppp/ppp_generic.c +@@ -192,6 +192,7 @@ struct channel { + struct list_head clist; /* link in list of channels per unit */ + rwlock_t upl; /* protects `ppp' and 'bridge' */ + struct channel __rcu *bridge; /* "bridged" ppp channel */ ++ struct rcu_head rcu; /* for RCU-deferred free of the channel */ + #ifdef CONFIG_PPP_MULTILINK + u8 avail; /* flag used in multilink stuff */ + u8 had_frag; /* >= 1 fragments have been sent */ +@@ -3555,6 +3556,18 @@ ppp_disconnect_channel(struct channel *pch) + return err; + } + ++/* Purge after the grace period: a late ppp_input() may still queue an ++ * skb on pch->file.rq before the last RCU reader drains. ++ */ ++static void ppp_release_channel_free(struct rcu_head *rcu) ++{ ++ struct channel *pch = container_of(rcu, struct channel, rcu); ++ ++ skb_queue_purge(&pch->file.xq); ++ skb_queue_purge(&pch->file.rq); ++ kfree(pch); ++} ++ + /* + * Free up the resources used by a ppp channel. + */ +@@ -3570,9 +3583,7 @@ static void ppp_destroy_channel(struct channel *pch) + pr_err("ppp: destroying undead channel %p !\n", pch); + return; + } +- skb_queue_purge(&pch->file.xq); +- skb_queue_purge(&pch->file.rq); +- kfree(pch); ++ call_rcu(&pch->rcu, ppp_release_channel_free); + } + + static void __exit ppp_cleanup(void) +@@ -3585,6 +3596,7 @@ static void __exit ppp_cleanup(void) + device_destroy(ppp_class, MKDEV(PPP_MAJOR, 0)); + class_destroy(ppp_class); + unregister_pernet_device(&ppp_net_ops); ++ rcu_barrier(); /* wait for RCU callbacks before module unload */ + } + + /* +-- +2.53.0 + diff --git a/queue-6.6/rdma-cma-fix-hardware-address-comparison-length-in-n.patch b/queue-6.6/rdma-cma-fix-hardware-address-comparison-length-in-n.patch new file mode 100644 index 0000000000..9ac33f95c5 --- /dev/null +++ b/queue-6.6/rdma-cma-fix-hardware-address-comparison-length-in-n.patch @@ -0,0 +1,43 @@ +From a7895fc18177e74860b3c63cd87aa507757128f7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 17 Jun 2026 14:21:05 +0300 +Subject: RDMA/cma: Fix hardware address comparison length in netevent callback + +From: Or Gerlitz + +[ Upstream commit 18313833e2c6de222a4f6c072da759d0d5888528 ] + +The cited commit hardcoded the hardware address comparison len to ETH_ALEN. + +This breaks IPoIB, which uses 20-byte addresses. By truncating the +memcmp, the CMA may incorrectly assume the target address is +unchanged and fails to abort the stalled connection. + +Fix this by replacing ETH_ALEN with the dynamic neigh->dev->addr_len +to correctly evaluate the full address regardless of the link layer. + +Fixes: 925d046e7e52 ("RDMA/core: Add a netevent notifier to cma") +Signed-off-by: Or Gerlitz +Link: https://patch.msgid.link/20260617-fix-cma-ipoib-v1-1-03f869344304@ddn.com +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + drivers/infiniband/core/cma.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c +index 7db79ff3fa06c3..87164dd745ecb5 100644 +--- a/drivers/infiniband/core/cma.c ++++ b/drivers/infiniband/core/cma.c +@@ -5215,7 +5215,7 @@ static int cma_netevent_callback(struct notifier_block *self, + + list_for_each_entry(current_id, &ips_node->id_list, id_list_entry) { + if (!memcmp(current_id->id.route.addr.dev_addr.dst_dev_addr, +- neigh->ha, ETH_ALEN)) ++ neigh->ha, neigh->dev->addr_len)) + continue; + cma_id_get(current_id); + if (!queue_work(cma_wq, ¤t_id->id.net_work)) +-- +2.53.0 + diff --git a/queue-6.6/rdma-erdma-initialize-ret-for-empty-receive-wr-lists.patch b/queue-6.6/rdma-erdma-initialize-ret-for-empty-receive-wr-lists.patch new file mode 100644 index 0000000000..f80a98dec7 --- /dev/null +++ b/queue-6.6/rdma-erdma-initialize-ret-for-empty-receive-wr-lists.patch @@ -0,0 +1,42 @@ +From aa1a55447ce6233e8ce7cad1b879998491277fb2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 18 Jun 2026 12:17:51 +0800 +Subject: RDMA/erdma: initialize ret for empty receive WR lists + +From: Ruoyu Wang + +[ Upstream commit 2815a277c53e9a84784d6410cd55a9da5b33068d ] + +erdma_post_recv() returns ret after walking the receive work request list. +If the caller passes an empty list, the loop is skipped and ret is not +assigned. + +Initialize ret to 0 so an empty receive work request list returns success +instead of stack data. + +Fixes: 155055771704 ("RDMA/erdma: Add verbs implementation") +Link: https://patch.msgid.link/r/20260618041752.481193-1-ruoyuw560@gmail.com +Signed-off-by: Ruoyu Wang +Reviewed-by: Cheng Xu +Signed-off-by: Jason Gunthorpe +Signed-off-by: Sasha Levin +--- + drivers/infiniband/hw/erdma/erdma_qp.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/infiniband/hw/erdma/erdma_qp.c b/drivers/infiniband/hw/erdma/erdma_qp.c +index 6d0330badd68e8..e3a731a45e8861 100644 +--- a/drivers/infiniband/hw/erdma/erdma_qp.c ++++ b/drivers/infiniband/hw/erdma/erdma_qp.c +@@ -573,7 +573,7 @@ int erdma_post_recv(struct ib_qp *ibqp, const struct ib_recv_wr *recv_wr, + const struct ib_recv_wr *wr = recv_wr; + struct erdma_qp *qp = to_eqp(ibqp); + unsigned long flags; +- int ret; ++ int ret = 0; + + spin_lock_irqsave(&qp->lock, flags); + +-- +2.53.0 + diff --git a/queue-6.6/rdma-hns-fix-potential-integer-overflow-in-mhop-hem-.patch b/queue-6.6/rdma-hns-fix-potential-integer-overflow-in-mhop-hem-.patch new file mode 100644 index 0000000000..64901d1894 --- /dev/null +++ b/queue-6.6/rdma-hns-fix-potential-integer-overflow-in-mhop-hem-.patch @@ -0,0 +1,52 @@ +From 6b8f33774c5bb1f1c0f48e5fcedf6ba0a1784f95 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 27 Jun 2026 09:59:51 +0000 +Subject: RDMA/hns: Fix potential integer overflow in mhop hem cleanup + +From: Danila Chernetsov + +[ Upstream commit 9f0f2d2121f16d420199a82ac5bbc242269133b3 ] + +In hns_roce_cleanup_mhop_hem_table(), the expression: + + obj = i * buf_chunk_size / table->obj_size; + +is evaluated using 32-bit unsigned arithmetic because +'buf_chunk_size' is u32 and the usual arithmetic conversions convert +'i' to unsigned int. The result is assigned to a u64 variable, but the +multiplication may overflow before the assignment. + +For sufficiently large HEM tables, this produces an incorrect object +index passed to hns_roce_table_mhop_put(). + +Cast 'i' to u64 before the multiplication so that the intermediate +calculation is performed with 64-bit arithmetic. + +Found by Linux Verification Center (linuxtesting.org) with SVACE. + +Fixes: a25d13cbe816 ("RDMA/hns: Add the interfaces to support multi hop addressing for the contexts in hip08") +Link: https://patch.msgid.link/r/20260627095951.51378-1-listdansp@mail.ru +Signed-off-by: Danila Chernetsov +Reviewed-by: Junxian Huang +Signed-off-by: Jason Gunthorpe +Signed-off-by: Sasha Levin +--- + drivers/infiniband/hw/hns/hns_roce_hem.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/infiniband/hw/hns/hns_roce_hem.c b/drivers/infiniband/hw/hns/hns_roce_hem.c +index d6fcb1a4bd4fca..112248ddf02367 100644 +--- a/drivers/infiniband/hw/hns/hns_roce_hem.c ++++ b/drivers/infiniband/hw/hns/hns_roce_hem.c +@@ -907,7 +907,7 @@ static void hns_roce_cleanup_mhop_hem_table(struct hns_roce_dev *hr_dev, + mhop.bt_chunk_size; + + for (i = 0; i < table->num_hem; ++i) { +- obj = i * buf_chunk_size / table->obj_size; ++ obj = (u64)i * buf_chunk_size / table->obj_size; + if (table->hem[i]) + hns_roce_table_mhop_put(hr_dev, table, obj, 0); + } +-- +2.53.0 + diff --git a/queue-6.6/rdma-irdma-prevent-overflows-in-memory-contiguity-ch.patch b/queue-6.6/rdma-irdma-prevent-overflows-in-memory-contiguity-ch.patch new file mode 100644 index 0000000000..471bc715ab --- /dev/null +++ b/queue-6.6/rdma-irdma-prevent-overflows-in-memory-contiguity-ch.patch @@ -0,0 +1,64 @@ +From eb7db8eb8b1ae9c013798dfa6d55be3354073043 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 24 Jun 2026 17:48:46 +0300 +Subject: RDMA/irdma: Prevent overflows in memory contiguity checks + +From: Aleksandrova Alyona + +[ Upstream commit 3cda0dfe8c651dcbb9e38977905d3d3b1750c4ab ] + +irdma_check_mem_contiguous() and irdma_check_mr_contiguous() verify that +PBL entries describe physically contiguous memory ranges. + +Both functions calculate byte offsets using 32-bit operands. For example, +with 4 KiB pages, pg_size * pg_idx overflows 32-bit arithmetic when +pg_idx reaches 1048576. In the level-2 check, PBLE_PER_PAGE is 512, so +i * pg_size * PBLE_PER_PAGE overflows when i reaches 2048. + +These values are reachable in the driver. For MRs, palloc->total_cnt +comes from iwmr->page_cnt, which is calculated by +ib_umem_num_dma_blocks(). The MR size is limited by IRDMA_MAX_MR_SIZE, +so a 4 GiB MR with 4 KiB pages can reach page_cnt of 1048576. PBLE +resources do not exclude this value either: for gen3, the limit is based +on avail_sds * MAX_PBLE_PER_SD, and MAX_PBLE_PER_SD is 0x40000, so 4 SDs +are enough for 1048576 PBLEs. + +Cast one operand to u64 before the multiplications so that the offset +calculations are performed in 64-bit arithmetic. + +Found by Linux Verification Center (linuxtesting.org) with SVACE. + +Fixes: b48c24c2d710 ("RDMA/irdma: Implement device supported verb APIs") +Signed-off-by: Aleksandrova Alyona +Link: https://patch.msgid.link/20260624144846.61242-1-aga@itb.spb.ru +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + drivers/infiniband/hw/irdma/verbs.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/infiniband/hw/irdma/verbs.c b/drivers/infiniband/hw/irdma/verbs.c +index 1779d2a9945945..136e367b40d874 100644 +--- a/drivers/infiniband/hw/irdma/verbs.c ++++ b/drivers/infiniband/hw/irdma/verbs.c +@@ -2366,7 +2366,7 @@ static bool irdma_check_mem_contiguous(u64 *arr, u32 npages, u32 pg_size) + u32 pg_idx; + + for (pg_idx = 0; pg_idx < npages; pg_idx++) { +- if ((*arr + (pg_size * pg_idx)) != arr[pg_idx]) ++ if ((*arr + ((u64)pg_size * pg_idx)) != arr[pg_idx]) + return false; + } + +@@ -2399,7 +2399,7 @@ static bool irdma_check_mr_contiguous(struct irdma_pble_alloc *palloc, + + for (i = 0; i < lvl2->leaf_cnt; i++, leaf++) { + arr = leaf->addr; +- if ((*start_addr + (i * pg_size * PBLE_PER_PAGE)) != *arr) ++ if ((*start_addr + ((u64)i * pg_size * PBLE_PER_PAGE)) != *arr) + return false; + ret = irdma_check_mem_contiguous(arr, leaf->cnt, pg_size); + if (!ret) +-- +2.53.0 + diff --git a/queue-6.6/rdma-irdma-prevent-rereg_mr-for-non-mem-regions.patch b/queue-6.6/rdma-irdma-prevent-rereg_mr-for-non-mem-regions.patch new file mode 100644 index 0000000000..180885e45d --- /dev/null +++ b/queue-6.6/rdma-irdma-prevent-rereg_mr-for-non-mem-regions.patch @@ -0,0 +1,51 @@ +From cf41ad7a0f507dfdd962799005671cb5133f02c2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 17 Jun 2026 14:19:36 +0000 +Subject: RDMA/irdma: Prevent rereg_mr for non-mem regions + +From: Jacob Moroni + +[ Upstream commit a846aecb931b4d65d5eafa92a0623545af46d4f2 ] + +When a QP/CQ/SRQ is created, a two step process is used +where the buffer is allocated in userspace and explicitly +registered with the normal reg_mr mechanism prior to creating +the actual QP/CQ/SRQ object. + +These special registrations are indicated via an ABI field +so the driver knows that they do not have a valid mkey and +to skip the actual CQP command submission. + +Since these are real MR objects from the core's perspective, +it is possible for a user application to invoke rereg_mr on them +and cause a real CQP op to be emitted with the zero-initialized +mkey value of 0. + +Fix this by preventing rereg_mr on these special regions. + +Fixes: 5ac388db27c4 ("RDMA/irdma: Add support to re-register a memory region") +Signed-off-by: Jacob Moroni +Reviewed-by: David Hu +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + drivers/infiniband/hw/irdma/verbs.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/infiniband/hw/irdma/verbs.c b/drivers/infiniband/hw/irdma/verbs.c +index 8ffbc790c1681e..1779d2a9945945 100644 +--- a/drivers/infiniband/hw/irdma/verbs.c ++++ b/drivers/infiniband/hw/irdma/verbs.c +@@ -3251,6 +3251,9 @@ static struct ib_mr *irdma_rereg_user_mr(struct ib_mr *ib_mr, int flags, + if (flags & ~(IB_MR_REREG_TRANS | IB_MR_REREG_PD | IB_MR_REREG_ACCESS)) + return ERR_PTR(-EOPNOTSUPP); + ++ if (iwmr->type != IRDMA_MEMREG_TYPE_MEM) ++ return ERR_PTR(-EINVAL); ++ + ret = ib_umem_check_rereg(iwmr->region, flags, new_access); + if (ret) + return ERR_PTR(ret); +-- +2.53.0 + diff --git a/queue-6.6/rdma-siw-only-check-attrs-cap.max_send_wr-in-siw_cre.patch b/queue-6.6/rdma-siw-only-check-attrs-cap.max_send_wr-in-siw_cre.patch new file mode 100644 index 0000000000..fcb6d9f01b --- /dev/null +++ b/queue-6.6/rdma-siw-only-check-attrs-cap.max_send_wr-in-siw_cre.patch @@ -0,0 +1,69 @@ +From 76f72e296857861765ca657660b5507678a9739d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 13 Nov 2023 19:57:24 +0800 +Subject: RDMA/siw: Only check attrs->cap.max_send_wr in siw_create_qp + +From: Guoqing Jiang + +[ Upstream commit 788bbf4c2fc6e0c35bae9ed5068f484272539d3e ] + +We can just check max_send_wr here given both max_send_wr and +max_recv_wr are defined as u32 type, and we also need to ensure +num_sqe (derived from max_send_wr) shouldn't be zero. + +Acked-by: Bernard Metzler +Signed-off-by: Guoqing Jiang +Link: https://lore.kernel.org/r/20231113115726.12762-16-guoqing.jiang@linux.dev +Signed-off-by: Leon Romanovsky +Stable-dep-of: bb27fcc67c42 ("RDMA/siw: publish QP after initialization") +Signed-off-by: Sasha Levin +--- + drivers/infiniband/sw/siw/siw_verbs.c | 18 +++++------------- + 1 file changed, 5 insertions(+), 13 deletions(-) + +diff --git a/drivers/infiniband/sw/siw/siw_verbs.c b/drivers/infiniband/sw/siw/siw_verbs.c +index 1768b8695c45ad..75a7ad323c8230 100644 +--- a/drivers/infiniband/sw/siw/siw_verbs.c ++++ b/drivers/infiniband/sw/siw/siw_verbs.c +@@ -336,11 +336,10 @@ int siw_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attrs, + goto err_atomic; + } + /* +- * NOTE: we allow for zero element SQ and RQ WQE's SGL's +- * but not for a QP unable to hold any WQE (SQ + RQ) ++ * NOTE: we don't allow for a QP unable to hold any SQ WQE + */ +- if (attrs->cap.max_send_wr + attrs->cap.max_recv_wr == 0) { +- siw_dbg(base_dev, "QP must have send or receive queue\n"); ++ if (attrs->cap.max_send_wr == 0) { ++ siw_dbg(base_dev, "QP must have send queue\n"); + rv = -EINVAL; + goto err_atomic; + } +@@ -360,21 +359,14 @@ int siw_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attrs, + if (rv) + goto err_atomic; + +- num_sqe = attrs->cap.max_send_wr; +- num_rqe = attrs->cap.max_recv_wr; + + /* All queue indices are derived from modulo operations + * on a free running 'get' (consumer) and 'put' (producer) + * unsigned counter. Having queue sizes at power of two + * avoids handling counter wrap around. + */ +- if (num_sqe) +- num_sqe = roundup_pow_of_two(num_sqe); +- else { +- /* Zero sized SQ is not supported */ +- rv = -EINVAL; +- goto err_out_xa; +- } ++ num_sqe = roundup_pow_of_two(attrs->cap.max_send_wr); ++ num_rqe = attrs->cap.max_recv_wr; + if (num_rqe) + num_rqe = roundup_pow_of_two(num_rqe); + +-- +2.53.0 + diff --git a/queue-6.6/rdma-siw-publish-qp-after-initialization.patch b/queue-6.6/rdma-siw-publish-qp-after-initialization.patch new file mode 100644 index 0000000000..dfd1c2f0ff --- /dev/null +++ b/queue-6.6/rdma-siw-publish-qp-after-initialization.patch @@ -0,0 +1,153 @@ +From fb9c215ee67a19c1a5e3483e0b29ede32d4c2493 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 30 Jun 2026 14:00:40 +0800 +Subject: RDMA/siw: publish QP after initialization + +From: Ruoyu Wang + +[ Upstream commit bb27fcc67c429d97f785c92c35a6c5adebb05d7f ] + +siw_create_qp() currently calls siw_qp_add() before the queues, CQ +pointers, state, completion, and device list entry are ready. A QPN +lookup can therefore reach a QP that is still being constructed. + +Move siw_qp_add() to the end of siw_create_qp(), after QP +initialization and before adding the QP to the siw device list. + +Fixes: f29dd55b0236 ("rdma/siw: queue pair methods") +Link: https://patch.msgid.link/r/20260630060040.966461-1-ruoyuw560@gmail.com +Suggested-by: Bernard Metzler +Signed-off-by: Ruoyu Wang +Acked-by: Bernard Metzler +Signed-off-by: Jason Gunthorpe +Signed-off-by: Sasha Levin +--- + drivers/infiniband/sw/siw/siw_verbs.c | 44 +++++++++++++++------------ + 1 file changed, 24 insertions(+), 20 deletions(-) + +diff --git a/drivers/infiniband/sw/siw/siw_verbs.c b/drivers/infiniband/sw/siw/siw_verbs.c +index 75a7ad323c8230..40e0e0a2486db5 100644 +--- a/drivers/infiniband/sw/siw/siw_verbs.c ++++ b/drivers/infiniband/sw/siw/siw_verbs.c +@@ -302,6 +302,7 @@ int siw_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attrs, + struct siw_ucontext *uctx = + rdma_udata_to_drv_context(udata, struct siw_ucontext, + base_ucontext); ++ struct siw_uresp_create_qp uresp = {}; + unsigned long flags; + int num_sqe, num_rqe, rv = 0; + size_t length; +@@ -355,11 +356,6 @@ int siw_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attrs, + spin_lock_init(&qp->rq_lock); + spin_lock_init(&qp->orq_lock); + +- rv = siw_qp_add(sdev, qp); +- if (rv) +- goto err_atomic; +- +- + /* All queue indices are derived from modulo operations + * on a free running 'get' (consumer) and 'put' (producer) + * unsigned counter. Having queue sizes at power of two +@@ -377,14 +373,14 @@ int siw_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attrs, + + if (qp->sendq == NULL) { + rv = -ENOMEM; +- goto err_out_xa; ++ goto err_out; + } + if (attrs->sq_sig_type != IB_SIGNAL_REQ_WR) { + if (attrs->sq_sig_type == IB_SIGNAL_ALL_WR) + qp->attrs.flags |= SIW_SIGNAL_ALL_WR; + else { + rv = -EINVAL; +- goto err_out_xa; ++ goto err_out; + } + } + qp->pd = pd; +@@ -410,7 +406,7 @@ int siw_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attrs, + + if (qp->recvq == NULL) { + rv = -ENOMEM; +- goto err_out_xa; ++ goto err_out; + } + qp->attrs.rq_size = num_rqe; + } +@@ -425,11 +421,8 @@ int siw_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attrs, + qp->attrs.state = SIW_QP_STATE_IDLE; + + if (udata) { +- struct siw_uresp_create_qp uresp = {}; +- + uresp.num_sqe = num_sqe; + uresp.num_rqe = num_rqe; +- uresp.qp_id = qp_id(qp); + + if (qp->sendq) { + length = num_sqe * sizeof(struct siw_sqe); +@@ -438,7 +431,7 @@ int siw_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attrs, + length, &uresp.sq_key); + if (!qp->sq_entry) { + rv = -ENOMEM; +- goto err_out_xa; ++ goto err_out; + } + } + +@@ -450,9 +443,23 @@ int siw_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attrs, + if (!qp->rq_entry) { + uresp.sq_key = SIW_INVAL_UOBJ_KEY; + rv = -ENOMEM; +- goto err_out_xa; ++ goto err_out; + } + } ++ } ++ qp->tx_cpu = siw_get_tx_cpu(sdev); ++ if (qp->tx_cpu < 0) { ++ rv = -EINVAL; ++ goto err_out; ++ } ++ init_completion(&qp->qp_free); ++ ++ rv = siw_qp_add(sdev, qp); ++ if (rv) ++ goto err_out_tx; ++ ++ if (udata) { ++ uresp.qp_id = qp_id(qp); + + if (udata->outlen < sizeof(uresp)) { + rv = -EINVAL; +@@ -462,22 +469,19 @@ int siw_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attrs, + if (rv) + goto err_out_xa; + } +- qp->tx_cpu = siw_get_tx_cpu(sdev); +- if (qp->tx_cpu < 0) { +- rv = -EINVAL; +- goto err_out_xa; +- } ++ + INIT_LIST_HEAD(&qp->devq); + spin_lock_irqsave(&sdev->lock, flags); + list_add_tail(&qp->devq, &sdev->qp_list); + spin_unlock_irqrestore(&sdev->lock, flags); + +- init_completion(&qp->qp_free); +- + return 0; + + err_out_xa: + xa_erase(&sdev->qp_xa, qp_id(qp)); ++err_out_tx: ++ siw_put_tx_cpu(qp->tx_cpu); ++err_out: + if (uctx) { + rdma_user_mmap_entry_remove(qp->sq_entry); + rdma_user_mmap_entry_remove(qp->rq_entry); +-- +2.53.0 + diff --git a/queue-6.6/rdma-umem-add-helpers-for-umem-dmabuf-revoke-lock.patch b/queue-6.6/rdma-umem-add-helpers-for-umem-dmabuf-revoke-lock.patch new file mode 100644 index 0000000000..400478b29d --- /dev/null +++ b/queue-6.6/rdma-umem-add-helpers-for-umem-dmabuf-revoke-lock.patch @@ -0,0 +1,77 @@ +From df10b8da39960b67f5f5115c98f6b5b29ef9d56c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 5 Mar 2026 17:08:25 +0000 +Subject: RDMA/umem: Add helpers for umem dmabuf revoke lock + +From: Jacob Moroni + +[ Upstream commit 3a0b171302eea1732a168e26db3b8461f51cc1f9 ] + +Added helpers to acquire and release the umem dmabuf revoke +lock. The intent is to avoid the need for drivers to peek +into the ib_umem_dmabuf internals to get the dma_resv_lock +and bring us one step closer to abstracting ib_umem_dmabuf +away from drivers in general. + +Signed-off-by: Jacob Moroni +Link: https://patch.msgid.link/20260305170826.3803155-5-jmoroni@google.com +Signed-off-by: Leon Romanovsky +Stable-dep-of: a846aecb931b ("RDMA/irdma: Prevent rereg_mr for non-mem regions") +Signed-off-by: Sasha Levin +--- + drivers/infiniband/core/umem_dmabuf.c | 16 ++++++++++++++++ + include/rdma/ib_umem.h | 4 ++++ + 2 files changed, 20 insertions(+) + +diff --git a/drivers/infiniband/core/umem_dmabuf.c b/drivers/infiniband/core/umem_dmabuf.c +index 091af1f7aa29db..1206993e2e3e83 100644 +--- a/drivers/infiniband/core/umem_dmabuf.c ++++ b/drivers/infiniband/core/umem_dmabuf.c +@@ -337,6 +337,22 @@ struct ib_umem_dmabuf *ib_umem_dmabuf_get_pinned(struct ib_device *device, + } + EXPORT_SYMBOL(ib_umem_dmabuf_get_pinned); + ++void ib_umem_dmabuf_revoke_lock(struct ib_umem_dmabuf *umem_dmabuf) ++{ ++ struct dma_buf *dmabuf = umem_dmabuf->attach->dmabuf; ++ ++ dma_resv_lock(dmabuf->resv, NULL); ++} ++EXPORT_SYMBOL(ib_umem_dmabuf_revoke_lock); ++ ++void ib_umem_dmabuf_revoke_unlock(struct ib_umem_dmabuf *umem_dmabuf) ++{ ++ struct dma_buf *dmabuf = umem_dmabuf->attach->dmabuf; ++ ++ dma_resv_unlock(dmabuf->resv); ++} ++EXPORT_SYMBOL(ib_umem_dmabuf_revoke_unlock); ++ + void ib_umem_dmabuf_revoke(struct ib_umem_dmabuf *umem_dmabuf) + { + struct dma_buf *dmabuf = umem_dmabuf->attach->dmabuf; +diff --git a/include/rdma/ib_umem.h b/include/rdma/ib_umem.h +index 7637ff06bb5b10..4c5329b504d0cb 100644 +--- a/include/rdma/ib_umem.h ++++ b/include/rdma/ib_umem.h +@@ -138,6 +138,8 @@ ib_umem_dmabuf_get_pinned_with_dma_device(struct ib_device *device, + int ib_umem_dmabuf_map_pages(struct ib_umem_dmabuf *umem_dmabuf); + void ib_umem_dmabuf_unmap_pages(struct ib_umem_dmabuf *umem_dmabuf); + void ib_umem_dmabuf_release(struct ib_umem_dmabuf *umem_dmabuf); ++void ib_umem_dmabuf_revoke_lock(struct ib_umem_dmabuf *umem_dmabuf); ++void ib_umem_dmabuf_revoke_unlock(struct ib_umem_dmabuf *umem_dmabuf); + void ib_umem_dmabuf_revoke(struct ib_umem_dmabuf *umem_dmabuf); + + int ib_umem_check_rereg(struct ib_umem *umem, int flags, int new_access_flags); +@@ -212,6 +214,8 @@ static inline int ib_umem_dmabuf_map_pages(struct ib_umem_dmabuf *umem_dmabuf) + } + static inline void ib_umem_dmabuf_unmap_pages(struct ib_umem_dmabuf *umem_dmabuf) { } + static inline void ib_umem_dmabuf_release(struct ib_umem_dmabuf *umem_dmabuf) { } ++static inline void ib_umem_dmabuf_revoke_lock(struct ib_umem_dmabuf *umem_dmabuf) {} ++static inline void ib_umem_dmabuf_revoke_unlock(struct ib_umem_dmabuf *umem_dmabuf) {} + static inline void ib_umem_dmabuf_revoke(struct ib_umem_dmabuf *umem_dmabuf) {} + + static inline int ib_umem_check_rereg(struct ib_umem *umem, int flags, +-- +2.53.0 + diff --git a/queue-6.6/rdma-umem-add-ib_umem_dmabuf_get_pinned_and_lock-hel.patch b/queue-6.6/rdma-umem-add-ib_umem_dmabuf_get_pinned_and_lock-hel.patch new file mode 100644 index 0000000000..00744f4b69 --- /dev/null +++ b/queue-6.6/rdma-umem-add-ib_umem_dmabuf_get_pinned_and_lock-hel.patch @@ -0,0 +1,91 @@ +From e8716a6fbe84676dda77f5999b9e6910ad41f6b1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 5 Mar 2026 17:08:22 +0000 +Subject: RDMA/umem: Add ib_umem_dmabuf_get_pinned_and_lock helper + +From: Jacob Moroni + +[ Upstream commit 553dfa8cbd0c6d36adae042d9738ddf8f8765ac7 ] + +Move the inner logic of ib_umem_dmabuf_get_pinned_with_dma_device() +to a new static function that returns with the lock held upon success. + +The intent is to allow reuse for the future get_pinned_revocable_and_lock +function. + +Signed-off-by: Jacob Moroni +Link: https://patch.msgid.link/20260305170826.3803155-2-jmoroni@google.com +Signed-off-by: Leon Romanovsky +Stable-dep-of: a846aecb931b ("RDMA/irdma: Prevent rereg_mr for non-mem regions") +Signed-off-by: Sasha Levin +--- + drivers/infiniband/core/umem_dmabuf.c | 35 ++++++++++++++++++++------- + 1 file changed, 26 insertions(+), 9 deletions(-) + +diff --git a/drivers/infiniband/core/umem_dmabuf.c b/drivers/infiniband/core/umem_dmabuf.c +index 44bb7449738cf4..acb0922a786131 100644 +--- a/drivers/infiniband/core/umem_dmabuf.c ++++ b/drivers/infiniband/core/umem_dmabuf.c +@@ -198,18 +198,19 @@ static struct dma_buf_attach_ops ib_umem_dmabuf_attach_pinned_ops = { + .move_notify = ib_umem_dmabuf_unsupported_move_notify, + }; + +-struct ib_umem_dmabuf * +-ib_umem_dmabuf_get_pinned_with_dma_device(struct ib_device *device, +- struct device *dma_device, +- unsigned long offset, size_t size, +- int fd, int access) ++static struct ib_umem_dmabuf * ++ib_umem_dmabuf_get_pinned_and_lock(struct ib_device *device, ++ struct device *dma_device, ++ unsigned long offset, ++ size_t size, int fd, int access, ++ const struct dma_buf_attach_ops *ops) + { + struct ib_umem_dmabuf *umem_dmabuf; + int err; + +- umem_dmabuf = ib_umem_dmabuf_get_with_dma_device(device, dma_device, offset, +- size, fd, access, +- &ib_umem_dmabuf_attach_pinned_ops); ++ umem_dmabuf = ++ ib_umem_dmabuf_get_with_dma_device(device, dma_device, offset, ++ size, fd, access, ops); + if (IS_ERR(umem_dmabuf)) + return umem_dmabuf; + +@@ -222,7 +223,6 @@ ib_umem_dmabuf_get_pinned_with_dma_device(struct ib_device *device, + err = ib_umem_dmabuf_map_pages(umem_dmabuf); + if (err) + goto err_release; +- dma_resv_unlock(umem_dmabuf->attach->dmabuf->resv); + + return umem_dmabuf; + +@@ -231,6 +231,23 @@ ib_umem_dmabuf_get_pinned_with_dma_device(struct ib_device *device, + ib_umem_release(&umem_dmabuf->umem); + return ERR_PTR(err); + } ++ ++struct ib_umem_dmabuf * ++ib_umem_dmabuf_get_pinned_with_dma_device(struct ib_device *device, ++ struct device *dma_device, ++ unsigned long offset, size_t size, ++ int fd, int access) ++{ ++ struct ib_umem_dmabuf *umem_dmabuf = ++ ib_umem_dmabuf_get_pinned_and_lock(device, dma_device, offset, ++ size, fd, access, ++ &ib_umem_dmabuf_attach_pinned_ops); ++ if (IS_ERR(umem_dmabuf)) ++ return umem_dmabuf; ++ ++ dma_resv_unlock(umem_dmabuf->attach->dmabuf->resv); ++ return umem_dmabuf; ++} + EXPORT_SYMBOL(ib_umem_dmabuf_get_pinned_with_dma_device); + + struct ib_umem_dmabuf *ib_umem_dmabuf_get_pinned(struct ib_device *device, +-- +2.53.0 + diff --git a/queue-6.6/rdma-umem-add-pinned-revocable-dmabuf-import-interfa.patch b/queue-6.6/rdma-umem-add-pinned-revocable-dmabuf-import-interfa.patch new file mode 100644 index 0000000000..b303f4ca61 --- /dev/null +++ b/queue-6.6/rdma-umem-add-pinned-revocable-dmabuf-import-interfa.patch @@ -0,0 +1,167 @@ +From 0ccc33fa4c063bf33215c82c57bcce9ca1df33a3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 5 Mar 2026 17:08:24 +0000 +Subject: RDMA/umem: Add pinned revocable dmabuf import interface + +From: Jacob Moroni + +[ Upstream commit ff85a2ebacbdaec9f28c4660c991295ace93cd1c ] + +Added an interface for importing a pinned but revocable dmabuf. +This interface can be used by drivers that are capable of revocation +so that they can import dmabufs from exporters that may require it, +such as VFIO. + +This interface implements a two step process, where drivers will first +call ib_umem_dmabuf_get_pinned_revocable_and_lock() which will pin and +map the dmabuf (and provide a functional move_notify/invalidate_mappings +callback), but will return with the lock still held so that the +driver can then populate the callback via +ib_umem_dmabuf_set_revoke_locked() without races from concurrent +revocations. This scheme also allows for easier integration with drivers +that may not have actually allocated their internal MR objects at the time +of the get_pinned_revocable* call. + +Signed-off-by: Jacob Moroni +Link: https://patch.msgid.link/20260305170826.3803155-4-jmoroni@google.com +Signed-off-by: Leon Romanovsky +Stable-dep-of: a846aecb931b ("RDMA/irdma: Prevent rereg_mr for non-mem regions") +Signed-off-by: Sasha Levin +--- + drivers/infiniband/core/umem_dmabuf.c | 61 +++++++++++++++++++++++++++ + include/rdma/ib_umem.h | 19 +++++++++ + 2 files changed, 80 insertions(+) + +diff --git a/drivers/infiniband/core/umem_dmabuf.c b/drivers/infiniband/core/umem_dmabuf.c +index be5977daafa1de..091af1f7aa29db 100644 +--- a/drivers/infiniband/core/umem_dmabuf.c ++++ b/drivers/infiniband/core/umem_dmabuf.c +@@ -206,6 +206,10 @@ static void ib_umem_dmabuf_revoke_locked(struct dma_buf_attachment *attach) + + if (umem_dmabuf->revoked) + return; ++ ++ if (umem_dmabuf->pinned_revoke) ++ umem_dmabuf->pinned_revoke(umem_dmabuf->private); ++ + ib_umem_dmabuf_unmap_pages(umem_dmabuf); + if (umem_dmabuf->pinned) { + dma_buf_unpin(umem_dmabuf->attach); +@@ -214,6 +218,11 @@ static void ib_umem_dmabuf_revoke_locked(struct dma_buf_attachment *attach) + umem_dmabuf->revoked = 1; + } + ++static struct dma_buf_attach_ops ib_umem_dmabuf_attach_pinned_revocable_ops = { ++ .allow_peer2peer = true, ++ .move_notify = ib_umem_dmabuf_revoke_locked, ++}; ++ + static struct ib_umem_dmabuf * + ib_umem_dmabuf_get_pinned_and_lock(struct ib_device *device, + struct device *dma_device, +@@ -266,6 +275,58 @@ ib_umem_dmabuf_get_pinned_with_dma_device(struct ib_device *device, + } + EXPORT_SYMBOL(ib_umem_dmabuf_get_pinned_with_dma_device); + ++/** ++ * ib_umem_dmabuf_get_pinned_revocable_and_lock - Map & pin a revocable dmabuf ++ * @device: IB device. ++ * @offset: Start offset. ++ * @size: Length. ++ * @fd: dmabuf fd. ++ * @access: Access flags. ++ * ++ * Obtains a umem from a dmabuf for drivers/devices that can support revocation. ++ * ++ * Returns with dma_resv_lock held upon success. The driver must set the revoke ++ * callback prior to unlock by calling ib_umem_dmabuf_set_revoke_locked(). ++ * ++ * When a revocation occurs, the revoke callback will be called. The driver must ++ * ensure that the region is no longer accessed when the callback returns. Any ++ * subsequent access attempts should also probably cause an AE for MRs. ++ * ++ * If the umem is used for an MR, the driver must ensure that the key remains in ++ * use such that it cannot be obtained by a new region until this region is ++ * fully deregistered (i.e., ibv_dereg_mr). If a driver needs to serialize with ++ * revoke calls, it can use dma_resv_lock. ++ * ++ * If successful, then the revoke callback may be called at any time and will ++ * also be called automatically upon ib_umem_release (serialized). The revoke ++ * callback will be called one time at most. ++ * ++ * Return: A pointer to ib_umem_dmabuf on success, or an ERR_PTR on failure. ++ */ ++struct ib_umem_dmabuf * ++ib_umem_dmabuf_get_pinned_revocable_and_lock(struct ib_device *device, ++ unsigned long offset, size_t size, ++ int fd, int access) ++{ ++ const struct dma_buf_attach_ops *ops = ++ &ib_umem_dmabuf_attach_pinned_revocable_ops; ++ ++ return ib_umem_dmabuf_get_pinned_and_lock(device, device->dma_device, ++ offset, size, fd, access, ++ ops); ++} ++EXPORT_SYMBOL(ib_umem_dmabuf_get_pinned_revocable_and_lock); ++ ++void ib_umem_dmabuf_set_revoke_locked(struct ib_umem_dmabuf *umem_dmabuf, ++ void (*revoke)(void *priv), void *priv) ++{ ++ dma_resv_assert_held(umem_dmabuf->attach->dmabuf->resv); ++ ++ umem_dmabuf->pinned_revoke = revoke; ++ umem_dmabuf->private = priv; ++} ++EXPORT_SYMBOL(ib_umem_dmabuf_set_revoke_locked); ++ + struct ib_umem_dmabuf *ib_umem_dmabuf_get_pinned(struct ib_device *device, + unsigned long offset, + size_t size, int fd, +diff --git a/include/rdma/ib_umem.h b/include/rdma/ib_umem.h +index 3ec9f1deca7db4..7637ff06bb5b10 100644 +--- a/include/rdma/ib_umem.h ++++ b/include/rdma/ib_umem.h +@@ -36,6 +36,7 @@ struct ib_umem_dmabuf { + struct scatterlist *last_sg; + unsigned long first_sg_offset; + unsigned long last_sg_trim; ++ void (*pinned_revoke)(void *priv); + void *private; + u8 pinned : 1; + u8 revoked : 1; +@@ -124,6 +125,12 @@ struct ib_umem_dmabuf *ib_umem_dmabuf_get_pinned(struct ib_device *device, + size_t size, int fd, + int access); + struct ib_umem_dmabuf * ++ib_umem_dmabuf_get_pinned_revocable_and_lock(struct ib_device *device, ++ unsigned long offset, size_t size, ++ int fd, int access); ++void ib_umem_dmabuf_set_revoke_locked(struct ib_umem_dmabuf *umem_dmabuf, ++ void (*revoke)(void *priv), void *priv); ++struct ib_umem_dmabuf * + ib_umem_dmabuf_get_pinned_with_dma_device(struct ib_device *device, + struct device *dma_device, + unsigned long offset, size_t size, +@@ -178,6 +185,18 @@ ib_umem_dmabuf_get_pinned(struct ib_device *device, unsigned long offset, + return ERR_PTR(-EOPNOTSUPP); + } + ++static inline struct ib_umem_dmabuf * ++ib_umem_dmabuf_get_pinned_revocable_and_lock(struct ib_device *device, ++ unsigned long offset, size_t size, ++ int fd, int access) ++{ ++ return ERR_PTR(-EOPNOTSUPP); ++} ++ ++static inline void ++ib_umem_dmabuf_set_revoke_locked(struct ib_umem_dmabuf *umem_dmabuf, ++ void (*revoke)(void *priv), void *priv) {} ++ + static inline struct ib_umem_dmabuf * + ib_umem_dmabuf_get_pinned_with_dma_device(struct ib_device *device, + struct device *dma_device, +-- +2.53.0 + diff --git a/queue-6.6/rdma-umem-add-support-for-creating-pinned-dmabuf-ume.patch b/queue-6.6/rdma-umem-add-support-for-creating-pinned-dmabuf-ume.patch new file mode 100644 index 0000000000..0206120d3e --- /dev/null +++ b/queue-6.6/rdma-umem-add-support-for-creating-pinned-dmabuf-ume.patch @@ -0,0 +1,150 @@ +From 0a8214db307121d59e27c82f22c17771c19a5486 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 1 Aug 2024 15:05:13 +0300 +Subject: RDMA/umem: Add support for creating pinned DMABUF umem with a given + dma device + +From: Yishai Hadas + +[ Upstream commit 682358fd35dece838e6ae2d9d6a69fc0b9a9d411 ] + +Add support for creating pinned DMABUF umem with a specified DMA device +instead of the DMA device of the given IB device. + +This API will be utilized in the upcoming patches of the series when +multiple path DMAs are implemented. + +Signed-off-by: Yishai Hadas +Link: https://patch.msgid.link/038aad36a43797e5591b20ba81051fc5758124f9.1722512548.git.leon@kernel.org +Signed-off-by: Leon Romanovsky +Stable-dep-of: a846aecb931b ("RDMA/irdma: Prevent rereg_mr for non-mem regions") +Signed-off-by: Sasha Levin +--- + drivers/infiniband/core/umem_dmabuf.c | 45 ++++++++++++++++++++------- + include/rdma/ib_umem.h | 15 +++++++++ + 2 files changed, 49 insertions(+), 11 deletions(-) + +diff --git a/drivers/infiniband/core/umem_dmabuf.c b/drivers/infiniband/core/umem_dmabuf.c +index 66f5760197479d..674a4b45e7bfe7 100644 +--- a/drivers/infiniband/core/umem_dmabuf.c ++++ b/drivers/infiniband/core/umem_dmabuf.c +@@ -110,10 +110,12 @@ void ib_umem_dmabuf_unmap_pages(struct ib_umem_dmabuf *umem_dmabuf) + } + EXPORT_SYMBOL(ib_umem_dmabuf_unmap_pages); + +-struct ib_umem_dmabuf *ib_umem_dmabuf_get(struct ib_device *device, +- unsigned long offset, size_t size, +- int fd, int access, +- const struct dma_buf_attach_ops *ops) ++static struct ib_umem_dmabuf * ++ib_umem_dmabuf_get_with_dma_device(struct ib_device *device, ++ struct device *dma_device, ++ unsigned long offset, size_t size, ++ int fd, int access, ++ const struct dma_buf_attach_ops *ops) + { + struct dma_buf *dmabuf; + struct ib_umem_dmabuf *umem_dmabuf; +@@ -152,7 +154,7 @@ struct ib_umem_dmabuf *ib_umem_dmabuf_get(struct ib_device *device, + + umem_dmabuf->attach = dma_buf_dynamic_attach( + dmabuf, +- device->dma_device, ++ dma_device, + ops, + umem_dmabuf); + if (IS_ERR(umem_dmabuf->attach)) { +@@ -168,6 +170,15 @@ struct ib_umem_dmabuf *ib_umem_dmabuf_get(struct ib_device *device, + dma_buf_put(dmabuf); + return ret; + } ++ ++struct ib_umem_dmabuf *ib_umem_dmabuf_get(struct ib_device *device, ++ unsigned long offset, size_t size, ++ int fd, int access, ++ const struct dma_buf_attach_ops *ops) ++{ ++ return ib_umem_dmabuf_get_with_dma_device(device, device->dma_device, ++ offset, size, fd, access, ops); ++} + EXPORT_SYMBOL(ib_umem_dmabuf_get); + + static void +@@ -184,16 +195,18 @@ static struct dma_buf_attach_ops ib_umem_dmabuf_attach_pinned_ops = { + .move_notify = ib_umem_dmabuf_unsupported_move_notify, + }; + +-struct ib_umem_dmabuf *ib_umem_dmabuf_get_pinned(struct ib_device *device, +- unsigned long offset, +- size_t size, int fd, +- int access) ++struct ib_umem_dmabuf * ++ib_umem_dmabuf_get_pinned_with_dma_device(struct ib_device *device, ++ struct device *dma_device, ++ unsigned long offset, size_t size, ++ int fd, int access) + { + struct ib_umem_dmabuf *umem_dmabuf; + int err; + +- umem_dmabuf = ib_umem_dmabuf_get(device, offset, size, fd, access, +- &ib_umem_dmabuf_attach_pinned_ops); ++ umem_dmabuf = ib_umem_dmabuf_get_with_dma_device(device, dma_device, offset, ++ size, fd, access, ++ &ib_umem_dmabuf_attach_pinned_ops); + if (IS_ERR(umem_dmabuf)) + return umem_dmabuf; + +@@ -215,6 +228,16 @@ struct ib_umem_dmabuf *ib_umem_dmabuf_get_pinned(struct ib_device *device, + ib_umem_release(&umem_dmabuf->umem); + return ERR_PTR(err); + } ++EXPORT_SYMBOL(ib_umem_dmabuf_get_pinned_with_dma_device); ++ ++struct ib_umem_dmabuf *ib_umem_dmabuf_get_pinned(struct ib_device *device, ++ unsigned long offset, ++ size_t size, int fd, ++ int access) ++{ ++ return ib_umem_dmabuf_get_pinned_with_dma_device(device, device->dma_device, ++ offset, size, fd, access); ++} + EXPORT_SYMBOL(ib_umem_dmabuf_get_pinned); + + void ib_umem_dmabuf_release(struct ib_umem_dmabuf *umem_dmabuf) +diff --git a/include/rdma/ib_umem.h b/include/rdma/ib_umem.h +index eac3c05278c153..3441ba9f2a0daf 100644 +--- a/include/rdma/ib_umem.h ++++ b/include/rdma/ib_umem.h +@@ -122,6 +122,11 @@ struct ib_umem_dmabuf *ib_umem_dmabuf_get_pinned(struct ib_device *device, + unsigned long offset, + size_t size, int fd, + int access); ++struct ib_umem_dmabuf * ++ib_umem_dmabuf_get_pinned_with_dma_device(struct ib_device *device, ++ struct device *dma_device, ++ unsigned long offset, size_t size, ++ int fd, int access); + int ib_umem_dmabuf_map_pages(struct ib_umem_dmabuf *umem_dmabuf); + void ib_umem_dmabuf_unmap_pages(struct ib_umem_dmabuf *umem_dmabuf); + void ib_umem_dmabuf_release(struct ib_umem_dmabuf *umem_dmabuf); +@@ -170,6 +175,16 @@ ib_umem_dmabuf_get_pinned(struct ib_device *device, unsigned long offset, + { + return ERR_PTR(-EOPNOTSUPP); + } ++ ++static inline struct ib_umem_dmabuf * ++ib_umem_dmabuf_get_pinned_with_dma_device(struct ib_device *device, ++ struct device *dma_device, ++ unsigned long offset, size_t size, ++ int fd, int access) ++{ ++ return ERR_PTR(-EOPNOTSUPP); ++} ++ + static inline int ib_umem_dmabuf_map_pages(struct ib_umem_dmabuf *umem_dmabuf) + { + return -EOPNOTSUPP; +-- +2.53.0 + diff --git a/queue-6.6/rdma-umem-introduce-an-option-to-revoke-dmabuf-umem.patch b/queue-6.6/rdma-umem-introduce-an-option-to-revoke-dmabuf-umem.patch new file mode 100644 index 0000000000..f82af71651 --- /dev/null +++ b/queue-6.6/rdma-umem-introduce-an-option-to-revoke-dmabuf-umem.patch @@ -0,0 +1,106 @@ +From 1480aecc4b7958d2cf9fc4bb1c987b129da174f5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 1 Aug 2024 15:05:14 +0300 +Subject: RDMA/umem: Introduce an option to revoke DMABUF umem + +From: Yishai Hadas + +[ Upstream commit 253c61dc256b3e6be65657f78b4a8452163ce00f ] + +Introduce an option to revoke DMABUF umem. + +This option will retain the umem allocation while revoking its DMA +mapping. Furthermore, any subsequent attempts to map the pages should +fail once the umem has been revoked. + +This functionality will be utilized in the upcoming patches in the +series, where we aim to delay umem deallocation until the mkey +deregistration. However, we must unmap its pages immediately. + +Signed-off-by: Yishai Hadas +Link: https://patch.msgid.link/a38270f2fe4a194868ca2312f4c1c760e51bcbff.1722512548.git.leon@kernel.org +Signed-off-by: Leon Romanovsky +Stable-dep-of: a846aecb931b ("RDMA/irdma: Prevent rereg_mr for non-mem regions") +Signed-off-by: Sasha Levin +--- + drivers/infiniband/core/umem_dmabuf.c | 21 +++++++++++++++++++-- + include/rdma/ib_umem.h | 3 +++ + 2 files changed, 22 insertions(+), 2 deletions(-) + +diff --git a/drivers/infiniband/core/umem_dmabuf.c b/drivers/infiniband/core/umem_dmabuf.c +index 674a4b45e7bfe7..44bb7449738cf4 100644 +--- a/drivers/infiniband/core/umem_dmabuf.c ++++ b/drivers/infiniband/core/umem_dmabuf.c +@@ -23,6 +23,9 @@ int ib_umem_dmabuf_map_pages(struct ib_umem_dmabuf *umem_dmabuf) + + dma_resv_assert_held(umem_dmabuf->attach->dmabuf->resv); + ++ if (umem_dmabuf->revoked) ++ return -EINVAL; ++ + if (umem_dmabuf->sgt) + goto wait_fence; + +@@ -240,15 +243,29 @@ struct ib_umem_dmabuf *ib_umem_dmabuf_get_pinned(struct ib_device *device, + } + EXPORT_SYMBOL(ib_umem_dmabuf_get_pinned); + +-void ib_umem_dmabuf_release(struct ib_umem_dmabuf *umem_dmabuf) ++void ib_umem_dmabuf_revoke(struct ib_umem_dmabuf *umem_dmabuf) + { + struct dma_buf *dmabuf = umem_dmabuf->attach->dmabuf; + + dma_resv_lock(dmabuf->resv, NULL); ++ if (umem_dmabuf->revoked) ++ goto end; + ib_umem_dmabuf_unmap_pages(umem_dmabuf); +- if (umem_dmabuf->pinned) ++ if (umem_dmabuf->pinned) { + dma_buf_unpin(umem_dmabuf->attach); ++ umem_dmabuf->pinned = 0; ++ } ++ umem_dmabuf->revoked = 1; ++end: + dma_resv_unlock(dmabuf->resv); ++} ++EXPORT_SYMBOL(ib_umem_dmabuf_revoke); ++ ++void ib_umem_dmabuf_release(struct ib_umem_dmabuf *umem_dmabuf) ++{ ++ struct dma_buf *dmabuf = umem_dmabuf->attach->dmabuf; ++ ++ ib_umem_dmabuf_revoke(umem_dmabuf); + + dma_buf_detach(dmabuf, umem_dmabuf->attach); + dma_buf_put(dmabuf); +diff --git a/include/rdma/ib_umem.h b/include/rdma/ib_umem.h +index 3441ba9f2a0daf..3ec9f1deca7db4 100644 +--- a/include/rdma/ib_umem.h ++++ b/include/rdma/ib_umem.h +@@ -38,6 +38,7 @@ struct ib_umem_dmabuf { + unsigned long last_sg_trim; + void *private; + u8 pinned : 1; ++ u8 revoked : 1; + }; + + static inline struct ib_umem_dmabuf *to_ib_umem_dmabuf(struct ib_umem *umem) +@@ -130,6 +131,7 @@ ib_umem_dmabuf_get_pinned_with_dma_device(struct ib_device *device, + int ib_umem_dmabuf_map_pages(struct ib_umem_dmabuf *umem_dmabuf); + void ib_umem_dmabuf_unmap_pages(struct ib_umem_dmabuf *umem_dmabuf); + void ib_umem_dmabuf_release(struct ib_umem_dmabuf *umem_dmabuf); ++void ib_umem_dmabuf_revoke(struct ib_umem_dmabuf *umem_dmabuf); + + int ib_umem_check_rereg(struct ib_umem *umem, int flags, int new_access_flags); + +@@ -191,6 +193,7 @@ static inline int ib_umem_dmabuf_map_pages(struct ib_umem_dmabuf *umem_dmabuf) + } + static inline void ib_umem_dmabuf_unmap_pages(struct ib_umem_dmabuf *umem_dmabuf) { } + static inline void ib_umem_dmabuf_release(struct ib_umem_dmabuf *umem_dmabuf) { } ++static inline void ib_umem_dmabuf_revoke(struct ib_umem_dmabuf *umem_dmabuf) {} + + static inline int ib_umem_check_rereg(struct ib_umem *umem, int flags, + int new_access_flags) +-- +2.53.0 + diff --git a/queue-6.6/rdma-umem-move-umem-dmabuf-revoke-logic-into-helper-.patch b/queue-6.6/rdma-umem-move-umem-dmabuf-revoke-logic-into-helper-.patch new file mode 100644 index 0000000000..eaab174803 --- /dev/null +++ b/queue-6.6/rdma-umem-move-umem-dmabuf-revoke-logic-into-helper-.patch @@ -0,0 +1,69 @@ +From 05eba777f42bb9fcb1b3bf363f5256bd87f8c64d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 5 Mar 2026 17:08:23 +0000 +Subject: RDMA/umem: Move umem dmabuf revoke logic into helper function + +From: Jacob Moroni + +[ Upstream commit 797291a66ce346c96114b72222fc290d402da005 ] + +This same logic will eventually be reused from within the +invalidate_mappings callback which already has the dma_resv_lock +held, so break it out into a separate function so it can be reused. + +Signed-off-by: Jacob Moroni +Link: https://patch.msgid.link/20260305170826.3803155-3-jmoroni@google.com +Signed-off-by: Leon Romanovsky +Stable-dep-of: a846aecb931b ("RDMA/irdma: Prevent rereg_mr for non-mem regions") +Signed-off-by: Sasha Levin +--- + drivers/infiniband/core/umem_dmabuf.c | 26 +++++++++++++++++--------- + 1 file changed, 17 insertions(+), 9 deletions(-) + +diff --git a/drivers/infiniband/core/umem_dmabuf.c b/drivers/infiniband/core/umem_dmabuf.c +index acb0922a786131..be5977daafa1de 100644 +--- a/drivers/infiniband/core/umem_dmabuf.c ++++ b/drivers/infiniband/core/umem_dmabuf.c +@@ -198,6 +198,22 @@ static struct dma_buf_attach_ops ib_umem_dmabuf_attach_pinned_ops = { + .move_notify = ib_umem_dmabuf_unsupported_move_notify, + }; + ++static void ib_umem_dmabuf_revoke_locked(struct dma_buf_attachment *attach) ++{ ++ struct ib_umem_dmabuf *umem_dmabuf = attach->importer_priv; ++ ++ dma_resv_assert_held(attach->dmabuf->resv); ++ ++ if (umem_dmabuf->revoked) ++ return; ++ ib_umem_dmabuf_unmap_pages(umem_dmabuf); ++ if (umem_dmabuf->pinned) { ++ dma_buf_unpin(umem_dmabuf->attach); ++ umem_dmabuf->pinned = 0; ++ } ++ umem_dmabuf->revoked = 1; ++} ++ + static struct ib_umem_dmabuf * + ib_umem_dmabuf_get_pinned_and_lock(struct ib_device *device, + struct device *dma_device, +@@ -265,15 +281,7 @@ void ib_umem_dmabuf_revoke(struct ib_umem_dmabuf *umem_dmabuf) + struct dma_buf *dmabuf = umem_dmabuf->attach->dmabuf; + + dma_resv_lock(dmabuf->resv, NULL); +- if (umem_dmabuf->revoked) +- goto end; +- ib_umem_dmabuf_unmap_pages(umem_dmabuf); +- if (umem_dmabuf->pinned) { +- dma_buf_unpin(umem_dmabuf->attach); +- umem_dmabuf->pinned = 0; +- } +- umem_dmabuf->revoked = 1; +-end: ++ ib_umem_dmabuf_revoke_locked(umem_dmabuf->attach); + dma_resv_unlock(dmabuf->resv); + } + EXPORT_SYMBOL(ib_umem_dmabuf_revoke); +-- +2.53.0 + diff --git a/queue-6.6/sched-vtime-get-rid-of-generic-vtime_task_switch-imp.patch b/queue-6.6/sched-vtime-get-rid-of-generic-vtime_task_switch-imp.patch new file mode 100644 index 0000000000..9cc848fdf7 --- /dev/null +++ b/queue-6.6/sched-vtime-get-rid-of-generic-vtime_task_switch-imp.patch @@ -0,0 +1,123 @@ +From ec3120c916d5695a70e5046d07563dac4d5d76b7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 10 Apr 2024 17:09:45 +0200 +Subject: sched/vtime: Get rid of generic vtime_task_switch() implementation + +From: Alexander Gordeev + +[ Upstream commit 89d6910cc562ab34d1f1c08f3cf0a9700b8bf2c4 ] + +The generic vtime_task_switch() implementation gets built only +if __ARCH_HAS_VTIME_TASK_SWITCH is not defined, but requires an +architecture to implement arch_vtime_task_switch() callback at +the same time, which is confusing. + +Further, arch_vtime_task_switch() is implemented for 32-bit PowerPC +architecture only and vtime_task_switch() generic variant is rather +superfluous. + +Simplify the whole vtime_task_switch() wiring by moving the existing +generic implementation to PowerPC. + +Signed-off-by: Alexander Gordeev +Signed-off-by: Ingo Molnar +Reviewed-by: Frederic Weisbecker +Reviewed-by: Nicholas Piggin +Acked-by: Michael Ellerman +Link: https://lore.kernel.org/r/2cb6e3caada93623f6d4f78ad938ac6cd0e2fda8.1712760275.git.agordeev@linux.ibm.com +Stable-dep-of: c1c1ffa490fc ("powerpc/vtime: Initialize starttime at boot for native accounting") +Signed-off-by: Sasha Levin +--- + arch/powerpc/include/asm/cputime.h | 13 ------------- + arch/powerpc/kernel/time.c | 22 ++++++++++++++++++++++ + kernel/sched/cputime.c | 13 ------------- + 3 files changed, 22 insertions(+), 26 deletions(-) + +diff --git a/arch/powerpc/include/asm/cputime.h b/arch/powerpc/include/asm/cputime.h +index 4961fb38e4385f..aff858ca99c05d 100644 +--- a/arch/powerpc/include/asm/cputime.h ++++ b/arch/powerpc/include/asm/cputime.h +@@ -32,23 +32,10 @@ + #ifdef CONFIG_PPC64 + #define get_accounting(tsk) (&get_paca()->accounting) + #define raw_get_accounting(tsk) (&local_paca->accounting) +-static inline void arch_vtime_task_switch(struct task_struct *tsk) { } + + #else + #define get_accounting(tsk) (&task_thread_info(tsk)->accounting) + #define raw_get_accounting(tsk) get_accounting(tsk) +-/* +- * Called from the context switch with interrupts disabled, to charge all +- * accumulated times to the current process, and to prepare accounting on +- * the next process. +- */ +-static inline void arch_vtime_task_switch(struct task_struct *prev) +-{ +- struct cpu_accounting_data *acct = get_accounting(current); +- struct cpu_accounting_data *acct0 = get_accounting(prev); +- +- acct->starttime = acct0->starttime; +-} + #endif + + /* +diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c +index dda35c404a6761..7fce6adb6f05fd 100644 +--- a/arch/powerpc/kernel/time.c ++++ b/arch/powerpc/kernel/time.c +@@ -354,6 +354,28 @@ void vtime_flush(struct task_struct *tsk) + acct->hardirq_time = 0; + acct->softirq_time = 0; + } ++ ++/* ++ * Called from the context switch with interrupts disabled, to charge all ++ * accumulated times to the current process, and to prepare accounting on ++ * the next process. ++ */ ++void vtime_task_switch(struct task_struct *prev) ++{ ++ if (is_idle_task(prev)) ++ vtime_account_idle(prev); ++ else ++ vtime_account_kernel(prev); ++ ++ vtime_flush(prev); ++ ++ if (!IS_ENABLED(CONFIG_PPC64)) { ++ struct cpu_accounting_data *acct = get_accounting(current); ++ struct cpu_accounting_data *acct0 = get_accounting(prev); ++ ++ acct->starttime = acct0->starttime; ++ } ++} + #endif /* CONFIG_VIRT_CPU_ACCOUNTING_NATIVE */ + + void __no_kcsan __delay(unsigned long loops) +diff --git a/kernel/sched/cputime.c b/kernel/sched/cputime.c +index b453f8a6a7c764..4feef0d4e4494d 100644 +--- a/kernel/sched/cputime.c ++++ b/kernel/sched/cputime.c +@@ -424,19 +424,6 @@ static inline void irqtime_account_process_tick(struct task_struct *p, int user_ + */ + #ifdef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE + +-# ifndef __ARCH_HAS_VTIME_TASK_SWITCH +-void vtime_task_switch(struct task_struct *prev) +-{ +- if (is_idle_task(prev)) +- vtime_account_idle(prev); +- else +- vtime_account_kernel(prev); +- +- vtime_flush(prev); +- arch_vtime_task_switch(prev); +-} +-# endif +- + void vtime_account_irq(struct task_struct *tsk, unsigned int offset) + { + unsigned int pc = irq_count() - offset; +-- +2.53.0 + diff --git a/queue-6.6/sctp-fix-auth_hmacs-array-size-in-struct-sctp_cookie.patch b/queue-6.6/sctp-fix-auth_hmacs-array-size-in-struct-sctp_cookie.patch new file mode 100644 index 0000000000..49d7b5069d --- /dev/null +++ b/queue-6.6/sctp-fix-auth_hmacs-array-size-in-struct-sctp_cookie.patch @@ -0,0 +1,56 @@ +From e760d764bd4310ffba7ec96600b727d9b46788a7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 10 Jul 2026 14:12:35 -0400 +Subject: sctp: fix auth_hmacs array size in struct sctp_cookie + +From: Xin Long + +[ Upstream commit e0b5252a59383b77d1b8dbeda00b7184dd95f4d3 ] + +The auth_hmacs array in struct sctp_cookie is supposed to store a complete +SCTP_AUTH_HMAC_ALGO parameter, which consists of a struct sctp_paramhdr +followed by N HMAC identifiers. + +However, the array size was calculated using an extra 2 bytes instead of +sizeof(struct sctp_paramhdr), which is 4 bytes. When four HMAC identifiers +are configured, the HMAC-ALGO parameter stored in the endpoint is larger +than the auth_hmacs buffer in the cookie. + +As a result, sctp_association_init() copies beyond the end of auth_hmacs +when initializing the association, corrupting the adjacent auth_chunks +field. This can lead to an invalid HMAC identifier being accepted and later +cause an out-of-bounds read in sctp_auth_get_hmac(). + +Fix the array size calculation by including the full SCTP parameter header +size. + +Fixes: 1f485649f529 ("[SCTP]: Implement SCTP-AUTH internals") +Reported-by: Yuan Tan +Reported-by: Xin Liu +Reported-by: Zihan Xi +Reported-by: Ren Wei +Signed-off-by: Xin Long +Link: https://patch.msgid.link/634a0de0d5de29532915e6d47c92a0cbc206e03f.1783707155.git.lucien.xin@gmail.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + include/net/sctp/structs.h | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h +index d943bb454b1769..5baf98eac3db9d 100644 +--- a/include/net/sctp/structs.h ++++ b/include/net/sctp/structs.h +@@ -322,7 +322,8 @@ struct sctp_cookie { + + __u8 auth_random[sizeof(struct sctp_paramhdr) + + SCTP_AUTH_RANDOM_LENGTH]; +- __u8 auth_hmacs[SCTP_AUTH_NUM_HMACS * sizeof(__u16) + 2]; ++ __u8 auth_hmacs[sizeof(struct sctp_paramhdr) + ++ SCTP_AUTH_NUM_HMACS * sizeof(__u16)]; + __u8 auth_chunks[sizeof(struct sctp_paramhdr) + SCTP_AUTH_MAX_CHUNKS]; + + /* This is a shim for my peer's INIT packet, followed by +-- +2.53.0 + diff --git a/queue-6.6/selftests-alsa-fix-memory-leak-in-find_controls-erro.patch b/queue-6.6/selftests-alsa-fix-memory-leak-in-find_controls-erro.patch new file mode 100644 index 0000000000..5b4ed9bea9 --- /dev/null +++ b/queue-6.6/selftests-alsa-fix-memory-leak-in-find_controls-erro.patch @@ -0,0 +1,41 @@ +From 606adfd90c63f599ab60a5d50e3648d42a708b54 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 4 Jul 2026 16:27:36 +0530 +Subject: selftests/alsa: Fix memory leak in find_controls error path + +From: Malaya Kumar Rout + +[ Upstream commit cb89f0c1aed02eb233c4271f76f830b37e222ff6 ] + +In find_controls(), card_data is allocated with malloc() but when +snd_ctl_open_lconf() fails, the code jumps to next_card without +freeing the allocated memory. This results in a memory leak for +each card where snd_ctl_open_lconf() fails. + +Add free(card_data) before goto next_card to ensure proper cleanup +of the allocated memory in the error path. + +Fixes: 5aaf9efffc57 ("kselftest: alsa: Add simplistic test for ALSA mixer controls kselftest") +Signed-off-by: Malaya Kumar Rout +Link: https://patch.msgid.link/20260704105736.94874-1-malayarout91@gmail.com +Signed-off-by: Takashi Iwai +Signed-off-by: Sasha Levin +--- + tools/testing/selftests/alsa/mixer-test.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/tools/testing/selftests/alsa/mixer-test.c b/tools/testing/selftests/alsa/mixer-test.c +index df942149c6f6c5..6fe4be43072fb1 100644 +--- a/tools/testing/selftests/alsa/mixer-test.c ++++ b/tools/testing/selftests/alsa/mixer-test.c +@@ -82,6 +82,7 @@ static void find_controls(void) + if (err < 0) { + ksft_print_msg("Failed to get hctl for card %d: %s\n", + card, snd_strerror(err)); ++ free(card_data); + goto next_card; + } + +-- +2.53.0 + diff --git a/queue-6.6/series b/queue-6.6/series index f1b0ecf287..edd89ec044 100644 --- a/queue-6.6/series +++ b/queue-6.6/series @@ -27,3 +27,70 @@ xprtrdma-clear-receive-side-ownership-pointers-on-re.patch input-ims-pcu-fix-heap-buffer-overflow-in-ims_pcu_pr.patch input-ims-pcu-fix-logic-error-in-packet-reset.patch mm-refactor-mm_access-to-not-return-null.patch +arm64-tegra-fix-cpu-compatible-string-to-cortex-a78a.patch +ib-mad-drop-unmatched-rmpp-responses-before-reassemb.patch +mtd-mtdswap-remove-debugfs-stats-file-on-teardown.patch +mtd-nand-mtk-ecc-stop-on-ecc-idle-timeouts.patch +btrfs-reject-free-space-cache-with-more-entries-than.patch +btrfs-fix-root-leak-if-its-reloc-root-is-unexpected-.patch +firmware-arm_ffa-fix-null-dereference-in-ffa_partiti.patch +rdma-cma-fix-hardware-address-comparison-length-in-n.patch +rdma-umem-add-support-for-creating-pinned-dmabuf-ume.patch +rdma-umem-introduce-an-option-to-revoke-dmabuf-umem.patch +rdma-umem-add-ib_umem_dmabuf_get_pinned_and_lock-hel.patch +rdma-umem-move-umem-dmabuf-revoke-logic-into-helper-.patch +rdma-umem-add-pinned-revocable-dmabuf-import-interfa.patch +rdma-umem-add-helpers-for-umem-dmabuf-revoke-lock.patch +rdma-irdma-prevent-rereg_mr-for-non-mem-regions.patch +rdma-erdma-initialize-ret-for-empty-receive-wr-lists.patch +rdma-hns-fix-potential-integer-overflow-in-mhop-hem-.patch +rdma-siw-only-check-attrs-cap.max_send_wr-in-siw_cre.patch +rdma-siw-publish-qp-after-initialization.patch +mtd-fix-double-free-and-warn_on-in-add_mtd_device-er.patch +selftests-alsa-fix-memory-leak-in-find_controls-erro.patch +rdma-irdma-prevent-overflows-in-memory-contiguity-ch.patch +xfrm6-clear-dst.dev-on-error-to-avoid-double-netdev_.patch +xfrm-policy-preallocate-inexact-bins-before-xfrm_has.patch +wifi-cfg80211-cancel-sched-scan-results-work-on-unre.patch +wifi-ipw2100-fix-potential-memory-leak-in-ipw2100_pc.patch +wifi-mac80211_hwsim-clamp-virtio-rx-length-before-sk.patch +wifi-libertas-fix-memory-leak-in-helper_firmware_cb.patch +wifi-p54-validate-rx-frame-length-in-p54_rx_eeprom_r.patch +wifi-nl80211-free-rnr-data-on-mbssid-mismatch.patch +wifi-nl80211-validate-nested-mbssid-ie-blobs.patch +wifi-cfg80211-validate-pmsr-measurement-type-data.patch +wifi-cfg80211-validate-pmsr-ftm-preamble-range.patch +wifi-cfg80211-reject-unsupported-pmsr-ftm-location-r.patch +wifi-mac80211-free-ap_vlan-bc_buf-skbs-outside-irq-l.patch +wifi-brcmfmac-initialize-sdio-data-work-before-clean.patch +wifi-cfg80211-bound-element-id-read-when-checking-no.patch +asoc-meson-aiu-fifo-spdif-soft-reset-the-s-pdif-data.patch +asoc-amd-ps-fix-wrong-acp-version-string-in-pci_requ.patch +asoc-cs42l43-correct-report-for-forced-microphone-ja.patch +asoc-tas2562-fix-deprecated-shut-down-gpio-always-cl.patch +firmware-arm_scmi-rate-limit-queue-full-warnings-in-.patch +ppp-defer-channel-free-to-an-rcu-grace-period-to-fix.patch +ipv4-fib-free-fib_alias-with-kfree_rcu-on-insert-err.patch +net-iucv-take-a-reference-on-the-socket-found-in-afi.patch +ata-sata_dwc_460ex-enable-sata-interrupts-only-after.patch +ata-sata_dwc_460ex-use-platform_get_irq.patch +ata-sata_dwc_460ex-fix-clear_interrupt_bit-clearing-.patch +ata-sata_dwc_460ex-fix-infinite-loop-in-ncq-tag-comp.patch +alsa-usb-audio-skip-dsd-quirk-for-musical-fidelity-m.patch +bluetooth-qca-fix-nvm-tag-length-underflow-in-tlv-pa.patch +bluetooth-mgmt-fix-locking-in-unpair_device-disconne.patch +bluetooth-mgmt-hold-reference-for-hci_conn-in-mgmt_p.patch +bluetooth-hci_qca-clear-memdump-state-on-invalid-dum.patch +smb-client-handle-overlapping-allocated-ranges-in-fa.patch +drm-i915-gt-use-correct-selftest-config-symbol.patch +sched-vtime-get-rid-of-generic-vtime_task_switch-imp.patch +powerpc-time-prepare-to-stop-elapsing-in-dynticks-id.patch +powerpc-vtime-initialize-starttime-at-boot-for-nativ.patch +bpf-sockmap-reject-unhashed-udp-sockets-on-sockmap-u.patch +can-j1939-fix-lockless-local-destination-check.patch +ksmbd-pin-conn-during-async-oplock-break-notificatio.patch +ksmbd-validate-compound-request-size-before-reading-.patch +drm-i915-selftests-fix-gt-pm-sort-comparators.patch +net-sched-act_tunnel_key-defer-dst_release-to-rcu-ca.patch +sctp-fix-auth_hmacs-array-size-in-struct-sctp_cookie.patch +mpls-fix-null-deref-in-mpls_valid_fib_dump_req-on-co.patch diff --git a/queue-6.6/smb-client-handle-overlapping-allocated-ranges-in-fa.patch b/queue-6.6/smb-client-handle-overlapping-allocated-ranges-in-fa.patch new file mode 100644 index 0000000000..b340d6bc4f --- /dev/null +++ b/queue-6.6/smb-client-handle-overlapping-allocated-ranges-in-fa.patch @@ -0,0 +1,110 @@ +From e71bc2b578a8a2893f421fb3df44389b5260f02e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 3 Jul 2026 13:32:56 +0800 +Subject: smb/client: handle overlapping allocated ranges in fallocate + +From: Huiwen He + +[ Upstream commit b09ae45d85dc816987a71db9eebc54b0ae288e94 ] + +smb3_simple_fallocate_range() can skip holes when an allocated range +returned by the server starts before the current fallocate offset. The +skipped hole is not zero-filled, but fallocate still returns success. A +later write to that hole may therefore fail with ENOSPC. + +The function queries allocated ranges so that it can preserve existing +contents and write zeroes only into holes. However, the server may return +a range that starts before the current fallocate offset. + +For example, assume the fallocate request is [100, 400) and the only +allocated range returned by the server is [0, 200): + + Request: [100, 400) + Server range: [ 0, 200) allocated + + Correct: + [100, 200) allocated data, skip + [200, 400) hole, zero-fill + + Current: + [100, 300) skipped + [300, 400) zero-filled afterwards + +The current code adds the full server range length, 200, to the current +offset 100 and moves to 300. As a result, the hole in [200, 300) is +skipped without being zero-filled. + +Fix this by advancing only over the part of the allocated range that +overlaps the current fallocate offset. Ignore ranges that end before the +current offset and reject ranges whose end offset overflows. + +This also prevents a malformed range length from causing an out-of-bounds +zero-buffer read. + +Fixes: 966a3cb7c7db ("cifs: improve fallocate emulation") +Signed-off-by: Huiwen He +Reviewed-by: ChenXiaoSong +Signed-off-by: Steve French +Signed-off-by: Sasha Levin +--- + fs/smb/client/smb2ops.c | 25 ++++++++++++++++++------- + 1 file changed, 18 insertions(+), 7 deletions(-) + +diff --git a/fs/smb/client/smb2ops.c b/fs/smb/client/smb2ops.c +index c66b02f67d3391..8a15694c1bbb56 100644 +--- a/fs/smb/client/smb2ops.c ++++ b/fs/smb/client/smb2ops.c +@@ -3417,6 +3417,7 @@ static int smb3_simple_fallocate_range(unsigned int xid, + struct file_allocated_range_buffer in_data, *out_data = NULL, *tmp_data; + u32 out_data_len; + char *buf = NULL; ++ u64 range_start, range_len, range_end; + loff_t l; + int rc; + +@@ -3453,13 +3454,21 @@ static int smb3_simple_fallocate_range(unsigned int xid, + goto out; + } + +- if (off < le64_to_cpu(tmp_data->file_offset)) { ++ range_start = le64_to_cpu(tmp_data->file_offset); ++ range_len = le64_to_cpu(tmp_data->length); ++ if (check_add_overflow(range_start, range_len, &range_end) || ++ range_end > S64_MAX) { ++ rc = -EINVAL; ++ goto out; ++ } ++ ++ if (off < range_start) { + /* + * We are at a hole. Write until the end of the region + * or until the next allocated data, + * whichever comes next. + */ +- l = le64_to_cpu(tmp_data->file_offset) - off; ++ l = range_start - off; + if (len < l) + l = len; + rc = smb3_simple_fallocate_write_range(xid, tcon, +@@ -3476,11 +3485,13 @@ static int smb3_simple_fallocate_range(unsigned int xid, + * until the end of the data or the end of the region + * we are supposed to fallocate, whichever comes first. + */ +- l = le64_to_cpu(tmp_data->length); +- if (len < l) +- l = len; +- off += l; +- len -= l; ++ if (off < range_end) { ++ l = range_end - off; ++ if (len < l) ++ l = len; ++ off += l; ++ len -= l; ++ } + + tmp_data = &tmp_data[1]; + out_data_len -= sizeof(struct file_allocated_range_buffer); +-- +2.53.0 + diff --git a/queue-6.6/wifi-brcmfmac-initialize-sdio-data-work-before-clean.patch b/queue-6.6/wifi-brcmfmac-initialize-sdio-data-work-before-clean.patch new file mode 100644 index 0000000000..ecedad1e98 --- /dev/null +++ b/queue-6.6/wifi-brcmfmac-initialize-sdio-data-work-before-clean.patch @@ -0,0 +1,61 @@ +From 83ac3b585e11ff08709d134ee8a6dfb2ebcd2557 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 19 Jun 2026 14:44:01 +0800 +Subject: wifi: brcmfmac: initialize SDIO data work before cleanup + +From: Runyu Xiao + +[ Upstream commit 2a665946e0407a05a3f81bd56a08553c446498e0 ] + +brcmf_sdio_probe() stores the newly allocated bus in sdiodev->bus before +allocating the ordered workqueue. If that allocation fails, the function +jumps to fail and calls brcmf_sdio_remove(). + +brcmf_sdio_remove() unconditionally cancels bus->datawork. Initialize the +work item before the first failure path that can reach brcmf_sdio_remove(), +so the cleanup path always observes a valid work object. + +This issue was found by our static analysis tool and then confirmed by +manual review of the probe error path and the remove-time work drain. The +problem pattern is an early setup failure that reaches a cleanup helper +which cancels an embedded work item before its initializer has run. + +A QEMU PoC forced alloc_ordered_workqueue() to fail at the same point in +brcmf_sdio_probe(), before INIT_WORK(&bus->datawork) is reached. The +resulting fail path calls brcmf_sdio_remove(), and DEBUG_OBJECTS reports +the invalid work drain with brcmf_sdio_probe() and brcmf_sdio_remove() in +the stack. + +Fixes: 9982464379e8 ("brcmfmac: make sdio suspend wait for threads to freeze") +Signed-off-by: Runyu Xiao +Acked-by: Arend van Spriel +Link: https://patch.msgid.link/20260619064401.1048976-1-runyu.xiao@seu.edu.cn +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c +index a4d0db371c8976..1ab0f501017bcf 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c +@@ -4458,6 +4458,7 @@ struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev) + bus->sdiodev = sdiodev; + sdiodev->bus = bus; + skb_queue_head_init(&bus->glom); ++ INIT_WORK(&bus->datawork, brcmf_sdio_dataworker); + bus->txbound = BRCMF_TXBOUND; + bus->rxbound = BRCMF_RXBOUND; + bus->txminmax = BRCMF_TXMINMAX; +@@ -4471,7 +4472,6 @@ struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev) + goto fail; + } + brcmf_sdiod_freezer_count(sdiodev); +- INIT_WORK(&bus->datawork, brcmf_sdio_dataworker); + bus->brcmf_wq = wq; + + /* attempt to attach to the dongle */ +-- +2.53.0 + diff --git a/queue-6.6/wifi-cfg80211-bound-element-id-read-when-checking-no.patch b/queue-6.6/wifi-cfg80211-bound-element-id-read-when-checking-no.patch new file mode 100644 index 0000000000..8997bc940d --- /dev/null +++ b/queue-6.6/wifi-cfg80211-bound-element-id-read-when-checking-no.patch @@ -0,0 +1,58 @@ +From 81d3347cdac3e5a2bf1815c117929b03cdeb29b1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 7 Jul 2026 18:48:28 +0900 +Subject: wifi: cfg80211: bound element ID read when checking non-inheritance +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: HE WEI (ギカク) + +[ Upstream commit cb8afea4655ff004fa7feee825d5c79783525383 ] + +cfg80211_is_element_inherited() reads the first data octet of the +candidate element (id = elem->data[0]) to look it up in an extension +non-inheritance list. It does so after testing elem->id, but without +verifying that the element actually has a data octet. A zero-length +extension element (WLAN_EID_EXTENSION with length 0) therefore makes it +read one octet past the end of the element. + +_ieee802_11_parse_elems_full() runs this check for every element of a +frame once a non-inheritance context exists -- e.g. while parsing a +per-STA profile of a Multi-Link element in a (re)association response, +or a non-transmitted BSS profile -- so a crafted frame from an AP can +trigger a one-octet slab-out-of-bounds read during element parsing: + + BUG: KASAN: slab-out-of-bounds in cfg80211_is_element_inherited + Read of size 1 ... in net/wireless/scan.c + +Return early (treat the element as inherited) when an extension element +carries no data, mirroring the existing handling of empty ID lists. + +The bug was found by fuzzing ieee802_11_parse_elems_full() under KASAN. + +Fixes: f7dacfb11475 ("cfg80211: support non-inheritance element") +Signed-off-by: HE WEI (ギカク) +Link: https://patch.msgid.link/20260707094828.16465-1-skyexpoc@gmail.com +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + net/wireless/scan.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/wireless/scan.c b/net/wireless/scan.c +index b12508188a18d2..c978e6252f7a1e 100644 +--- a/net/wireless/scan.c ++++ b/net/wireless/scan.c +@@ -243,7 +243,7 @@ bool cfg80211_is_element_inherited(const struct element *elem, + return true; + + if (elem->id == WLAN_EID_EXTENSION) { +- if (!ext_id_len) ++ if (!ext_id_len || !elem->datalen) + return true; + loop_len = ext_id_len; + list = &non_inherit_elem->data[3 + id_len]; +-- +2.53.0 + diff --git a/queue-6.6/wifi-cfg80211-cancel-sched-scan-results-work-on-unre.patch b/queue-6.6/wifi-cfg80211-cancel-sched-scan-results-work-on-unre.patch new file mode 100644 index 0000000000..46f64d1320 --- /dev/null +++ b/queue-6.6/wifi-cfg80211-cancel-sched-scan-results-work-on-unre.patch @@ -0,0 +1,83 @@ +From 6326f62ad46a6e24a355710b83ad31096acaf579 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 20 Jun 2026 00:25:42 +0800 +Subject: wifi: cfg80211: cancel sched scan results work on unregister + +From: Cen Zhang + +[ Upstream commit edf0730be33696a1bd142792830d392129e495cc ] + +cfg80211_sched_scan_results() can queue rdev->sched_scan_res_wk from a +driver result notification while a scheduled scan request is present. The +work callback recovers the containing cfg80211_registered_device and then +locks the wiphy and walks the scheduled-scan request list. + +wiphy_unregister() already makes the wiphy unreachable and drains rdev work +items before cfg80211_dev_free() can release the object, but it does not +drain sched_scan_res_wk. A queued or running result work item can therefore +cross the unregister/free boundary and access freed rdev state. + +The buggy scenario involves two paths, with each column showing the order +within that path: + +scheduled-scan result path: unregister/free path: +1. cfg80211_sched_scan_results() 1. interface teardown stops and + queues rdev->sched_scan_res_wk. removes the scheduled scan request. +2. cfg80211_wq starts the work 2. wiphy_unregister() drains other + item and recovers rdev. rdev work items. +3. The worker locks rdev->wiphy 3. cfg80211_dev_free() destroys and + and walks rdev state. frees rdev. + +Cancel sched_scan_res_wk in wiphy_unregister() alongside the other rdev +work items. cancel_work_sync() removes a pending result notification and +waits for an already running callback, so cfg80211_dev_free() cannot free +rdev while this work item is still active. + +Validation reproduced this kernel report: +BUG: KASAN: use-after-free in cfg80211_sched_scan_results_wk+0x4a6/0x530 +Workqueue: cfg80211 cfg80211_sched_scan_results_wk [cfg80211] +Read of size 8 +Call trace: + dump_stack_lvl+0x66/0xa0 + print_report+0xce/0x630 + cfg80211_sched_scan_results_wk+0x4a6/0x530 + srso_alias_return_thunk+0x5/0xfbef5 + __virt_addr_valid+0x224/0x430 + kasan_report+0xac/0xe0 + lockdep_hardirqs_on_prepare+0xea/0x1a0 + process_one_work+0x8d0/0x18f0 (kernel/workqueue.c:3212) + lock_is_held_type+0x8f/0x100 + worker_thread+0x5ad/0xfd0 + __kthread_parkme+0xc6/0x200 + kthread+0x31e/0x410 + trace_hardirqs_on+0x1a/0x170 + ret_from_fork+0x576/0x810 + __switch_to+0x57e/0xe20 + __switch_to_asm+0x33/0x70 + ret_from_fork_asm+0x1a/0x30 + +Fixes: 807f8a8c3004 ("cfg80211/nl80211: add support for scheduled scans") +Assisted-by: Codex:gpt-5.5 +Signed-off-by: Cen Zhang +Link: https://patch.msgid.link/20260619162542.3878296-1-zzzccc427@gmail.com +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + net/wireless/core.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/net/wireless/core.c b/net/wireless/core.c +index d07c4baa32d9f4..800fbfd5919491 100644 +--- a/net/wireless/core.c ++++ b/net/wireless/core.c +@@ -1132,6 +1132,7 @@ void wiphy_unregister(struct wiphy *wiphy) + /* this has nothing to do now but make sure it's gone */ + cancel_work_sync(&rdev->wiphy_work); + ++ cancel_work_sync(&rdev->sched_scan_res_wk); + cancel_work_sync(&rdev->rfkill_block); + cancel_work_sync(&rdev->conn_work); + flush_work(&rdev->event_work); +-- +2.53.0 + diff --git a/queue-6.6/wifi-cfg80211-reject-unsupported-pmsr-ftm-location-r.patch b/queue-6.6/wifi-cfg80211-reject-unsupported-pmsr-ftm-location-r.patch new file mode 100644 index 0000000000..3578682a33 --- /dev/null +++ b/queue-6.6/wifi-cfg80211-reject-unsupported-pmsr-ftm-location-r.patch @@ -0,0 +1,50 @@ +From d4f7b8d1257d12d4ef01df5b7dbf3f2dfeadbb59 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 12 Jun 2026 21:37:11 +0800 +Subject: wifi: cfg80211: reject unsupported PMSR FTM location requests + +From: Zhao Li + +[ Upstream commit 69ef6a7ec277f16d216be8da2b3cbe872786c999 ] + +PMSR FTM location request flags are syntactically valid, but they must +be rejected when the device capability does not advertise support for +them. + +Return an error immediately after rejecting unsupported LCI or civic +location request bits so the request cannot reach the driver. + +Fixes: 9bb7e0f24e7e7 ("cfg80211: add peer measurement with FTM initiator API") +Assisted-by: Codex:gpt-5.5 +Assisted-by: Claude:claude-opus-4.8 +Signed-off-by: Zhao Li +Link: https://patch.msgid.link/20260612133710.93544-2-enderaoelyther@gmail.com +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + net/wireless/pmsr.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/net/wireless/pmsr.c b/net/wireless/pmsr.c +index f9de0057085f93..678bbe5bf455fe 100644 +--- a/net/wireless/pmsr.c ++++ b/net/wireless/pmsr.c +@@ -114,6 +114,7 @@ static int pmsr_parse_ftm(struct cfg80211_registered_device *rdev, + NL_SET_ERR_MSG_ATTR(info->extack, + tb[NL80211_PMSR_FTM_REQ_ATTR_REQUEST_LCI], + "FTM: LCI request not supported"); ++ return -EOPNOTSUPP; + } + + out->ftm.request_civicloc = +@@ -122,6 +123,7 @@ static int pmsr_parse_ftm(struct cfg80211_registered_device *rdev, + NL_SET_ERR_MSG_ATTR(info->extack, + tb[NL80211_PMSR_FTM_REQ_ATTR_REQUEST_CIVICLOC], + "FTM: civic location request not supported"); ++ return -EOPNOTSUPP; + } + + out->ftm.trigger_based = +-- +2.53.0 + diff --git a/queue-6.6/wifi-cfg80211-validate-pmsr-ftm-preamble-range.patch b/queue-6.6/wifi-cfg80211-validate-pmsr-ftm-preamble-range.patch new file mode 100644 index 0000000000..8549690b69 --- /dev/null +++ b/queue-6.6/wifi-cfg80211-validate-pmsr-ftm-preamble-range.patch @@ -0,0 +1,45 @@ +From cffe19106d039a5183064a5b79d9b0e282a72db9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 12 Jun 2026 21:37:04 +0800 +Subject: wifi: cfg80211: validate PMSR FTM preamble range + +From: Zhao Li + +[ Upstream commit 36230936468f0ba4930e94aef496fc229d4bb951 ] + +PMSR FTM request parsing accepts preamble values outside the +enumerated nl80211 preamble range. + +Reject out-of-range values before using them in the parser capability +bit test using the policy. + +Fixes: 9bb7e0f24e7e7 ("cfg80211: add peer measurement with FTM initiator API") +Assisted-by: Codex:gpt-5.5 +Assisted-by: Claude:claude-opus-4.8 +Signed-off-by: Zhao Li +Link: https://patch.msgid.link/20260612133703.93274-2-enderaoelyther@gmail.com +[drop unnecessary check] +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + net/wireless/nl80211.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c +index 93dac673f2a348..545f7ecaad76ff 100644 +--- a/net/wireless/nl80211.c ++++ b/net/wireless/nl80211.c +@@ -309,7 +309,9 @@ nl80211_ftm_responder_policy[NL80211_FTM_RESP_ATTR_MAX + 1] = { + static const struct nla_policy + nl80211_pmsr_ftm_req_attr_policy[NL80211_PMSR_FTM_REQ_ATTR_MAX + 1] = { + [NL80211_PMSR_FTM_REQ_ATTR_ASAP] = { .type = NLA_FLAG }, +- [NL80211_PMSR_FTM_REQ_ATTR_PREAMBLE] = { .type = NLA_U32 }, ++ [NL80211_PMSR_FTM_REQ_ATTR_PREAMBLE] = ++ NLA_POLICY_RANGE(NLA_U32, NL80211_PREAMBLE_LEGACY, ++ NL80211_PREAMBLE_HE), + [NL80211_PMSR_FTM_REQ_ATTR_NUM_BURSTS_EXP] = + NLA_POLICY_MAX(NLA_U8, 15), + [NL80211_PMSR_FTM_REQ_ATTR_BURST_PERIOD] = { .type = NLA_U16 }, +-- +2.53.0 + diff --git a/queue-6.6/wifi-cfg80211-validate-pmsr-measurement-type-data.patch b/queue-6.6/wifi-cfg80211-validate-pmsr-measurement-type-data.patch new file mode 100644 index 0000000000..e0e46150c1 --- /dev/null +++ b/queue-6.6/wifi-cfg80211-validate-pmsr-measurement-type-data.patch @@ -0,0 +1,76 @@ +From 482f7c81a1f2ca59fe0eed0e7516b21dfd60e572 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 12 Jun 2026 21:36:57 +0800 +Subject: wifi: cfg80211: validate PMSR measurement type data + +From: Zhao Li + +[ Upstream commit 41aa973eb05922848dded26875c55ef982ac1c49 ] + +PMSR request parsing accepts missing or duplicated measurement type +entries in NL80211_PMSR_REQ_ATTR_DATA. + +Track whether one measurement type was already provided, reject a +second one immediately, and return an error if the request data block +contains no measurement type at all. + +Fixes: 9bb7e0f24e7e7 ("cfg80211: add peer measurement with FTM initiator API") +Assisted-by: Codex:gpt-5.5 +Assisted-by: Claude:claude-opus-4.8 +Signed-off-by: Zhao Li +Link: https://patch.msgid.link/20260612133656.92900-2-enderaoelyther@gmail.com +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + net/wireless/pmsr.c | 19 +++++++++++++++++-- + 1 file changed, 17 insertions(+), 2 deletions(-) + +diff --git a/net/wireless/pmsr.c b/net/wireless/pmsr.c +index 77cb1de9fc13b4..f9de0057085f93 100644 +--- a/net/wireless/pmsr.c ++++ b/net/wireless/pmsr.c +@@ -188,6 +188,7 @@ static int pmsr_parse_peer(struct cfg80211_registered_device *rdev, + { + struct nlattr *tb[NL80211_PMSR_PEER_ATTR_MAX + 1]; + struct nlattr *req[NL80211_PMSR_REQ_ATTR_MAX + 1]; ++ bool have_measurement_type = false; + struct nlattr *treq; + int err, rem; + +@@ -240,6 +241,14 @@ static int pmsr_parse_peer(struct cfg80211_registered_device *rdev, + } + + nla_for_each_nested(treq, req[NL80211_PMSR_REQ_ATTR_DATA], rem) { ++ if (have_measurement_type) { ++ NL_SET_ERR_MSG_ATTR(info->extack, treq, ++ "multiple measurement types in request data"); ++ return -EINVAL; ++ } ++ ++ have_measurement_type = true; ++ + switch (nla_type(treq)) { + case NL80211_PMSR_TYPE_FTM: + err = pmsr_parse_ftm(rdev, treq, out, info); +@@ -249,10 +258,16 @@ static int pmsr_parse_peer(struct cfg80211_registered_device *rdev, + "unsupported measurement type"); + err = -EINVAL; + } ++ if (err) ++ return err; + } + +- if (err) +- return err; ++ if (!have_measurement_type) { ++ NL_SET_ERR_MSG_ATTR(info->extack, ++ req[NL80211_PMSR_REQ_ATTR_DATA], ++ "missing measurement type in request data"); ++ return -EINVAL; ++ } + + return 0; + } +-- +2.53.0 + diff --git a/queue-6.6/wifi-ipw2100-fix-potential-memory-leak-in-ipw2100_pc.patch b/queue-6.6/wifi-ipw2100-fix-potential-memory-leak-in-ipw2100_pc.patch new file mode 100644 index 0000000000..4b89939757 --- /dev/null +++ b/queue-6.6/wifi-ipw2100-fix-potential-memory-leak-in-ipw2100_pc.patch @@ -0,0 +1,60 @@ +From 7d815d5b5e5fbdca7f8727b3908df41a9d1fe49e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 20 Jun 2026 12:22:39 +0530 +Subject: wifi: ipw2100: fix potential memory leak in ipw2100_pci_init_one() + +From: Abdun Nihaal + +[ Upstream commit 0d388f62031dbabcba0f44bb91b59f10e88cac17 ] + +The memory allocated in the ipw2100_alloc_device() function is not freed +in some of the error paths in ipw2100_pci_init_one(). Fix that by +converting the direct return into a goto to the error path return. + +The error path when pci_enable_device() fails cannot jump to fail, since +at this point priv is not set, so perform error handling inline. + +Fixes: 2c86c275015c ("Add ipw2100 wireless driver.") +Signed-off-by: Abdun Nihaal +Link: https://patch.msgid.link/20260620065242.93798-1-nihaal@cse.iitm.ac.in +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/intel/ipw2x00/ipw2100.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/drivers/net/wireless/intel/ipw2x00/ipw2100.c b/drivers/net/wireless/intel/ipw2x00/ipw2100.c +index 9e9ff0cb724cac..a1eb69efecc6d1 100644 +--- a/drivers/net/wireless/intel/ipw2x00/ipw2100.c ++++ b/drivers/net/wireless/intel/ipw2x00/ipw2100.c +@@ -6172,6 +6172,8 @@ static int ipw2100_pci_init_one(struct pci_dev *pci_dev, + if (err) { + printk(KERN_WARNING DRV_NAME + "Error calling pci_enable_device.\n"); ++ free_libipw(dev, 0); ++ pci_iounmap(pci_dev, ioaddr); + return err; + } + +@@ -6184,16 +6186,14 @@ static int ipw2100_pci_init_one(struct pci_dev *pci_dev, + if (err) { + printk(KERN_WARNING DRV_NAME + "Error calling pci_set_dma_mask.\n"); +- pci_disable_device(pci_dev); +- return err; ++ goto fail; + } + + err = pci_request_regions(pci_dev, DRV_NAME); + if (err) { + printk(KERN_WARNING DRV_NAME + "Error calling pci_request_regions.\n"); +- pci_disable_device(pci_dev); +- return err; ++ goto fail; + } + + /* We disable the RETRY_TIMEOUT register (0x41) to keep +-- +2.53.0 + diff --git a/queue-6.6/wifi-libertas-fix-memory-leak-in-helper_firmware_cb.patch b/queue-6.6/wifi-libertas-fix-memory-leak-in-helper_firmware_cb.patch new file mode 100644 index 0000000000..c9ebe355a7 --- /dev/null +++ b/queue-6.6/wifi-libertas-fix-memory-leak-in-helper_firmware_cb.patch @@ -0,0 +1,50 @@ +From e451f9c756147bf5ac33d52c298d1c8586f77f18 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 24 Jun 2026 16:53:43 +0800 +Subject: wifi: libertas: fix memory leak in helper_firmware_cb() + +From: Dawei Feng + +[ Upstream commit 63c2391deefb31e1b801b7f32bd502ca4808639b ] + +helper_firmware_cb() neglects to free the single-stage firmware image +after a successful async load, leading to a memory leak in the USB +firmware-download path. + +Fix this memory leak by calling release_firmware() immediately after +lbs_fw_loaded() returns. + +The bug was first flagged by an experimental analysis tool we are +developing for kernel memory-management bugs while analyzing +v6.13-rc1. The tool is still under development and is not yet publicly +available. Manual inspection confirms that the bug is still present in +the current wireless tree. + +An x86_64 allyesconfig build showed no new warnings. As we do not have +compatible Libertas USB hardware for exercising this firmware-download +path, no runtime testing was able to be performed. + +Fixes: 1dfba3060fe7 ("libertas: move firmware lifetime handling to firmware.c") +Signed-off-by: Dawei Feng +Link: https://patch.msgid.link/20260624085343.575508-1-dawei.feng@seu.edu.cn +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/marvell/libertas/firmware.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/net/wireless/marvell/libertas/firmware.c b/drivers/net/wireless/marvell/libertas/firmware.c +index f124110944b7e9..9bf7d4c207b9ed 100644 +--- a/drivers/net/wireless/marvell/libertas/firmware.c ++++ b/drivers/net/wireless/marvell/libertas/firmware.c +@@ -78,6 +78,7 @@ static void helper_firmware_cb(const struct firmware *firmware, void *context) + } else { + /* No main firmware needed for this helper --> success! */ + lbs_fw_loaded(priv, 0, firmware, NULL); ++ release_firmware(firmware); + } + } + +-- +2.53.0 + diff --git a/queue-6.6/wifi-mac80211-free-ap_vlan-bc_buf-skbs-outside-irq-l.patch b/queue-6.6/wifi-mac80211-free-ap_vlan-bc_buf-skbs-outside-irq-l.patch new file mode 100644 index 0000000000..54faa7160b --- /dev/null +++ b/queue-6.6/wifi-mac80211-free-ap_vlan-bc_buf-skbs-outside-irq-l.patch @@ -0,0 +1,77 @@ +From 964ff284138ac3de75248167174db221ee1b8b07 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 6 Jul 2026 22:08:41 +0800 +Subject: wifi: mac80211: free AP_VLAN bc_buf SKBs outside IRQ lock + +From: Cen Zhang + +[ Upstream commit f3858d5b1432098c1936e03d6e03dd0e33facf60 ] + +ieee80211_do_stop() removes AP_VLAN packets from the parent AP +ps->bc_buf while holding ps->bc_buf.lock with IRQs disabled. It then +calls ieee80211_free_txskb() before dropping the lock. + +ieee80211_free_txskb() is not just a passive SKB release. For SKBs with +TX status state it can report a dropped frame through cfg80211/nl80211, +and that path can reach netlink tap transmit. This is the same reason +the pending queue cleanup in ieee80211_do_stop() already unlinks SKBs +under the queue lock and frees them after IRQ state is restored. + +The buggy scenario involves two paths, with each column showing the +order within that path: + +AP_VLAN management TX: AP_VLAN stop: +1. attach ACK-status state 1. clear the running state +2. queue a multicast SKB on 2. take ps->bc_buf.lock with IRQs + parent ps->bc_buf disabled + 3. unlink the AP_VLAN SKB + 4. call ieee80211_free_txskb() + +Unlink matching AP_VLAN SKBs from ps->bc_buf under the existing lock, +but move them to a local free queue. Drop the lock and restore IRQ state +before calling ieee80211_free_txskb(). + +WARNING: kernel/softirq.c:430 at __local_bh_enable_ip + +Fixes: 397a7a24ef8c ("mac80211: free ps->bc_buf skbs on vlan device stop") +Assisted-by: Codex:gpt-5.5 +Signed-off-by: Cen Zhang +Link: https://patch.msgid.link/20260706140841.581566-1-zzzccc427@gmail.com +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + net/mac80211/iface.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c +index c8c53f4d1bdbfa..d4a554d6d5de5a 100644 +--- a/net/mac80211/iface.c ++++ b/net/mac80211/iface.c +@@ -591,6 +591,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, bool going_do + WARN_ON(!list_empty(&sdata->u.ap.vlans)); + } else if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) { + /* remove all packets in parent bc_buf pointing to this dev */ ++ __skb_queue_head_init(&freeq); + ps = &sdata->bss->ps; + + spin_lock_irqsave(&ps->bc_buf.lock, flags); +@@ -598,10 +599,15 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, bool going_do + if (skb->dev == sdata->dev) { + __skb_unlink(skb, &ps->bc_buf); + local->total_ps_buffered--; +- ieee80211_free_txskb(&local->hw, skb); ++ __skb_queue_tail(&freeq, skb); + } + } + spin_unlock_irqrestore(&ps->bc_buf.lock, flags); ++ ++ skb_queue_walk_safe(&freeq, skb, tmp) { ++ __skb_unlink(skb, &freeq); ++ ieee80211_free_txskb(&local->hw, skb); ++ } + } + + if (going_down) +-- +2.53.0 + diff --git a/queue-6.6/wifi-mac80211_hwsim-clamp-virtio-rx-length-before-sk.patch b/queue-6.6/wifi-mac80211_hwsim-clamp-virtio-rx-length-before-sk.patch new file mode 100644 index 0000000000..8804b50cb0 --- /dev/null +++ b/queue-6.6/wifi-mac80211_hwsim-clamp-virtio-rx-length-before-sk.patch @@ -0,0 +1,46 @@ +From 73958f77f62251ac2f51359dd3f08b18eda0dabf Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 20 Jun 2026 21:45:18 -0500 +Subject: wifi: mac80211_hwsim: clamp virtio RX length before skb_put + +From: Bryam Vargas + +[ Upstream commit 10a2b430f8f06ae14b9590b6f6faa6b588ef0654 ] + +hwsim_virtio_rx_work() passes the virtqueue used-ring length reported by +the device straight to skb_put() on a fixed-size receive skb. A backend +reporting a length larger than the skb tailroom drives skb_put() past the +buffer end and hits skb_over_panic() -- a host-triggerable guest panic +(denial of service). + +Clamp the length to the skb's available room before skb_put(). A +conforming device never reports more than the posted buffer size, so valid +frames are unaffected; a truncated over-report then fails the +length/header checks in hwsim_virtio_handle_cmd() and is dropped, so +truncating rather than dropping here cannot be turned into a parsing +problem. + +Fixes: 5d44fe7c9808 ("mac80211_hwsim: add frame transmission support over virtio") +Signed-off-by: Bryam Vargas +Link: https://patch.msgid.link/20260620-b4-disp-474bee37-v1-1-1a4d37f3e2d4@proton.me +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/virtual/mac80211_hwsim.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/net/wireless/virtual/mac80211_hwsim.c b/drivers/net/wireless/virtual/mac80211_hwsim.c +index bf12ff0ab06ab3..c9bfea77d0ecae 100644 +--- a/drivers/net/wireless/virtual/mac80211_hwsim.c ++++ b/drivers/net/wireless/virtual/mac80211_hwsim.c +@@ -6383,6 +6383,7 @@ static void hwsim_virtio_rx_work(struct work_struct *work) + + skb->data = skb->head; + skb_reset_tail_pointer(skb); ++ len = min(len, skb_end_offset(skb)); + skb_put(skb, len); + hwsim_virtio_handle_cmd(skb); + +-- +2.53.0 + diff --git a/queue-6.6/wifi-nl80211-free-rnr-data-on-mbssid-mismatch.patch b/queue-6.6/wifi-nl80211-free-rnr-data-on-mbssid-mismatch.patch new file mode 100644 index 0000000000..7594d24390 --- /dev/null +++ b/queue-6.6/wifi-nl80211-free-rnr-data-on-mbssid-mismatch.patch @@ -0,0 +1,43 @@ +From 1d2b31c2d0bf39544c456f779a058b1f7da111d9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 10 Jun 2026 19:22:09 +0800 +Subject: wifi: nl80211: free RNR data on MBSSID mismatch + +From: Zhao Li + +[ Upstream commit 07a95ec2b54774201fdf4ef7ffb0ca2ab19ed29c ] + +nl80211_parse_beacon() rejects EMA RNR data when there are fewer RNR +entries than MBSSID entries. + +The rejected RNR allocation has not been attached to the beacon data yet, +so free it before returning the error. + +Fixes: dbbb27e183b1 ("cfg80211: support RNR for EMA AP") +Signed-off-by: Zhao Li +Link: https://patch.msgid.link/20260610112208.1308-2-enderaoelyther@gmail.com +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + net/wireless/nl80211.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c +index e4a490d12b504e..15c8f98bf5e235 100644 +--- a/net/wireless/nl80211.c ++++ b/net/wireless/nl80211.c +@@ -5651,8 +5651,10 @@ static int nl80211_parse_beacon(struct cfg80211_registered_device *rdev, + if (IS_ERR(rnr)) + return PTR_ERR(rnr); + +- if (rnr && rnr->cnt < bcn->mbssid_ies->cnt) ++ if (rnr && rnr->cnt < bcn->mbssid_ies->cnt) { ++ kfree(rnr); + return -EINVAL; ++ } + + bcn->rnr_ies = rnr; + } +-- +2.53.0 + diff --git a/queue-6.6/wifi-nl80211-validate-nested-mbssid-ie-blobs.patch b/queue-6.6/wifi-nl80211-validate-nested-mbssid-ie-blobs.patch new file mode 100644 index 0000000000..f569af6260 --- /dev/null +++ b/queue-6.6/wifi-nl80211-validate-nested-mbssid-ie-blobs.patch @@ -0,0 +1,67 @@ +From f86c2031b04eac3fa2a51e6a16d42894ef38cfce Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 12 Jun 2026 21:18:55 +0800 +Subject: wifi: nl80211: validate nested MBSSID IE blobs + +From: Zhao Li + +[ Upstream commit 7f4b01812323443b55e4c65381c9dc851ff009e3 ] + +Validate each nested NL80211_ATTR_MBSSID_ELEMS entry as a well-formed +information-element stream before storing it for beacon construction. + +RNR parsing already validates each nested blob with validate_ie_attr() +before storing it. Apply the same syntactic IE validation to MBSSID +entries before counting and copying their data and length pointers. + +Fixes: dc1e3cb8da8b ("nl80211: MBSSID and EMA support in AP mode") +Assisted-by: Codex:gpt-5.5 +Assisted-by: Claude:claude-opus-4.8 +Signed-off-by: Zhao Li +Link: https://patch.msgid.link/20260612131854.43575-3-enderaoelyther@gmail.com +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + net/wireless/nl80211.c | 12 ++++++++++-- + 1 file changed, 10 insertions(+), 2 deletions(-) + +diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c +index 15c8f98bf5e235..93dac673f2a348 100644 +--- a/net/wireless/nl80211.c ++++ b/net/wireless/nl80211.c +@@ -5453,7 +5453,8 @@ static int nl80211_parse_mbssid_config(struct wiphy *wiphy, + } + + static struct cfg80211_mbssid_elems * +-nl80211_parse_mbssid_elems(struct wiphy *wiphy, struct nlattr *attrs) ++nl80211_parse_mbssid_elems(struct wiphy *wiphy, struct nlattr *attrs, ++ struct netlink_ext_ack *extack) + { + struct nlattr *nl_elems; + struct cfg80211_mbssid_elems *elems; +@@ -5464,6 +5465,12 @@ nl80211_parse_mbssid_elems(struct wiphy *wiphy, struct nlattr *attrs) + return ERR_PTR(-EINVAL); + + nla_for_each_nested(nl_elems, attrs, rem_elems) { ++ int ret; ++ ++ ret = validate_ie_attr(nl_elems, extack); ++ if (ret) ++ return ERR_PTR(ret); ++ + if (num_elems >= 255) + return ERR_PTR(-EINVAL); + num_elems++; +@@ -5635,7 +5642,8 @@ static int nl80211_parse_beacon(struct cfg80211_registered_device *rdev, + if (attrs[NL80211_ATTR_MBSSID_ELEMS]) { + struct cfg80211_mbssid_elems *mbssid = + nl80211_parse_mbssid_elems(&rdev->wiphy, +- attrs[NL80211_ATTR_MBSSID_ELEMS]); ++ attrs[NL80211_ATTR_MBSSID_ELEMS], ++ extack); + + if (IS_ERR(mbssid)) + return PTR_ERR(mbssid); +-- +2.53.0 + diff --git a/queue-6.6/wifi-p54-validate-rx-frame-length-in-p54_rx_eeprom_r.patch b/queue-6.6/wifi-p54-validate-rx-frame-length-in-p54_rx_eeprom_r.patch new file mode 100644 index 0000000000..4f69b09c4f --- /dev/null +++ b/queue-6.6/wifi-p54-validate-rx-frame-length-in-p54_rx_eeprom_r.patch @@ -0,0 +1,80 @@ +From b47db3ef7c7e22eecc5e1fb20fcd8f4e7cfeb45e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 27 Jun 2026 17:05:10 -0700 +Subject: wifi: p54: validate RX frame length in p54_rx_eeprom_readback() + +From: Xiang Mei + +[ Upstream commit ebd6d37fa94bee929e0b4c9ca19fdf9b1dcf6cea ] + +p54_rx_eeprom_readback() copies the requested EEPROM slice out of a +device-supplied readback frame without checking that the skb actually holds +that many bytes. Commit da1b9a55ff11 ("wifi: p54: prevent buffer-overflow in +p54_rx_eeprom_readback()") closed the destination overflow by copying a +fixed priv->eeprom_slice_size (and rejecting a mismatched advertised len), +but the source side is still unbounded: nothing verifies the frame is long +enough to supply that many bytes. + +A malicious USB device can send a short frame whose advertised len matches +priv->eeprom_slice_size while the payload is truncated. The equality check +passes and memcpy() reads past the end of the skb, leaking adjacent heap: + + BUG: KASAN: slab-out-of-bounds in p54_rx (drivers/net/wireless/intersil/p54/txrx.c:507) + Read of size 1016 at addr ffff88800f077114 by task swapper/0/0 + Call Trace: + + ... + __asan_memcpy (mm/kasan/shadow.c:105) + p54_rx (drivers/net/wireless/intersil/p54/txrx.c:507) + p54u_rx_cb (drivers/net/wireless/intersil/p54/p54usb.c:163) + __usb_hcd_giveback_urb (drivers/usb/core/hcd.c:1657) + dummy_timer (drivers/usb/gadget/udc/dummy_hcd.c:2005) + ... + + + The buggy address belongs to the object at ffff88800f0770c0 + which belongs to the cache skbuff_small_head of size 704 + The buggy address is located 84 bytes inside of + allocated 704-byte region [ffff88800f0770c0, ffff88800f077380) + +Check that the slice fits in the skb before copying. + +Fixes: 7cb770729ba8 ("p54: move eeprom code into common library") +Reported-by: Weiming Shi +Assisted-by: Claude:claude-opus-4-8 +Signed-off-by: Xiang Mei +Acked-by: Christian Lamparter +Link: https://patch.msgid.link/20260628000510.4152481-1-xmei5@asu.edu +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/intersil/p54/txrx.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/drivers/net/wireless/intersil/p54/txrx.c b/drivers/net/wireless/intersil/p54/txrx.c +index 2deb1bb54f24bd..dc7bf54e30bba1 100644 +--- a/drivers/net/wireless/intersil/p54/txrx.c ++++ b/drivers/net/wireless/intersil/p54/txrx.c +@@ -499,11 +499,19 @@ static void p54_rx_eeprom_readback(struct p54_common *priv, + if (le16_to_cpu(eeprom->v2.len) != priv->eeprom_slice_size) + return; + ++ if (eeprom->v2.data + priv->eeprom_slice_size > ++ skb_tail_pointer(skb)) ++ return; ++ + memcpy(priv->eeprom, eeprom->v2.data, priv->eeprom_slice_size); + } else { + if (le16_to_cpu(eeprom->v1.len) != priv->eeprom_slice_size) + return; + ++ if (eeprom->v1.data + priv->eeprom_slice_size > ++ skb_tail_pointer(skb)) ++ return; ++ + memcpy(priv->eeprom, eeprom->v1.data, priv->eeprom_slice_size); + } + +-- +2.53.0 + diff --git a/queue-6.6/xfrm-policy-preallocate-inexact-bins-before-xfrm_has.patch b/queue-6.6/xfrm-policy-preallocate-inexact-bins-before-xfrm_has.patch new file mode 100644 index 0000000000..f6aa330d4c --- /dev/null +++ b/queue-6.6/xfrm-policy-preallocate-inexact-bins-before-xfrm_has.patch @@ -0,0 +1,75 @@ +From b1ed50c32e174abe8cff828a2e6b1a98de44820e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 3 Jul 2026 05:19:32 +0000 +Subject: xfrm: policy: preallocate inexact bins before xfrm_hash_rebuild + reinsert + +From: Xiang Mei (Microsoft) + +[ Upstream commit f38f8cce2f7e79775b3db7e8a5eacda04ac908e4 ] + +xfrm_hash_rebuild()'s first loop preallocates the bins/chains the reinsert +loop needs, so the reinsert (after hlist_del_rcu()) cannot allocate or +fail. But its guard is inverted: it skips policies with prefixlen < +threshold and preallocates for the rest. + +prefixlen < threshold is exactly when policy_hash_bysel() returns NULL and +the reinsert takes the allocating xfrm_policy_inexact_insert() path. So the +loop preallocates for the exact policies (which never allocate) and skips +the inexact ones, whose bin/node is then allocated GFP_ATOMIC during +reinsert. On failure the error path only WARN_ONCE()s and continues, +leaving a poisoned bydst node; the next rebuild's hlist_del_rcu() +dereferences LIST_POISON2 and takes a GPF. Reachable under memory pressure, +deterministic via failslab. + +Invert the guard so preallocation covers exactly the reinserted policies; +the reinsert then allocates nothing and cannot fail. + +Crash: + Oops: general protection fault, probably for non-canonical address + 0xfbd59c0000000024: 0000 [#1] SMP KASAN NOPTI + KASAN: maybe wild-memory-access in range [0xdead...] + ... + Workqueue: events xfrm_hash_rebuild + RIP: 0010:xfrm_hash_rebuild+0x5b3/0x1190 + RAX: dead000000000122 (LIST_POISON2 + offset) + ... + Call Trace: + hlist_del_rcu (include/linux/rculist.h:599) + xfrm_hash_rebuild (net/xfrm/xfrm_policy.c:1365) + process_one_work (kernel/workqueue.c:3322) + worker_thread (kernel/workqueue.c:3486) + kthread (kernel/kthread.c:436) + ret_from_fork (arch/x86/kernel/process.c:158) + ret_from_fork_asm (arch/x86/entry/entry_64.S:245) + ... + Kernel panic - not syncing: Fatal exception in interrupt + +Fixes: 24969facd704 ("xfrm: policy: store inexact policies in an rhashtable") +Reported-by: AutonomousCodeSecurity@microsoft.com +Signed-off-by: Xiang Mei (Microsoft) +Reviewed-by: Florian Westphal +Signed-off-by: Steffen Klassert +Signed-off-by: Sasha Levin +--- + net/xfrm/xfrm_policy.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c +index 7eaaaf56e631a0..00d9693c13ae72 100644 +--- a/net/xfrm/xfrm_policy.c ++++ b/net/xfrm/xfrm_policy.c +@@ -1298,8 +1298,8 @@ static void xfrm_hash_rebuild(struct work_struct *work) + } + } + +- if (policy->selector.prefixlen_d < dbits || +- policy->selector.prefixlen_s < sbits) ++ if (policy->selector.prefixlen_d >= dbits && ++ policy->selector.prefixlen_s >= sbits) + continue; + + bin = xfrm_policy_inexact_alloc_bin(policy, dir); +-- +2.53.0 + diff --git a/queue-6.6/xfrm6-clear-dst.dev-on-error-to-avoid-double-netdev_.patch b/queue-6.6/xfrm6-clear-dst.dev-on-error-to-avoid-double-netdev_.patch new file mode 100644 index 0000000000..691445ea46 --- /dev/null +++ b/queue-6.6/xfrm6-clear-dst.dev-on-error-to-avoid-double-netdev_.patch @@ -0,0 +1,60 @@ +From 3003f24df89f9b024e81ee781e811ab56c3fac41 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 2 Jul 2026 01:05:16 +0000 +Subject: xfrm6: clear dst.dev on error to avoid double netdev_put in + xfrm6_fill_dst() + +From: Xiang Mei (Microsoft) + +[ Upstream commit 136992de9bb91871084ae52d172610541c76e4d2 ] + +On the error path where in6_dev_get(dev) returns NULL, xfrm6_fill_dst() +releases the device reference with netdev_put() but leaves +xdst->u.dst.dev set. dst_destroy() later calls netdev_put(dst->dev) +again, so the same net_device reference is released twice, underflowing +its refcount (ref_tracker WARNING + "unregister_netdevice: waiting for + to become free"). + +Clear xdst->u.dst.dev after the netdev_put(), the same way the XFRM +device-offload paths xfrm_dev_state_add() and xfrm_dev_policy_add() in +net/xfrm/xfrm_device.c NULL ->dev when releasing the reference on error. + + ref_tracker: reference already released. + ref_tracker: allocated in: + xfrm6_fill_dst (net/ipv6/xfrm6_policy.c:86) + ... + udpv6_sendmsg (net/ipv6/udp.c:1696) + ... + ref_tracker: freed in: + xfrm6_fill_dst (net/ipv6/xfrm6_policy.c:90) + ... + WARNING: lib/ref_tracker.c:322 at ref_tracker_free+0x58b/0x780 + dst_destroy (net/core/dst.c:115) + rcu_core + handle_softirqs + ... + +Fixes: 84c4a9dfbf43 ("xfrm6: release dev before returning error") +Reported-by: AutonomousCodeSecurity@microsoft.com +Signed-off-by: Xiang Mei (Microsoft) +Signed-off-by: Steffen Klassert +Signed-off-by: Sasha Levin +--- + net/ipv6/xfrm6_policy.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c +index e5d76e782b9613..6bf22fd9cd3802 100644 +--- a/net/ipv6/xfrm6_policy.c ++++ b/net/ipv6/xfrm6_policy.c +@@ -88,6 +88,7 @@ static int xfrm6_fill_dst(struct xfrm_dst *xdst, struct net_device *dev, + xdst->u.rt6.rt6i_idev = in6_dev_get(dev); + if (!xdst->u.rt6.rt6i_idev) { + netdev_put(dev, &xdst->u.dst.dev_tracker); ++ xdst->u.dst.dev = NULL; + return -ENODEV; + } + +-- +2.53.0 + diff --git a/queue-7.1/accel-amdxdna-fix-use-after-free-of-mm_struct-in-job.patch b/queue-7.1/accel-amdxdna-fix-use-after-free-of-mm_struct-in-job.patch new file mode 100644 index 0000000000..0e7fdfed22 --- /dev/null +++ b/queue-7.1/accel-amdxdna-fix-use-after-free-of-mm_struct-in-job.patch @@ -0,0 +1,58 @@ +From 534e93aa75419726d993dc58b2213954a231e9b2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 16 Jul 2026 08:13:05 -0700 +Subject: accel/amdxdna: Fix use-after-free of mm_struct in job scheduler + +From: Lizhi Hou + +[ Upstream commit faebb7ba1ac65fa5810b640df02ce04e509fdc11 ] + +amdxdna_cmd_submit() stores current->mm in job->mm without holding any +reference. aie2_sched_job_run() later access job->mm from the DRM +scheduler worker thread. With only a raw pointer and no structural +reference, the mm_struct can be freed before the scheduler runs the job. + +Fix this by calling mmgrab() to hold a structural mm_count reference for +the lifetime of the job, paired with mmdrop() in every cleanup path. + +Fixes: aac243092b70 ("accel/amdxdna: Add command execution") +Reviewed-by: Max Zhen +Signed-off-by: Lizhi Hou +Link: https://patch.msgid.link/20260716151305.1595780-1-lizhi.hou@amd.com +Signed-off-by: Sasha Levin +--- + drivers/accel/amdxdna/amdxdna_ctx.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/drivers/accel/amdxdna/amdxdna_ctx.c b/drivers/accel/amdxdna/amdxdna_ctx.c +index 5315466f137b55..f6fece060dfedf 100644 +--- a/drivers/accel/amdxdna/amdxdna_ctx.c ++++ b/drivers/accel/amdxdna/amdxdna_ctx.c +@@ -483,6 +483,7 @@ void amdxdna_sched_job_cleanup(struct amdxdna_sched_job *job) + amdxdna_arg_bos_put(job); + amdxdna_gem_put_obj(job->cmd_bo); + dma_fence_put(job->fence); ++ mmdrop(job->mm); + } + + int amdxdna_cmd_submit(struct amdxdna_client *client, +@@ -549,6 +550,7 @@ int amdxdna_cmd_submit(struct amdxdna_client *client, + + job->hwctx = hwctx; + job->mm = current->mm; ++ mmgrab(job->mm); + + job->fence = amdxdna_fence_create(hwctx); + if (!job->fence) { +@@ -583,6 +585,8 @@ int amdxdna_cmd_submit(struct amdxdna_client *client, + cmd_put: + amdxdna_gem_put_obj(job->cmd_bo); + free_job: ++ if (job->mm) ++ mmdrop(job->mm); + kfree(job); + return ret; + } +-- +2.53.0 + diff --git a/queue-7.1/accel-ivpu-fix-wrong-register-read-in-lnl-failure-di.patch b/queue-7.1/accel-ivpu-fix-wrong-register-read-in-lnl-failure-di.patch new file mode 100644 index 0000000000..1a7c46d593 --- /dev/null +++ b/queue-7.1/accel-ivpu-fix-wrong-register-read-in-lnl-failure-di.patch @@ -0,0 +1,40 @@ +From e9a808c7a6224d4309339a7fe8f4ea2937a9a006 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 10 Jul 2026 12:13:31 +0200 +Subject: accel/ivpu: Fix wrong register read in LNL failure diagnostics + +From: Karol Wachowski + +[ Upstream commit e4159045c2704dfe146f0ccb0445d9d074cd6882 ] + +diagnose_failure_lnl() read VPU_HW_BTRS_MTL_INTERRUPT_STAT instead of +VPU_HW_BTRS_LNL_INTERRUPT_STAT, which on LNL and newer parts is a +different register with a different bit layout, so failure diagnostics +decoded the wrong register and reported a bogus error cause. +Read the LNL interrupt status register instead. + +Fixes: 8a27ad81f7d3 ("accel/ivpu: Split IP and buttress code") +Reviewed-by: Andrzej Kacprowski +Signed-off-by: Karol Wachowski +Link: https://patch.msgid.link/20260710101331.1899505-1-karol.wachowski@linux.intel.com +Signed-off-by: Sasha Levin +--- + drivers/accel/ivpu/ivpu_hw_btrs.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/accel/ivpu/ivpu_hw_btrs.c b/drivers/accel/ivpu/ivpu_hw_btrs.c +index 06e65c59261854..992addabbd3c65 100644 +--- a/drivers/accel/ivpu/ivpu_hw_btrs.c ++++ b/drivers/accel/ivpu/ivpu_hw_btrs.c +@@ -861,7 +861,7 @@ static void diagnose_failure_mtl(struct ivpu_device *vdev) + + static void diagnose_failure_lnl(struct ivpu_device *vdev) + { +- u32 reg = REGB_RD32(VPU_HW_BTRS_MTL_INTERRUPT_STAT) & BTRS_LNL_IRQ_MASK; ++ u32 reg = REGB_RD32(VPU_HW_BTRS_LNL_INTERRUPT_STAT) & BTRS_LNL_IRQ_MASK; + + if (REG_TEST_FLD(VPU_HW_BTRS_LNL_INTERRUPT_STAT, ATS_ERR, reg)) { + ivpu_err(vdev, "ATS_ERR_LOG1 0x%08x ATS_ERR_LOG2 0x%08x\n", +-- +2.53.0 + diff --git a/queue-7.1/alsa-usb-audio-fix-imbalance-per-channel-volume-of-s.patch b/queue-7.1/alsa-usb-audio-fix-imbalance-per-channel-volume-of-s.patch new file mode 100644 index 0000000000..2b99a2c83b --- /dev/null +++ b/queue-7.1/alsa-usb-audio-fix-imbalance-per-channel-volume-of-s.patch @@ -0,0 +1,44 @@ +From 10c485c077b92499065e064d4a4b3988484786d1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 6 Jul 2026 02:19:31 +0800 +Subject: ALSA: usb-audio: Fix imbalance per-channel volume of sticky mixers + +From: Rong Zhang + +[ Upstream commit ea588e4c7484ea883d3dab308f1f2c2f0f51f7d6 ] + +I accidentally made an off-by-a-line mistake when mimicking other code +paths that set all channels. The mistake breaks sticky mixers with +multiple channels. + +I didn't realize this mistake at that time, as my device's mixer is +single-channel. + +Fix it, so that per-channel volume of sticky mixers is balanced. + +Fixes: aa2f4addab44 ("ALSA: usb-audio: Set the value of potential sticky mixers to maximum") +Signed-off-by: Rong Zhang +Link: https://patch.msgid.link/20260706-uac-sticky-channels-fix-v1-1-92741c538283@rong.moe +Signed-off-by: Takashi Iwai +Signed-off-by: Sasha Levin +--- + sound/usb/mixer.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c +index fb37bb8ad9a9a6..dbcefcaf7c3612 100644 +--- a/sound/usb/mixer.c ++++ b/sound/usb/mixer.c +@@ -1447,8 +1447,8 @@ static int get_min_max_with_quirks(struct usb_mixer_elem_info *cval, + if (!cval->cmask) { + snd_usb_set_cur_mix_value(cval, 0, 0, cval->max); + } else { ++ idx = 0; + for (i = 0; i < MAX_CHANNELS; i++) { +- idx = 0; + if (cval->cmask & BIT(i)) { + snd_usb_set_cur_mix_value(cval, i + 1, idx, cval->max); + idx++; +-- +2.53.0 + diff --git a/queue-7.1/alsa-usb-audio-skip-dsd-quirk-for-musical-fidelity-m.patch b/queue-7.1/alsa-usb-audio-skip-dsd-quirk-for-musical-fidelity-m.patch new file mode 100644 index 0000000000..12b3d99ca9 --- /dev/null +++ b/queue-7.1/alsa-usb-audio-skip-dsd-quirk-for-musical-fidelity-m.patch @@ -0,0 +1,47 @@ +From 08edfe85ebd7fa634caac260f044b6cb671c3f4e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 9 Jul 2026 11:56:06 +0200 +Subject: ALSA: usb-audio: Skip DSD quirk for Musical Fidelity M6s DAC + +From: Takashi Iwai + +[ Upstream commit 93b47e66cc6d6c6382d44b44f5e7f6fc3a7b38c3 ] + +Salvador reported that the recent fix for applying the DSD quirk to +Musical Fidelity devices broke for his M6s DAC model (2772:0502). + +Although this is basically a firmware bug, the model in question is +fairly old, and no further firmware update can be expected, so it'd be +better to address in the driver side. + +As an ad hoc workaround, skip the DSD quirk for this device by adding +an empty quirk entry of 2772:0502; this essentially skips the later +DSD quirk entry by the match with the vendor 2772. + +Fixes: da3a7efff64e ("ALSA: usb-audio: Update for native DSD support quirks") +Reported-by: Salvador Blaya +Closes: https://lore.kernel.org/CAOdyq+qFaqCh=tK_wNnA64hv5pQuA1Y09ANxQ=xK8yR-t4mf9Q@mail.gmail.com +Tested-by: Salvador Blaya +Signed-off-by: Takashi Iwai +Link: https://patch.msgid.link/20260709095614.1418838-1-tiwai@suse.de +Signed-off-by: Sasha Levin +--- + sound/usb/quirks.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c +index ed66e2af95143b..33eb8be48af876 100644 +--- a/sound/usb/quirks.c ++++ b/sound/usb/quirks.c +@@ -2457,6 +2457,8 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = { + QUIRK_FLAG_DSD_RAW), + DEVICE_FLG(0x2708, 0x0002, /* Audient iD14 */ + QUIRK_FLAG_IGNORE_CTL_ERROR), ++ DEVICE_FLG(0x2772, 0x0502, /* Musical Fidelity M6s DAC */ ++ 0), /* for avoiding QUIRK_FLAG_DSD_RAW with vendor match */ + DEVICE_FLG(0x2912, 0x30c8, /* Audioengine D1 */ + QUIRK_FLAG_GET_SAMPLE_RATE), + DEVICE_FLG(0x2a70, 0x1881, /* OnePlus Technology (Shenzhen) Co., Ltd. BE02T */ +-- +2.53.0 + diff --git a/queue-7.1/arm64-tegra-fix-cpu-compatible-string-to-cortex-a78a.patch b/queue-7.1/arm64-tegra-fix-cpu-compatible-string-to-cortex-a78a.patch new file mode 100644 index 0000000000..3ecdcb33fa --- /dev/null +++ b/queue-7.1/arm64-tegra-fix-cpu-compatible-string-to-cortex-a78a.patch @@ -0,0 +1,144 @@ +From 94a1e1206bbe78c56a3d4eb300cd922a3e094380 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 21 Jan 2026 16:15:34 +0530 +Subject: arm64: tegra: Fix CPU compatible string to cortex-a78ae on Tegra234 + +From: Sumit Gupta + +[ Upstream commit 0dfa1e960f86e032007882b032c5cc7d14ebe73e ] + +The Tegra234 SoC uses Cortex-A78AE cores, not Cortex-A78. Update the +compatible string for all CPU nodes to match the actual hardware. + +Tegra234 hardware reports: + # head /proc/cpuinfo | egrep 'implementer|part' + CPU implementer : 0x41 + CPU part : 0xd42 + +Which maps to (from arch/arm64/include/asm/cputype.h): + #define ARM_CPU_IMP_ARM 0x41 + #define ARM_CPU_PART_CORTEX_A78AE 0xD42 + +Fixes: a12cf5c339b08 ("arm64: tegra: Describe Tegra234 CPU hierarchy") +Signed-off-by: Sumit Gupta +Signed-off-by: Thierry Reding +Signed-off-by: Sasha Levin +--- + arch/arm64/boot/dts/nvidia/tegra234.dtsi | 24 ++++++++++++------------ + 1 file changed, 12 insertions(+), 12 deletions(-) + +diff --git a/arch/arm64/boot/dts/nvidia/tegra234.dtsi b/arch/arm64/boot/dts/nvidia/tegra234.dtsi +index 18220cdac9f9bb..eda23431ed05ea 100644 +--- a/arch/arm64/boot/dts/nvidia/tegra234.dtsi ++++ b/arch/arm64/boot/dts/nvidia/tegra234.dtsi +@@ -5339,7 +5339,7 @@ cpus { + #size-cells = <0>; + + cpu0_0: cpu@0 { +- compatible = "arm,cortex-a78"; ++ compatible = "arm,cortex-a78ae"; + device_type = "cpu"; + reg = <0x00000>; + +@@ -5358,7 +5358,7 @@ cpu0_0: cpu@0 { + }; + + cpu0_1: cpu@100 { +- compatible = "arm,cortex-a78"; ++ compatible = "arm,cortex-a78ae"; + device_type = "cpu"; + reg = <0x00100>; + +@@ -5377,7 +5377,7 @@ cpu0_1: cpu@100 { + }; + + cpu0_2: cpu@200 { +- compatible = "arm,cortex-a78"; ++ compatible = "arm,cortex-a78ae"; + device_type = "cpu"; + reg = <0x00200>; + +@@ -5396,7 +5396,7 @@ cpu0_2: cpu@200 { + }; + + cpu0_3: cpu@300 { +- compatible = "arm,cortex-a78"; ++ compatible = "arm,cortex-a78ae"; + device_type = "cpu"; + reg = <0x00300>; + +@@ -5415,7 +5415,7 @@ cpu0_3: cpu@300 { + }; + + cpu1_0: cpu@10000 { +- compatible = "arm,cortex-a78"; ++ compatible = "arm,cortex-a78ae"; + device_type = "cpu"; + reg = <0x10000>; + +@@ -5434,7 +5434,7 @@ cpu1_0: cpu@10000 { + }; + + cpu1_1: cpu@10100 { +- compatible = "arm,cortex-a78"; ++ compatible = "arm,cortex-a78ae"; + device_type = "cpu"; + reg = <0x10100>; + +@@ -5453,7 +5453,7 @@ cpu1_1: cpu@10100 { + }; + + cpu1_2: cpu@10200 { +- compatible = "arm,cortex-a78"; ++ compatible = "arm,cortex-a78ae"; + device_type = "cpu"; + reg = <0x10200>; + +@@ -5472,7 +5472,7 @@ cpu1_2: cpu@10200 { + }; + + cpu1_3: cpu@10300 { +- compatible = "arm,cortex-a78"; ++ compatible = "arm,cortex-a78ae"; + device_type = "cpu"; + reg = <0x10300>; + +@@ -5491,7 +5491,7 @@ cpu1_3: cpu@10300 { + }; + + cpu2_0: cpu@20000 { +- compatible = "arm,cortex-a78"; ++ compatible = "arm,cortex-a78ae"; + device_type = "cpu"; + reg = <0x20000>; + +@@ -5510,7 +5510,7 @@ cpu2_0: cpu@20000 { + }; + + cpu2_1: cpu@20100 { +- compatible = "arm,cortex-a78"; ++ compatible = "arm,cortex-a78ae"; + device_type = "cpu"; + reg = <0x20100>; + +@@ -5529,7 +5529,7 @@ cpu2_1: cpu@20100 { + }; + + cpu2_2: cpu@20200 { +- compatible = "arm,cortex-a78"; ++ compatible = "arm,cortex-a78ae"; + device_type = "cpu"; + reg = <0x20200>; + +@@ -5548,7 +5548,7 @@ cpu2_2: cpu@20200 { + }; + + cpu2_3: cpu@20300 { +- compatible = "arm,cortex-a78"; ++ compatible = "arm,cortex-a78ae"; + device_type = "cpu"; + reg = <0x20300>; + +-- +2.53.0 + diff --git a/queue-7.1/arm64-tegra-remove-fallback-compatible-for-gpcdma.patch b/queue-7.1/arm64-tegra-remove-fallback-compatible-for-gpcdma.patch new file mode 100644 index 0000000000..06f1254a5c --- /dev/null +++ b/queue-7.1/arm64-tegra-remove-fallback-compatible-for-gpcdma.patch @@ -0,0 +1,38 @@ +From b05b9529f015915b7fc738d982aee21fc738ae07 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 31 Mar 2026 15:52:55 +0530 +Subject: arm64: tegra: Remove fallback compatible for GPCDMA + +From: Akhil R + +[ Upstream commit ee7863e43228a3143398dc5bbb943c9a735a8fca ] + +Remove the fallback compatible string "nvidia,tegra186-gpcdma" for GPCDMA +in Tegra264. Tegra186 compatible cannot work on Tegra264 because of the +register offset changes and absence of the reset property. + +Fixes: 65ef237e4810 ("arm64: tegra: Add Tegra264 support") +Signed-off-by: Akhil R +Reviewed-by: Jon Hunter +Signed-off-by: Thierry Reding +Signed-off-by: Sasha Levin +--- + arch/arm64/boot/dts/nvidia/tegra264.dtsi | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/arm64/boot/dts/nvidia/tegra264.dtsi b/arch/arm64/boot/dts/nvidia/tegra264.dtsi +index 2d8e7e37830ff2..3dfdd7bb28a911 100644 +--- a/arch/arm64/boot/dts/nvidia/tegra264.dtsi ++++ b/arch/arm64/boot/dts/nvidia/tegra264.dtsi +@@ -3208,7 +3208,7 @@ agic_page5: interrupt-controller@99b0000 { + }; + + gpcdma: dma-controller@8400000 { +- compatible = "nvidia,tegra264-gpcdma", "nvidia,tegra186-gpcdma"; ++ compatible = "nvidia,tegra264-gpcdma"; + reg = <0x0 0x08400000 0x0 0x210000>; + interrupts = , + , +-- +2.53.0 + diff --git a/queue-7.1/asoc-amd-acp-fix-linker-error-with-sdca-quirks.patch b/queue-7.1/asoc-amd-acp-fix-linker-error-with-sdca-quirks.patch new file mode 100644 index 0000000000..06e461ea7f --- /dev/null +++ b/queue-7.1/asoc-amd-acp-fix-linker-error-with-sdca-quirks.patch @@ -0,0 +1,110 @@ +From d15e85a5b7a56f6c6b17e09828fea441c5b57c62 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 3 Jul 2026 18:02:47 +0530 +Subject: ASoC: amd: acp: Fix linker error with SDCA quirks + +From: Syed Saba Kareem + +[ Upstream commit dbbb5bc5176e36b13aa22e2174ab4779c5ae1dca ] + +Fix undefined reference to `snd_soc_acpi_amd_sdca_is_device_rt712_vb` +linker error when CONFIG_SND_SOC_ACPI_AMD_MATCH=y and +CONFIG_SND_SOC_ACPI_AMD_SDCA_QUIRKS=m, which causes built-in code to +reference a symbol only available in a module. + +Fix this by changing SND_SOC_ACPI_AMD_SDCA_QUIRKS from tristate to bool +and compiling the quirks code directly into snd-soc-acpi-amd-match +rather than as a separate module. This ensures the quirks symbols are +always available at link time when the match tables reference them. + +Fixes: 10d366a846be ("ASoC: amd: acp: Fix Kconfig dependencies for SND_SOC_ACPI_AMD_SDCA_QUIRKS") +Reported-by: Arnd Bergmann +Tested-by: Arnd Bergmann +Signed-off-by: Syed Saba Kareem +Reviewed-by: Vijendar Mukunda +Link: https://patch.msgid.link/20260703123314.147977-1-syed.sabakareem@amd.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/amd/acp/Kconfig | 10 +++++++--- + sound/soc/amd/acp/Makefile | 3 +-- + sound/soc/amd/acp/amd-acp70-acpi-match.c | 2 +- + sound/soc/amd/acp/soc-acpi-amd-sdca-quirks.c | 4 ---- + 4 files changed, 9 insertions(+), 10 deletions(-) + +diff --git a/sound/soc/amd/acp/Kconfig b/sound/soc/amd/acp/Kconfig +index 977e4f2a7a7015..a04c301df4d616 100644 +--- a/sound/soc/amd/acp/Kconfig ++++ b/sound/soc/amd/acp/Kconfig +@@ -15,13 +15,17 @@ config SND_SOC_AMD_ACP_COMMON + + config SND_SOC_ACPI_AMD_MATCH + tristate +- select SND_SOC_ACPI_AMD_SDCA_QUIRKS if SND_SOC_SDCA + select SND_SOC_ACPI if ACPI + + config SND_SOC_ACPI_AMD_SDCA_QUIRKS +- tristate +- depends on ACPI ++ bool "AMD ACPI SDCA quirks" ++ depends on SND_SOC_ACPI_AMD_MATCH + depends on SND_SOC_SDCA ++ depends on SND_SOC_ACPI_AMD_MATCH = m || SND_SOC_SDCA = y ++ default y ++ help ++ Enable SDCA quirk support for AMD ACPI match tables. ++ This is compiled into the snd-soc-acpi-amd-match module. + + if SND_SOC_AMD_ACP_COMMON + +diff --git a/sound/soc/amd/acp/Makefile b/sound/soc/amd/acp/Makefile +index 81d23aded348d1..ab5f9dc871a677 100644 +--- a/sound/soc/amd/acp/Makefile ++++ b/sound/soc/amd/acp/Makefile +@@ -24,10 +24,10 @@ snd-acp-mach-y := acp-mach-common.o + snd-acp-legacy-mach-y := acp-legacy-mach.o acp3x-es83xx/acp3x-es83xx.o + snd-acp-sof-mach-y := acp-sof-mach.o + snd-soc-acpi-amd-match-y := amd-acp63-acpi-match.o amd-acp70-acpi-match.o ++snd-soc-acpi-amd-match-$(CONFIG_SND_SOC_ACPI_AMD_SDCA_QUIRKS) += soc-acpi-amd-sdca-quirks.o + snd-acp-sdw-mach-y := acp-sdw-mach-common.o + snd-acp-sdw-sof-mach-y += acp-sdw-sof-mach.o + snd-acp-sdw-legacy-mach-y += acp-sdw-legacy-mach.o +-snd-soc-acpi-amd-sdca-quirks-y += soc-acpi-amd-sdca-quirks.o + + obj-$(CONFIG_SND_SOC_AMD_ACP_PCM) += snd-acp-pcm.o + obj-$(CONFIG_SND_SOC_AMD_ACP_I2S) += snd-acp-i2s.o +@@ -41,7 +41,6 @@ obj-$(CONFIG_SND_AMD_ASOC_REMBRANDT) += snd-acp-rembrandt.o + obj-$(CONFIG_SND_AMD_ASOC_ACP63) += snd-acp63.o + obj-$(CONFIG_SND_AMD_ASOC_ACP70) += snd-acp70.o + +-obj-$(CONFIG_SND_SOC_ACPI_AMD_SDCA_QUIRKS) += snd-soc-acpi-amd-sdca-quirks.o + obj-$(CONFIG_SND_AMD_SOUNDWIRE_ACPI) += snd-amd-sdw-acpi.o + obj-$(CONFIG_SND_SOC_AMD_MACH_COMMON) += snd-acp-mach.o + obj-$(CONFIG_SND_SOC_AMD_LEGACY_MACH) += snd-acp-legacy-mach.o +diff --git a/sound/soc/amd/acp/amd-acp70-acpi-match.c b/sound/soc/amd/acp/amd-acp70-acpi-match.c +index 18f2918d4ada4d..9e97a805d0dffa 100644 +--- a/sound/soc/amd/acp/amd-acp70-acpi-match.c ++++ b/sound/soc/amd/acp/amd-acp70-acpi-match.c +@@ -775,5 +775,5 @@ MODULE_DESCRIPTION("AMD ACP7.0 & ACP7.1 tables and support for ACPI enumeration" + MODULE_LICENSE("GPL"); + MODULE_AUTHOR("Vijendar.Mukunda@amd.com"); + #if IS_ENABLED(CONFIG_SND_SOC_ACPI_AMD_SDCA_QUIRKS) +-MODULE_IMPORT_NS("SND_SOC_ACPI_AMD_SDCA_QUIRKS"); ++MODULE_IMPORT_NS("SND_SOC_SDCA"); + #endif +diff --git a/sound/soc/amd/acp/soc-acpi-amd-sdca-quirks.c b/sound/soc/amd/acp/soc-acpi-amd-sdca-quirks.c +index 63bf9e3c0ae180..9248b6d09e76fe 100644 +--- a/sound/soc/amd/acp/soc-acpi-amd-sdca-quirks.c ++++ b/sound/soc/amd/acp/soc-acpi-amd-sdca-quirks.c +@@ -35,8 +35,4 @@ bool snd_soc_acpi_amd_sdca_is_device_rt712_vb(void *arg) + + return false; + } +-EXPORT_SYMBOL_NS(snd_soc_acpi_amd_sdca_is_device_rt712_vb, "SND_SOC_ACPI_AMD_SDCA_QUIRKS"); + +-MODULE_DESCRIPTION("ASoC ACPI AMD SDCA quirks"); +-MODULE_LICENSE("GPL"); +-MODULE_IMPORT_NS("SND_SOC_SDCA"); +-- +2.53.0 + diff --git a/queue-7.1/asoc-amd-ps-disable-msi-on-resume-in-acp-pci-driver.patch b/queue-7.1/asoc-amd-ps-disable-msi-on-resume-in-acp-pci-driver.patch new file mode 100644 index 0000000000..2692891e24 --- /dev/null +++ b/queue-7.1/asoc-amd-ps-disable-msi-on-resume-in-acp-pci-driver.patch @@ -0,0 +1,73 @@ +From 4e02b9fa26267533105b03c809a6670dde9fc296 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 7 Jul 2026 11:29:36 +0530 +Subject: ASoC: amd: ps: disable MSI on resume in ACP PCI driver + +From: Vijendar Mukunda + +[ Upstream commit 5893013efabb056399a01e267f410cf76eba25eb ] + +BIOS/firmware may re-enable MSI in PCI config space during system +level resume even though this driver only uses legacy INTx interrupts. +If MSI is left enabled with stale address/data registers, the device +will write interrupts to a bogus address causing IOMMU IO_PAGE_FAULT +and interrupt delivery failure. + +Clear the MSI Enable bit before reinitializing the ACP hardware on +system level resume. + +Fixes: 491628388005 ("ASoC: amd: ps: add callback functions for acp pci driver pm ops") +Signed-off-by: Vijendar Mukunda +Reviewed-by: Mario Limonciello (AMD) +Link: https://patch.msgid.link/20260707060130.2514138-2-Vijendar.Mukunda@amd.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/amd/ps/pci-ps.c | 29 +++++++++++++++++++++++++++++ + 1 file changed, 29 insertions(+) + +diff --git a/sound/soc/amd/ps/pci-ps.c b/sound/soc/amd/ps/pci-ps.c +index 9751cf0784a6db..cccf9d85c860f0 100644 +--- a/sound/soc/amd/ps/pci-ps.c ++++ b/sound/soc/amd/ps/pci-ps.c +@@ -692,8 +692,37 @@ static int snd_acp_runtime_resume(struct device *dev) + return acp_hw_runtime_resume(dev); + } + ++static void acp_disable_msi_on_resume(struct pci_dev *pdev) ++{ ++ u16 control; ++ ++ if (!pdev->msi_cap) ++ return; ++ ++ pci_read_config_word(pdev, pdev->msi_cap + PCI_MSI_FLAGS, &control); ++ if (control & PCI_MSI_FLAGS_ENABLE) { ++ dev_warn(&pdev->dev, ++ "ACP: MSI unexpectedly enabled after resume (flags=0x%04x), disabling\n", ++ control); ++ control &= ~PCI_MSI_FLAGS_ENABLE; ++ pci_write_config_word(pdev, pdev->msi_cap + PCI_MSI_FLAGS, control); ++ } ++} ++ + static int snd_acp_resume(struct device *dev) + { ++ struct pci_dev *pdev = to_pci_dev(dev); ++ ++ /* ++ * BIOS/firmware may re-enable MSI in PCI config space during ++ * system resume even though this driver only uses legacy INTx ++ * interrupts. If MSI is left enabled with stale address/data ++ * registers, the device will write interrupts to a bogus address ++ * causing IOMMU IO_PAGE_FAULT and interrupt delivery failure. ++ * Explicitly clear the MSI Enable bit before reinitializing ++ * the ACP hardware. ++ */ ++ acp_disable_msi_on_resume(pdev); + return acp_hw_resume(dev); + } + +-- +2.53.0 + diff --git a/queue-7.1/asoc-amd-ps-fix-wrong-acp-version-string-in-pci_requ.patch b/queue-7.1/asoc-amd-ps-fix-wrong-acp-version-string-in-pci_requ.patch new file mode 100644 index 0000000000..d2ebd71bc1 --- /dev/null +++ b/queue-7.1/asoc-amd-ps-fix-wrong-acp-version-string-in-pci_requ.patch @@ -0,0 +1,39 @@ +From 98e764bd0446d581d488aba49f05583c1cfb7030 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 7 Jul 2026 11:29:37 +0530 +Subject: ASoC: amd: ps: fix wrong ACP version string in pci_request_regions() + +From: Vijendar Mukunda + +[ Upstream commit f7697ecf6eab9d4887dd731038b3dc405c7e755e ] + +The driver handles ACP6.3/7.0/7.1/7.2 platforms but the region was +claimed with the stale name "AMD ACP6.2 audio" left over from the +original ACP6.2 driver. Correct it to "AMD ACP6.3 audio". + +Fixes: 95e43a170bb1 ("ASoC: amd: add Pink Sardine ACP PCI driver") +Signed-off-by: Vijendar Mukunda +Reviewed-by: Mario Limonciello (AMD) +Link: https://patch.msgid.link/20260707060130.2514138-3-Vijendar.Mukunda@amd.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/amd/ps/pci-ps.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/sound/soc/amd/ps/pci-ps.c b/sound/soc/amd/ps/pci-ps.c +index cccf9d85c860f0..edff7f274a39d5 100644 +--- a/sound/soc/amd/ps/pci-ps.c ++++ b/sound/soc/amd/ps/pci-ps.c +@@ -601,7 +601,7 @@ static int snd_acp63_probe(struct pci_dev *pci, + return -ENODEV; + } + +- ret = pci_request_regions(pci, "AMD ACP6.2 audio"); ++ ret = pci_request_regions(pci, "AMD ACP6.3 audio"); + if (ret < 0) { + dev_err(&pci->dev, "pci_request_regions failed\n"); + goto disable_pci; +-- +2.53.0 + diff --git a/queue-7.1/asoc-amd-ps-replace-bitwise-or-with-logical-or-in-ir.patch b/queue-7.1/asoc-amd-ps-replace-bitwise-or-with-logical-or-in-ir.patch new file mode 100644 index 0000000000..87c131362e --- /dev/null +++ b/queue-7.1/asoc-amd-ps-replace-bitwise-or-with-logical-or-in-ir.patch @@ -0,0 +1,39 @@ +From bc718557f972039489caef02a195f2f565b6f66f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 7 Jul 2026 11:29:38 +0530 +Subject: ASoC: amd: ps: replace bitwise OR with logical OR in IRQ return check + +From: Vijendar Mukunda + +[ Upstream commit dec5aaa27603e1d7b426ce3504af6d1a62e4d444 ] + +The condition 'irq_flag | wake_irq_flag' uses bitwise OR to combine two +integer flags that are used as booleans. Replace with logical OR '||' to +correctly express the intended boolean check. + +Signed-off-by: Vijendar Mukunda +Reviewed-by: Mario Limonciello (AMD) +Fixes: 7f91f012c1df0 ("ASoC: amd: ps: fix for irq handler return status") +Link: https://patch.msgid.link/20260707060130.2514138-4-Vijendar.Mukunda@amd.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/amd/ps/pci-ps.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/sound/soc/amd/ps/pci-ps.c b/sound/soc/amd/ps/pci-ps.c +index edff7f274a39d5..5e73fb20e152a0 100644 +--- a/sound/soc/amd/ps/pci-ps.c ++++ b/sound/soc/amd/ps/pci-ps.c +@@ -248,7 +248,7 @@ static irqreturn_t acp63_irq_handler(int irq, void *dev_id) + if (sdw_dma_irq_flag) + return IRQ_WAKE_THREAD; + +- if (irq_flag | wake_irq_flag) ++ if (irq_flag || wake_irq_flag) + return IRQ_HANDLED; + else + return IRQ_NONE; +-- +2.53.0 + diff --git a/queue-7.1/asoc-cs42l43-correct-report-for-forced-microphone-ja.patch b/queue-7.1/asoc-cs42l43-correct-report-for-forced-microphone-ja.patch new file mode 100644 index 0000000000..a7583dbf59 --- /dev/null +++ b/queue-7.1/asoc-cs42l43-correct-report-for-forced-microphone-ja.patch @@ -0,0 +1,45 @@ +From 748aaa8413eef1831915c4ef699d2f5c7ee30189 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 8 Jul 2026 11:34:30 +0100 +Subject: ASoC: cs42l43: Correct report for forced microphone jack + +From: Charles Keepax + +[ Upstream commit f74e6e15485b68b92b2807071e822db6309b7e38 ] + +Currently if the jack is forced to the microphone mode, it will report +as line in. Correct the report to microphone. + +Fixes: fc918cbe874e ("ASoC: cs42l43: Add support for the cs42l43") +Signed-off-by: Charles Keepax +Link: https://patch.msgid.link/20260708103430.1395207-1-ckeepax@opensource.cirrus.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/codecs/cs42l43-jack.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/sound/soc/codecs/cs42l43-jack.c b/sound/soc/codecs/cs42l43-jack.c +index 3e04e6897b1423..e88109979c1831 100644 +--- a/sound/soc/codecs/cs42l43-jack.c ++++ b/sound/soc/codecs/cs42l43-jack.c +@@ -310,6 +310,7 @@ irqreturn_t cs42l43_bias_detect_clamp(int irq, void *data) + #define CS42L43_JACK_ABSENT 0x0 + + #define CS42L43_JACK_OPTICAL (SND_JACK_MECHANICAL | SND_JACK_AVOUT) ++#define CS42L43_JACK_MICROPHONE (SND_JACK_MECHANICAL | SND_JACK_MICROPHONE) + #define CS42L43_JACK_HEADPHONE (SND_JACK_MECHANICAL | SND_JACK_HEADPHONE) + #define CS42L43_JACK_HEADSET (SND_JACK_MECHANICAL | SND_JACK_HEADSET) + #define CS42L43_JACK_LINEOUT (SND_JACK_MECHANICAL | SND_JACK_LINEOUT) +@@ -871,7 +872,7 @@ static const struct cs42l43_jack_override_mode { + .hsdet_mode = CS42L43_JACK_3_POLE_SWITCHES, + .mic_ctrl = (0x3 << CS42L43_JACK_STEREO_CONFIG_SHIFT) | + CS42L43_HS1_BIAS_EN_MASK | CS42L43_HS2_BIAS_EN_MASK, +- .report = CS42L43_JACK_LINEIN, ++ .report = CS42L43_JACK_MICROPHONE, + }, + [CS42L43_JACK_RAW_OPTICAL] = { + .hsdet_mode = CS42L43_JACK_3_POLE_SWITCHES, +-- +2.53.0 + diff --git a/queue-7.1/asoc-meson-aiu-fifo-spdif-soft-reset-the-s-pdif-data.patch b/queue-7.1/asoc-meson-aiu-fifo-spdif-soft-reset-the-s-pdif-data.patch new file mode 100644 index 0000000000..03e592417e --- /dev/null +++ b/queue-7.1/asoc-meson-aiu-fifo-spdif-soft-reset-the-s-pdif-data.patch @@ -0,0 +1,64 @@ +From 6f4d1b8501480386ad445ae9ec70de68c98c5db4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 27 Jun 2026 13:12:05 +0000 +Subject: ASoC: meson: aiu: fifo-spdif: soft reset the S/PDIF datapath on + start/stop + +From: Christian Hewitt + +[ Upstream commit 6b59c53c8adc2b522327407af5e1793a65b67e4b ] + +The I2S FIFO soft-resets its fast domain on start (AIU_RST_SOFT bit 0 + +AIU_I2S_SYNC read in aiu_fifo_i2s_trigger), mirroring the downstream +vendor driver's audio_out_i2s_enable(). The S/PDIF FIFO has no equivalent: +it only toggles the IEC958 DCU, so a stale datapath FIFO can be replayed, +producing the "machine gun noise" buffer underrun - on start when switching +outputs, and on stop when playback ends. The latter is audible on devices +with an always-on S/PDIF-fed DAC (e.g. the ES7144 on the WeTek Play2). + +The vendor driver resets the IEC958 fast domain (AIU_RST_SOFT bit 2) on +both enable and disable (audio_hw_958_enable), and when reconfiguring +(audio_hw_958_reset clears AIU_958_DCU_FF_CTRL then resets). Do the same: +reset before enabling the DCU on start, and before disabling on stop. + +Fixes: 6ae9ca9ce986bf ("ASoC: meson: aiu: add i2s and spdif support") +Signed-off-by: Christian Hewitt +Reviewed-by: Martin Blumenstingl +Link: https://patch.msgid.link/20260627131205.808800-1-christianshewitt@gmail.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/meson/aiu-fifo-spdif.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/sound/soc/meson/aiu-fifo-spdif.c b/sound/soc/meson/aiu-fifo-spdif.c +index e0e00ec026dcc4..a9861c5d663745 100644 +--- a/sound/soc/meson/aiu-fifo-spdif.c ++++ b/sound/soc/meson/aiu-fifo-spdif.c +@@ -24,6 +24,7 @@ + #define AIU_MEM_IEC958_CONTROL_MODE_16BIT BIT(7) + #define AIU_MEM_IEC958_CONTROL_MODE_LINEAR BIT(8) + #define AIU_MEM_IEC958_BUF_CNTL_INIT BIT(0) ++#define AIU_RST_SOFT_958_FAST BIT(2) + + #define AIU_FIFO_SPDIF_BLOCK 8 + +@@ -68,11 +69,15 @@ static int fifo_spdif_trigger(struct snd_pcm_substream *substream, int cmd, + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: ++ snd_soc_component_write(component, AIU_RST_SOFT, ++ AIU_RST_SOFT_958_FAST); + fifo_spdif_dcu_enable(component, true); + break; + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + case SNDRV_PCM_TRIGGER_STOP: ++ snd_soc_component_write(component, AIU_RST_SOFT, ++ AIU_RST_SOFT_958_FAST); + fifo_spdif_dcu_enable(component, false); + break; + default: +-- +2.53.0 + diff --git a/queue-7.1/asoc-tas2562-fix-deprecated-shut-down-gpio-always-cl.patch b/queue-7.1/asoc-tas2562-fix-deprecated-shut-down-gpio-always-cl.patch new file mode 100644 index 0000000000..8a83c6c902 --- /dev/null +++ b/queue-7.1/asoc-tas2562-fix-deprecated-shut-down-gpio-always-cl.patch @@ -0,0 +1,62 @@ +From b263ffc1639adec6f61b34bc12229b6151d9bb5d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 6 Jul 2026 21:01:09 +0530 +Subject: ASoC: tas2562: fix deprecated 'shut-down' GPIO always cleared after + lookup + +From: Uday Khare + +[ Upstream commit 3238c634725afbb2a137fdda762208510828f71d ] + +In tas2562_parse_dt(), the fallback lookup for the deprecated +"shut-down" GPIO property is broken due to a missing pair of braces. + +The code intends to reset sdz_gpio to NULL only when the lookup +returns an error that is not -EPROBE_DEFER (so the driver gracefully +continues without a GPIO). However, without braces the statement: + + tas2562->sdz_gpio = NULL; + +falls outside the IS_ERR() check and is executed unconditionally +for every path through the if block, including a successful GPIO +lookup. + +This means any device using the deprecated 'shut-down' DT property +will always have sdz_gpio == NULL after probe, making the GPIO +completely non-functional. + +Fix this by adding the missing braces to scope the NULL assignment +inside the IS_ERR() branch, matching the pattern already used for +the primary 'shutdown' GPIO lookup above. + +Fixes: f78a97003b8b ("ASoC: tas2562: Update shutdown GPIO property") +Signed-off-by: Uday Khare +Link: https://patch.msgid.link/20260706153109.10953-1-udaykhare77@gmail.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/codecs/tas2562.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/sound/soc/codecs/tas2562.c b/sound/soc/codecs/tas2562.c +index ceb367ae05ba5a..adc4fdef3beed3 100644 +--- a/sound/soc/codecs/tas2562.c ++++ b/sound/soc/codecs/tas2562.c +@@ -675,11 +675,12 @@ static int tas2562_parse_dt(struct tas2562_data *tas2562) + if (tas2562->sdz_gpio == NULL) { + tas2562->sdz_gpio = devm_gpiod_get_optional(dev, "shut-down", + GPIOD_OUT_HIGH); +- if (IS_ERR(tas2562->sdz_gpio)) ++ if (IS_ERR(tas2562->sdz_gpio)) { + if (PTR_ERR(tas2562->sdz_gpio) == -EPROBE_DEFER) + return -EPROBE_DEFER; + +- tas2562->sdz_gpio = NULL; ++ tas2562->sdz_gpio = NULL; ++ } + } + + if (tas2562->model_id == TAS2110) +-- +2.53.0 + diff --git a/queue-7.1/ata-sata_dwc_460ex-enable-sata-interrupts-only-after.patch b/queue-7.1/ata-sata_dwc_460ex-enable-sata-interrupts-only-after.patch new file mode 100644 index 0000000000..163cdb4c2b --- /dev/null +++ b/queue-7.1/ata-sata_dwc_460ex-enable-sata-interrupts-only-after.patch @@ -0,0 +1,56 @@ +From 754fe8cf5f51e37886b6258fa2de2be131cb2c44 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 12 Jul 2026 14:37:26 -0700 +Subject: ata: sata_dwc_460ex: enable SATA interrupts only after IRQ handler is + registered + +From: Rosen Penev + +[ Upstream commit 4bbc16a353a98023e5ddfca7c1fc0e49971cf4d0 ] + +sata_dwc_enable_interrupts() is called before platform_get_irq() and +ata_host_activate(), leaving the SATA controller's interrupt mask +enabled without a registered handler. If a later step fails (irq +request, phy init, etc.) or if the controller asserts an interrupt +during probe, the irq line may fire with no handler, causing a +spurious interrupt storm. + +Move sata_dwc_enable_interrupts() after ata_host_activate() so that +interrupts are only unmasked once the handler is registered and the +core is fully initialized. + +Fixes: 62936009f35a ("[libata] Add 460EX on-chip SATA driver, sata_dwc_460ex") +Assisted-by: opencode:big-pickle +Signed-off-by: Rosen Penev +Signed-off-by: Damien Le Moal +Signed-off-by: Sasha Levin +--- + drivers/ata/sata_dwc_460ex.c | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c +index 64cb544903d888..47313dd4757859 100644 +--- a/drivers/ata/sata_dwc_460ex.c ++++ b/drivers/ata/sata_dwc_460ex.c +@@ -1168,9 +1168,6 @@ static int sata_dwc_probe(struct platform_device *ofdev) + /* Save dev for later use in dev_xxx() routines */ + hsdev->dev = dev; + +- /* Enable SATA Interrupts */ +- sata_dwc_enable_interrupts(hsdev); +- + /* Get SATA interrupt number */ + irq = irq_of_parse_and_map(np, 0); + if (!irq) { +@@ -1203,6 +1200,8 @@ static int sata_dwc_probe(struct platform_device *ofdev) + if (err) + dev_err(dev, "failed to activate host"); + ++ /* Enable SATA Interrupts */ ++ sata_dwc_enable_interrupts(hsdev); + return 0; + + error_out: +-- +2.53.0 + diff --git a/queue-7.1/ata-sata_dwc_460ex-fix-clear_interrupt_bit-clearing-.patch b/queue-7.1/ata-sata_dwc_460ex-fix-clear_interrupt_bit-clearing-.patch new file mode 100644 index 0000000000..a77bec44bb --- /dev/null +++ b/queue-7.1/ata-sata_dwc_460ex-fix-clear_interrupt_bit-clearing-.patch @@ -0,0 +1,45 @@ +From fdc75635ae5f6d9ef208424ab8561145bf31f7e6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 12 Jul 2026 14:37:27 -0700 +Subject: ata: sata_dwc_460ex: fix clear_interrupt_bit() clearing all pending + interrupts + +From: Rosen Penev + +[ Upstream commit 66c4e310ad71f41e41736d33dd8a1fb5eaaec7f3 ] + +clear_interrupt_bit() ignores the bit argument and performs a +read-write-back of the entire INTPR register. If INTPR uses standard +Write-1-to-Clear semantics, this clears every pending interrupt bit, +not just the intended one. Coalesced interrupts (e.g. DMAT + NEWFP) +would be cleared together, silently losing the second event. + +Write only the specific bit to clear so that other pending interrupts +are preserved. + +Fixes: 62936009f35a ("[libata] Add 460EX on-chip SATA driver, sata_dwc_460ex") +Assisted-by: opencode:big-pickle +Signed-off-by: Rosen Penev +Signed-off-by: Damien Le Moal +Signed-off-by: Sasha Levin +--- + drivers/ata/sata_dwc_460ex.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c +index e9b821d6fd6362..6c062efa2c6fda 100644 +--- a/drivers/ata/sata_dwc_460ex.c ++++ b/drivers/ata/sata_dwc_460ex.c +@@ -394,8 +394,7 @@ static void clear_serror(struct ata_port *ap) + + static void clear_interrupt_bit(struct sata_dwc_device *hsdev, u32 bit) + { +- sata_dwc_writel(&hsdev->sata_dwc_regs->intpr, +- sata_dwc_readl(&hsdev->sata_dwc_regs->intpr)); ++ sata_dwc_writel(&hsdev->sata_dwc_regs->intpr, bit); + } + + static u32 qcmd_tag_to_mask(u8 tag) +-- +2.53.0 + diff --git a/queue-7.1/ata-sata_dwc_460ex-fix-infinite-loop-in-ncq-tag-comp.patch b/queue-7.1/ata-sata_dwc_460ex-fix-infinite-loop-in-ncq-tag-comp.patch new file mode 100644 index 0000000000..f001b6d1e7 --- /dev/null +++ b/queue-7.1/ata-sata_dwc_460ex-fix-infinite-loop-in-ncq-tag-comp.patch @@ -0,0 +1,54 @@ +From 57a96ebee4277e64b7ce7277f2bff063655ea45b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 12 Jul 2026 14:37:28 -0700 +Subject: ata: sata_dwc_460ex: fix infinite loop in NCQ tag completion + bit-scanning + +From: Rosen Penev + +[ Upstream commit c2130f6553f4a5cbdc259de069600117a995f197 ] + +The hand-rolled bit-scanning loop in the NCQ completion path has an +infinite loop bug. When tag_mask has only high bits set (e.g. +0x80000000), the inner while loop left-shifts tag_mask until it +overflows to 0. At that point !(0 & 1) is always true and 0 <<= 1 +stays 0, causing an infinite loop in hardirq context with a spinlock +held. + +Replace the open-coded bit-scanning with __ffs() which correctly +finds the least significant set bit and is bounded by the width of +the argument. + +Fixes: 62936009f35a ("[libata] Add 460EX on-chip SATA driver, sata_dwc_460ex") +Assisted-by: opencode:big-pickle +Signed-off-by: Rosen Penev +Signed-off-by: Damien Le Moal +Signed-off-by: Sasha Levin +--- + drivers/ata/sata_dwc_460ex.c | 9 ++------- + 1 file changed, 2 insertions(+), 7 deletions(-) + +diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c +index 6c062efa2c6fda..cf723ef39d7cc2 100644 +--- a/drivers/ata/sata_dwc_460ex.c ++++ b/drivers/ata/sata_dwc_460ex.c +@@ -607,14 +607,9 @@ static irqreturn_t sata_dwc_isr(int irq, void *dev_instance) + status = ap->ops->sff_check_status(ap); + dev_dbg(ap->dev, "%s ATA status register=0x%x\n", __func__, status); + +- tag = 0; + while (tag_mask) { +- while (!(tag_mask & 0x00000001)) { +- tag++; +- tag_mask <<= 1; +- } +- +- tag_mask &= (~0x00000001); ++ tag = __ffs(tag_mask); ++ tag_mask &= ~(1U << tag); + qc = ata_qc_from_tag(ap, tag); + if (unlikely(!qc)) { + dev_err(ap->dev, "failed to get qc"); +-- +2.53.0 + diff --git a/queue-7.1/ata-sata_dwc_460ex-use-platform_get_irq.patch b/queue-7.1/ata-sata_dwc_460ex-use-platform_get_irq.patch new file mode 100644 index 0000000000..27cec23e28 --- /dev/null +++ b/queue-7.1/ata-sata_dwc_460ex-use-platform_get_irq.patch @@ -0,0 +1,92 @@ +From f6b98de9710acfb29661706b194dbe3622761732 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 12 Jul 2026 14:37:25 -0700 +Subject: ata: sata_dwc_460ex: use platform_get_irq() + +From: Rosen Penev + +[ Upstream commit a4af122106f73ea510bb35a9ea1dedd980fc0db7 ] + +Replace irq_of_parse_and_map() with platform_get_irq() in both +sata_dwc_dma_init_old() and sata_dwc_probe(). This is the preferred +way to obtain IRQs for platform devices and provides better error +reporting. Remove the now-unnecessary #include . + +irq_of_parse_and_map() requires irq_dispose_mapping(), which is missing. + +Also fix unused variable when CONFIG_SATA_DWC_OLD_DMA is disabled. + +Fixes: 62936009f35a ("[libata] Add 460EX on-chip SATA driver, sata_dwc_460ex") +Assisted-by: opencode:big-pickle +Signed-off-by: Rosen Penev +Signed-off-by: Damien Le Moal +Signed-off-by: Sasha Levin +--- + drivers/ata/sata_dwc_460ex.c | 21 +++++++-------------- + 1 file changed, 7 insertions(+), 14 deletions(-) + +diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c +index 47313dd4757859..e9b821d6fd6362 100644 +--- a/drivers/ata/sata_dwc_460ex.c ++++ b/drivers/ata/sata_dwc_460ex.c +@@ -19,7 +19,6 @@ + #include + #include + #include +-#include + #include + #include + #include +@@ -226,7 +225,6 @@ static int sata_dwc_dma_init_old(struct platform_device *pdev, + struct sata_dwc_device *hsdev) + { + struct device *dev = &pdev->dev; +- struct device_node *np = dev->of_node; + + hsdev->dma = devm_kzalloc(dev, sizeof(*hsdev->dma), GFP_KERNEL); + if (!hsdev->dma) +@@ -236,11 +234,9 @@ static int sata_dwc_dma_init_old(struct platform_device *pdev, + hsdev->dma->id = pdev->id; + + /* Get SATA DMA interrupt number */ +- hsdev->dma->irq = irq_of_parse_and_map(np, 1); +- if (!hsdev->dma->irq) { +- dev_err(dev, "no SATA DMA irq\n"); +- return -ENODEV; +- } ++ hsdev->dma->irq = platform_get_irq(pdev, 1); ++ if (hsdev->dma->irq < 0) ++ return hsdev->dma->irq; + + /* Get physical SATA DMA register base address */ + hsdev->dma->regs = devm_platform_ioremap_resource(pdev, 1); +@@ -1125,7 +1121,6 @@ static const struct ata_port_info sata_dwc_port_info[] = { + static int sata_dwc_probe(struct platform_device *ofdev) + { + struct device *dev = &ofdev->dev; +- struct device_node *np = dev->of_node; + struct sata_dwc_device *hsdev; + u32 idr, versionr; + char *ver = (char *)&versionr; +@@ -1169,14 +1164,12 @@ static int sata_dwc_probe(struct platform_device *ofdev) + hsdev->dev = dev; + + /* Get SATA interrupt number */ +- irq = irq_of_parse_and_map(np, 0); +- if (!irq) { +- dev_err(dev, "no SATA DMA irq\n"); +- return -ENODEV; +- } ++ irq = platform_get_irq(ofdev, 0); ++ if (irq < 0) ++ return irq; + + #ifdef CONFIG_SATA_DWC_OLD_DMA +- if (!of_property_present(np, "dmas")) { ++ if (!of_property_present(dev->of_node, "dmas")) { + err = sata_dwc_dma_init_old(ofdev, hsdev); + if (err) + return err; +-- +2.53.0 + diff --git a/queue-7.1/bluetooth-hci_qca-clear-memdump-state-on-invalid-dum.patch b/queue-7.1/bluetooth-hci_qca-clear-memdump-state-on-invalid-dum.patch new file mode 100644 index 0000000000..d29c0ff8f0 --- /dev/null +++ b/queue-7.1/bluetooth-hci_qca-clear-memdump-state-on-invalid-dum.patch @@ -0,0 +1,55 @@ +From 06876535d5e4a7b59022cd10f826da7723370c4e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 9 Jul 2026 14:22:50 +0800 +Subject: Bluetooth: hci_qca: Clear memdump state on invalid dump size + +From: Ruoyu Wang + +[ Upstream commit bf587a10c33e5571a299742e45bc18960b9912e7 ] + +qca_controller_memdump() allocates qca->qca_memdump before processing +the first dump packet. For a sequence-zero packet it then disables IBS, +marks memdump collection active, and reads the advertised dump size. + +If the controller reports a zero dump size, the error path frees the +local qca_memdump object and returns without clearing qca->qca_memdump +or undoing the collection state. A later memdump work item initializes +its local pointer from qca->qca_memdump and skips allocation when that +pointer is non-NULL, so it can operate on freed memory. The stale +collection and IBS-disabled flags can also leave waiters or later +transmit handling blocked behind an aborted dump. + +Clear the saved pointer and memdump state before returning from the +invalid-size path, matching the cleanup used when hci_devcd_init() fails. + +A static analysis checker reported the stale memdump state, and manual +source review confirmed the invalid-size failure path. + +Fixes: 06d3fdfcdf5c ("Bluetooth: hci_qca: Add qcom devcoredump support") +Signed-off-by: Ruoyu Wang +Reviewed-by: Paul Menzel +Reviewed-by: Zijun Hu +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + drivers/bluetooth/hci_qca.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c +index 2444471956197b..bd29d422c2090a 100644 +--- a/drivers/bluetooth/hci_qca.c ++++ b/drivers/bluetooth/hci_qca.c +@@ -1088,6 +1088,10 @@ static void qca_controller_memdump(struct work_struct *work) + if (!(qca_memdump->ram_dump_size)) { + bt_dev_err(hu->hdev, "Rx invalid memdump size"); + kfree(qca_memdump); ++ qca->qca_memdump = NULL; ++ qca->memdump_state = QCA_MEMDUMP_COLLECTED; ++ clear_and_wake_up_bit(QCA_MEMDUMP_COLLECTION, &qca->flags); ++ clear_bit(QCA_IBS_DISABLED, &qca->flags); + kfree_skb(skb); + mutex_unlock(&qca->hci_memdump_lock); + return; +-- +2.53.0 + diff --git a/queue-7.1/bluetooth-hci_sync-extend-conn_hash-lookup-critical-.patch b/queue-7.1/bluetooth-hci_sync-extend-conn_hash-lookup-critical-.patch new file mode 100644 index 0000000000..13adc9b4ba --- /dev/null +++ b/queue-7.1/bluetooth-hci_sync-extend-conn_hash-lookup-critical-.patch @@ -0,0 +1,193 @@ +From 3b76f4ae01c39f0631c7f592759679774662af26 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 10 Jul 2026 11:23:40 +0300 +Subject: Bluetooth: hci_sync: extend conn_hash lookup critical sections + +From: Pauli Virtanen + +[ Upstream commit d5efd6e4b8b0634af6843178fe1a7dd2b2178a3d ] + +Using RCU-protected pointers outside the critical sections without +refcount is incorrect and may result to UAF. + +Extend critical section to cover both hci_conn_hash lookup and use of +the returned conn. + +Add surrounding rcu_read_lock() also when return value is not used, in +preparation for RCU lockdep requirement to hci_lookup_le_connect(). + +This avoids concurrent deletion of the conn before we are done +dereferencing it. + +Also, make sure to hold hdev->lock when accessing hdev->accept_list. + +Fixes: 6d0417e4e1cf ("Bluetooth: hci_conn: Fix not setting conn_timeout for Broadcast Receiver") +Signed-off-by: Pauli Virtanen +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/hci_sync.c | 42 +++++++++++++++++++++++++++++++++++++--- + 1 file changed, 39 insertions(+), 3 deletions(-) + +diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c +index a3df69bdec1e06..eb216d86a6ddf3 100644 +--- a/net/bluetooth/hci_sync.c ++++ b/net/bluetooth/hci_sync.c +@@ -1054,14 +1054,19 @@ static int hci_set_random_addr_sync(struct hci_dev *hdev, bdaddr_t *rpa) + * In this kind of scenario skip the update and let the random + * address be updated at the next cycle. + */ ++ rcu_read_lock(); ++ + if (bacmp(&hdev->random_addr, BDADDR_ANY) && + (hci_dev_test_flag(hdev, HCI_LE_ADV) || + hci_lookup_le_connect(hdev))) { + bt_dev_dbg(hdev, "Deferring random address update"); + hci_dev_set_flag(hdev, HCI_RPA_EXPIRED); ++ rcu_read_unlock(); + return 0; + } + ++ rcu_read_unlock(); ++ + return __hci_cmd_sync_status(hdev, HCI_OP_LE_SET_RANDOM_ADDR, + 6, rpa, HCI_CMD_TIMEOUT); + } +@@ -2647,12 +2652,17 @@ static int hci_pause_addr_resolution(struct hci_dev *hdev) + /* Cannot disable addr resolution if scanning is enabled or + * when initiating an LE connection. + */ ++ rcu_read_lock(); ++ + if (hci_dev_test_flag(hdev, HCI_LE_SCAN) || + hci_lookup_le_connect(hdev)) { ++ rcu_read_unlock(); + bt_dev_err(hdev, "Command not allowed when scan/LE connect"); + return -EPERM; + } + ++ rcu_read_unlock(); ++ + /* Cannot disable addr resolution if advertising is enabled. */ + err = hci_pause_advertising_sync(hdev); + if (err) { +@@ -2790,6 +2800,8 @@ static u8 hci_update_accept_list_sync(struct hci_dev *hdev) + if (hci_dev_test_flag(hdev, HCI_PA_SYNC)) { + struct hci_conn *conn; + ++ rcu_read_lock(); ++ + conn = hci_conn_hash_lookup_create_pa_sync(hdev); + if (conn) { + struct conn_params pa; +@@ -2799,6 +2811,8 @@ static u8 hci_update_accept_list_sync(struct hci_dev *hdev) + bacpy(&pa.addr, &conn->dst); + pa.addr_type = conn->dst_type; + ++ rcu_read_unlock(); ++ + /* Clear first since there could be addresses left + * behind. + */ +@@ -2808,6 +2822,8 @@ static u8 hci_update_accept_list_sync(struct hci_dev *hdev) + err = hci_le_add_accept_list_sync(hdev, &pa, + &num_entries); + goto done; ++ } else { ++ rcu_read_unlock(); + } + } + +@@ -2818,10 +2834,13 @@ static u8 hci_update_accept_list_sync(struct hci_dev *hdev) + * the controller. + */ + list_for_each_entry_safe(b, t, &hdev->le_accept_list, list) { +- if (hci_conn_hash_lookup_le(hdev, &b->bdaddr, b->bdaddr_type)) ++ rcu_read_lock(); ++ ++ if (hci_conn_hash_lookup_le(hdev, &b->bdaddr, b->bdaddr_type)) { ++ rcu_read_unlock(); + continue; ++ } + +- /* Pointers not dereferenced, no locks needed */ + pend_conn = hci_pend_le_action_lookup(&hdev->pend_le_conns, + &b->bdaddr, + b->bdaddr_type); +@@ -2829,6 +2848,8 @@ static u8 hci_update_accept_list_sync(struct hci_dev *hdev) + &b->bdaddr, + b->bdaddr_type); + ++ rcu_read_unlock(); ++ + /* If the device is not likely to connect or report, + * remove it from the acceptlist. + */ +@@ -2955,6 +2976,8 @@ static int hci_le_set_ext_scan_param_sync(struct hci_dev *hdev, u8 type, + if (sent) { + struct hci_conn *conn; + ++ rcu_read_lock(); ++ + conn = hci_conn_hash_lookup_ba(hdev, PA_LINK, + &sent->bdaddr); + if (conn) { +@@ -2979,8 +3002,12 @@ static int hci_le_set_ext_scan_param_sync(struct hci_dev *hdev, u8 type, + phy++; + } + ++ rcu_read_unlock(); ++ + if (num_phy) + goto done; ++ } else { ++ rcu_read_unlock(); + } + } + } +@@ -3231,12 +3258,16 @@ int hci_update_passive_scan_sync(struct hci_dev *hdev) + /* If there is at least one pending LE connection, we should + * keep the background scan running. + */ ++ bool exists; + + /* If controller is connecting, we should not start scanning + * since some controllers are not able to scan and connect at + * the same time. + */ +- if (hci_lookup_le_connect(hdev)) ++ rcu_read_lock(); ++ exists = hci_lookup_le_connect(hdev); ++ rcu_read_unlock(); ++ if (exists) + return 0; + + bt_dev_dbg(hdev, "start background scanning"); +@@ -3454,6 +3485,7 @@ int hci_write_fast_connectable_sync(struct hci_dev *hdev, bool enable) + } + + static bool disconnected_accept_list_entries(struct hci_dev *hdev) ++ __must_hold(&hdev->lock) + { + struct bdaddr_list *b; + +@@ -3494,12 +3526,16 @@ int hci_update_scan_sync(struct hci_dev *hdev) + if (hdev->scanning_paused) + return 0; + ++ hci_dev_lock(hdev); ++ + if (hci_dev_test_flag(hdev, HCI_CONNECTABLE) || + disconnected_accept_list_entries(hdev)) + scan = SCAN_PAGE; + else + scan = SCAN_DISABLED; + ++ hci_dev_unlock(hdev); ++ + if (hci_dev_test_flag(hdev, HCI_DISCOVERABLE)) + scan |= SCAN_INQUIRY; + +-- +2.53.0 + diff --git a/queue-7.1/bluetooth-hci_sync-hold-hdev-lock-for-hci_conn_param.patch b/queue-7.1/bluetooth-hci_sync-hold-hdev-lock-for-hci_conn_param.patch new file mode 100644 index 0000000000..a47d83211d --- /dev/null +++ b/queue-7.1/bluetooth-hci_sync-hold-hdev-lock-for-hci_conn_param.patch @@ -0,0 +1,94 @@ +From 305cb1f34d429c624071013089491cfae795d070 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 10 Jul 2026 11:23:43 +0300 +Subject: Bluetooth: hci_sync: hold hdev->lock for hci_conn_params lookups + +From: Pauli Virtanen + +[ Upstream commit c363202ec841df36421ec280eea3d5f94f556143 ] + +hci_conn_params_lookup requires hdev->lock be held, otherwise the list +iteration or param access is not safe. + +Hold hdev->lock for params lookups in hci_sync. + +Fixes: c530569adc19 ("Bluetooth: hci_core: Introduce HCI_CONN_FLAG_PAST") +Signed-off-by: Pauli Virtanen +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/hci_sync.c | 24 ++++++++++++++++++++---- + 1 file changed, 20 insertions(+), 4 deletions(-) + +diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c +index eb216d86a6ddf3..d20f69858d22d6 100644 +--- a/net/bluetooth/hci_sync.c ++++ b/net/bluetooth/hci_sync.c +@@ -6679,6 +6679,8 @@ static int hci_le_create_conn_sync(struct hci_dev *hdev, void *data) + if (!hci_dev_test_flag(hdev, HCI_LE_SIMULTANEOUS_ROLES)) + hci_pause_advertising_sync(hdev); + ++ hci_dev_lock(hdev); ++ + params = hci_conn_params_lookup(hdev, &conn->dst, conn->dst_type); + if (params) { + conn->le_conn_min_interval = params->conn_min_interval; +@@ -6692,6 +6694,8 @@ static int hci_le_create_conn_sync(struct hci_dev *hdev, void *data) + conn->le_supv_timeout = hdev->le_supv_timeout; + } + ++ hci_dev_unlock(hdev); ++ + /* If controller is scanning, we stop it since some controllers are + * not able to scan and connect at the same time. Also set the + * HCI_LE_SCAN_INTERRUPTED flag so that the command complete +@@ -7249,13 +7253,13 @@ static void create_pa_complete(struct hci_dev *hdev, void *data, int err) + } + + static int hci_le_past_params_sync(struct hci_dev *hdev, struct hci_conn *conn, +- struct hci_conn *acl, struct bt_iso_qos *qos) ++ u16 acl_handle, struct bt_iso_qos *qos) + { + struct hci_cp_le_past_params cp; + int err; + + memset(&cp, 0, sizeof(cp)); +- cp.handle = cpu_to_le16(acl->handle); ++ cp.handle = cpu_to_le16(acl_handle); + /* An HCI_LE_Periodic_Advertising_Sync_Transfer_Received event is sent + * to the Host. HCI_LE_Periodic_Advertising_Report events will be + * enabled with duplicate filtering enabled. +@@ -7320,16 +7324,28 @@ static int hci_le_pa_create_sync(struct hci_dev *hdev, void *data) + * 2. Check if that HCI_CONN_FLAG_PAST has been set which indicates that + * user really intended to use PAST. + */ ++ hci_dev_lock(hdev); ++ + le = hci_conn_hash_lookup_le(hdev, &conn->dst, conn->dst_type); + if (le) { + struct hci_conn_params *params; ++ hci_conn_flags_t flags = 0; ++ u16 le_handle = le->handle; + + params = hci_conn_params_lookup(hdev, &le->dst, le->dst_type); +- if (params && params->flags & HCI_CONN_FLAG_PAST) { +- err = hci_le_past_params_sync(hdev, conn, le, qos); ++ if (params) ++ flags = params->flags; ++ ++ hci_dev_unlock(hdev); ++ ++ if (flags & HCI_CONN_FLAG_PAST) { ++ err = hci_le_past_params_sync(hdev, conn, le_handle, ++ qos); + if (!err) + goto done; + } ++ } else { ++ hci_dev_unlock(hdev); + } + + /* SID has not been set listen for HCI_EV_LE_EXT_ADV_REPORT to update +-- +2.53.0 + diff --git a/queue-7.1/bluetooth-mgmt-fix-locking-in-unpair_device-disconne.patch b/queue-7.1/bluetooth-mgmt-fix-locking-in-unpair_device-disconne.patch new file mode 100644 index 0000000000..6914256e9a --- /dev/null +++ b/queue-7.1/bluetooth-mgmt-fix-locking-in-unpair_device-disconne.patch @@ -0,0 +1,88 @@ +From 9ab9ff78b3434912746ce4711209af67d70ad2f1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 10 Jul 2026 11:23:41 +0300 +Subject: Bluetooth: mgmt: fix locking in unpair_device/disconnect_sync + +From: Pauli Virtanen + +[ Upstream commit 16cd66443957e4ad42155c6fec401012f600c6f8 ] + +Dereferencing RCU-protected pointers outside critical sections is +invalid and may lead to UAF. + +Take hdev->lock for hci_conn lookup and hci_abort_conn(). Don't use RCU +to ensure the conn is fully initialized at this point. + +Fixes: 227a0cdf4a028 ("Bluetooth: MGMT: Fix not generating command complete for MGMT_OP_DISCONNECT") +Signed-off-by: Pauli Virtanen +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/mgmt.c | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + +diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c +index f24b7bbfcb5b6f..186850538a8bb5 100644 +--- a/net/bluetooth/mgmt.c ++++ b/net/bluetooth/mgmt.c +@@ -3094,6 +3094,8 @@ static int unpair_device_sync(struct hci_dev *hdev, void *data) + struct mgmt_cp_unpair_device *cp = cmd->param; + struct hci_conn *conn; + ++ hci_dev_lock(hdev); ++ + if (cp->addr.type == BDADDR_BREDR) + conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, + &cp->addr.bdaddr); +@@ -3101,6 +3103,11 @@ static int unpair_device_sync(struct hci_dev *hdev, void *data) + conn = hci_conn_hash_lookup_le(hdev, &cp->addr.bdaddr, + le_addr_type(cp->addr.type)); + ++ if (conn) ++ hci_conn_get(conn); ++ ++ hci_dev_unlock(hdev); ++ + if (!conn) + return 0; + +@@ -3108,6 +3115,7 @@ static int unpair_device_sync(struct hci_dev *hdev, void *data) + * will clean up the connection no matter the error. + */ + hci_abort_conn(conn, HCI_ERROR_REMOTE_USER_TERM); ++ hci_conn_put(conn); + + return 0; + } +@@ -3255,6 +3263,8 @@ static int disconnect_sync(struct hci_dev *hdev, void *data) + struct mgmt_cp_disconnect *cp = cmd->param; + struct hci_conn *conn; + ++ hci_dev_lock(hdev); ++ + if (cp->addr.type == BDADDR_BREDR) + conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, + &cp->addr.bdaddr); +@@ -3262,6 +3272,11 @@ static int disconnect_sync(struct hci_dev *hdev, void *data) + conn = hci_conn_hash_lookup_le(hdev, &cp->addr.bdaddr, + le_addr_type(cp->addr.type)); + ++ if (conn) ++ hci_conn_get(conn); ++ ++ hci_dev_unlock(hdev); ++ + if (!conn) + return -ENOTCONN; + +@@ -3269,6 +3284,7 @@ static int disconnect_sync(struct hci_dev *hdev, void *data) + * will clean up the connection no matter the error. + */ + hci_abort_conn(conn, HCI_ERROR_REMOTE_USER_TERM); ++ hci_conn_put(conn); + + return 0; + } +-- +2.53.0 + diff --git a/queue-7.1/bluetooth-mgmt-hold-reference-for-hci_conn-in-mgmt_p.patch b/queue-7.1/bluetooth-mgmt-hold-reference-for-hci_conn-in-mgmt_p.patch new file mode 100644 index 0000000000..113d851ba7 --- /dev/null +++ b/queue-7.1/bluetooth-mgmt-hold-reference-for-hci_conn-in-mgmt_p.patch @@ -0,0 +1,107 @@ +From b030faa3c4733f0e5767b1b10074a6cf38326673 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 10 Jul 2026 11:23:42 +0300 +Subject: Bluetooth: mgmt: hold reference for hci_conn in mgmt_pending_cmds + +From: Pauli Virtanen + +[ Upstream commit da55f570191d5d72f10c607a7043b947eb05ea46 ] + +Dereferencing RCU-protected pointers outside critical sections is +invalid and may lead to UAF. Use of hci_conn in hci_sync callbacks also +needs to hold refcount to avoid UAF. + +Take appropriate locks for hci_conn lookups, and take refcount for +hci_conn pointers stored in mgmt_pending_cmd so that the pointer stays +valid. + +When accessing conn->state, ensure hdev->lock is held to avoid data +race. + +Fixes: 7b445e220db9 ("Bluetooth: MGMT: Fix holding hci_conn reference while command is queued") +Signed-off-by: Pauli Virtanen +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/mgmt.c | 26 ++++++++++++++++++++++---- + 1 file changed, 22 insertions(+), 4 deletions(-) + +diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c +index 186850538a8bb5..9604c3025f7b7c 100644 +--- a/net/bluetooth/mgmt.c ++++ b/net/bluetooth/mgmt.c +@@ -7407,6 +7407,9 @@ static void get_conn_info_complete(struct hci_dev *hdev, void *data, int err) + rp.max_tx_power = HCI_TX_POWER_INVALID; + } + ++ if (conn) ++ hci_conn_put(conn); ++ + mgmt_cmd_complete(cmd->sk, cmd->hdev->id, MGMT_OP_GET_CONN_INFO, status, + &rp, sizeof(rp)); + +@@ -7421,6 +7424,8 @@ static int get_conn_info_sync(struct hci_dev *hdev, void *data) + int err; + __le16 handle; + ++ hci_dev_lock(hdev); ++ + /* Make sure we are still connected */ + if (cp->addr.type == BDADDR_BREDR) + conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, +@@ -7428,12 +7433,16 @@ static int get_conn_info_sync(struct hci_dev *hdev, void *data) + else + conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr); + +- if (!conn || conn->state != BT_CONNECTED) ++ if (!conn || conn->state != BT_CONNECTED) { ++ hci_dev_unlock(hdev); + return MGMT_STATUS_NOT_CONNECTED; ++ } + +- cmd->user_data = conn; ++ cmd->user_data = hci_conn_get(conn); + handle = cpu_to_le16(conn->handle); + ++ hci_dev_unlock(hdev); ++ + /* Refresh RSSI each time */ + err = hci_read_rssi_sync(hdev, handle); + +@@ -7567,6 +7576,9 @@ static void get_clock_info_complete(struct hci_dev *hdev, void *data, int err) + } + + complete: ++ if (conn) ++ hci_conn_put(conn); ++ + mgmt_cmd_complete(cmd->sk, cmd->hdev->id, cmd->opcode, status, &rp, + sizeof(rp)); + +@@ -7583,15 +7595,21 @@ static int get_clock_info_sync(struct hci_dev *hdev, void *data) + memset(&hci_cp, 0, sizeof(hci_cp)); + hci_read_clock_sync(hdev, &hci_cp); + ++ hci_dev_lock(hdev); ++ + /* Make sure connection still exists */ + conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->addr.bdaddr); +- if (!conn || conn->state != BT_CONNECTED) ++ if (!conn || conn->state != BT_CONNECTED) { ++ hci_dev_unlock(hdev); + return MGMT_STATUS_NOT_CONNECTED; ++ } + +- cmd->user_data = conn; ++ cmd->user_data = hci_conn_get(conn); + hci_cp.handle = cpu_to_le16(conn->handle); + hci_cp.which = 0x01; /* Piconet clock */ + ++ hci_dev_unlock(hdev); ++ + return hci_read_clock_sync(hdev, &hci_cp); + } + +-- +2.53.0 + diff --git a/queue-7.1/bluetooth-mgmt-revalidate-load_conn_param-queued-upd.patch b/queue-7.1/bluetooth-mgmt-revalidate-load_conn_param-queued-upd.patch new file mode 100644 index 0000000000..17e8f07582 --- /dev/null +++ b/queue-7.1/bluetooth-mgmt-revalidate-load_conn_param-queued-upd.patch @@ -0,0 +1,131 @@ +From adae0aa5c922460f7546f40a5cc8275adbc15ca0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 7 Jul 2026 12:15:18 +0800 +Subject: Bluetooth: MGMT: revalidate LOAD_CONN_PARAM queued update + +From: Cen Zhang + +[ Upstream commit 2bf282f8f715f5d05d6f4c49ffb3bd241c5e667e ] + +MGMT_OP_LOAD_CONN_PARAM queues conn_update_sync() when a single parameter +update changes an existing LE central connection. The queued work currently +stores a borrowed hci_conn_params entry from hdev->le_conn_params. A later +LOAD_CONN_PARAM request can clear disabled parameters and free that entry +before hci_cmd_sync_work() runs the queued callback. + +Do not keep the borrowed hci_conn_params pointer in queued work. Queue the +hci_conn instead and hold a reference until the queued callback completes. +When the work runs, revalidate that the connection is still present, look +up the current hci_conn_params entry, and cancel the update if userspace +removed that entry while the work was pending. + +Copy the interval values from the current params entry under hdev->lock, +then drop the lock and keep using hci_le_conn_update_sync() to issue the +update. + +Validation reproduced this kernel report: +BUG: KASAN: slab-use-after-free in conn_update_sync+0x2a/0xf0 [bluetooth] +Read of size 1 at addr ffff88810c697126 by task kworker/u17:0/377 +Workqueue: hci0 hci_cmd_sync_work [bluetooth] + +Call Trace: + + dump_stack_lvl+0x66/0xa0 + print_report+0xce/0x5f0 + kasan_report+0xe0/0x110 + conn_update_sync+0x2a/0xf0 [bluetooth] + hci_cmd_sync_work+0x187/0x210 [bluetooth] + process_one_work+0x4fd/0xbc0 + worker_thread+0x2d8/0x570 + kthread+0x1ad/0x1f0 + ret_from_fork+0x3c9/0x540 + ret_from_fork_asm+0x1a/0x30 + +Allocated by task 466: + hci_conn_params_add+0xa6/0x240 [bluetooth] + load_conn_param+0x4e1/0x850 [bluetooth] + hci_sock_sendmsg+0x96b/0xf80 [bluetooth] + +Freed by task 474: + kfree+0x313/0x590 + hci_conn_params_clear_disabled+0x9b/0xc0 [bluetooth] + load_conn_param+0x4bf/0x850 [bluetooth] + hci_sock_sendmsg+0x96b/0xf80 [bluetooth] + +Fixes: 0ece498c27d8c ("Bluetooth: MGMT: Make MGMT_OP_LOAD_CONN_PARAM update existing connection") +Suggested-by: Luiz Augusto von Dentz +Assisted-by: Codex:gpt-5.5 +Signed-off-by: Cen Zhang +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/mgmt.c | 44 +++++++++++++++++++++++++++++++++++--------- + 1 file changed, 35 insertions(+), 9 deletions(-) + +diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c +index e8544194a52424..f24b7bbfcb5b6f 100644 +--- a/net/bluetooth/mgmt.c ++++ b/net/bluetooth/mgmt.c +@@ -7940,14 +7940,36 @@ static int remove_device(struct sock *sk, struct hci_dev *hdev, + + static int conn_update_sync(struct hci_dev *hdev, void *data) + { +- struct hci_conn_params *params = data; +- struct hci_conn *conn; ++ struct hci_conn *conn = data; ++ struct hci_conn_params *params; ++ struct hci_conn_params local = {}; + +- conn = hci_conn_hash_lookup_le(hdev, ¶ms->addr, params->addr_type); +- if (!conn) +- return -ECANCELED; ++ hci_dev_lock(hdev); ++ ++ if (!hci_conn_valid(hdev, conn) || conn->role != HCI_ROLE_MASTER) ++ goto cancel; ++ ++ params = hci_conn_params_lookup(hdev, &conn->dst, conn->dst_type); ++ if (!params) ++ goto cancel; ++ ++ local.conn_min_interval = params->conn_min_interval; ++ local.conn_max_interval = params->conn_max_interval; ++ local.conn_latency = params->conn_latency; ++ local.supervision_timeout = params->supervision_timeout; + +- return hci_le_conn_update_sync(hdev, conn, params); ++ hci_dev_unlock(hdev); ++ ++ return hci_le_conn_update_sync(hdev, conn, &local); ++ ++cancel: ++ hci_dev_unlock(hdev); ++ return -ECANCELED; ++} ++ ++static void conn_update_sync_destroy(struct hci_dev *hdev, void *data, int err) ++{ ++ hci_conn_put(data); + } + + static int load_conn_param(struct sock *sk, struct hci_dev *hdev, void *data, +@@ -8057,9 +8079,13 @@ static int load_conn_param(struct sock *sk, struct hci_dev *hdev, void *data, + (conn->le_conn_min_interval != min || + conn->le_conn_max_interval != max || + conn->le_conn_latency != latency || +- conn->le_supv_timeout != timeout)) +- hci_cmd_sync_queue(hdev, conn_update_sync, +- hci_param, NULL); ++ conn->le_supv_timeout != timeout)) { ++ hci_conn_get(conn); ++ if (hci_cmd_sync_queue(hdev, conn_update_sync, ++ conn, ++ conn_update_sync_destroy) < 0) ++ hci_conn_put(conn); ++ } + } + } + +-- +2.53.0 + diff --git a/queue-7.1/bluetooth-mgmt-translate-hci-reason-in-device-discon.patch b/queue-7.1/bluetooth-mgmt-translate-hci-reason-in-device-discon.patch new file mode 100644 index 0000000000..11e6f1e268 --- /dev/null +++ b/queue-7.1/bluetooth-mgmt-translate-hci-reason-in-device-discon.patch @@ -0,0 +1,136 @@ +From 8204c6d5e8ea6fd4220cd4cf1c083f39410b6e1c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 10 Jul 2026 14:47:31 +0500 +Subject: Bluetooth: mgmt: Translate HCI reason in Device Disconnected event + +From: Mikhail Gavrilov + +[ Upstream commit c1cec2bbbeb5922d42d28c6af1707c4f3f8647e3 ] + +MGMT_EV_DEVICE_DISCONNECTED carries a reason field which is defined to +be one of MGMT_DEV_DISCONN_* (0x00..0x05). hci_disconn_complete_evt() +converts the HCI error with hci_to_mgmt_reason(), but two other paths +pass the raw HCI error straight through: + + hci_cs_disconnect() -> cp->reason + mgmt_connect_failed() -> status + +The latter is reached whenever the adapter is powered off or suspended: +hci_disconnect_all_sync() aborts every link with +HCI_ERROR_REMOTE_POWER_OFF, hci_disconnect_sync() deliberately does not +wait for HCI_EV_DISCONN_COMPLETE for that reason, so that +hci_abort_conn_sync() finishes the connection off through +hci_conn_failed() instead. + +As a result userspace sees an out of range reason: + + @ MGMT Event: Device Disconnected (0x000c) plen 8 + BR/EDR Address: 8C:A9:6F:2C:51:46 + Reason: Reserved (0x15) + + bluetoothd: btd_bearer_disconnected() Unknown disconnection value: 21 + bluetoothd: device_disconnected() Unknown disconnection value: 21 + +Export hci_to_mgmt_reason() and use it in both places, so that a power +off is reported as MGMT_DEV_DISCONN_REMOTE rather than as the raw +HCI_ERROR_REMOTE_POWER_OFF (0x15). + +Fixes: d47da6bd4cfa ("Bluetooth: hci_core: Fix sending MGMT_EV_CONNECT_FAILED") +Fixes: 182ee45da083 ("Bluetooth: hci_sync: Rework hci_suspend_notifier") +Signed-off-by: Mikhail Gavrilov +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + include/net/bluetooth/hci_core.h | 1 + + net/bluetooth/hci_event.c | 18 +----------------- + net/bluetooth/mgmt.c | 19 ++++++++++++++++++- + 3 files changed, 20 insertions(+), 18 deletions(-) + +diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h +index aa554c34f9ec35..02ba1cba6b236c 100644 +--- a/include/net/bluetooth/hci_core.h ++++ b/include/net/bluetooth/hci_core.h +@@ -2433,6 +2433,7 @@ void mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key, + bool persistent); + void mgmt_device_connected(struct hci_dev *hdev, struct hci_conn *conn, + u8 *name, u8 name_len); ++u8 hci_to_mgmt_reason(u8 err); + void mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr, + u8 link_type, u8 addr_type, u8 reason, + bool mgmt_connected); +diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c +index 1cd5f97daafe32..55a2de5c8c8e5a 100644 +--- a/net/bluetooth/hci_event.c ++++ b/net/bluetooth/hci_event.c +@@ -2766,7 +2766,7 @@ static void hci_cs_disconnect(struct hci_dev *hdev, u8 status) + } + + mgmt_device_disconnected(hdev, &conn->dst, conn->type, conn->dst_type, +- cp->reason, mgmt_conn); ++ hci_to_mgmt_reason(cp->reason), mgmt_conn); + + hci_disconn_cfm(conn, cp->reason); + +@@ -3384,22 +3384,6 @@ static void hci_conn_request_evt(struct hci_dev *hdev, void *data, + hci_dev_unlock(hdev); + } + +-static u8 hci_to_mgmt_reason(u8 err) +-{ +- switch (err) { +- case HCI_ERROR_CONNECTION_TIMEOUT: +- return MGMT_DEV_DISCONN_TIMEOUT; +- case HCI_ERROR_REMOTE_USER_TERM: +- case HCI_ERROR_REMOTE_LOW_RESOURCES: +- case HCI_ERROR_REMOTE_POWER_OFF: +- return MGMT_DEV_DISCONN_REMOTE; +- case HCI_ERROR_LOCAL_HOST_TERM: +- return MGMT_DEV_DISCONN_LOCAL_HOST; +- default: +- return MGMT_DEV_DISCONN_UNKNOWN; +- } +-} +- + static void hci_disconn_complete_evt(struct hci_dev *hdev, void *data, + struct sk_buff *skb) + { +diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c +index 9604c3025f7b7c..c18eea5eb78104 100644 +--- a/net/bluetooth/mgmt.c ++++ b/net/bluetooth/mgmt.c +@@ -9911,6 +9911,22 @@ bool mgmt_powering_down(struct hci_dev *hdev) + return false; + } + ++u8 hci_to_mgmt_reason(u8 err) ++{ ++ switch (err) { ++ case HCI_ERROR_CONNECTION_TIMEOUT: ++ return MGMT_DEV_DISCONN_TIMEOUT; ++ case HCI_ERROR_REMOTE_USER_TERM: ++ case HCI_ERROR_REMOTE_LOW_RESOURCES: ++ case HCI_ERROR_REMOTE_POWER_OFF: ++ return MGMT_DEV_DISCONN_REMOTE; ++ case HCI_ERROR_LOCAL_HOST_TERM: ++ return MGMT_DEV_DISCONN_LOCAL_HOST; ++ default: ++ return MGMT_DEV_DISCONN_UNKNOWN; ++ } ++} ++ + void mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr, + u8 link_type, u8 addr_type, u8 reason, + bool mgmt_connected) +@@ -9972,7 +9988,8 @@ void mgmt_connect_failed(struct hci_dev *hdev, struct hci_conn *conn, u8 status) + + if (test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) { + mgmt_device_disconnected(hdev, &conn->dst, conn->type, +- conn->dst_type, status, true); ++ conn->dst_type, ++ hci_to_mgmt_reason(status), true); + return; + } + +-- +2.53.0 + diff --git a/queue-7.1/bluetooth-qca-fix-nvm-tag-length-underflow-in-tlv-pa.patch b/queue-7.1/bluetooth-qca-fix-nvm-tag-length-underflow-in-tlv-pa.patch new file mode 100644 index 0000000000..700ab70a96 --- /dev/null +++ b/queue-7.1/bluetooth-qca-fix-nvm-tag-length-underflow-in-tlv-pa.patch @@ -0,0 +1,68 @@ +From 0a083f1aebd0038a62c1b81ac5209e6269ffc381 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 4 Jul 2026 16:10:30 -0700 +Subject: Bluetooth: qca: fix NVM tag length underflow in TLV parser + +From: Xiang Mei + +[ Upstream commit c90164ca0f7036942ba088eb7ea8d3f6c2352020 ] + +In the TLV_TYPE_NVM branch of qca_tlv_check_data() the tag loop bound is +"while (idx < length - sizeof(struct tlv_type_nvm))". "length" is a signed +int from the firmware TLV header and sizeof(struct tlv_type_nvm) is a +size_t (12), so "length" is converted to size_t and any firmware-supplied +"length" < 12 makes the subtraction wrap to a huge value. The loop body +then reads a 12-byte struct tlv_type_nvm past the end of the short +vmalloc'd firmware buffer (and the EDL_TAG_ID_* handlers can write past it). + +Rewrite the bound as "idx + sizeof(struct tlv_type_nvm) <= length"; both +operands are non-negative, so it no longer underflows and a "length" too +small for one record correctly skips the loop. + + BUG: KASAN: vmalloc-out-of-bounds in qca_download_firmware.isra.0 (drivers/bluetooth/btqca.c:421) + Read of size 2 at addr ffffc900000e5004 by task kworker/u9:0/52 + Workqueue: hci0 hci_power_on + Call Trace: + ... + kasan_report (mm/kasan/report.c:595) + qca_download_firmware.isra.0 (drivers/bluetooth/btqca.c:421 drivers/bluetooth/btqca.c:617) + qca_uart_setup (drivers/bluetooth/btqca.c:948) + qca_setup (drivers/bluetooth/hci_qca.c:2029) + hci_uart_setup (drivers/bluetooth/hci_ldisc.c:438) + hci_dev_open_sync (net/bluetooth/hci_sync.c:5227) + hci_power_on (net/bluetooth/hci_core.c:920) + process_one_work (kernel/workqueue.c:3322) + worker_thread (kernel/workqueue.c:3486) + kthread (kernel/kthread.c:436) + ret_from_fork (arch/x86/kernel/process.c:158) + ret_from_fork_asm (arch/x86/entry/entry_64.S:245) + +Fixes: 2e4edfa1e2bd ("Bluetooth: qca: add missing firmware sanity checks") +Reported-by: Weiming Shi +Assisted-by: Claude:claude-opus-4-8 +Signed-off-by: Xiang Mei +Reported-by: Weiming Shi +Reviewed-by: Johan Hovold +Acked-by: Bartosz Golaszewski +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + drivers/bluetooth/btqca.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/bluetooth/btqca.c b/drivers/bluetooth/btqca.c +index dda76365726f0b..fff1dd64383a3d 100644 +--- a/drivers/bluetooth/btqca.c ++++ b/drivers/bluetooth/btqca.c +@@ -413,7 +413,7 @@ static int qca_tlv_check_data(struct hci_dev *hdev, + + idx = 0; + data = tlv->data; +- while (idx < length - sizeof(struct tlv_type_nvm)) { ++ while (idx + sizeof(struct tlv_type_nvm) <= length) { + tlv_nvm = (struct tlv_type_nvm *)(data + idx); + + tag_id = le16_to_cpu(tlv_nvm->tag_id); +-- +2.53.0 + diff --git a/queue-7.1/bnxt_en-handle-partially-initialized-auxiliary-devic.patch b/queue-7.1/bnxt_en-handle-partially-initialized-auxiliary-devic.patch new file mode 100644 index 0000000000..a1683e4165 --- /dev/null +++ b/queue-7.1/bnxt_en-handle-partially-initialized-auxiliary-devic.patch @@ -0,0 +1,110 @@ +From 6737670f6595c40b67b6122dc8ccfe4076c1c0b3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 12 Jul 2026 00:37:16 +0800 +Subject: bnxt_en: Handle partially initialized auxiliary devices + +From: Ruoyu Wang + +[ Upstream commit 1cb8553c02e93e5a150cebd42f9ee3db0ece4707 ] + +bnxt_aux_devices_init() calls auxiliary_device_init() before all fields +used by bnxt_aux_dev_release() are initialized. After +auxiliary_device_init() succeeds, later errors must unwind with +auxiliary_device_uninit(), which invokes the release callback. + +The release callback assumes that aux_priv->id, aux_priv->edev, +edev->net and edev->ulp_tbl are all populated. If allocation fails +after auxiliary_device_init(), the release path can otherwise dereference +or clear partially initialized state. + +Allocate and attach the bnxt_en_dev and ULP table before calling +auxiliary_device_init(), so the release callback only sees a fully +initialized auxiliary private object. If auxiliary_device_init() itself +fails, free those allocations directly because device_initialize() has not +run and the release callback will not be invoked. + +This issue was found by a static analysis checker and confirmed by manual +source review. + +Fixes: 194fad5b2781 ("bnxt_en: Refactor bnxt_rdma_aux_device_init/uninit functions") +Signed-off-by: Ruoyu Wang +Reviewed-by: Pavan Chebbi +Link: https://patch.msgid.link/20260711163716.3996929-1-ruoyuw560@gmail.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.c | 39 ++++++++++--------- + 1 file changed, 20 insertions(+), 19 deletions(-) + +diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.c +index 5c751933da6a9d..a515c368bac015 100644 +--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.c ++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.c +@@ -566,6 +566,18 @@ void bnxt_aux_devices_init(struct bnxt *bp) + if (!aux_priv) + goto next_auxdev; + ++ edev = kzalloc_obj(*edev); ++ if (!edev) ++ goto aux_priv_free; ++ aux_priv->edev = edev; ++ bnxt_set_edev_info(edev, bp); ++ ++ ulp = kzalloc_obj(*ulp); ++ if (!ulp) ++ goto edev_free; ++ edev->ulp_tbl = ulp; ++ aux_priv->id = idx; ++ + aux_dev = &aux_priv->aux_dev; + aux_dev->id = bp->auxdev_id; + aux_dev->name = bnxt_aux_devices[idx].name; +@@ -573,37 +585,26 @@ void bnxt_aux_devices_init(struct bnxt *bp) + aux_dev->dev.release = bnxt_aux_dev_release; + + rc = auxiliary_device_init(aux_dev); +- if (rc) { +- kfree(aux_priv); +- goto next_auxdev; +- } ++ if (rc) ++ goto ulp_free; + bp->aux_priv[idx] = aux_priv; + + /* From this point, all cleanup will happen via the .release + * callback & any error unwinding will need to include a call + * to auxiliary_device_uninit. + */ +- edev = kzalloc_obj(*edev); +- if (!edev) +- goto aux_dev_uninit; +- +- aux_priv->edev = edev; +- bnxt_set_edev_info(edev, bp); +- +- ulp = kzalloc_obj(*ulp); +- if (!ulp) +- goto aux_dev_uninit; +- +- edev->ulp_tbl = ulp; + bp->edev[idx] = edev; + if (idx == BNXT_AUXDEV_RDMA) + bp->ulp_num_msix_want = bnxt_set_dflt_ulp_msix(bp); +- aux_priv->id = idx; + bnxt_auxdev_set_state(bp, idx, BNXT_ADEV_STATE_INIT); + + continue; +-aux_dev_uninit: +- auxiliary_device_uninit(aux_dev); ++ulp_free: ++ kfree(ulp); ++edev_free: ++ kfree(edev); ++aux_priv_free: ++ kfree(aux_priv); + next_auxdev: + if (idx == BNXT_AUXDEV_RDMA) + bp->flags &= ~BNXT_FLAG_ROCE_CAP; +-- +2.53.0 + diff --git a/queue-7.1/bpf-fix-uaf-in-sock-clone-early-bailouts.patch b/queue-7.1/bpf-fix-uaf-in-sock-clone-early-bailouts.patch new file mode 100644 index 0000000000..f5f66f1e49 --- /dev/null +++ b/queue-7.1/bpf-fix-uaf-in-sock-clone-early-bailouts.patch @@ -0,0 +1,68 @@ +From 5b06edca601daed6f9ff96f64beb6903f36a5488 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 9 Jul 2026 02:53:16 +0000 +Subject: bpf: Fix UAF in sock clone early bailouts + +From: Matt Bobrowski + +[ Upstream commit 7cbd0c4cebe4c9f678d15e6b9ba975e1155a107f ] + +Similar to recent commit 9b51a6155d14 ("bpf,fork: wipe ->bpf_storage +before bailouts that access it"), sk_clone() performs an initial +shallow copy of the socket field ->sk_bpf_storage via sock_copy() +for the cloned socket newsk. + +If sk_clone() bails out early (e.g. if sk_filter_charge() fails) prior +to calling bpf_sk_storage_clone(), newsk->sk_bpf_storage still points +to the parent socket's BPF local storage. When newsk is subsequently +freed via sk_free(), the deallocation path (__sk_destruct() -> +bpf_sk_storage_free()) destroys the parent socket's BPF local storage, +leading to a use-after-free (UAF) on the parent socket. + +Fix this by resetting newsk->sk_bpf_storage to NULL immediately after +sock_copy() in sk_clone(), and remove the now redundant initialization +from bpf_sk_storage_clone(). + +Fixes: 6ac99e8f23d4 ("bpf: Introduce bpf sk local storage") +Fixes: f12dd75959b0 ("bpf: net: Set sk_bpf_storage back to NULL for cloned sk") +Signed-off-by: Matt Bobrowski +Signed-off-by: Daniel Borkmann +Reviewed-by: Kuniyuki Iwashima +Acked-by: Daniel Borkmann +Link: https://lore.kernel.org/bpf/20260709025316.999913-1-mattbobrowski@google.com +Signed-off-by: Sasha Levin +--- + net/core/bpf_sk_storage.c | 2 -- + net/core/sock.c | 3 +++ + 2 files changed, 3 insertions(+), 2 deletions(-) + +diff --git a/net/core/bpf_sk_storage.c b/net/core/bpf_sk_storage.c +index ecd659f79fd4a0..1d295a8769fad5 100644 +--- a/net/core/bpf_sk_storage.c ++++ b/net/core/bpf_sk_storage.c +@@ -158,8 +158,6 @@ int bpf_sk_storage_clone(const struct sock *sk, struct sock *newsk) + struct bpf_local_storage_elem *selem; + int ret = 0; + +- RCU_INIT_POINTER(newsk->sk_bpf_storage, NULL); +- + rcu_read_lock_dont_migrate(); + sk_storage = rcu_dereference(sk->sk_bpf_storage); + +diff --git a/net/core/sock.c b/net/core/sock.c +index cab041b57d2865..1c73b6841d0ae9 100644 +--- a/net/core/sock.c ++++ b/net/core/sock.c +@@ -2492,6 +2492,9 @@ struct sock *sk_clone(const struct sock *sk, const gfp_t priority, + sock_copy(newsk, sk); + + newsk->sk_prot_creator = prot; ++#ifdef CONFIG_BPF_SYSCALL ++ RCU_INIT_POINTER(newsk->sk_bpf_storage, NULL); ++#endif + + /* SANITY */ + if (likely(newsk->sk_net_refcnt)) { +-- +2.53.0 + diff --git a/queue-7.1/bpf-sockmap-reject-unhashed-udp-sockets-on-sockmap-u.patch b/queue-7.1/bpf-sockmap-reject-unhashed-udp-sockets-on-sockmap-u.patch new file mode 100644 index 0000000000..4fb404545f --- /dev/null +++ b/queue-7.1/bpf-sockmap-reject-unhashed-udp-sockets-on-sockmap-u.patch @@ -0,0 +1,74 @@ +From 07f1ac46874e0aea6b608029e041ab8614950da5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 7 Jul 2026 06:23:57 +0200 +Subject: bpf, sockmap: Reject unhashed UDP sockets on sockmap update + +From: Michal Luczaj + +[ Upstream commit 66efd3368ae10d05e08fbe6425b50fdec7186ac7 ] + +UDP sockets get SOCK_RCU_FREE set when (auto-)bound. This means +sk_is_refcounted(unbound) = true, while sk_is_refcounted(bound) = false. + +Because sockmap accepts unbound UDP sockets, a BPF program can increment a +socket's refcount via lookup. If the socket is subsequently bound, the +transition from unbound to bound causes bpf_sk_release() to skip the +decrement of the refcount, causing a memory leak. + +unreferenced object 0xffff88810bc2eb40 (size 1984): + comm "test_progs", pid 2451, jiffies 4295320596 + hex dump (first 32 bytes): + 7f 00 00 01 7f 00 00 01 d2 04 1b b7 04 d2 00 00 ................ + 02 00 01 40 00 00 00 00 00 00 00 00 00 00 00 00 ...@............ + backtrace (crc bdee079d): + kmem_cache_alloc_noprof+0x557/0x660 + sk_prot_alloc+0x69/0x240 + sk_alloc+0x30/0x460 + inet_create+0x2ce/0xf80 + __sock_create+0x25b/0x5c0 + __sys_socket+0x119/0x1d0 + __x64_sys_socket+0x72/0xd0 + do_syscall_64+0xa1/0x5f0 + entry_SYSCALL_64_after_hwframe+0x76/0x7e + +Instead of special-casing for refcounted sockets, reject unhashed UDP +sockets during sockmap updates, as there is no benefit to supporting those. +This effectively reverts the commit under Fixes, with two exceptions: + +1. sock_map_sk_state_allowed() maintains a fall-through `return true`. +2. In the spirit of commit b8b8315e39ff ("bpf, sockmap: Remove unhash + handler for BPF sockmap usage"), the proto::unhash BPF handler is not + reintroduced. + +Historical note: this issue is related to commit 67312adc96b5 ("bpf: reject +unhashed sockets in bpf_sk_assign"). + +Fixes: 0c48eefae712 ("sock_map: Lift socket state restriction for datagram sockets") +Suggested-by: Kuniyuki Iwashima +Signed-off-by: Michal Luczaj +Reviewed-by: Kuniyuki Iwashima +Reviewed-by: Jakub Sitnicki +Reviewed-by: John Fastabend +Link: https://lore.kernel.org/bpf/20260707-sockmap-lookup-udp-leak-v4-2-f878346f27ab@rbox.co +Signed-off-by: Kumar Kartikeya Dwivedi +Signed-off-by: Sasha Levin +--- + net/core/sock_map.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/net/core/sock_map.c b/net/core/sock_map.c +index 99e3789492a09e..9ece7bafe27c91 100644 +--- a/net/core/sock_map.c ++++ b/net/core/sock_map.c +@@ -542,6 +542,8 @@ static bool sock_map_sk_state_allowed(const struct sock *sk) + { + if (sk_is_tcp(sk)) + return (1 << sk->sk_state) & (TCPF_ESTABLISHED | TCPF_LISTEN); ++ if (sk_is_udp(sk)) ++ return sk_hashed(sk); + if (sk_is_stream_unix(sk)) + return (1 << READ_ONCE(sk->sk_state)) & TCPF_ESTABLISHED; + if (sk_is_vsock(sk) && +-- +2.53.0 + diff --git a/queue-7.1/btrfs-fallback-to-transaction-csum-tree-on-a-commit-.patch b/queue-7.1/btrfs-fallback-to-transaction-csum-tree-on-a-commit-.patch new file mode 100644 index 0000000000..c28efaf0a6 --- /dev/null +++ b/queue-7.1/btrfs-fallback-to-transaction-csum-tree-on-a-commit-.patch @@ -0,0 +1,92 @@ +From 10a4a4142c15f34a374f6659397c27a7da0eba45 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 11 Jun 2026 14:40:17 -0700 +Subject: btrfs: fallback to transaction csum tree on a commit root csum miss + +From: Boris Burkov + +[ Upstream commit 3dcd50730814e5220072d2b26d0587af6bfb6dbe ] + +We have been running with commit root csums enabled for some time and +have noticed a slight uptick in zero csum errors. Investigating those +revealed that they were same transaction reads of extents that were just +relocated, but the extent map generation was long ago. + +It turns out that relocation intentionally does not update the extent +generation (replace_file_extents()), but must write a new csum since the +data has moved, so we must account for this with commit root csum reading. + +Luckily this is a short lived condition: after the relocation transaction +the commit root will once again have the csum. So we can add a generic +fallback to the lookup to try again with the transaction csum root. + +Fixes: f07b855c56b1 ("btrfs: try to search for data csums in commit root") +Reviewed-by: Filipe Manana +Signed-off-by: Boris Burkov +Signed-off-by: David Sterba +Signed-off-by: Sasha Levin +--- + fs/btrfs/file-item.c | 26 +++++++++++++++++++++++++- + 1 file changed, 25 insertions(+), 1 deletion(-) + +diff --git a/fs/btrfs/file-item.c b/fs/btrfs/file-item.c +index d72249390030f4..e50b10b30c717b 100644 +--- a/fs/btrfs/file-item.c ++++ b/fs/btrfs/file-item.c +@@ -356,6 +356,7 @@ int btrfs_lookup_bio_sums(struct btrfs_bio *bbio) + const unsigned int nblocks = orig_len >> fs_info->sectorsize_bits; + int ret = 0; + u32 bio_offset = 0; ++ bool using_commit_root = false; + + if ((inode->flags & BTRFS_INODE_NODATASUM) || + test_bit(BTRFS_FS_STATE_NO_DATA_CSUMS, &fs_info->fs_state)) +@@ -429,6 +430,7 @@ int btrfs_lookup_bio_sums(struct btrfs_bio *bbio) + * from across transactions. + */ + if (bbio->csum_search_commit_root) { ++ using_commit_root = true; + path->search_commit_root = true; + path->skip_locking = true; + down_read(&fs_info->commit_root_sem); +@@ -461,6 +463,28 @@ int btrfs_lookup_bio_sums(struct btrfs_bio *bbio) + * assume this is the case. + */ + if (count == 0) { ++ /* ++ * If an extent is relocated in the current transaction ++ * then relocation writes a new csum without updating ++ * the extent map generation. Until the next commit, we ++ * will see a hole in that case, so we need to fallback ++ * to searching the transaction csum root. ++ * ++ * Note that a commit root lookup of a referenced extent can ++ * only miss, not return a stale csum. A freed extent's csum ++ * is deleted in the same transaction and its bytenr is not ++ * reusable until that transaction has committed and the ++ * extent is unpinned. ++ */ ++ if (using_commit_root) { ++ up_read(&fs_info->commit_root_sem); ++ using_commit_root = false; ++ path->search_commit_root = false; ++ path->skip_locking = false; ++ btrfs_release_path(path); ++ continue; ++ } ++ + memset(csum_dst, 0, csum_size); + count = 1; + +@@ -479,7 +503,7 @@ int btrfs_lookup_bio_sums(struct btrfs_bio *bbio) + bio_offset += count * sectorsize; + } + +- if (bbio->csum_search_commit_root) ++ if (using_commit_root) + up_read(&fs_info->commit_root_sem); + return ret; + } +-- +2.53.0 + diff --git a/queue-7.1/btrfs-fix-root-leak-if-its-reloc-root-is-unexpected-.patch b/queue-7.1/btrfs-fix-root-leak-if-its-reloc-root-is-unexpected-.patch new file mode 100644 index 0000000000..71fa87c04d --- /dev/null +++ b/queue-7.1/btrfs-fix-root-leak-if-its-reloc-root-is-unexpected-.patch @@ -0,0 +1,40 @@ +From 83e3ad031342a5352c01d5f61f397dc8a05d7339 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 11 Jun 2026 15:16:21 +0100 +Subject: btrfs: fix root leak if its reloc root is unexpected in + merge_reloc_roots() + +From: Filipe Manana + +[ Upstream commit ce6050bafb4e33377dc17fcc357736bfc351180c ] + +If we have an unexpected reloc_root for our root, we jump to the out label +but never drop the reference we obtained for root, resulting in a leak. +Add a missing btrfs_put_root() call. + +Fixes: 24213fa46c70 ("btrfs: do proper error handling in merge_reloc_roots") +Reviewed-by: Qu Wenruo +Reviewed-by: Johannes Thumshirn +Signed-off-by: Filipe Manana +Reviewed-by: David Sterba +Signed-off-by: David Sterba +Signed-off-by: Sasha Levin +--- + fs/btrfs/relocation.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c +index 3ebaf5880125fa..6c826be4174934 100644 +--- a/fs/btrfs/relocation.c ++++ b/fs/btrfs/relocation.c +@@ -1850,6 +1850,7 @@ void merge_reloc_roots(struct reloc_control *rc) + * corruption, e.g. bad reloc tree key offset. + */ + ret = -EINVAL; ++ btrfs_put_root(root); + goto out; + } + ret = merge_reloc_root(rc, root); +-- +2.53.0 + diff --git a/queue-7.1/btrfs-reject-free-space-cache-with-more-entries-than.patch b/queue-7.1/btrfs-reject-free-space-cache-with-more-entries-than.patch new file mode 100644 index 0000000000..b8b0505f47 --- /dev/null +++ b/queue-7.1/btrfs-reject-free-space-cache-with-more-entries-than.patch @@ -0,0 +1,88 @@ +From 221b95fcedd21f939091b9b1d6f5ba0697af46eb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 10 Jun 2026 10:29:26 -0700 +Subject: btrfs: reject free space cache with more entries than pages + +From: Xiang Mei + +[ Upstream commit a2d8d5647ed854e38f941741aea45b9eb15a6350 ] + +When loading a v1 free space cache, __load_free_space_cache() takes +num_entries and num_bitmaps straight from the on-disk +btrfs_free_space_header. That header is stored in the tree_root under a key +with type 0, which the tree-checker has no case for, so neither count is +validated before the load trusts it. + +The load loops num_entries times and maps the next page whenever the current +one runs out, going through io_ctl_check_crc() -> io_ctl_map_page(), which +does io_ctl->pages[io_ctl->index++]. But pages[] is allocated in +io_ctl_init() from the cache inode's i_size, not from num_entries: + + num_pages = DIV_ROUND_UP(i_size_read(inode), PAGE_SIZE); + io_ctl->pages = kcalloc(num_pages, sizeof(struct page *), GFP_NOFS); + +So if num_entries claims more records than the pages can hold, io_ctl->index +runs off the end of pages[]. The write side never hits this because +io_ctl_add_entry() and io_ctl_add_bitmap() both stop once +io_ctl->index >= io_ctl->num_pages; the read side just never had the same +check. + +To trigger it, take a clean cache (num_entries = here), set num_entries +in the header to 0x10000, and fix up the leaf checksum so it still passes +the tree-checker. The cache inode has i_size = 65536, so num_pages is 16 and +pages[] is a 16-pointer (kmalloc-128) array. The load now tries to read +65536 entries, io_ctl->index walks up to 16, and pages[16] is read past the +array: + + BUG: KASAN: slab-out-of-bounds in io_ctl_check_crc (fs/btrfs/free-space-cache.c:420 fs/btrfs/free-space-cache.c:565) + Read of size 8 at addr ffff88800c833a80 by task kworker/u8:3/58 + io_ctl_check_crc (fs/btrfs/free-space-cache.c:420 fs/btrfs/free-space-cache.c:565) + __load_free_space_cache (fs/btrfs/free-space-cache.c:655 fs/btrfs/free-space-cache.c:820) + load_free_space_cache (fs/btrfs/free-space-cache.c:1017) + caching_thread (fs/btrfs/block-group.c:880) + btrfs_work_helper (fs/btrfs/async-thread.c:312) + process_one_work + worker_thread + kthread + ret_from_fork + +free-space-cache.c:420 is io_ctl_map_page(), inlined into io_ctl_check_crc() +at line 565, which is why that is the frame KASAN names. The out-of-bounds +slot is then treated as a struct page and handed to crc32c(), so the bad +read turns into a GP fault. + +Add the missing check to io_ctl_check_crc(), which is where both the entry +loop and the bitmap loop end up. When num_entries is too large the load now +fails like any corrupt cache: __load_free_space_cache() drops it and rebuilds +the free space from the extent tree, so a valid cache is never rejected. + +Reported-by: Weiming Shi +Fixes: 5b0e95bf607d ("Btrfs: inline checksums into the disk free space cache") +Link: https://lore.kernel.org/linux-btrfs/CAPpSM+RMPByMCKXvM5QFKToxsyNccfuFLWMdD0mfd0wh2Ja62w@mail.gmail.com/ +Assisted-by: Claude:claude-opus-4-8 +Reviewed-by: Qu Wenruo +Signed-off-by: Xiang Mei +Reviewed-by: David Sterba +Signed-off-by: David Sterba +Signed-off-by: Sasha Levin +--- + fs/btrfs/free-space-cache.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c +index ab22e4f9ffdde0..bbc4db7fe74bbd 100644 +--- a/fs/btrfs/free-space-cache.c ++++ b/fs/btrfs/free-space-cache.c +@@ -555,6 +555,9 @@ static int io_ctl_check_crc(struct btrfs_io_ctl *io_ctl, int index) + u32 crc = ~(u32)0; + unsigned offset = 0; + ++ if (index >= io_ctl->num_pages) ++ return -EIO; ++ + if (index == 0) + offset = sizeof(u32) * io_ctl->num_pages; + +-- +2.53.0 + diff --git a/queue-7.1/can-j1939-fix-lockless-local-destination-check.patch b/queue-7.1/can-j1939-fix-lockless-local-destination-check.patch new file mode 100644 index 0000000000..19beb21ff5 --- /dev/null +++ b/queue-7.1/can-j1939-fix-lockless-local-destination-check.patch @@ -0,0 +1,81 @@ +From f3ff92f092cdf9b7237226e29f773b1582aec8db Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 7 May 2026 10:22:26 +0200 +Subject: can: j1939: fix lockless local-destination check + +From: Shuhao Fu + +[ Upstream commit e4e8af62adab2fdcca230006f829407a953070cd ] + +j1939_priv.ents[].nusers is documented as protected by priv->lock, and +its updates already happen under that lock. j1939_can_recv() also reads +it under read_lock_bh(). However, j1939_session_skb_queue() and +j1939_tp_send() still read priv->ents[da].nusers without taking the +lock. + +Those transport-side checks decide whether to set J1939_ECU_LOCAL_DST, so +they can race with j1939_local_ecu_get() and j1939_local_ecu_put() while +userspace is binding or releasing sockets concurrently with TP traffic. +This can misclassify TP/ETP sessions as local or remote and take the wrong +transport path. + +Fix both transport paths by routing the destination-locality check through +a helper that reads ents[].nusers under read_lock_bh(&priv->lock). + +Fixes: 9d71dd0c7009 ("can: add support of SAE J1939 protocol") +Signed-off-by: Shuhao Fu +Tested-by: Oleksij Rempel +Acked-by: Oleksij Rempel +Link: https://patch.msgid.link/20260419140614.GA4041240@chcpu16 +Signed-off-by: Marc Kleine-Budde +Signed-off-by: Sasha Levin +--- + net/can/j1939/transport.c | 18 ++++++++++++++---- + 1 file changed, 14 insertions(+), 4 deletions(-) + +diff --git a/net/can/j1939/transport.c b/net/can/j1939/transport.c +index df93d57907da7e..8a31cb23bc76d0 100644 +--- a/net/can/j1939/transport.c ++++ b/net/can/j1939/transport.c +@@ -351,6 +351,18 @@ static void j1939_session_skb_drop_old(struct j1939_session *session) + } + } + ++static bool j1939_address_is_local(struct j1939_priv *priv, u8 addr) ++{ ++ bool local = false; ++ ++ read_lock_bh(&priv->lock); ++ if (j1939_address_is_unicast(addr) && priv->ents[addr].nusers) ++ local = true; ++ read_unlock_bh(&priv->lock); ++ ++ return local; ++} ++ + void j1939_session_skb_queue(struct j1939_session *session, + struct sk_buff *skb) + { +@@ -359,8 +371,7 @@ void j1939_session_skb_queue(struct j1939_session *session, + + j1939_ac_fixup(priv, skb); + +- if (j1939_address_is_unicast(skcb->addr.da) && +- priv->ents[skcb->addr.da].nusers) ++ if (j1939_address_is_local(priv, skcb->addr.da)) + skcb->flags |= J1939_ECU_LOCAL_DST; + + skcb->flags |= J1939_ECU_LOCAL_SRC; +@@ -2038,8 +2049,7 @@ struct j1939_session *j1939_tp_send(struct j1939_priv *priv, + return ERR_PTR(ret); + + /* fix DST flags, it may be used there soon */ +- if (j1939_address_is_unicast(skcb->addr.da) && +- priv->ents[skcb->addr.da].nusers) ++ if (j1939_address_is_local(priv, skcb->addr.da)) + skcb->flags |= J1939_ECU_LOCAL_DST; + + /* src is always local, I'm sending ... */ +-- +2.53.0 + diff --git a/queue-7.1/can-raw-add-locking-for-raw-flags-bitfield.patch b/queue-7.1/can-raw-add-locking-for-raw-flags-bitfield.patch new file mode 100644 index 0000000000..c5709a0aa6 --- /dev/null +++ b/queue-7.1/can-raw-add-locking-for-raw-flags-bitfield.patch @@ -0,0 +1,172 @@ +From a19b39cf85ee94560a0eb3c2d049dd3d6301c131 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 7 May 2026 10:22:23 +0200 +Subject: can: raw: add locking for raw flags bitfield + +From: Oliver Hartkopp + +[ Upstream commit 1e5185c090589f4146d728ab36417d8a5419f127 ] + +With commit 890e5198a6e5 ("can: raw: use bitfields to store flags in +struct raw_sock") the formerly separate integer values have been integrated +into a single bitfield. This led to a read-modify-write operation when +changing a flag in raw_setsockopt() which now needs a locking to prevent +concurrent access. + +Instead of adding a lock/unlock hell in each of the flag manipulations this +patch introduces a wrapper for a new raw_setsockopt_locked() function +analogue to the isotp_setsockopt[_locked]() approach in net/can/isotp.c + +Fixes: 890e5198a6e5 ("can: raw: use bitfields to store flags in struct raw_sock") +Reported-by: Eulgyu Kim +Closes: https://lore.kernel.org/linux-can/20260503112200.22727-1-eulgyukim@snu.ac.kr/ +Tested-by: Eulgyu Kim +Signed-off-by: Oliver Hartkopp +Reviewed-by: Vincent Mailhol +Tested-by: Vincent Mailhol +Link: https://patch.msgid.link/20260504111928.41856-1-socketcan@hartkopp.net +[mkl: use Closes tag instead of Link] +Signed-off-by: Marc Kleine-Budde +Signed-off-by: Sasha Levin +--- + net/can/raw.c | 66 +++++++++++++++++++++++---------------------------- + 1 file changed, 30 insertions(+), 36 deletions(-) + +diff --git a/net/can/raw.c b/net/can/raw.c +index a26942e78e6887..82d9c0499c95fa 100644 +--- a/net/can/raw.c ++++ b/net/can/raw.c +@@ -562,8 +562,8 @@ static int raw_getname(struct socket *sock, struct sockaddr *uaddr, + return RAW_MIN_NAMELEN; + } + +-static int raw_setsockopt(struct socket *sock, int level, int optname, +- sockptr_t optval, unsigned int optlen) ++static int raw_setsockopt_locked(struct socket *sock, int optname, ++ sockptr_t optval, unsigned int optlen) + { + struct sock *sk = sock->sk; + struct raw_sock *ro = raw_sk(sk); +@@ -575,9 +575,6 @@ static int raw_setsockopt(struct socket *sock, int level, int optname, + int flag; + int err = 0; + +- if (level != SOL_CAN_RAW) +- return -EINVAL; +- + switch (optname) { + case CAN_RAW_FILTER: + if (optlen % sizeof(struct can_filter) != 0) +@@ -598,17 +595,11 @@ static int raw_setsockopt(struct socket *sock, int level, int optname, + return -EFAULT; + } + +- rtnl_lock(); +- lock_sock(sk); +- + dev = ro->dev; +- if (ro->bound && dev) { +- if (dev->reg_state != NETREG_REGISTERED) { +- if (count > 1) +- kfree(filter); +- err = -ENODEV; +- goto out_fil; +- } ++ if (ro->bound && dev && dev->reg_state != NETREG_REGISTERED) { ++ if (count > 1) ++ kfree(filter); ++ return -ENODEV; + } + + if (ro->bound) { +@@ -622,7 +613,7 @@ static int raw_setsockopt(struct socket *sock, int level, int optname, + if (err) { + if (count > 1) + kfree(filter); +- goto out_fil; ++ return err; + } + + /* remove old filter registrations */ +@@ -642,11 +633,6 @@ static int raw_setsockopt(struct socket *sock, int level, int optname, + } + ro->filter = filter; + ro->count = count; +- +- out_fil: +- release_sock(sk); +- rtnl_unlock(); +- + break; + + case CAN_RAW_ERR_FILTER: +@@ -658,16 +644,9 @@ static int raw_setsockopt(struct socket *sock, int level, int optname, + + err_mask &= CAN_ERR_MASK; + +- rtnl_lock(); +- lock_sock(sk); +- + dev = ro->dev; +- if (ro->bound && dev) { +- if (dev->reg_state != NETREG_REGISTERED) { +- err = -ENODEV; +- goto out_err; +- } +- } ++ if (ro->bound && dev && dev->reg_state != NETREG_REGISTERED) ++ return -ENODEV; + + /* remove current error mask */ + if (ro->bound) { +@@ -676,7 +655,7 @@ static int raw_setsockopt(struct socket *sock, int level, int optname, + err_mask); + + if (err) +- goto out_err; ++ return err; + + /* remove old err_mask registration */ + raw_disable_errfilter(sock_net(sk), dev, sk, +@@ -685,11 +664,6 @@ static int raw_setsockopt(struct socket *sock, int level, int optname, + + /* link new err_mask to the socket */ + ro->err_mask = err_mask; +- +- out_err: +- release_sock(sk); +- rtnl_unlock(); +- + break; + + case CAN_RAW_LOOPBACK: +@@ -769,6 +743,26 @@ static int raw_setsockopt(struct socket *sock, int level, int optname, + return err; + } + ++static int raw_setsockopt(struct socket *sock, int level, int optname, ++ sockptr_t optval, unsigned int optlen) ++{ ++ struct sock *sk = sock->sk; ++ int err; ++ ++ if (level != SOL_CAN_RAW) ++ return -EINVAL; ++ ++ rtnl_lock(); ++ lock_sock(sk); ++ ++ err = raw_setsockopt_locked(sock, optname, optval, optlen); ++ ++ release_sock(sk); ++ rtnl_unlock(); ++ ++ return err; ++} ++ + static int raw_getsockopt(struct socket *sock, int level, int optname, + sockopt_t *opt) + { +-- +2.53.0 + diff --git a/queue-7.1/cpufreq-make-cpufreq_update_pressure-fall-back-to-cp.patch b/queue-7.1/cpufreq-make-cpufreq_update_pressure-fall-back-to-cp.patch new file mode 100644 index 0000000000..d8c3f2d28b --- /dev/null +++ b/queue-7.1/cpufreq-make-cpufreq_update_pressure-fall-back-to-cp.patch @@ -0,0 +1,55 @@ +From b7fdce13dcc180f4eccbe55f009025b3d8bdd50d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 7 Jul 2026 19:25:39 +0200 +Subject: cpufreq: Make cpufreq_update_pressure() fall back to cpuinfo.max_freq + +From: Rafael J. Wysocki + +[ Upstream commit d2d5c129d07ea8eb91cd8a8633b5774116c4d171 ] + +If arch_scale_freq_ref() is not defined for a given arch (like x86, for +example), cpufreq_update_pressure() will always set cpufreq_pressure to +zero for all CPUs in the system, which is generally problematic on +systems with asymmetric capacity [1]. + +However, in the absence of arch_scale_freq_ref(), it is reasonable +to assume that cpuinfo.max_freq is the maximum sustainable frequency +for the given cpufreq policy. Moreover, there are cases in which +arch_scale_freq_ref() would need to be defined to return essentially +the cpuinfo.max_freq value anyway (for example, intel_pstate on +hybrid platforms). + +For the above reasons, update cpufreq_update_pressure() to fall back to +using cpuinfo.max_freq as the reference frequency if zero is returned by +arch_scale_freq_ref(). + +Fixes: 75d659317bb1 ("cpufreq: Add a cpufreq pressure feedback for the scheduler") +Link: https://lore.kernel.org/lkml/CAKfTPtBuRLfYNnR4w--cFZYZy-R8gaPEgVwCcaMmbCcJ2H-muQ@mail.gmail.com/ [1] +Signed-off-by: Rafael J. Wysocki +Acked-by: Viresh Kumar +Reviewed-by: Zhongqiu Han +Tested-by: Ricardo Neri # cluster scheduling +Acked-by: Vincent Guittot +Link: https://patch.msgid.link/5086499.GXAFRqVoOG@rafael.j.wysocki +Signed-off-by: Sasha Levin +--- + drivers/cpufreq/cpufreq.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c +index d41067cd1f1b25..2debe39fc477be 100644 +--- a/drivers/cpufreq/cpufreq.c ++++ b/drivers/cpufreq/cpufreq.c +@@ -2583,6 +2583,9 @@ static void cpufreq_update_pressure(struct cpufreq_policy *policy) + + cpu = cpumask_first(policy->related_cpus); + max_freq = arch_scale_freq_ref(cpu); ++ if (!max_freq) ++ max_freq = policy->cpuinfo.max_freq; ++ + capped_freq = policy->max; + + /* +-- +2.53.0 + diff --git a/queue-7.1/docs-admin-guide-cgroup-v2-fix-memory.stat-doc-detai.patch b/queue-7.1/docs-admin-guide-cgroup-v2-fix-memory.stat-doc-detai.patch new file mode 100644 index 0000000000..71f1ef8732 --- /dev/null +++ b/queue-7.1/docs-admin-guide-cgroup-v2-fix-memory.stat-doc-detai.patch @@ -0,0 +1,53 @@ +From 9f60f93aba6b635d57ef1b3a87f2ca42922bcb06 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 20 Jun 2026 12:27:51 +0000 +Subject: Docs/admin-guide/cgroup-v2: fix memory.stat doc details +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Doehyun Baek + +[ Upstream commit 46d65096ce8d278abf4528e254878c14ddd0b459 ] + +Fix minor cgroup v2 memory.stat documentation issues. Correct the +vmalloc per-node marker now that vmalloc uses the native NR_VMALLOC node +stat, and document zswap_incomp as a byte-valued memory amount instead +of as a page counter. + +Fixes: c466412c73c3 ("mm: memcontrol: switch to native NR_VMALLOC vmstat counter") +Fixes: 5ad41a38c364 ("mm: zswap: add per-memcg stat for incompressible pages") +Signed-off-by: Doehyun Baek +Reviewed-by: Nhat Pham +Acked-by: Michal Koutný +Signed-off-by: Tejun Heo +Signed-off-by: Sasha Levin +--- + Documentation/admin-guide/cgroup-v2.rst | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/Documentation/admin-guide/cgroup-v2.rst b/Documentation/admin-guide/cgroup-v2.rst +index 6efd0095ed995b..5cc33d87c3dffe 100644 +--- a/Documentation/admin-guide/cgroup-v2.rst ++++ b/Documentation/admin-guide/cgroup-v2.rst +@@ -1570,7 +1570,7 @@ The following nested keys are defined. + sock (npn) + Amount of memory used in network transmission buffers + +- vmalloc (npn) ++ vmalloc + Amount of memory used for vmap backed memory. + + shmem +@@ -1735,7 +1735,7 @@ The following nested keys are defined. + Number of pages written from zswap to swap. + + zswap_incomp +- Number of incompressible pages currently stored in zswap ++ Amount of memory used by incompressible pages currently stored in zswap + without compression. These pages could not be compressed to + a size smaller than PAGE_SIZE, so they are stored as-is. + +-- +2.53.0 + diff --git a/queue-7.1/dpll-fix-null-pointer-dereference-in-dpll_msg_add_pi.patch b/queue-7.1/dpll-fix-null-pointer-dereference-in-dpll_msg_add_pi.patch new file mode 100644 index 0000000000..b54e5b72cb --- /dev/null +++ b/queue-7.1/dpll-fix-null-pointer-dereference-in-dpll_msg_add_pi.patch @@ -0,0 +1,71 @@ +From 165fcdd2305162a2176e29984c9c75e0dc6ce452 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 10 Jul 2026 21:36:25 +0200 +Subject: dpll: fix NULL pointer dereference in dpll_msg_add_pin_ref_sync() + +From: Ivan Vecera + +[ Upstream commit d2e914a4a0d0f753dbae830264850d044026167c ] + +When a dpll_pin is shared across multiple dpll_device instances and +those devices are being unregistered (e.g. during driver module removal), +a NULL pointer dereference can occur in dpll_msg_add_pin_ref_sync(). + +This happens under the following conditions: + - A pin is registered with two or more dpll devices (dpll_A, dpll_B) + - The pin has ref_sync pairs with other pins + - During unregistration of dpll_A's pins, a ref_sync partner pin is + unregistered first, removing it from dpll_A->pin_refs + - But since the partner pin is still registered with dpll_B, its + dpll_refs is not empty, so dpll_pin_ref_sync_pair_del() does NOT + run and the partner stays in the pin's ref_sync_pins xarray + - When the pin itself is then unregistered from dpll_A, the delete + notification calls dpll_msg_add_pin_ref_sync() which finds the + partner in ref_sync_pins, passes dpll_pin_available() (partner is + still registered with dpll_B), but dpll_pin_on_dpll_priv(dpll_A, + partner) returns NULL because partner was already removed from + dpll_A->pin_refs + - The NULL priv pointer is passed to the driver's ref_sync_get + callback, which dereferences it + + BUG: kernel NULL pointer dereference, address: 0000000000000034 + Oops: Oops: 0000 [#1] SMP NOPTI + RIP: 0010:zl3073x_dpll_input_pin_ref_sync_get+0x73/0x80 [zl3073x] + Call Trace: + dpll_msg_add_pin_ref_sync+0xb8/0x200 + dpll_cmd_pin_get_one+0x3b6/0x4b0 + dpll_pin_event_send+0x72/0x140 + __dpll_pin_unregister+0x5a/0x2b0 + dpll_pin_unregister+0x49/0x70 + +Fix this by skipping ref_sync pins whose priv pointer cannot be resolved +for the current dpll device. + +Fixes: 58256a26bfb3 ("dpll: add reference sync get/set") +Signed-off-by: Ivan Vecera +Reviewed-by: Vadim Fedorenko +Reviewed-by: Jiri Pirko +Link: https://patch.msgid.link/20260710193625.1378822-1-ivecera@redhat.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/dpll/dpll_netlink.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/dpll/dpll_netlink.c b/drivers/dpll/dpll_netlink.c +index 75e3ae0c16d077..8163521188c06c 100644 +--- a/drivers/dpll/dpll_netlink.c ++++ b/drivers/dpll/dpll_netlink.c +@@ -557,6 +557,9 @@ dpll_msg_add_pin_ref_sync(struct sk_buff *msg, struct dpll_pin *pin, + if (!dpll_pin_available(ref_sync_pin)) + continue; + ref_sync_pin_priv = dpll_pin_on_dpll_priv(dpll, ref_sync_pin); ++ /* Pin may have been unregistered from this dpll already */ ++ if (!ref_sync_pin_priv) ++ continue; + if (WARN_ON(!ops->ref_sync_get)) + return -EOPNOTSUPP; + ret = ops->ref_sync_get(pin, pin_priv, ref_sync_pin, +-- +2.53.0 + diff --git a/queue-7.1/drm-i915-gt-use-correct-selftest-config-symbol.patch b/queue-7.1/drm-i915-gt-use-correct-selftest-config-symbol.patch new file mode 100644 index 0000000000..9366131d52 --- /dev/null +++ b/queue-7.1/drm-i915-gt-use-correct-selftest-config-symbol.patch @@ -0,0 +1,50 @@ +From 6cc50909b76c522a0ede033d895ce4c788c2dbd2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 5 Jul 2026 16:02:25 +0800 +Subject: drm/i915/gt: use correct selftest config symbol + +From: Pengpeng Hou + +[ Upstream commit a82f1bb8191aec98a971a2196136016ef70c0880 ] + +intel_engine_user.c checks CONFIG_DRM_I915_SELFTESTS before running +the engine UABI isolation check. Kconfig defines DRM_I915_SELFTEST, +without the trailing "S", and the rest of i915 uses +CONFIG_DRM_I915_SELFTEST. + +Because CONFIG_DRM_I915_SELFTESTS is not backed by any Kconfig symbol, +the IS_ENABLED() test is always false. Use the existing selftest symbol +so the debug/selftest guarded path can be reached when selftests are +enabled. + +This is a source-level fix. It does not claim dynamic hardware +reproduction; the evidence is the Kconfig definition and the inconsistent +guard in intel_engine_user.c. + +Fixes: 750e76b4f9f6 ("drm/i915/gt: Move the [class][inst] lookup for engines onto the GT") +Signed-off-by: Pengpeng Hou +Signed-off-by: Tvrtko Ursulin +Link: https://lore.kernel.org/r/20260705080225.436-1-pengpeng@iscas.ac.cn +(cherry picked from commit 14a2012a490258f3f93857bc4f1b203405964be7) +Signed-off-by: Rodrigo Vivi +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/i915/gt/intel_engine_user.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/i915/gt/intel_engine_user.c b/drivers/gpu/drm/i915/gt/intel_engine_user.c +index be4bbff1a57c9c..d5190e11b27062 100644 +--- a/drivers/gpu/drm/i915/gt/intel_engine_user.c ++++ b/drivers/gpu/drm/i915/gt/intel_engine_user.c +@@ -259,7 +259,7 @@ void intel_engines_driver_register(struct drm_i915_private *i915) + p = &prev->rb_right; + } + +- if (IS_ENABLED(CONFIG_DRM_I915_SELFTESTS) && ++ if (IS_ENABLED(CONFIG_DRM_I915_SELFTEST) && + IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM)) { + struct intel_engine_cs *engine; + unsigned int isolation; +-- +2.53.0 + diff --git a/queue-7.1/drm-i915-selftests-fix-gt-pm-sort-comparators.patch b/queue-7.1/drm-i915-selftests-fix-gt-pm-sort-comparators.patch new file mode 100644 index 0000000000..68ca1ea1ac --- /dev/null +++ b/queue-7.1/drm-i915-selftests-fix-gt-pm-sort-comparators.patch @@ -0,0 +1,55 @@ +From cb351d8683f64bf468f32873cf8235c4ec0901af Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 15 Jul 2026 01:04:30 +0300 +Subject: drm/i915/selftests: Fix GT PM sort comparators + +From: Emre Cecanpunar + +[ Upstream commit 612978b83f45bf7018815209db5395d759db6f26 ] + +Compare the sampled clock values instead of their addresses. Comparing +addresses leaves the samples unsorted, preventing the code from discarding +the minimum and maximum samples. + +Fixes: 1a5392479207 ("drm/i915/selftests: Measure CS_TIMESTAMP") +Signed-off-by: Emre Cecanpunar +Signed-off-by: Tvrtko Ursulin +Link: https://lore.kernel.org/r/20260714220430.238433-1-emreleno@gmail.com +(cherry picked from commit 682ea2d28d18bb06f9fc663cb5ab7e80dc0e606a) +Signed-off-by: Rodrigo Vivi +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/i915/gt/selftest_gt_pm.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/drivers/gpu/drm/i915/gt/selftest_gt_pm.c b/drivers/gpu/drm/i915/gt/selftest_gt_pm.c +index 33351deeea4f0b..07eaf71955c447 100644 +--- a/drivers/gpu/drm/i915/gt/selftest_gt_pm.c ++++ b/drivers/gpu/drm/i915/gt/selftest_gt_pm.c +@@ -16,9 +16,9 @@ static int cmp_u64(const void *A, const void *B) + { + const u64 *a = A, *b = B; + +- if (a < b) ++ if (*a < *b) + return -1; +- else if (a > b) ++ else if (*a > *b) + return 1; + else + return 0; +@@ -28,9 +28,9 @@ static int cmp_u32(const void *A, const void *B) + { + const u32 *a = A, *b = B; + +- if (a < b) ++ if (*a < *b) + return -1; +- else if (a > b) ++ else if (*a > *b) + return 1; + else + return 0; +-- +2.53.0 + diff --git a/queue-7.1/drm-i915-wm-clear-the-plane-ddb_y-entries-on-plane-d.patch b/queue-7.1/drm-i915-wm-clear-the-plane-ddb_y-entries-on-plane-d.patch new file mode 100644 index 0000000000..2e003e753d --- /dev/null +++ b/queue-7.1/drm-i915-wm-clear-the-plane-ddb_y-entries-on-plane-d.patch @@ -0,0 +1,41 @@ +From a091269771446f65f39d81b31a2d7e4bf4cc01b0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 15 Jun 2026 23:33:49 +0300 +Subject: drm/i915/wm: clear the plane ddb_y entries on plane disable + +From: Vinod Govindapillai + +[ Upstream commit e89978c1cff54e265345c66e1177d19ea5a8bc00 ] + +The UV/Y plane DDB entriess are never cleared on +sk_wm_plane_disable_noatomic() and can leave stale DDB state +for NV12 planes on pre-Gen11 devices + +Fixes: d34b59d5ba41 ("drm/i915: Add skl_wm_plane_disable_noatomic()") +Assisted-by: Copilot:claude-sonnet-4.6 +Signed-off-by: Vinod Govindapillai +Reviewed-by: Suraj Kandpal +Link: https://patch.msgid.link/20260615203355.218578-2-vinod.govindapillai@intel.com +(cherry picked from commit 60f68a6ba298fd1e971a2d91576304bee89a16fc) +Signed-off-by: Rodrigo Vivi +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/i915/display/skl_watermark.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/i915/display/skl_watermark.c b/drivers/gpu/drm/i915/display/skl_watermark.c +index e0ac4e2ce4dcb6..29b7661f88141d 100644 +--- a/drivers/gpu/drm/i915/display/skl_watermark.c ++++ b/drivers/gpu/drm/i915/display/skl_watermark.c +@@ -3908,7 +3908,7 @@ void skl_wm_plane_disable_noatomic(struct intel_crtc *crtc, + return; + + skl_ddb_entry_init(&crtc_state->wm.skl.plane_ddb[plane->id], 0, 0); +- skl_ddb_entry_init(&crtc_state->wm.skl.plane_ddb[plane->id], 0, 0); ++ skl_ddb_entry_init(&crtc_state->wm.skl.plane_ddb_y[plane->id], 0, 0); + + crtc_state->wm.skl.plane_min_ddb[plane->id] = 0; + crtc_state->wm.skl.plane_interim_ddb[plane->id] = 0; +-- +2.53.0 + diff --git a/queue-7.1/drm-panthor-check-debugfs-gem-lock-initialization.patch b/queue-7.1/drm-panthor-check-debugfs-gem-lock-initialization.patch new file mode 100644 index 0000000000..217bb125dd --- /dev/null +++ b/queue-7.1/drm-panthor-check-debugfs-gem-lock-initialization.patch @@ -0,0 +1,46 @@ +From ce3228a495604907c03b59645390ff52b2cefb98 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 13 Jul 2026 16:29:12 +0800 +Subject: drm/panthor: Check debugfs GEM lock initialization + +From: Linmao Li + +[ Upstream commit 022e901333c3054656a640794e842bab7af5a75c ] + +drmm_mutex_init() can fail while registering the managed cleanup action. +When that happens, drmm_add_action_or_reset() destroys the mutex before +returning the error. Continuing initialization would therefore leave the +debugfs GEM object list with an unusable lock. + +Propagate the error as is already done for the other managed mutexes in +panthor_device_init(). + +Fixes: a3707f53eb3f ("drm/panthor: show device-wide list of DRM GEM objects over DebugFS") +Signed-off-by: Linmao Li +Reviewed-by: Liviu Dudau +Link: https://patch.msgid.link/20260713082912.321021-1-lilinmao@kylinos.cn +Signed-off-by: Liviu Dudau +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/panthor/panthor_device.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/panthor/panthor_device.c b/drivers/gpu/drm/panthor/panthor_device.c +index 4f522a912d8968..48bb33bac36631 100644 +--- a/drivers/gpu/drm/panthor/panthor_device.c ++++ b/drivers/gpu/drm/panthor/panthor_device.c +@@ -207,7 +207,10 @@ int panthor_device_init(struct panthor_device *ptdev) + return ret; + + #ifdef CONFIG_DEBUG_FS +- drmm_mutex_init(&ptdev->base, &ptdev->gems.lock); ++ ret = drmm_mutex_init(&ptdev->base, &ptdev->gems.lock); ++ if (ret) ++ return ret; ++ + INIT_LIST_HEAD(&ptdev->gems.node); + #endif + +-- +2.53.0 + diff --git a/queue-7.1/drm-xe-assign-queue-name-in-time-for-drm_sched_init.patch b/queue-7.1/drm-xe-assign-queue-name-in-time-for-drm_sched_init.patch new file mode 100644 index 0000000000..8ddc55c169 --- /dev/null +++ b/queue-7.1/drm-xe-assign-queue-name-in-time-for-drm_sched_init.patch @@ -0,0 +1,192 @@ +From e8c09786377951b5fb7d430544dc18dd793b2665 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 23 May 2026 11:34:18 +0100 +Subject: drm/xe: Assign queue name in time for drm_sched_init + +From: Tvrtko Ursulin + +[ Upstream commit 24f60b8e9f44b10614b43dbc4ba4b029f8ede3b6 ] + +Currently the queue name is only assigned after the drm scheduler instance +has been created. This loses information with all logging or debug +workqueue facilities so lets re-order things a bit so the name gets +assigned in time. + +To be able to assign a GuC ID early we split the allocation into +reservation and publish phases. + +First, with the submission state lock held, we reserve the ID in the GuC +ID manager, which serves as an authoritative source of truth. Then we can +drop the lock and reserve entries in the exec queue lookup XArray. This +can be lockless since the NULL entries are invisible both to the kernel +and userspace. Only after the queue has been fully created we replace the +reserved entries with the queue pointer, which can be done locklessly for +single width queues. + +Signed-off-by: Tvrtko Ursulin +Cc: Matthew Brost +Cc: Rodrigo Vivi +Cc: Thomas Hellstrom +Reviewed-by: Rodrigo Vivi +Link: https://patch.msgid.link/20260523103418.61832-1-tvrtko.ursulin@igalia.com +Signed-off-by: Rodrigo Vivi +Stable-dep-of: 299bc6d50b1b ("drm/xe/guc: Keep scheduler timeline name alive") +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/xe/xe_guc_submit.c | 72 +++++++++++++++++------------- + 1 file changed, 40 insertions(+), 32 deletions(-) + +diff --git a/drivers/gpu/drm/xe/xe_guc_submit.c b/drivers/gpu/drm/xe/xe_guc_submit.c +index 42110e01b7d096..1752039d333f39 100644 +--- a/drivers/gpu/drm/xe/xe_guc_submit.c ++++ b/drivers/gpu/drm/xe/xe_guc_submit.c +@@ -397,46 +397,43 @@ void xe_guc_submit_disable(struct xe_guc *guc) + guc->submission_state.enabled = false; + } + +-static void __release_guc_id(struct xe_guc *guc, struct xe_exec_queue *q, u32 xa_count) ++static void __release_guc_id(struct xe_guc *guc, struct xe_exec_queue *q, ++ int count) + { + int i; + +- lockdep_assert_held(&guc->submission_state.lock); ++ mutex_lock(&guc->submission_state.lock); + +- for (i = 0; i < xa_count; ++i) +- xa_erase(&guc->submission_state.exec_queue_lookup, q->guc->id + i); ++ for (i = 0; i < count; ++i) ++ xa_erase(&guc->submission_state.exec_queue_lookup, ++ q->guc->id + i); + + xe_guc_id_mgr_release_locked(&guc->submission_state.idm, + q->guc->id, q->width); + + if (xa_empty(&guc->submission_state.exec_queue_lookup)) + wake_up(&guc->submission_state.fini_wq); ++ ++ mutex_unlock(&guc->submission_state.lock); + } + + static int alloc_guc_id(struct xe_guc *guc, struct xe_exec_queue *q) + { +- int ret; +- int i; +- +- /* +- * Must use GFP_NOWAIT as this lock is in the dma fence signalling path, +- * worse case user gets -ENOMEM on engine create and has to try again. +- * +- * FIXME: Have caller pre-alloc or post-alloc /w GFP_KERNEL to prevent +- * failure. +- */ +- lockdep_assert_held(&guc->submission_state.lock); ++ int ret, i; + ++ mutex_lock(&guc->submission_state.lock); + ret = xe_guc_id_mgr_reserve_locked(&guc->submission_state.idm, + q->width); ++ mutex_unlock(&guc->submission_state.lock); + if (ret < 0) + return ret; + + q->guc->id = ret; + ++ /* Reserve empty slots. */ + for (i = 0; i < q->width; ++i) { +- ret = xa_err(xa_store(&guc->submission_state.exec_queue_lookup, +- q->guc->id + i, q, GFP_NOWAIT)); ++ ret = xa_insert(&guc->submission_state.exec_queue_lookup, ++ q->guc->id + i, NULL, GFP_KERNEL); + if (ret) + goto err_release; + } +@@ -449,11 +446,24 @@ static int alloc_guc_id(struct xe_guc *guc, struct xe_exec_queue *q) + return ret; + } + ++static void publish_guc_id(struct xe_guc *guc, struct xe_exec_queue *q) ++{ ++ int i; ++ ++ lockdep_assert_held(&guc->submission_state.lock); ++ ++ for (i = 0; i < q->width; ++i) { ++ void *old; ++ ++ old = xa_store(&guc->submission_state.exec_queue_lookup, ++ q->guc->id + i, q, GFP_NOWAIT); ++ XE_WARN_ON(old || xa_is_err(old)); ++ } ++} ++ + static void release_guc_id(struct xe_guc *guc, struct xe_exec_queue *q) + { +- mutex_lock(&guc->submission_state.lock); + __release_guc_id(guc, q, q->width); +- mutex_unlock(&guc->submission_state.lock); + } + + struct exec_queue_policy { +@@ -1957,6 +1967,12 @@ static int guc_exec_queue_init(struct xe_exec_queue *q) + timeout = (q->vm && xe_vm_in_lr_mode(q->vm)) ? MAX_SCHEDULE_TIMEOUT : + msecs_to_jiffies(q->sched_props.job_timeout_ms); + ++ err = alloc_guc_id(guc, q); ++ if (err) ++ goto err_free; ++ ++ xe_exec_queue_assign_name(q, q->guc->id); ++ + /* + * Use primary queue's submit_wq for all secondary queues of a + * multi queue group. This serialization avoids any locking around +@@ -1973,28 +1989,21 @@ static int guc_exec_queue_init(struct xe_exec_queue *q) + timeout, guc_to_gt(guc)->ordered_wq, NULL, + q->name, gt_to_xe(q->gt)->drm.dev); + if (err) +- goto err_free; ++ goto err_release_id; + + sched = &ge->sched; + err = xe_sched_entity_init(&ge->entity, sched); + if (err) + goto err_sched; + +- mutex_lock(&guc->submission_state.lock); +- +- err = alloc_guc_id(guc, q); +- if (err) +- goto err_entity; +- + q->entity = &ge->entity; + ++ mutex_lock(&guc->submission_state.lock); + if (xe_guc_read_stopped(guc) || vf_recovery(guc)) + xe_sched_stop(sched); +- ++ publish_guc_id(guc, q); + mutex_unlock(&guc->submission_state.lock); + +- xe_exec_queue_assign_name(q, q->guc->id); +- + /* + * Maintain secondary queues of the multi queue group in a list + * for handling dependencies across the queues in the group. +@@ -2017,11 +2026,10 @@ static int guc_exec_queue_init(struct xe_exec_queue *q) + + return 0; + +-err_entity: +- mutex_unlock(&guc->submission_state.lock); +- xe_sched_entity_fini(&ge->entity); + err_sched: + xe_sched_fini(&ge->sched); ++err_release_id: ++ release_guc_id(guc, q); + err_free: + kfree(ge); + +-- +2.53.0 + diff --git a/queue-7.1/drm-xe-guc-hold-device-ref-until-queue-teardown-comp.patch b/queue-7.1/drm-xe-guc-hold-device-ref-until-queue-teardown-comp.patch new file mode 100644 index 0000000000..0438f70a0b --- /dev/null +++ b/queue-7.1/drm-xe-guc-hold-device-ref-until-queue-teardown-comp.patch @@ -0,0 +1,415 @@ +From 1b9160852d1ed247c508f5fae306c72c1d249b85 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 16 Jul 2026 11:56:24 +0530 +Subject: drm/xe/guc: Hold device ref until queue teardown completes +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Arvind Yadav + +[ Upstream commit 9b7e60184f4b22e893d4ae95234d5f26261a430c ] + +GuC exec queue destruction can run asynchronously. If the final device +put happens from a destroy worker, drmm cleanup can end up draining +the same workqueue and deadlock. + +Hold a drm_device reference for the queue lifetime and drop it after +queue teardown completes. This keeps drmm cleanup from running while +async destroy work is still pending. + +Move GuC destroy work to a module-lifetime Xe workqueue and flush it +on PCI remove so hot-unbind/rebind still waits for pending destroy work. + +With queue-held device refs, guc_submit_sw_fini() cannot run with live +GuC IDs. Replace the fini wait with an assertion and remove the unused +fini_wq. + +v2: + - Rebase + +v3: + - Switch to queue-lifetime drm_dev_get()/drm_dev_put() model. (Matt) + - Queue async teardown on system_dfl_wq instead of xe->destroy_wq. (Matt) + - Drop separate deferred drm_dev_put worker. + - Remove stale drain_workqueue(xe->destroy_wq) from guc_submit_sw_fini(). + +v4: + - Replace the guc_submit_sw_fini() wait with an assertion and remove + the now-unused fini_wq. (sashiko) + +v5: + - Move destroy work to a module-lifetime Xe workqueue instead of + system_dfl_wq. (Matt) + - Flush the module-lifetime destroy workqueue during PCI remove to + preserve the old device-remove wait semantics. + +v6: + - Keep SVM pagemap destroy work on the per-device destroy_wq to avoid + letting it outlive the xe_device/drm_device. (Sashiko) + - Use WQ_MEM_RECLAIM for xe->destroy_wq because SVM pagemap destroy work + can be queued from the reclaim path. + +v7: + - Drop the per-device xe->destroy_wq and use the module-level destroy WQ + for SVM pagemap destroy as well. (Matt) + - Rename xe_exec_queue_destroy_wq_*() helpers to xe_destroy_wq_*() + helpers because the WQ is no longer exec-queue specific. (Matt) + +v8: + - Rebase. + +v9: + - Keep SVM pagemap destroy work on the per-device WQ_MEM_RECLAIM + destroy_wq because it can be queued from reclaim and embeds + the dev_pagemap used by devres teardown. (Sashiko) + - Keep the module-level destroy WQ GuC-only and drop WQ_MEM_RECLAIM + from it. + - Update the module-WQ kdoc to document the GuC/SVM split. + +v10: + - Keep xe->destroy_wq per-cpu while adding WQ_MEM_RECLAIM to fix the + workqueue allocation warning. + +v11: + - Drop the SVM pagemap destroy comment as it was revision-specific. + (Thomas) + +v12: + - Rebase. + +Fixes: 2d2be279f1ca ("drm/xe: fix UAF around queue destruction") +Cc: Thomas Hellström +Cc: Rodrigo Vivi +Cc: Himal Prasad Ghimiray +Cc: Tejas Upadhyay +Reviewed-by: Matthew Brost +Signed-off-by: Arvind Yadav +Link: https://patch.msgid.link/20260716062624.211396-1-arvind.yadav@intel.com +Signed-off-by: Tejas Upadhyay +(cherry picked from commit da1124abac689cc2b1d8995e5f0a816f8a122edb) +Signed-off-by: Thomas Hellström +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/xe/xe_device.c | 2 +- + drivers/gpu/drm/xe/xe_device_types.h | 2 +- + drivers/gpu/drm/xe/xe_guc_submit.c | 66 ++++++++++++++++------------ + drivers/gpu/drm/xe/xe_guc_types.h | 2 - + drivers/gpu/drm/xe/xe_module.c | 49 +++++++++++++++++++++ + drivers/gpu/drm/xe/xe_module.h | 5 +++ + drivers/gpu/drm/xe/xe_pci.c | 6 +++ + 7 files changed, 100 insertions(+), 32 deletions(-) + +diff --git a/drivers/gpu/drm/xe/xe_device.c b/drivers/gpu/drm/xe/xe_device.c +index ffea4a453c01ca..991b0ea9218bb2 100644 +--- a/drivers/gpu/drm/xe/xe_device.c ++++ b/drivers/gpu/drm/xe/xe_device.c +@@ -509,7 +509,7 @@ struct xe_device *xe_device_create(struct pci_dev *pdev, + WQ_MEM_RECLAIM); + xe->ordered_wq = alloc_ordered_workqueue("xe-ordered-wq", 0); + xe->unordered_wq = alloc_workqueue("xe-unordered-wq", WQ_PERCPU, 0); +- xe->destroy_wq = alloc_workqueue("xe-destroy-wq", WQ_PERCPU, 0); ++ xe->destroy_wq = alloc_workqueue("xe-destroy-wq", WQ_PERCPU | WQ_MEM_RECLAIM, 0); + if (!xe->ordered_wq || !xe->unordered_wq || + !xe->preempt_fence_wq || !xe->destroy_wq) { + /* +diff --git a/drivers/gpu/drm/xe/xe_device_types.h b/drivers/gpu/drm/xe/xe_device_types.h +index 615218d775b14e..7e0901ac95c91d 100644 +--- a/drivers/gpu/drm/xe/xe_device_types.h ++++ b/drivers/gpu/drm/xe/xe_device_types.h +@@ -351,7 +351,7 @@ struct xe_device { + /** @unordered_wq: used to serialize unordered work */ + struct workqueue_struct *unordered_wq; + +- /** @destroy_wq: used to serialize user destroy work, like queue */ ++ /** @destroy_wq: used to serialize SVM pagemap destroy work */ + struct workqueue_struct *destroy_wq; + + /** @tiles: device tiles */ +diff --git a/drivers/gpu/drm/xe/xe_guc_submit.c b/drivers/gpu/drm/xe/xe_guc_submit.c +index 54606367eea3b3..b8465553aed2dc 100644 +--- a/drivers/gpu/drm/xe/xe_guc_submit.c ++++ b/drivers/gpu/drm/xe/xe_guc_submit.c +@@ -10,6 +10,7 @@ + #include + #include + ++#include + #include + + #include "abi/guc_actions_abi.h" +@@ -37,6 +38,7 @@ + #include "xe_macros.h" + #include "xe_map.h" + #include "xe_mocs.h" ++#include "xe_module.h" + #include "xe_pm.h" + #include "xe_ring_ops_types.h" + #include "xe_sched_job.h" +@@ -232,17 +234,9 @@ static bool exec_queue_killed_or_banned_or_wedged(struct xe_exec_queue *q) + static void guc_submit_sw_fini(struct drm_device *drm, void *arg) + { + struct xe_guc *guc = arg; +- struct xe_device *xe = guc_to_xe(guc); + struct xe_gt *gt = guc_to_gt(guc); +- int ret; +- +- ret = wait_event_timeout(guc->submission_state.fini_wq, +- xa_empty(&guc->submission_state.exec_queue_lookup), +- HZ * 5); + +- drain_workqueue(xe->destroy_wq); +- +- xe_gt_assert(gt, ret); ++ xe_gt_assert(gt, xa_empty(&guc->submission_state.exec_queue_lookup)); + + xa_destroy(&guc->submission_state.exec_queue_lookup); + } +@@ -319,8 +313,6 @@ int xe_guc_submit_init(struct xe_guc *guc, unsigned int num_ids) + + xa_init(&guc->submission_state.exec_queue_lookup); + +- init_waitqueue_head(&guc->submission_state.fini_wq); +- + primelockdep(guc); + + guc->submission_state.initialized = true; +@@ -411,9 +403,6 @@ static void __release_guc_id(struct xe_guc *guc, struct xe_exec_queue *q, + xe_guc_id_mgr_release_locked(&guc->submission_state.idm, + q->guc->id, q->width); + +- if (xa_empty(&guc->submission_state.exec_queue_lookup)) +- wake_up(&guc->submission_state.fini_wq); +- + mutex_unlock(&guc->submission_state.lock); + } + +@@ -1690,6 +1679,7 @@ static void guc_exec_queue_fini(struct xe_exec_queue *q) + { + struct xe_guc_exec_queue *ge = q->guc; + struct xe_guc *guc = exec_queue_to_guc(q); ++ struct drm_device *drm = &guc_to_xe(guc)->drm; + + if (xe_exec_queue_is_multi_queue_secondary(q)) { + struct xe_exec_queue_group *group = q->multi_queue.group; +@@ -1708,36 +1698,52 @@ static void guc_exec_queue_fini(struct xe_exec_queue *q) + * (timeline name). + */ + kfree_rcu(ge, rcu); ++ ++ drm_dev_put(drm); + } + +-static void __guc_exec_queue_destroy_async(struct work_struct *w) ++static void guc_exec_queue_do_destroy(struct xe_exec_queue *q) + { +- struct xe_guc_exec_queue *ge = +- container_of(w, struct xe_guc_exec_queue, destroy_async); +- struct xe_exec_queue *q = ge->q; ++ struct xe_guc_exec_queue *ge = q->guc; + struct xe_guc *guc = exec_queue_to_guc(q); ++ struct xe_device *xe = guc_to_xe(guc); ++ struct drm_device *drm = &xe->drm; + +- guard(xe_pm_runtime)(guc_to_xe(guc)); +- trace_xe_exec_queue_destroy(q); ++ /* ++ * guc_exec_queue_fini() drops the queue's drm_device ref. ++ * Keep the device alive until the PM-runtime guard unwinds. ++ */ ++ drm_dev_get(drm); + +- /* Confirm no work left behind accessing device structures */ +- cancel_delayed_work_sync(&ge->sched.base.work_tdr); ++ scoped_guard(xe_pm_runtime, xe) { ++ trace_xe_exec_queue_destroy(q); + +- xe_exec_queue_fini(q); ++ /* Confirm no work left behind accessing device structures */ ++ cancel_delayed_work_sync(&ge->sched.base.work_tdr); ++ ++ xe_exec_queue_fini(q); ++ } ++ ++ drm_dev_put(drm); + } + +-static void guc_exec_queue_destroy_async(struct xe_exec_queue *q) ++static void __guc_exec_queue_destroy_async(struct work_struct *w) + { +- struct xe_guc *guc = exec_queue_to_guc(q); +- struct xe_device *xe = guc_to_xe(guc); ++ struct xe_guc_exec_queue *ge = ++ container_of(w, struct xe_guc_exec_queue, destroy_async); ++ ++ guc_exec_queue_do_destroy(ge->q); ++} + ++static void guc_exec_queue_destroy_async(struct xe_exec_queue *q) ++{ + INIT_WORK(&q->guc->destroy_async, __guc_exec_queue_destroy_async); + + /* We must block on kernel engines so slabs are empty on driver unload */ + if (q->flags & EXEC_QUEUE_FLAG_PERMANENT || exec_queue_wedged(q)) +- __guc_exec_queue_destroy_async(&q->guc->destroy_async); ++ guc_exec_queue_do_destroy(q); + else +- queue_work(xe->destroy_wq, &q->guc->destroy_async); ++ xe_destroy_wq_queue(&q->guc->destroy_async); + } + + static void __guc_exec_queue_destroy(struct xe_guc *guc, struct xe_exec_queue *q) +@@ -1945,6 +1951,7 @@ static int guc_exec_queue_init(struct xe_exec_queue *q) + { + struct xe_gpu_scheduler *sched; + struct xe_guc *guc = exec_queue_to_guc(q); ++ struct drm_device *drm = &guc_to_xe(guc)->drm; + struct workqueue_struct *submit_wq = NULL; + struct xe_guc_exec_queue *ge; + long timeout; +@@ -1956,6 +1963,8 @@ static int guc_exec_queue_init(struct xe_exec_queue *q) + if (!ge) + return -ENOMEM; + ++ drm_dev_get(drm); ++ + q->guc = ge; + ge->q = q; + init_rcu_head(&ge->rcu); +@@ -2034,6 +2043,7 @@ static int guc_exec_queue_init(struct xe_exec_queue *q) + release_guc_id(guc, q); + err_free: + kfree(ge); ++ drm_dev_put(drm); + + return err; + } +diff --git a/drivers/gpu/drm/xe/xe_guc_types.h b/drivers/gpu/drm/xe/xe_guc_types.h +index c7b9642b41ba74..31a2acb63ac34d 100644 +--- a/drivers/gpu/drm/xe/xe_guc_types.h ++++ b/drivers/gpu/drm/xe/xe_guc_types.h +@@ -100,8 +100,6 @@ struct xe_guc { + * even initialized - before that not even the lock is valid + */ + bool initialized; +- /** @submission_state.fini_wq: submit fini wait queue */ +- wait_queue_head_t fini_wq; + } submission_state; + + /** @hwconfig: Hardware config state */ +diff --git a/drivers/gpu/drm/xe/xe_module.c b/drivers/gpu/drm/xe/xe_module.c +index 4cb57818291229..99347f216ec893 100644 +--- a/drivers/gpu/drm/xe/xe_module.c ++++ b/drivers/gpu/drm/xe/xe_module.c +@@ -7,6 +7,7 @@ + + #include + #include ++#include + + #include + +@@ -91,6 +92,50 @@ static int xe_check_nomodeset(void) + return 0; + } + ++static struct workqueue_struct *xe_destroy_wq; ++ ++static int __init xe_destroy_wq_module_init(void) ++{ ++ xe_destroy_wq = alloc_workqueue("xe-guc-destroy-wq", WQ_UNBOUND, 0); ++ if (!xe_destroy_wq) ++ return -ENOMEM; ++ return 0; ++} ++ ++static void xe_destroy_wq_module_exit(void) ++{ ++ if (xe_destroy_wq) ++ destroy_workqueue(xe_destroy_wq); ++ xe_destroy_wq = NULL; ++} ++ ++/** ++ * xe_destroy_wq_queue() - Queue work on the destroy workqueue ++ * @work: work item to queue ++ * ++ * The destroy workqueue has module lifetime and is used for GuC exec queue ++ * teardown that can outlive a single xe_device. SVM pagemap destroy uses the ++ * per-device xe->destroy_wq instead. ++ * ++ * Return: %true if @work was queued, %false if it was already pending. ++ */ ++bool xe_destroy_wq_queue(struct work_struct *work) ++{ ++ return queue_work(xe_destroy_wq, work); ++} ++ ++/** ++ * xe_destroy_wq_flush() - Flush the destroy workqueue ++ * ++ * Drains all pending destroy work. Called from PCI remove to ensure ++ * teardown ordering before the device is destroyed. ++ */ ++void xe_destroy_wq_flush(void) ++{ ++ if (xe_destroy_wq) ++ flush_workqueue(xe_destroy_wq); ++} ++ + struct init_funcs { + int (*init)(void); + void (*exit)(void); +@@ -112,6 +157,10 @@ static const struct init_funcs init_funcs[] = { + .init = xe_sched_job_module_init, + .exit = xe_sched_job_module_exit, + }, ++ { ++ .init = xe_destroy_wq_module_init, ++ .exit = xe_destroy_wq_module_exit, ++ }, + { + .init = xe_register_pci_driver, + .exit = xe_unregister_pci_driver, +diff --git a/drivers/gpu/drm/xe/xe_module.h b/drivers/gpu/drm/xe/xe_module.h +index 79cb9639c0f3df..e8e54f701cf3ee 100644 +--- a/drivers/gpu/drm/xe/xe_module.h ++++ b/drivers/gpu/drm/xe/xe_module.h +@@ -8,6 +8,8 @@ + + #include + ++struct work_struct; ++ + /* Module modprobe variables */ + struct xe_modparam { + bool force_execlist; +@@ -27,5 +29,8 @@ struct xe_modparam { + + extern struct xe_modparam xe_modparam; + ++bool xe_destroy_wq_queue(struct work_struct *work); ++void xe_destroy_wq_flush(void); ++ + #endif + +diff --git a/drivers/gpu/drm/xe/xe_pci.c b/drivers/gpu/drm/xe/xe_pci.c +index c2ecd27ec770a2..ad4955fe5ade7e 100644 +--- a/drivers/gpu/drm/xe/xe_pci.c ++++ b/drivers/gpu/drm/xe/xe_pci.c +@@ -1029,6 +1029,12 @@ static void xe_pci_remove(struct pci_dev *pdev) + return; + + xe_device_remove(xe); ++ ++ /* ++ * Preserve remove-time flush after moving destroy work to module ++ * lifetime. ++ */ ++ xe_destroy_wq_flush(); + xe_pm_fini(xe); + } + +-- +2.53.0 + diff --git a/queue-7.1/drm-xe-guc-keep-scheduler-timeline-name-alive.patch b/queue-7.1/drm-xe-guc-keep-scheduler-timeline-name-alive.patch new file mode 100644 index 0000000000..13913c41f2 --- /dev/null +++ b/queue-7.1/drm-xe-guc-keep-scheduler-timeline-name-alive.patch @@ -0,0 +1,85 @@ +From 887a612e8395e2eaf20faf3e67bfa22152967843 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 14 Jul 2026 12:14:02 +0530 +Subject: drm/xe/guc: Keep scheduler timeline name alive +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Arvind Yadav + +[ Upstream commit 299bc6d50b1bed7d1f408391736712f01a0855e2 ] + +The scheduler keeps a pointer to the timeline name, but q->name +is freed with the exec queue while scheduler fences can still +reference it. + +Store the name in struct xe_guc_exec_queue so it shares +the scheduler's RCU-deferred lifetime. + +Fixes: 6bd90e700b42 ("drm/xe: Make dma-fences compliant with the safe access rules") +Cc: Thomas Hellström +Cc: Rodrigo Vivi +Cc: Himal Prasad Ghimiray +Cc: Matthew Brost +Signed-off-by: Arvind Yadav +Reviewed-by: Tvrtko Ursulin +Acked-by: Matthew Brost +Link: https://patch.msgid.link/20260714064402.2457257-1-arvind.yadav@intel.com +Signed-off-by: Tejas Upadhyay +(cherry picked from commit 41075f0eb5dcbd3b065d15f15ef7bbe9315188e8) +Signed-off-by: Thomas Hellström +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/xe/xe_guc_exec_queue_types.h | 5 +++++ + drivers/gpu/drm/xe/xe_guc_submit.c | 4 +++- + 2 files changed, 8 insertions(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/xe/xe_guc_exec_queue_types.h b/drivers/gpu/drm/xe/xe_guc_exec_queue_types.h +index e5e53b421f29fb..cda14d954e572f 100644 +--- a/drivers/gpu/drm/xe/xe_guc_exec_queue_types.h ++++ b/drivers/gpu/drm/xe/xe_guc_exec_queue_types.h +@@ -10,6 +10,7 @@ + #include + + #include "xe_gpu_scheduler_types.h" ++#include "xe_hw_fence_types.h" + + struct dma_fence; + struct xe_exec_queue; +@@ -24,6 +25,10 @@ struct xe_guc_exec_queue { + struct rcu_head rcu; + /** @sched: GPU scheduler for this xe_exec_queue */ + struct xe_gpu_scheduler sched; ++ /** ++ * @name: Scheduler timeline name, kept with @sched until RCU free. ++ */ ++ char name[MAX_FENCE_NAME_LEN]; + /** @entity: Scheduler entity for this xe_exec_queue */ + struct xe_sched_entity entity; + /** +diff --git a/drivers/gpu/drm/xe/xe_guc_submit.c b/drivers/gpu/drm/xe/xe_guc_submit.c +index 1752039d333f39..54606367eea3b3 100644 +--- a/drivers/gpu/drm/xe/xe_guc_submit.c ++++ b/drivers/gpu/drm/xe/xe_guc_submit.c +@@ -1973,6 +1973,8 @@ static int guc_exec_queue_init(struct xe_exec_queue *q) + + xe_exec_queue_assign_name(q, q->guc->id); + ++ strscpy(ge->name, q->name, sizeof(ge->name)); ++ + /* + * Use primary queue's submit_wq for all secondary queues of a + * multi queue group. This serialization avoids any locking around +@@ -1987,7 +1989,7 @@ static int guc_exec_queue_init(struct xe_exec_queue *q) + err = xe_sched_init(&ge->sched, &drm_sched_ops, &xe_sched_ops, + submit_wq, xe_lrc_ring_size() / MAX_JOB_SIZE_BYTES, 64, + timeout, guc_to_gt(guc)->ordered_wq, NULL, +- q->name, gt_to_xe(q->gt)->drm.dev); ++ ge->name, gt_to_xe(q->gt)->drm.dev); + if (err) + goto err_release_id; + +-- +2.53.0 + diff --git a/queue-7.1/drm-xe-vf-fix-vf-ccs-attach-detach-race-with-in-flig.patch b/queue-7.1/drm-xe-vf-fix-vf-ccs-attach-detach-race-with-in-flig.patch new file mode 100644 index 0000000000..061ad6fa38 --- /dev/null +++ b/queue-7.1/drm-xe-vf-fix-vf-ccs-attach-detach-race-with-in-flig.patch @@ -0,0 +1,235 @@ +From 9cd76176faeb20c7478933f90e38ebd5492b48f3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 13 Jul 2026 23:24:40 -0700 +Subject: drm/xe/vf: Fix VF CCS attach/detach race with in-flight BO moves +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Matthew Brost + +[ Upstream commit 56441f9e08ad68697295b8835266d2bc48ab59b5 ] + +xe_bo_move() attaches VF CCS read/write batch buffers (BBs) to a BO +after it transitions NULL/SYSTEM -> TT, and detaches them after it +transitions TT -> SYSTEM. Both operations were done synchronously on +the CPU immediately after building the move's copy/clear fence, +without waiting for that fence to signal. This creates two races with +VF migration: + +- Attach happens too late relative to the copy job it is meant to + protect. If the copy job is submitted before the CCS BBs are + attached, a VF migration event that pauses execution mid-copy can + observe partially copied CCS metadata without the attach state + needed to correctly save/restore it. + +- Detach happens too early relative to the copy job that moves data + out of TT. The CCS BBs are torn down right after the copy fence is + obtained, while the actual blit may still be in flight. A VF + migration event that pauses execution mid-copy can then race the + save/restore path against the still-running blit, and the CCS BBs + it would need to make sense of the paused state have already been + removed. + +Fix both races: + +- Move the attach call to before the copy/clear job is submitted, so + the CCS BBs are already registered by the time the copy runs. On + attach failure, unwind and bail out of the move. xe_migrate_ccs_rw_copy() + now takes the destination resource explicitly, since bo->ttm.resource + is not updated to the new resource until after the move commits. + +- Detach only after explicitly waiting for the copy fence to signal, + instead of tearing down the CCS BBs immediately after obtaining it. + +While here, also fix xe_sriov_vf_ccs_attach_bo() to properly unwind and +propagate errors: the per-context loop previously never broke out on +error, silently discarding earlier failures. Unwind by clearing each +attached context directly via xe_migrate_ccs_rw_copy_clear() instead of +reusing xe_sriov_vf_ccs_detach_bo(), which requires both contexts to be +attached before it will clean up either one. + +Fixes: 864690cf4dd6 ("drm/xe/vf: Attach and detach CCS copy commands with BO") +Cc: Michal Wajdeczko +Cc: Matthew Auld +Cc: Michał Winiarski +Cc: Satyanarayana K V P +Assisted-by: GitHub_Copilot:claude-sonnet-5 +Signed-off-by: Matthew Brost +Acked-by: Satyanarayana K V P +Reviewed-by: Matthew Auld +Link: https://patch.msgid.link/20260714062440.3421225-1-matthew.brost@intel.com +(cherry picked from commit d45ad0aa7a1eb5d7288b5ed948b05695611dc39e) +Signed-off-by: Thomas Hellström +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/xe/xe_bo.c | 34 +++++++++++++++++++--------- + drivers/gpu/drm/xe/xe_migrate.c | 5 +++- + drivers/gpu/drm/xe/xe_migrate.h | 1 + + drivers/gpu/drm/xe/xe_sriov_vf_ccs.c | 20 ++++++++++++++-- + drivers/gpu/drm/xe/xe_sriov_vf_ccs.h | 3 ++- + 5 files changed, 48 insertions(+), 15 deletions(-) + +diff --git a/drivers/gpu/drm/xe/xe_bo.c b/drivers/gpu/drm/xe/xe_bo.c +index 6b518858538f57..261c38c9fa985a 100644 +--- a/drivers/gpu/drm/xe/xe_bo.c ++++ b/drivers/gpu/drm/xe/xe_bo.c +@@ -1109,6 +1109,21 @@ static int xe_bo_move(struct ttm_buffer_object *ttm_bo, bool evict, + xe_pm_runtime_get_noresume(xe); + } + ++ /* ++ * Attach CCS BBs before submitting the copy job below so a VF ++ * migration racing the copy sees valid, up to date attach state. ++ */ ++ if (IS_VF_CCS_READY(xe) && ++ ((move_lacks_source && new_mem->mem_type == XE_PL_TT) || ++ (old_mem_type == XE_PL_SYSTEM && new_mem->mem_type == XE_PL_TT)) && ++ handle_system_ccs) { ++ ret = xe_sriov_vf_ccs_attach_bo(bo, new_mem); ++ if (ret) { ++ xe_pm_runtime_put(xe); ++ goto out; ++ } ++ } ++ + if (move_lacks_source) { + u32 flags = 0; + +@@ -1146,22 +1161,19 @@ static int xe_bo_move(struct ttm_buffer_object *ttm_bo, bool evict, + ttm_bo_move_null(ttm_bo, new_mem); + } + +- dma_fence_put(fence); +- xe_pm_runtime_put(xe); +- + /* +- * CCS meta data is migrated from TT -> SMEM. So, let us detach the +- * BBs from BO as it is no longer needed. ++ * Detach must wait for the copy above to complete: a VF migration ++ * racing an in-flight copy must still see valid CCS BBs, so don't ++ * tear them down until the copy fence has signaled. + */ + if (IS_VF_CCS_READY(xe) && old_mem_type == XE_PL_TT && +- new_mem->mem_type == XE_PL_SYSTEM) ++ new_mem->mem_type == XE_PL_SYSTEM) { ++ dma_fence_wait(fence, false); + xe_sriov_vf_ccs_detach_bo(bo); ++ } + +- if (IS_VF_CCS_READY(xe) && +- ((move_lacks_source && new_mem->mem_type == XE_PL_TT) || +- (old_mem_type == XE_PL_SYSTEM && new_mem->mem_type == XE_PL_TT)) && +- handle_system_ccs) +- ret = xe_sriov_vf_ccs_attach_bo(bo); ++ dma_fence_put(fence); ++ xe_pm_runtime_put(xe); + + out: + if ((!ttm_bo->resource || ttm_bo->resource->mem_type == XE_PL_SYSTEM) && +diff --git a/drivers/gpu/drm/xe/xe_migrate.c b/drivers/gpu/drm/xe/xe_migrate.c +index a22413f892a096..f4160e844b4c33 100644 +--- a/drivers/gpu/drm/xe/xe_migrate.c ++++ b/drivers/gpu/drm/xe/xe_migrate.c +@@ -1145,6 +1145,8 @@ static int emit_flush_invalidate(u32 *dw, int i, u32 flags) + * @tile: Tile whose migration context to be used. + * @q : Execution to be used along with migration context. + * @src_bo: The buffer object @src is currently bound to. ++ * @new_mem: The (not yet committed) destination resource @src_bo is being ++ * moved into; src_bo->ttm.resource is still the old resource. + * @read_write : Creates BB commands for CCS read/write. + * + * Creates batch buffer instructions to copy CCS metadata from CCS pool to +@@ -1156,12 +1158,13 @@ static int emit_flush_invalidate(u32 *dw, int i, u32 flags) + */ + int xe_migrate_ccs_rw_copy(struct xe_tile *tile, struct xe_exec_queue *q, + struct xe_bo *src_bo, ++ struct ttm_resource *new_mem, + enum xe_sriov_vf_ccs_rw_ctxs read_write) + + { + bool src_is_pltt = read_write == XE_SRIOV_VF_CCS_READ_CTX; + bool dst_is_pltt = read_write == XE_SRIOV_VF_CCS_WRITE_CTX; +- struct ttm_resource *src = src_bo->ttm.resource; ++ struct ttm_resource *src = new_mem; + struct xe_migrate *m = tile->migrate; + struct xe_gt *gt = tile->primary_gt; + u32 batch_size, batch_size_allocated; +diff --git a/drivers/gpu/drm/xe/xe_migrate.h b/drivers/gpu/drm/xe/xe_migrate.h +index 169279d9d8c247..7761c02b4d86d6 100644 +--- a/drivers/gpu/drm/xe/xe_migrate.h ++++ b/drivers/gpu/drm/xe/xe_migrate.h +@@ -138,6 +138,7 @@ struct dma_fence *xe_migrate_resolve(struct xe_migrate *m, + + int xe_migrate_ccs_rw_copy(struct xe_tile *tile, struct xe_exec_queue *q, + struct xe_bo *src_bo, ++ struct ttm_resource *new_mem, + enum xe_sriov_vf_ccs_rw_ctxs read_write); + + void xe_migrate_ccs_rw_copy_clear(struct xe_bo *src_bo, +diff --git a/drivers/gpu/drm/xe/xe_sriov_vf_ccs.c b/drivers/gpu/drm/xe/xe_sriov_vf_ccs.c +index 09b99fb2608bce..6787564629c65f 100644 +--- a/drivers/gpu/drm/xe/xe_sriov_vf_ccs.c ++++ b/drivers/gpu/drm/xe/xe_sriov_vf_ccs.c +@@ -404,6 +404,8 @@ void xe_sriov_vf_ccs_rw_update_bb_addr(struct xe_sriov_vf_ccs_ctx *ctx) + /** + * xe_sriov_vf_ccs_attach_bo - Insert CCS read write commands in the BO. + * @bo: the &buffer object to which batch buffer commands will be added. ++ * @new_mem: the (not yet committed) destination resource @bo is being moved ++ * into; bo->ttm.resource is still the old resource at this point. + * + * This function shall be called only by VF. It inserts the PTEs and copy + * command instructions in the BO by calling xe_migrate_ccs_rw_copy() +@@ -411,7 +413,7 @@ void xe_sriov_vf_ccs_rw_update_bb_addr(struct xe_sriov_vf_ccs_ctx *ctx) + * + * Returns: 0 if successful, negative error code on failure. + */ +-int xe_sriov_vf_ccs_attach_bo(struct xe_bo *bo) ++int xe_sriov_vf_ccs_attach_bo(struct xe_bo *bo, struct ttm_resource *new_mem) + { + struct xe_device *xe = xe_bo_device(bo); + enum xe_sriov_vf_ccs_rw_ctxs ctx_id; +@@ -430,7 +432,21 @@ int xe_sriov_vf_ccs_attach_bo(struct xe_bo *bo) + xe_assert(xe, !bb); + + ctx = &xe->sriov.vf.ccs.contexts[ctx_id]; +- err = xe_migrate_ccs_rw_copy(tile, ctx->mig_q, bo, ctx_id); ++ err = xe_migrate_ccs_rw_copy(tile, ctx->mig_q, bo, new_mem, ctx_id); ++ if (err) ++ goto err_unwind; ++ } ++ return 0; ++ ++err_unwind: ++ /* ++ * Clean up any contexts already attached. Can't reuse ++ * xe_sriov_vf_ccs_detach_bo() here as it requires both contexts ++ * attached before cleaning up either one. ++ */ ++ for_each_ccs_rw_ctx(ctx_id) { ++ if (bo->bb_ccs[ctx_id]) ++ xe_migrate_ccs_rw_copy_clear(bo, ctx_id); + } + return err; + } +diff --git a/drivers/gpu/drm/xe/xe_sriov_vf_ccs.h b/drivers/gpu/drm/xe/xe_sriov_vf_ccs.h +index 00e58b36c510ac..e1034d85210406 100644 +--- a/drivers/gpu/drm/xe/xe_sriov_vf_ccs.h ++++ b/drivers/gpu/drm/xe/xe_sriov_vf_ccs.h +@@ -11,11 +11,12 @@ + #include "xe_sriov_vf_ccs_types.h" + + struct drm_printer; ++struct ttm_resource; + struct xe_device; + struct xe_bo; + + int xe_sriov_vf_ccs_init(struct xe_device *xe); +-int xe_sriov_vf_ccs_attach_bo(struct xe_bo *bo); ++int xe_sriov_vf_ccs_attach_bo(struct xe_bo *bo, struct ttm_resource *new_mem); + int xe_sriov_vf_ccs_detach_bo(struct xe_bo *bo); + int xe_sriov_vf_ccs_register_context(struct xe_device *xe); + void xe_sriov_vf_ccs_rebase(struct xe_device *xe); +-- +2.53.0 + diff --git a/queue-7.1/drm-xe-wopcm-fix-wopcm-size-for-lnl.patch b/queue-7.1/drm-xe-wopcm-fix-wopcm-size-for-lnl.patch new file mode 100644 index 0000000000..6bcf3a7f9d --- /dev/null +++ b/queue-7.1/drm-xe-wopcm-fix-wopcm-size-for-lnl.patch @@ -0,0 +1,71 @@ +From 108e5ed9c2fccd519c31f2631750ccc33e155a74 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 13 Jul 2026 15:17:59 -0700 +Subject: drm/xe/wopcm: fix WOPCM size for LNL+ +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Daniele Ceraolo Spurio + +[ Upstream commit ad87e2476b3b246580f407afc8ffa91d621bc849 ] + +Starting on LNL the WOPCM size is 8MB instead of 4, so we need to avoid +using the [0, 8MB) range of the GGTT as that can be unaccessible from +the microcontrollers. + +Note that the proper long-term fix here is to read the WOPCM size from +the HW, but that is a more serious rework that would be difficult to +backport, so we can do that as a follow-up. + +Fixes: 9c57bc08652a ("drm/xe/lnl: Drop force_probe requirement") +Signed-off-by: Daniele Ceraolo Spurio +Cc: Rodrigo Vivi +Cc: Shuicheng Lin +Cc: Matt Roper +Reviewed-by: Shuicheng Lin +Link: https://patch.msgid.link/20260713221758.3285744-2-daniele.ceraolospurio@intel.com +(cherry picked from commit 3033b0b24ed0e2f5e56bdd4d9c183417c365a45b) +Signed-off-by: Thomas Hellström +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/xe/xe_wopcm.c | 15 ++++++++++----- + 1 file changed, 10 insertions(+), 5 deletions(-) + +diff --git a/drivers/gpu/drm/xe/xe_wopcm.c b/drivers/gpu/drm/xe/xe_wopcm.c +index 900daf1d1b1bb5..fe65ed246775d9 100644 +--- a/drivers/gpu/drm/xe/xe_wopcm.c ++++ b/drivers/gpu/drm/xe/xe_wopcm.c +@@ -49,9 +49,9 @@ + */ + + /* Default WOPCM size is 2MB from Gen11, 1MB on previous platforms */ +-/* FIXME: Larger size require for 2 tile PVC, do a proper probe sooner or later */ ++/* FIXME: Larger size require for some platforms, do a proper probe sooner or later */ + #define DGFX_WOPCM_SIZE SZ_4M +-/* FIXME: Larger size require for MTL, do a proper probe sooner or later */ ++#define LNL_WOPCM_SIZE SZ_8M + #define MTL_WOPCM_SIZE SZ_4M + #define WOPCM_SIZE SZ_2M + +@@ -179,9 +179,14 @@ static int __wopcm_init_regs(struct xe_device *xe, struct xe_gt *gt, + + u32 xe_wopcm_size(struct xe_device *xe) + { +- return IS_DGFX(xe) ? DGFX_WOPCM_SIZE : +- xe->info.platform == XE_METEORLAKE ? MTL_WOPCM_SIZE : +- WOPCM_SIZE; ++ if (xe->info.platform >= XE_LUNARLAKE) ++ return LNL_WOPCM_SIZE; ++ else if (IS_DGFX(xe)) ++ return DGFX_WOPCM_SIZE; ++ else if (xe->info.platform == XE_METEORLAKE) ++ return MTL_WOPCM_SIZE; ++ else ++ return WOPCM_SIZE; + } + + static u32 max_wopcm_size(struct xe_device *xe) +-- +2.53.0 + diff --git a/queue-7.1/erofs-relax-sanity-check-for-tail-pclusters-due-to-z.patch b/queue-7.1/erofs-relax-sanity-check-for-tail-pclusters-due-to-z.patch new file mode 100644 index 0000000000..425ec625d9 --- /dev/null +++ b/queue-7.1/erofs-relax-sanity-check-for-tail-pclusters-due-to-z.patch @@ -0,0 +1,45 @@ +From cf2f0c2e3957fc9f3f7d749475f1700e601a57f9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 8 Jul 2026 11:18:45 +0800 +Subject: erofs: relax sanity check for tail pclusters due to ztailpacking + +From: Gao Xiang + +[ Upstream commit d3386e17393bec1341cfeedb9d08d6846ccd6fb2 ] + +If the tail data can be inlined into the inode meta block, it should +be converted into a regular tail pcluster. + +In principle, it should be converted into an uncompressed pcluster if +there is not enough gain to use compression (map->m_llen < map->m_plen); +but since there are various shipped images, relax the condition for +ztailpacking tail pcluster fallback instead of reporting corruption +incorrectly. + +Reported-and-tested-by: Yifan Zhao +Reported-by: Alberto Salvia Novella +Closes: https://github.com/erofs/erofs-utils/issues/51 +Fixes: a5242d37c83a ("erofs: error out obviously illegal extents in advance") +Signed-off-by: Gao Xiang +Signed-off-by: Sasha Levin +--- + fs/erofs/zmap.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/fs/erofs/zmap.c b/fs/erofs/zmap.c +index e1a02a2c8406bf..53e8a9f2fb9109 100644 +--- a/fs/erofs/zmap.c ++++ b/fs/erofs/zmap.c +@@ -721,7 +721,8 @@ static int z_erofs_map_sanity_check(struct inode *inode, + map->m_algorithmformat, EROFS_I(inode)->nid); + return -EFSCORRUPTED; + } +- if (EROFS_MAP_FULL(map->m_flags) && map->m_llen < map->m_plen) { ++ if (EROFS_MAP_FULL(map->m_flags) && map->m_llen < map->m_plen && ++ map->m_la + map->m_llen < inode->i_size) { + erofs_err(inode->i_sb, "too much compressed data @ la %llu of nid %llu", + map->m_la, EROFS_I(inode)->nid); + return -EFSCORRUPTED; +-- +2.53.0 + diff --git a/queue-7.1/firmware-arm_ffa-fix-endpoint-memory-access-descript.patch b/queue-7.1/firmware-arm_ffa-fix-endpoint-memory-access-descript.patch new file mode 100644 index 0000000000..376cab6df6 --- /dev/null +++ b/queue-7.1/firmware-arm_ffa-fix-endpoint-memory-access-descript.patch @@ -0,0 +1,93 @@ +From 42880e05ffd19ac3e703d7e495ddd2583190956f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 2 Jul 2026 10:38:39 +0000 +Subject: firmware: arm_ffa: Fix Endpoint Memory Access Descriptor offset + calculation + +From: Sebastian Ene + +[ Upstream commit b4d961351aa84fdf0148783fb1f3a1391b8a0adb ] + +Use the descriptor's `ep_mem_offset` to calculate the start of the endpoint +memory access array and to comply with the FF-A spec instead of defaulting +to `sizeof(struct ffa_mem_region)`. +This requires moving `ffa_mem_region_additional_setup()` earlier in the setup +flow. +Also, add sanity checks to ensure the calculated descriptor offsets do not +exceed `max_fragsize`. + +Fixes: 113580530ee7 ("firmware: arm_ffa: Update memory descriptor to support v1.1 format") +Reviewed-by: Sudeep Holla +Signed-off-by: Mostafa Saleh +Signed-off-by: Sebastian Ene +Link: https://patch.msgid.link/20260702103848.1647249-3-sebastianene@google.com +Signed-off-by: Marc Zyngier +Signed-off-by: Sasha Levin +--- + drivers/firmware/arm_ffa/driver.c | 20 +++++++++++++++----- + include/linux/arm_ffa.h | 2 +- + 2 files changed, 16 insertions(+), 6 deletions(-) + +diff --git a/drivers/firmware/arm_ffa/driver.c b/drivers/firmware/arm_ffa/driver.c +index c9e3d0f246913c..4cbf7537e6242d 100644 +--- a/drivers/firmware/arm_ffa/driver.c ++++ b/drivers/firmware/arm_ffa/driver.c +@@ -711,19 +711,30 @@ ffa_setup_and_transmit(u32 func_id, void *buffer, u32 max_fragsize, + struct ffa_composite_mem_region *composite; + struct ffa_mem_region_addr_range *constituents; + struct ffa_mem_region_attributes *ep_mem_access; +- u32 idx, frag_len, length, buf_sz = 0, num_entries = sg_nents(args->sg); ++ u32 idx, frag_len, length, buf_sz = 0, num_entries = sg_nents(args->sg), ep_offset; ++ u32 emad_end, emad_size = ffa_emad_size_get(drv_info->version); + + mem_region->tag = args->tag; + mem_region->flags = args->flags; + mem_region->sender_id = drv_info->vm_id; + mem_region->attributes = ffa_memory_attributes_get(func_id); ++ ++ ffa_mem_region_additional_setup(drv_info->version, mem_region); + composite_offset = ffa_mem_desc_offset(buffer, args->nattrs, + drv_info->version); ++ if (composite_offset + sizeof(*composite) > max_fragsize) ++ return -ENXIO; + + for (idx = 0; idx < args->nattrs; idx++) { +- ep_mem_access = buffer + +- ffa_mem_desc_offset(buffer, idx, drv_info->version); +- memset(ep_mem_access, 0, ffa_emad_size_get(drv_info->version)); ++ ep_offset = ffa_mem_desc_offset(buffer, idx, drv_info->version); ++ if (check_add_overflow(ep_offset, emad_size, &emad_end)) ++ return -ENXIO; ++ ++ if (emad_end > max_fragsize) ++ return -ENXIO; ++ ++ ep_mem_access = buffer + ep_offset; ++ memset(ep_mem_access, 0, emad_size); + ep_mem_access->receiver = args->attrs[idx].receiver; + ep_mem_access->attrs = args->attrs[idx].attrs; + ep_mem_access->composite_off = composite_offset; +@@ -733,7 +744,6 @@ ffa_setup_and_transmit(u32 func_id, void *buffer, u32 max_fragsize, + } + mem_region->handle = 0; + mem_region->ep_count = args->nattrs; +- ffa_mem_region_additional_setup(drv_info->version, mem_region); + + composite = buffer + composite_offset; + composite->total_pg_cnt = ffa_get_num_pages_sg(args->sg); +diff --git a/include/linux/arm_ffa.h b/include/linux/arm_ffa.h +index 81e603839c4a51..62d67dae8b7033 100644 +--- a/include/linux/arm_ffa.h ++++ b/include/linux/arm_ffa.h +@@ -445,7 +445,7 @@ ffa_mem_desc_offset(struct ffa_mem_region *buf, int count, u32 ffa_version) + if (!FFA_MEM_REGION_HAS_EP_MEM_OFFSET(ffa_version)) + offset += offsetof(struct ffa_mem_region, ep_mem_offset); + else +- offset += sizeof(struct ffa_mem_region); ++ offset += buf->ep_mem_offset; + + return offset; + } +-- +2.53.0 + diff --git a/queue-7.1/firmware-arm_ffa-fix-null-dereference-in-ffa_partiti.patch b/queue-7.1/firmware-arm_ffa-fix-null-dereference-in-ffa_partiti.patch new file mode 100644 index 0000000000..92055f8ff7 --- /dev/null +++ b/queue-7.1/firmware-arm_ffa-fix-null-dereference-in-ffa_partiti.patch @@ -0,0 +1,48 @@ +From 601e3e4c18b72da8525a194463a679c34fce91ea Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 17 Jun 2026 16:35:00 -0700 +Subject: firmware: arm_ffa: Fix NULL dereference in ffa_partition_info_get() + +From: Unnathi Chalicheemala + +[ Upstream commit 8ae5f8e4836667fcaffdf2e3c6068b0a8b364dd8 ] + +ffa_partition_info_get() passes uuid_str directly to uuid_parse() +without a NULL check. When a caller passes NULL, uuid_parse() -> +__uuid_parse() -> uuid_is_valid() dereferences the pointer, causing +a kernel panic: + + | Unable to handle kernel NULL pointer dereference at virtual address + | 0000000000000040 + | pc : uuid_parse+0x40/0xac + | lr : ffa_partition_info_get+0x1c/0x94 [arm_ffa] + +Add a NULL guard before uuid_parse() so a NULL argument returns +-ENODEV instead of crashing. Callers are expected to always supply +a valid partition UUID, so NULL is not a supported input. + +Fixes: d0c0bce83122 ("firmware: arm_ffa: Setup in-kernel users of FFA partitions") +Signed-off-by: Unnathi Chalicheemala +Link: https://patch.msgid.link/20260617-ffa_partition_nullptr_fix-v2-1-bc801b4ce34c@oss.qualcomm.com +Signed-off-by: Sudeep Holla +Signed-off-by: Sasha Levin +--- + drivers/firmware/arm_ffa/driver.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/firmware/arm_ffa/driver.c b/drivers/firmware/arm_ffa/driver.c +index e2438ca09da24b..ea0671180a16d9 100644 +--- a/drivers/firmware/arm_ffa/driver.c ++++ b/drivers/firmware/arm_ffa/driver.c +@@ -1137,7 +1137,7 @@ static int ffa_partition_info_get(const char *uuid_str, + uuid_t uuid; + struct ffa_partition_info *pbuf; + +- if (uuid_parse(uuid_str, &uuid)) { ++ if (!uuid_str || uuid_parse(uuid_str, &uuid)) { + pr_err("invalid uuid (%s)\n", uuid_str); + return -ENODEV; + } +-- +2.53.0 + diff --git a/queue-7.1/firmware-arm_ffa-fix-out-of-bound-writes-in-ffa_setu.patch b/queue-7.1/firmware-arm_ffa-fix-out-of-bound-writes-in-ffa_setu.patch new file mode 100644 index 0000000000..227646f954 --- /dev/null +++ b/queue-7.1/firmware-arm_ffa-fix-out-of-bound-writes-in-ffa_setu.patch @@ -0,0 +1,72 @@ +From 48dfc2f64ca877f73a5067e2c72ee4597615c037 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 2 Jul 2026 10:38:38 +0000 +Subject: firmware: arm_ffa: Fix out-of-bound writes in + ffa_setup_and_transmit() + +From: Mostafa Saleh + +[ Upstream commit 3383ffb7ef937317361713ffcc21921a7848511a ] + +Sashiko (locally) reports multiple out-of-bound issues in +ffa_setup_and_transmit: +1) Writing ep_mem_access->reserved can write out of bounds for FFA + versions < 1.2 as ffa_emad_size_get() returns 16 bytes in that case + while reserved has an offset of 24. + Instead of zeroing fields, memset the struct to zero first based on + the FFA version. + +2) Make sure there is enough size to write constituents. + +While at it, convert the only sizeof() in the driver that uses a +type instead of variable. + +Reviewed-by: Sudeep Holla +Fixes: 111a833dc5cb ("firmware: arm_ffa: Set reserved/MBZ fields to zero in the memory descriptors") +Signed-off-by: Mostafa Saleh +Signed-off-by: Sebastian Ene +Link: https://patch.msgid.link/20260702103848.1647249-2-sebastianene@google.com +Signed-off-by: Marc Zyngier +Signed-off-by: Sasha Levin +--- + drivers/firmware/arm_ffa/driver.c | 7 +++---- + 1 file changed, 3 insertions(+), 4 deletions(-) + +diff --git a/drivers/firmware/arm_ffa/driver.c b/drivers/firmware/arm_ffa/driver.c +index ea0671180a16d9..c9e3d0f246913c 100644 +--- a/drivers/firmware/arm_ffa/driver.c ++++ b/drivers/firmware/arm_ffa/driver.c +@@ -723,11 +723,10 @@ ffa_setup_and_transmit(u32 func_id, void *buffer, u32 max_fragsize, + for (idx = 0; idx < args->nattrs; idx++) { + ep_mem_access = buffer + + ffa_mem_desc_offset(buffer, idx, drv_info->version); ++ memset(ep_mem_access, 0, ffa_emad_size_get(drv_info->version)); + ep_mem_access->receiver = args->attrs[idx].receiver; + ep_mem_access->attrs = args->attrs[idx].attrs; + ep_mem_access->composite_off = composite_offset; +- ep_mem_access->flag = 0; +- ep_mem_access->reserved = 0; + ffa_emad_impdef_value_init(drv_info->version, + ep_mem_access->impdef_val, + args->attrs[idx].impdef_val); +@@ -767,7 +766,7 @@ ffa_setup_and_transmit(u32 func_id, void *buffer, u32 max_fragsize, + constituents = buffer; + } + +- if ((void *)constituents - buffer > max_fragsize) { ++ if ((void *)constituents + sizeof(*constituents) - buffer > max_fragsize) { + pr_err("Memory Region Fragment > Tx Buffer size\n"); + return -EFAULT; + } +@@ -776,7 +775,7 @@ ffa_setup_and_transmit(u32 func_id, void *buffer, u32 max_fragsize, + constituents->pg_cnt = args->sg->length / FFA_PAGE_SIZE; + constituents->reserved = 0; + constituents++; +- frag_len += sizeof(struct ffa_mem_region_addr_range); ++ frag_len += sizeof(*constituents); + } while ((args->sg = sg_next(args->sg))); + + return ffa_transmit_fragment(func_id, addr, buf_sz, frag_len, +-- +2.53.0 + diff --git a/queue-7.1/firmware-arm_ffa-respect-firmware-advertised-rx-tx-b.patch b/queue-7.1/firmware-arm_ffa-respect-firmware-advertised-rx-tx-b.patch new file mode 100644 index 0000000000..cdf81925b7 --- /dev/null +++ b/queue-7.1/firmware-arm_ffa-respect-firmware-advertised-rx-tx-b.patch @@ -0,0 +1,118 @@ +From 7a4d9262663a59e4cf9272051d39ce7bee7ffe3b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 2 Jun 2026 21:54:06 +0000 +Subject: firmware: arm_ffa: Respect firmware advertised RX/TX buffer size + limits + +From: Seth Forshee + +[ Upstream commit 53716a4d745f1dac7aff33f3d1494b701eb2f888 ] + +FFA_FEATURES reports the minimum size and alignment boundary required +for RXTX_MAP. In FF-A v1.2 and later it can also report a maximum buffer +size, with zero meaning that no maximum is enforced. + +The driver only used the minimum value and then rounded it up to PAGE_SIZE +before invoking RXTX_MAP after commit 83210251fd70 ("firmware: arm_ffa: +Use the correct buffer size during RXTX_MAP"). On systems where PAGE_SIZE +is larger than the advertised minimum, this can exceed a non-zero maximum +reported by firmware. Older implementations do not advertise a maximum and +may also reject the rounded-up size. + +Decode the maximum size and clamp the page-aligned minimum to it when it +is present. If no maximum is advertised and RXTX_MAP rejects the rounded +size with INVALID_PARAMETERS, retry with the advertised minimum size. +Record drv_info->rxtx_bufsz only after RXTX_MAP succeeds so it reflects +the size registered with firmware. + +While there, also update RXTX_MAP_MIN_BUFSZ() to use FIELD_GET() for +consistency. + +Fixes: 83210251fd70 ("firmware: arm_ffa: Use the correct buffer size during RXTX_MAP") +Suggested-by: Sudeep Holla +Signed-off-by: Seth Forshee +Link: https://patch.msgid.link/20260602-b4-ffa-rxtx-map-fixes-v2-1-7cb06508da84@nvidia.com +(sudeep.holla: Minor rewording subject and commit message) +Signed-off-by: Sudeep Holla +Signed-off-by: Sasha Levin +--- + drivers/firmware/arm_ffa/driver.c | 27 ++++++++++++++++++++------- + 1 file changed, 20 insertions(+), 7 deletions(-) + +diff --git a/drivers/firmware/arm_ffa/driver.c b/drivers/firmware/arm_ffa/driver.c +index cab32cfdac4236..e2438ca09da24b 100644 +--- a/drivers/firmware/arm_ffa/driver.c ++++ b/drivers/firmware/arm_ffa/driver.c +@@ -32,6 +32,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -55,7 +56,9 @@ + (FIELD_PREP(SENDER_ID_MASK, (s)) | FIELD_PREP(RECEIVER_ID_MASK, (r))) + + #define RXTX_MAP_MIN_BUFSZ_MASK GENMASK(1, 0) +-#define RXTX_MAP_MIN_BUFSZ(x) ((x) & RXTX_MAP_MIN_BUFSZ_MASK) ++#define RXTX_MAP_MAX_BUFSZ_MASK GENMASK(31, 16) ++#define RXTX_MAP_MIN_BUFSZ(x) (FIELD_GET(RXTX_MAP_MIN_BUFSZ_MASK, (x))) ++#define RXTX_MAP_MAX_BUFSZ(x) (FIELD_GET(RXTX_MAP_MAX_BUFSZ_MASK, (x))) + + #define FFA_MAX_NOTIFICATIONS 64 + +@@ -2095,7 +2098,7 @@ static int __init ffa_init(void) + { + int ret; + u32 buf_sz; +- size_t rxtx_bufsz = SZ_4K; ++ size_t rxtx_min_bufsz = SZ_4K, rxtx_max_bufsz = 0, rxtx_bufsz; + + ret = ffa_transport_init(&invoke_ffa_fn); + if (ret) +@@ -2118,15 +2121,18 @@ static int __init ffa_init(void) + ret = ffa_features(FFA_FN_NATIVE(RXTX_MAP), 0, &buf_sz, NULL); + if (!ret) { + if (RXTX_MAP_MIN_BUFSZ(buf_sz) == 1) +- rxtx_bufsz = SZ_64K; ++ rxtx_min_bufsz = SZ_64K; + else if (RXTX_MAP_MIN_BUFSZ(buf_sz) == 2) +- rxtx_bufsz = SZ_16K; ++ rxtx_min_bufsz = SZ_16K; + else +- rxtx_bufsz = SZ_4K; ++ rxtx_min_bufsz = SZ_4K; ++ ++ rxtx_max_bufsz = RXTX_MAP_MAX_BUFSZ(buf_sz) * SZ_4K; ++ if (rxtx_max_bufsz != 0 && rxtx_max_bufsz < rxtx_min_bufsz) ++ rxtx_max_bufsz = rxtx_min_bufsz; + } + +- rxtx_bufsz = PAGE_ALIGN(rxtx_bufsz); +- drv_info->rxtx_bufsz = rxtx_bufsz; ++ rxtx_bufsz = min_not_zero(PAGE_ALIGN(rxtx_min_bufsz), rxtx_max_bufsz); + drv_info->rx_buffer = alloc_pages_exact(rxtx_bufsz, GFP_KERNEL); + if (!drv_info->rx_buffer) { + ret = -ENOMEM; +@@ -2142,10 +2148,17 @@ static int __init ffa_init(void) + ret = ffa_rxtx_map(virt_to_phys(drv_info->tx_buffer), + virt_to_phys(drv_info->rx_buffer), + rxtx_bufsz / FFA_PAGE_SIZE); ++ if (ret == -EINVAL && !rxtx_max_bufsz && rxtx_min_bufsz < rxtx_bufsz) { ++ rxtx_bufsz = rxtx_min_bufsz; ++ ret = ffa_rxtx_map(virt_to_phys(drv_info->tx_buffer), ++ virt_to_phys(drv_info->rx_buffer), ++ rxtx_bufsz / FFA_PAGE_SIZE); ++ } + if (ret) { + pr_err("failed to register FFA RxTx buffers\n"); + goto free_pages; + } ++ drv_info->rxtx_bufsz = rxtx_bufsz; + + mutex_init(&drv_info->rx_lock); + mutex_init(&drv_info->tx_lock); +-- +2.53.0 + diff --git a/queue-7.1/firmware-arm_scmi-rate-limit-queue-full-warnings-in-.patch b/queue-7.1/firmware-arm_scmi-rate-limit-queue-full-warnings-in-.patch new file mode 100644 index 0000000000..01addc5946 --- /dev/null +++ b/queue-7.1/firmware-arm_scmi-rate-limit-queue-full-warnings-in-.patch @@ -0,0 +1,54 @@ +From 825bf576b206300c39fc7d59893baad62ed03b3d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 8 Jul 2026 12:53:39 +0530 +Subject: firmware: arm_scmi: Rate-limit queue-full warnings in IRQ context + +From: Pushpendra Singh + +[ Upstream commit a4447c0693830d5ecadd6e755cb7fdc55d86aacc ] + +The scmi_notify() function is called from interrupt context to queue +received notification events onto a per-protocol kfifo. When the kfifo +is full, it logs a warning via dev_warn() for every dropped event. + +Under conditions where the platform sends a burst of SCMI notifications +faster than the deferred worker can drain the queue, this results in a +flood of dev_warn() calls from IRQ context. Each call acquires the +console lock and may execute blocking console writes, causing the CPU +to be held in interrupt context for an extended period and leading to +observable system stalls. + +Fix this by switching to dev_warn_ratelimited() to limit the frequency +of log messages when the notification queue is full. This reduces +console overhead in interrupt context and prevents CPU stalls caused by +excessive logging, while still preserving diagnostic visibility. + +Fixes: bd31b249692e ("firmware: arm_scmi: Add notification dispatch and delivery") +Signed-off-by: Pushpendra Singh +Link: https://patch.msgid.link/20260708072339.3021140-1-pushpendra.singh@oss.qualcomm.com +Signed-off-by: Sudeep Holla +Signed-off-by: Sasha Levin +--- + drivers/firmware/arm_scmi/notify.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/firmware/arm_scmi/notify.c b/drivers/firmware/arm_scmi/notify.c +index 40ec184eedaecc..0a192cf2deab62 100644 +--- a/drivers/firmware/arm_scmi/notify.c ++++ b/drivers/firmware/arm_scmi/notify.c +@@ -600,9 +600,9 @@ int scmi_notify(const struct scmi_handle *handle, u8 proto_id, u8 evt_id, + return -EINVAL; + } + if (kfifo_avail(&r_evt->proto->equeue.kfifo) < sizeof(eh) + len) { +- dev_warn(handle->dev, +- "queue full, dropping proto_id:%d evt_id:%d ts:%lld\n", +- proto_id, evt_id, ktime_to_ns(ts)); ++ dev_warn_ratelimited(handle->dev, ++ "queue full, dropping proto_id:%d evt_id:%d ts:%lld\n", ++ proto_id, evt_id, ktime_to_ns(ts)); + return -ENOMEM; + } + +-- +2.53.0 + diff --git a/queue-7.1/ib-mad-drop-unmatched-rmpp-responses-before-reassemb.patch b/queue-7.1/ib-mad-drop-unmatched-rmpp-responses-before-reassemb.patch new file mode 100644 index 0000000000..317f1468e1 --- /dev/null +++ b/queue-7.1/ib-mad-drop-unmatched-rmpp-responses-before-reassemb.patch @@ -0,0 +1,90 @@ +From 7e8784dcda18217f0ff477deb27ee98ab28c86e5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 6 Jun 2026 16:01:55 -0400 +Subject: IB/mad: Drop unmatched RMPP responses before reassembly + +From: Michael Bommarito + +[ Upstream commit d2e52d610b9b09694261632340b801a421e0b0c5 ] + +Kernel-handled RMPP receive processing starts reassembly for active +DATA responses before the response is matched to an outstanding send. +The normal match happens later, after ib_process_rmpp_recv_wc() has +either assembled a complete message or consumed the segment. + +That ordering lets an unsolicited response that routes to a kernel +RMPP agent by the high TID bits allocate or extend RMPP receive state +before the full TID and source address are checked against a real +request. A reordered burst can therefore reach the receive-side +insertion path even though the response would not match any send. + +For kernel-handled RMPP DATA responses, require the existing +ib_find_send_mad() match before entering RMPP reassembly. The matcher +already checks the full TID, management class and source address/GID +against the agent wait, backlog and in-flight send lists. If there is +no match, drop the response without creating RMPP state. + +This leaves the RMPP window behavior unchanged and only rejects +responses that have no corresponding request. + +Fixes: fa619a77046b ("[PATCH] IB: Add RMPP implementation") +Assisted-by: Codex:gpt-5-5-xhigh +Signed-off-by: Michael Bommarito +Link: https://patch.msgid.link/3170ff3bc389a930bb1641f2caa394a0b2241579.1780774907.git.michael.bommarito@gmail.com +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + drivers/infiniband/core/mad.c | 30 ++++++++++++++++++++++++++++++ + 1 file changed, 30 insertions(+) + +diff --git a/drivers/infiniband/core/mad.c b/drivers/infiniband/core/mad.c +index 8d19613179e3ee..e0b3b36b8b1496 100644 +--- a/drivers/infiniband/core/mad.c ++++ b/drivers/infiniband/core/mad.c +@@ -2031,6 +2031,24 @@ void ib_mark_mad_done(struct ib_mad_send_wr_private *mad_send_wr) + change_mad_state(mad_send_wr, IB_MAD_STATE_EARLY_RESP); + } + ++static bool is_kernel_rmpp_data_response(struct ib_mad_agent_private *agent, ++ struct ib_mad_recv_wc *mad_recv_wc) ++{ ++ const struct ib_mad_hdr *mad_hdr = &mad_recv_wc->recv_buf.mad->mad_hdr; ++ struct ib_rmpp_mad *rmpp_mad; ++ ++ if (!ib_mad_kernel_rmpp_agent(&agent->agent) || ++ !ib_response_mad(mad_hdr) || ++ !ib_is_mad_class_rmpp(mad_hdr->mgmt_class)) ++ return false; ++ ++ rmpp_mad = (struct ib_rmpp_mad *)mad_recv_wc->recv_buf.mad; ++ ++ return (ib_get_rmpp_flags(&rmpp_mad->rmpp_hdr) & ++ IB_MGMT_RMPP_FLAG_ACTIVE) && ++ rmpp_mad->rmpp_hdr.rmpp_type == IB_MGMT_RMPP_TYPE_DATA; ++} ++ + static void ib_mad_complete_recv(struct ib_mad_agent_private *mad_agent_priv, + struct ib_mad_recv_wc *mad_recv_wc) + { +@@ -2050,6 +2068,18 @@ static void ib_mad_complete_recv(struct ib_mad_agent_private *mad_agent_priv, + } + + list_add(&mad_recv_wc->recv_buf.list, &mad_recv_wc->rmpp_list); ++ if (is_kernel_rmpp_data_response(mad_agent_priv, mad_recv_wc)) { ++ spin_lock_irqsave(&mad_agent_priv->lock, flags); ++ mad_send_wr = ib_find_send_mad(mad_agent_priv, mad_recv_wc); ++ spin_unlock_irqrestore(&mad_agent_priv->lock, flags); ++ ++ if (!mad_send_wr) { ++ ib_free_recv_mad(mad_recv_wc); ++ deref_mad_agent(mad_agent_priv); ++ return; ++ } ++ } ++ + if (ib_mad_kernel_rmpp_agent(&mad_agent_priv->agent)) { + mad_recv_wc = ib_process_rmpp_recv_wc(mad_agent_priv, + mad_recv_wc); +-- +2.53.0 + diff --git a/queue-7.1/ipv4-fib-free-fib_alias-with-kfree_rcu-on-insert-err.patch b/queue-7.1/ipv4-fib-free-fib_alias-with-kfree_rcu-on-insert-err.patch new file mode 100644 index 0000000000..4923a3c467 --- /dev/null +++ b/queue-7.1/ipv4-fib-free-fib_alias-with-kfree_rcu-on-insert-err.patch @@ -0,0 +1,67 @@ +From 0edc2d979a81e7e5884dc405d2dea63c6b0c962b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 4 Jul 2026 10:14:21 -0700 +Subject: ipv4: fib: free fib_alias with kfree_rcu() on insert error path + +From: Weiming Shi + +[ Upstream commit f2f152e94a67bc746afaf05a1b2702c195553112 ] + +fib_table_insert() publishes new_fa into the leaf's fa_list with +fib_insert_alias() before calling the fib entry notifiers. When a +notifier fails, the error path removes new_fa with fib_remove_alias() +(hlist_del_rcu) and frees it right away with kmem_cache_free(). + +fib_table_lookup() walks that list under rcu_read_lock() only, so a +concurrent lookup that already reached new_fa keeps reading it after the +free: + + BUG: KASAN: slab-use-after-free in fib_table_lookup (net/ipv4/fib_trie.c:1601) + Read of size 1 at addr ffff88810676d4eb by task exploit/297 + Call Trace: + fib_table_lookup (net/ipv4/fib_trie.c:1601) + ip_route_output_key_hash_rcu (net/ipv4/route.c:2814) + ip_route_output_key_hash (net/ipv4/route.c:2705) + __ip4_datagram_connect (net/ipv4/datagram.c:49) + udp_connect (net/ipv4/udp.c:2144) + __sys_connect (net/socket.c:2167) + __x64_sys_connect (net/socket.c:2173) + do_syscall_64 + entry_SYSCALL_64_after_hwframe + which belongs to the cache ip_fib_alias of size 56 + +Triggering the error path needs CAP_NET_ADMIN and a registered fib +notifier that can reject a route; a netdevsim device whose IPv4 FIB +resource is exhausted is enough. + +Free new_fa with alias_free_mem_rcu(), as fib_table_delete() already +does for a fib_alias removed from the trie. + +Fixes: a6c76c17df02 ("ipv4: Notify route after insertion to the routing table") +Reported-by: Xiang Mei +Assisted-by: Claude:claude-opus-4-8 +Signed-off-by: Weiming Shi +Reviewed-by: Ido Schimmel +Link: https://patch.msgid.link/20260704171421.1786806-1-bestswngs@gmail.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/ipv4/fib_trie.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c +index dac543c1d6867a..9bf5550e2fb734 100644 +--- a/net/ipv4/fib_trie.c ++++ b/net/ipv4/fib_trie.c +@@ -1385,7 +1385,7 @@ int fib_table_insert(struct net *net, struct fib_table *tb, + out_remove_new_fa: + fib_remove_alias(t, tp, l, new_fa); + out_free_new_fa: +- kmem_cache_free(fn_alias_kmem, new_fa); ++ alias_free_mem_rcu(new_fa); + out: + fib_release_info(fi); + err: +-- +2.53.0 + diff --git a/queue-7.1/ksmbd-pin-conn-during-async-oplock-break-notificatio.patch b/queue-7.1/ksmbd-pin-conn-during-async-oplock-break-notificatio.patch new file mode 100644 index 0000000000..6d55a3516c --- /dev/null +++ b/queue-7.1/ksmbd-pin-conn-during-async-oplock-break-notificatio.patch @@ -0,0 +1,75 @@ +From 7eb5f1e5c6d9266e5164d21737ab5701b920e91d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 9 Jul 2026 22:49:55 +0800 +Subject: ksmbd: pin conn during async oplock break notification + +From: Qihang + +[ Upstream commit aa5d8f3f96aa11a4a54ce993c11ce8af11c546f9 ] + +smb2_oplock_break_noti() and smb2_lease_break_noti() store a ksmbd_conn +pointer in an async ksmbd_work and then queue that work on ksmbd-io. The +work only increments conn->r_count, which prevents teardown from passing +the pending-request wait after the increment, but it does not pin the +struct ksmbd_conn object. + +If connection teardown races with an oplock break notification, the last +conn reference can be dropped before the queued worker finishes. The +worker then uses the freed conn in ksmbd_conn_write() and +ksmbd_conn_r_count_dec(). + +Take a real conn reference when publishing the conn pointer to the async +work item, and drop it after the notification work has decremented +r_count. Apply the same lifetime rule to lease break notification, which +uses the same work->conn pattern. + +Fixes: 3aa660c05924 ("ksmbd: prevent connection release during oplock break notification") +Signed-off-by: Qihang +Acked-by: Namjae Jeon +Signed-off-by: Steve French +Signed-off-by: Sasha Levin +--- + fs/smb/server/oplock.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/fs/smb/server/oplock.c b/fs/smb/server/oplock.c +index 60e7e821c2455d..3f28dc3b7fc415 100644 +--- a/fs/smb/server/oplock.c ++++ b/fs/smb/server/oplock.c +@@ -705,6 +705,7 @@ static void __smb2_oplock_break_noti(struct work_struct *wk) + out: + ksmbd_free_work_struct(work); + ksmbd_conn_r_count_dec(conn); ++ ksmbd_conn_put(conn); + } + + /** +@@ -740,7 +741,7 @@ static int smb2_oplock_break_noti(struct oplock_info *opinfo) + br_info->open_trunc = opinfo->open_trunc; + + work->request_buf = (char *)br_info; +- work->conn = conn; ++ work->conn = ksmbd_conn_get(conn); + work->sess = opinfo->sess; + + ksmbd_conn_r_count_inc(conn); +@@ -814,6 +815,7 @@ static void __smb2_lease_break_noti(struct work_struct *wk) + out: + ksmbd_free_work_struct(work); + ksmbd_conn_r_count_dec(conn); ++ ksmbd_conn_put(conn); + } + + /** +@@ -853,7 +855,7 @@ static int smb2_lease_break_noti(struct oplock_info *opinfo) + memcpy(br_info->lease_key, lease->lease_key, SMB2_LEASE_KEY_SIZE); + + work->request_buf = (char *)br_info; +- work->conn = conn; ++ work->conn = ksmbd_conn_get(conn); + work->sess = opinfo->sess; + + ksmbd_conn_r_count_inc(conn); +-- +2.53.0 + diff --git a/queue-7.1/ksmbd-validate-compound-request-size-before-reading-.patch b/queue-7.1/ksmbd-validate-compound-request-size-before-reading-.patch new file mode 100644 index 0000000000..12f930c975 --- /dev/null +++ b/queue-7.1/ksmbd-validate-compound-request-size-before-reading-.patch @@ -0,0 +1,69 @@ +From 5e9a224853fbf0b1c5f9b6128e243c38ad762d73 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 13 Jul 2026 21:55:10 +0000 +Subject: ksmbd: validate compound request size before reading StructureSize2 + +From: Xiang Mei (Microsoft) + +[ Upstream commit 15b38176fd1530372905c602fde51fe89ec8c877 ] + +When ksmbd validates a compound (chained) SMB2 request, +ksmbd_smb2_check_message() reads pdu->StructureSize2 without first +checking that the compound element is large enough to contain it. +StructureSize2 is a 2-byte field at offset 64 +(__SMB2_HEADER_STRUCTURE_SIZE) from the start of each element. + +The compound-walking logic only guarantees that a full 64-byte SMB2 +header is present for the trailing element: when NextCommand is 0, len is +reduced to the number of bytes remaining after next_smb2_rcv_hdr_off. A +remote client can craft a compound request whose last element has exactly +64 bytes, so the 2-byte StructureSize2 read at offset 64 extends one byte +past the receive buffer, producing a slab-out-of-bounds read. + + BUG: KASAN: slab-out-of-bounds in ksmbd_smb2_check_message (fs/smb/server/smb2misc.c:402) + Read of size 2 at addr ffff888012ae31ac by task kworker/0:1/14 + The buggy address is located 172 bytes inside of allocated 173-byte region + Workqueue: ksmbd-io handle_ksmbd_work + Call Trace: + ... + kasan_report (mm/kasan/report.c:595) + ksmbd_smb2_check_message (fs/smb/server/smb2misc.c:402) + handle_ksmbd_work (fs/smb/server/server.c:119) + process_one_work (kernel/workqueue.c:3314) + worker_thread (kernel/workqueue.c:3397) + kthread (kernel/kthread.c:436) + ret_from_fork (arch/x86/kernel/process.c:158) + ret_from_fork_asm (arch/x86/entry/entry_64.S:245) + +Reject any compound element that is too small to hold StructureSize2 +before dereferencing it. + +Fixes: e2f34481b24d ("cifsd: add server-side procedures for SMB3") +Reported-by: AutonomousCodeSecurity@microsoft.com +Signed-off-by: Xiang Mei (Microsoft) +Acked-by: Namjae Jeon +Signed-off-by: Steve French +Signed-off-by: Sasha Levin +--- + fs/smb/server/smb2misc.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/fs/smb/server/smb2misc.c b/fs/smb/server/smb2misc.c +index a1ddca21c47bf9..29f33ece30a94e 100644 +--- a/fs/smb/server/smb2misc.c ++++ b/fs/smb/server/smb2misc.c +@@ -399,6 +399,11 @@ int ksmbd_smb2_check_message(struct ksmbd_work *work) + return 1; + } + ++ if (len < __SMB2_HEADER_STRUCTURE_SIZE + sizeof(__le16)) { ++ ksmbd_debug(SMB, "Message is too small for StructureSize2\n"); ++ return 1; ++ } ++ + if (smb2_req_struct_sizes[command] != pdu->StructureSize2) { + if (!(command == SMB2_OPLOCK_BREAK_HE && + (le16_to_cpu(pdu->StructureSize2) == OP_BREAK_STRUCT_SIZE_20 || +-- +2.53.0 + diff --git a/queue-7.1/mpls-fix-null-deref-in-mpls_valid_fib_dump_req-on-co.patch b/queue-7.1/mpls-fix-null-deref-in-mpls_valid_fib_dump_req-on-co.patch new file mode 100644 index 0000000000..c5c73818b5 --- /dev/null +++ b/queue-7.1/mpls-fix-null-deref-in-mpls_valid_fib_dump_req-on-co.patch @@ -0,0 +1,68 @@ +From f49a098fc019e13a696497b27c914a6207d98690 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 11 Jul 2026 04:50:00 -0700 +Subject: mpls: fix NULL deref in mpls_valid_fib_dump_req() on CONFIG_INET=n + +From: Weiming Shi + +[ Upstream commit 56d96fededd61192cd7cc8d2b0f36adfd59036c3 ] + +On CONFIG_INET=n builds, mpls_valid_fib_dump_req() walks the parsed +attribute table itself instead of calling ip_valid_fib_dump_req(). The +RTA_OIF arm passes tb[RTA_OIF] to nla_get_u32() without checking it is +present, so an RTM_GETROUTE dump for AF_MPLS with strict checking and no +RTA_OIF hits a NULL dereference. + +RTM_GETROUTE is RTNL_KIND_GET, which rtnetlink_rcv_msg() permits without +CAP_NET_ADMIN, so an unprivileged user can trigger it. + + Oops: general protection fault, probably for non-canonical address + 0xdffffc0000000000: 0000 [#1] SMP KASAN NOPTI + KASAN: null-ptr-deref in range [0x0000000000000000-0x0000000000000007] + RIP: 0010:mpls_valid_fib_dump_req (net/mpls/af_mpls.c:2189) + Call Trace: + mpls_dump_routes (net/mpls/af_mpls.c:2236) + netlink_dump (net/netlink/af_netlink.c:2331) + __netlink_dump_start (net/netlink/af_netlink.c:2446) + rtnetlink_rcv_msg (net/core/rtnetlink.c:7033) + netlink_rcv_skb (net/netlink/af_netlink.c:2556) + netlink_unicast (net/netlink/af_netlink.c:1345) + netlink_sendmsg (net/netlink/af_netlink.c:1900) + __sock_sendmsg (net/socket.c:790) + ____sys_sendmsg (net/socket.c:2684) + ___sys_sendmsg (net/socket.c:2738) + __sys_sendmsg (net/socket.c:2770) + do_syscall_64 (arch/x86/entry/syscall_64.c:94) + entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:121) + +Skip unset attributes, as ip_valid_fib_dump_req() does. + +Fixes: 196cfebf8972 ("net/mpls: Handle kernel side filtering of route dumps") +Assisted-by: Claude:claude-opus-4-8 +Reported-by: Xiang Mei +Signed-off-by: Weiming Shi +Reviewed-by: David Ahern +Link: https://patch.msgid.link/20260711114958.1009619-3-bestswngs@gmail.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/mpls/af_mpls.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/net/mpls/af_mpls.c b/net/mpls/af_mpls.c +index 26340a7306b591..b64a8b1bac0961 100644 +--- a/net/mpls/af_mpls.c ++++ b/net/mpls/af_mpls.c +@@ -2186,6 +2186,9 @@ static int mpls_valid_fib_dump_req(struct net *net, const struct nlmsghdr *nlh, + int ifindex; + + if (i == RTA_OIF) { ++ if (!tb[i]) ++ continue; ++ + ifindex = nla_get_u32(tb[i]); + filter->dev = dev_get_by_index_rcu(net, ifindex); + if (!filter->dev) +-- +2.53.0 + diff --git a/queue-7.1/mtd-fix-double-free-and-warn_on-in-add_mtd_device-er.patch b/queue-7.1/mtd-fix-double-free-and-warn_on-in-add_mtd_device-er.patch new file mode 100644 index 0000000000..3dd90ddeb8 --- /dev/null +++ b/queue-7.1/mtd-fix-double-free-and-warn_on-in-add_mtd_device-er.patch @@ -0,0 +1,102 @@ +From ba9c23cc262803ae82e8a122de13dfdffa5535e2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 1 Jul 2026 20:10:42 +0800 +Subject: mtd: fix double free and WARN_ON in add_mtd_device() error paths + +From: Xue Lei + +[ Upstream commit 9d4af746af8ce27eefc2338b2feaa1e01f28b6c3 ] + +When device_register() or mtd_nvmem_add() fails inside +add_mtd_device() for a partition, the error handling triggers +mtd_release() via put_device() or device_unregister(). mtd_release() +calls release_mtd_partition() which frees the mtd_info structure. +However, callers such as mtd_add_partition() and add_mtd_partitions() +also call free_partition() in their error paths, resulting in a double +free. + +Additionally, release_mtd_partition() hits WARN_ON(!list_empty( +&mtd->part.node)) because the partition node is still linked in the +parent's partitions list when the release callback fires from the +add_mtd_device() error path. + +Fix this by overriding dev->type and dev->release before put_device() +in the error paths, so that device_release() invokes a no-op function +instead of mtd_release(). For the mtd_nvmem_add() failure case, +device_unregister() is replaced with device_del() to separate the +device removal from the final kobject reference drop, allowing the +override to take effect before put_device() is called. + +The callers' error paths (list_del + free_partition) remain the sole +owners of mtd_info lifetime on add_mtd_device() failure, which is the +expected contract. + +The normal partition teardown path is not affected: del_mtd_device() +goes through kref_put() -> mtd_device_release() -> device_unregister() +with dev->type still set to &mtd_devtype, so mtd_release() -> +release_mtd_partition() continues to work correctly for the regular +removal case. + +Reported-by: syzbot+e9c76b56dc05023b8117@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=e9c76b56dc05023b8117 +Fixes: 19bfa9ebebb5 ("mtd: use refcount to prevent corruption") +Signed-off-by: Xue Lei +Signed-off-by: Miquel Raynal +Signed-off-by: Sasha Levin +--- + drivers/mtd/mtdcore.c | 23 +++++++++++++++++++---- + 1 file changed, 19 insertions(+), 4 deletions(-) + +diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c +index 57653777462887..16629382a787bd 100644 +--- a/drivers/mtd/mtdcore.c ++++ b/drivers/mtd/mtdcore.c +@@ -105,6 +105,15 @@ static void mtd_release(struct device *dev) + device_destroy(&mtd_class, index + 1); + } + ++/* ++ * No-op device release used in add_mtd_device() error paths. ++ * Prevents mtd_release() from being called via device_release(), ++ * which would free the mtd_info that the caller still manages. ++ */ ++static void mtd_dev_release_nop(struct device *dev) ++{ ++} ++ + static void mtd_device_release(struct kref *kref) + { + struct mtd_info *mtd = container_of(kref, struct mtd_info, refcnt); +@@ -799,10 +808,8 @@ int add_mtd_device(struct mtd_info *mtd) + mtd_check_of_node(mtd); + of_node_get(mtd_get_of_node(mtd)); + error = device_register(&mtd->dev); +- if (error) { +- put_device(&mtd->dev); ++ if (error) + goto fail_added; +- } + + /* Add the nvmem provider */ + error = mtd_nvmem_add(mtd); +@@ -840,8 +847,16 @@ int add_mtd_device(struct mtd_info *mtd) + return 0; + + fail_nvmem_add: +- device_unregister(&mtd->dev); ++ device_del(&mtd->dev); + fail_added: ++ /* ++ * Clear type and set nop release to prevent mtd_release() -> ++ * release_mtd_partition() -> free_partition() from freeing mtd. ++ * The caller handles cleanup on failure. ++ */ ++ mtd->dev.type = NULL; ++ mtd->dev.release = mtd_dev_release_nop; ++ put_device(&mtd->dev); + of_node_put(mtd_get_of_node(mtd)); + fail_devname: + idr_remove(&mtd_idr, i); +-- +2.53.0 + diff --git a/queue-7.1/mtd-mtdswap-remove-debugfs-stats-file-on-teardown.patch b/queue-7.1/mtd-mtdswap-remove-debugfs-stats-file-on-teardown.patch new file mode 100644 index 0000000000..45c98d72e8 --- /dev/null +++ b/queue-7.1/mtd-mtdswap-remove-debugfs-stats-file-on-teardown.patch @@ -0,0 +1,57 @@ +From fb3072abac909521520645fe9402932e8498680f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 23 Jun 2026 09:53:17 +0800 +Subject: mtd: mtdswap: remove debugfs stats file on teardown + +From: Pengpeng Hou + +[ Upstream commit 66fb31358108d10245b9e4ef0eef3e7d9747055e ] + +mtdswap_add_debugfs() creates an mtdswap_stats debugfs file under the +per-MTD debugfs directory, but mtdswap_remove_dev() never removes it +before freeing the mtdswap_dev. + +Store the returned dentry and remove it during device teardown before the +driver-private state is freed. + +Fixes: a32159024620 ("mtd: Add mtdswap block driver") +Signed-off-by: Pengpeng Hou +Signed-off-by: Miquel Raynal +Signed-off-by: Sasha Levin +--- + drivers/mtd/mtdswap.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/drivers/mtd/mtdswap.c b/drivers/mtd/mtdswap.c +index 866933fc84265d..f33f753f0a9fda 100644 +--- a/drivers/mtd/mtdswap.c ++++ b/drivers/mtd/mtdswap.c +@@ -125,6 +125,7 @@ struct mtdswap_dev { + + char *page_buf; + char *oob_buf; ++ struct dentry *debugfs_stats; + }; + + struct mtdswap_oobdata { +@@ -1262,7 +1263,8 @@ static int mtdswap_add_debugfs(struct mtdswap_dev *d) + if (IS_ERR_OR_NULL(root)) + return -1; + +- debugfs_create_file("mtdswap_stats", S_IRUSR, root, d, &mtdswap_fops); ++ d->debugfs_stats = debugfs_create_file("mtdswap_stats", 0400, root, ++ d, &mtdswap_fops); + + return 0; + } +@@ -1463,6 +1465,7 @@ static void mtdswap_remove_dev(struct mtd_blktrans_dev *dev) + { + struct mtdswap_dev *d = MTDSWAP_MBD_TO_MTDSWAP(dev); + ++ debugfs_remove(d->debugfs_stats); + del_mtd_blktrans_dev(dev); + mtdswap_cleanup(d); + kfree(d); +-- +2.53.0 + diff --git a/queue-7.1/mtd-nand-mtk-ecc-stop-on-ecc-idle-timeouts.patch b/queue-7.1/mtd-nand-mtk-ecc-stop-on-ecc-idle-timeouts.patch new file mode 100644 index 0000000000..71816142d8 --- /dev/null +++ b/queue-7.1/mtd-nand-mtk-ecc-stop-on-ecc-idle-timeouts.patch @@ -0,0 +1,75 @@ +From e68acff71a768916ec6e4af8adf17e056e484b9f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 23 Jun 2026 21:57:29 +0800 +Subject: mtd: nand: mtk-ecc: stop on ECC idle timeouts + +From: Pengpeng Hou + +[ Upstream commit 16f7ec8d5dc100eafd2c8e06cd30340a30b104a1 ] + +mtk_ecc_wait_idle() logs when the encoder or decoder does not become +idle, but returns void. Callers can therefore configure a non-idle ECC +engine or read parity bytes after an unconfirmed encoder idle state. + +Return the idle poll result and propagate it from the enable and encode +paths that require the engine to be idle before continuing. + +Fixes: 1d6b1e464950 ("mtd: mediatek: driver for MTK Smart Device") +Signed-off-by: Pengpeng Hou +Signed-off-by: Miquel Raynal +Signed-off-by: Sasha Levin +--- + drivers/mtd/nand/ecc-mtk.c | 16 ++++++++++++---- + 1 file changed, 12 insertions(+), 4 deletions(-) + +diff --git a/drivers/mtd/nand/ecc-mtk.c b/drivers/mtd/nand/ecc-mtk.c +index c75bb8b80cc1e1..96703f0a418ea2 100644 +--- a/drivers/mtd/nand/ecc-mtk.c ++++ b/drivers/mtd/nand/ecc-mtk.c +@@ -123,8 +123,8 @@ static int mt7622_ecc_regs[] = { + [ECC_DECIRQ_STA] = 0x144, + }; + +-static inline void mtk_ecc_wait_idle(struct mtk_ecc *ecc, +- enum mtk_ecc_operation op) ++static inline int mtk_ecc_wait_idle(struct mtk_ecc *ecc, ++ enum mtk_ecc_operation op) + { + struct device *dev = ecc->dev; + u32 val; +@@ -136,6 +136,8 @@ static inline void mtk_ecc_wait_idle(struct mtk_ecc *ecc, + if (ret) + dev_warn(dev, "%s NOT idle\n", + op == ECC_ENCODE ? "encoder" : "decoder"); ++ ++ return ret; + } + + static irqreturn_t mtk_ecc_irq(int irq, void *id) +@@ -312,7 +314,11 @@ int mtk_ecc_enable(struct mtk_ecc *ecc, struct mtk_ecc_config *config) + return ret; + } + +- mtk_ecc_wait_idle(ecc, op); ++ ret = mtk_ecc_wait_idle(ecc, op); ++ if (ret) { ++ mutex_unlock(&ecc->lock); ++ return ret; ++ } + + ret = mtk_ecc_config(ecc, config); + if (ret) { +@@ -412,7 +418,9 @@ int mtk_ecc_encode(struct mtk_ecc *ecc, struct mtk_ecc_config *config, + if (ret) + goto timeout; + +- mtk_ecc_wait_idle(ecc, ECC_ENCODE); ++ ret = mtk_ecc_wait_idle(ecc, ECC_ENCODE); ++ if (ret) ++ goto timeout; + + /* Program ECC bytes to OOB: per sector oob = FDM + ECC + SPARE */ + len = (config->strength * ecc->caps->parity_bits + 7) >> 3; +-- +2.53.0 + diff --git a/queue-7.1/mtd-virt_concat-fix-use-after-free-in-mtd_virt_conca.patch b/queue-7.1/mtd-virt_concat-fix-use-after-free-in-mtd_virt_conca.patch new file mode 100644 index 0000000000..ab68dca66e --- /dev/null +++ b/queue-7.1/mtd-virt_concat-fix-use-after-free-in-mtd_virt_conca.patch @@ -0,0 +1,42 @@ +From 387b03e12e51c7c44bda9b9a5e3e451731e8b93a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 14 Jun 2026 01:10:52 -0700 +Subject: mtd: virt_concat: fix use-after-free in + mtd_virt_concat_destroy_joins() + +From: Harshit Mogalapalli + +[ Upstream commit 75c0c09541b49daa08fddbc2c18c2232f4eab7d8 ] + +mtd_concat_destroy() frees item->concat so calling +mtd_virt_concat_put_mtd_devices(item->concat) leads to a use after free. + +Fix this by moving mtd_virt_concat_put_mtd_devices() before +mtd_concat_destroy() + +Fixes: 43db6366fc2d ("mtd: Add driver for concatenating devices") +Signed-off-by: Harshit Mogalapalli +Reviewed-by: Luca Ceresoli +Signed-off-by: Miquel Raynal +Signed-off-by: Sasha Levin +--- + drivers/mtd/mtd_virt_concat.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/mtd/mtd_virt_concat.c b/drivers/mtd/mtd_virt_concat.c +index 5db6e648927e29..5761816e7f4dca 100644 +--- a/drivers/mtd/mtd_virt_concat.c ++++ b/drivers/mtd/mtd_virt_concat.c +@@ -75,8 +75,8 @@ void mtd_virt_concat_destroy_joins(void) + if (item->concat) { + mtd_device_unregister(mtd); + kfree(mtd->name); +- mtd_concat_destroy(mtd); + mtd_virt_concat_put_mtd_devices(item->concat); ++ mtd_concat_destroy(mtd); + } + } + } +-- +2.53.0 + diff --git a/queue-7.1/mtd-virt_concat-fix-use-after-free-in-mtd_virt_conca.patch-15214 b/queue-7.1/mtd-virt_concat-fix-use-after-free-in-mtd_virt_conca.patch-15214 new file mode 100644 index 0000000000..9b450a2280 --- /dev/null +++ b/queue-7.1/mtd-virt_concat-fix-use-after-free-in-mtd_virt_conca.patch-15214 @@ -0,0 +1,41 @@ +From 871e2b0f1c27a0a18bc99d8ed324767e10f83917 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 16 Jun 2026 03:14:39 -0700 +Subject: mtd: virt_concat: fix use-after-free in mtd_virt_concat_destroy() + +From: Harshit Mogalapalli + +[ Upstream commit 4b45d7836b9526b8776af5f29219615be9417230 ] + +mtd_concat_destroy() frees item->concat so calling +mtd_virt_concat_put_mtd_devices(item->concat) after that leads to a +use-after-free. + +Fix it by moving mtd_virt_concat_put_mtd_devices() before +mtd_concat_destroy(). + +Fixes: 43db6366fc2d ("mtd: Add driver for concatenating devices") +Signed-off-by: Harshit Mogalapalli +Signed-off-by: Miquel Raynal +Signed-off-by: Sasha Levin +--- + drivers/mtd/mtd_virt_concat.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/mtd/mtd_virt_concat.c b/drivers/mtd/mtd_virt_concat.c +index 5761816e7f4dca..da4277ced4d63b 100644 +--- a/drivers/mtd/mtd_virt_concat.c ++++ b/drivers/mtd/mtd_virt_concat.c +@@ -126,8 +126,8 @@ int mtd_virt_concat_destroy(struct mtd_info *mtd) + if (concat->mtd.name) { + del_mtd_device(&concat->mtd); + kfree(concat->mtd.name); +- mtd_concat_destroy(&concat->mtd); + mtd_virt_concat_put_mtd_devices(item->concat); ++ mtd_concat_destroy(&concat->mtd); + } + + for (idx = 0; idx < item->count; idx++) +-- +2.53.0 + diff --git a/queue-7.1/net-iucv-take-a-reference-on-the-socket-found-in-afi.patch b/queue-7.1/net-iucv-take-a-reference-on-the-socket-found-in-afi.patch new file mode 100644 index 0000000000..ea1fe8abde --- /dev/null +++ b/queue-7.1/net-iucv-take-a-reference-on-the-socket-found-in-afi.patch @@ -0,0 +1,55 @@ +From 52a74c1890cfdd0bf5d494ced86c2ad515949edb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 5 Jul 2026 22:24:36 -0500 +Subject: net/iucv: take a reference on the socket found in afiucv_hs_rcv() + +From: Bryam Vargas + +[ Upstream commit 4fa349156043dc119721d067329714179f501749 ] + +afiucv_hs_rcv() looks up the destination socket under iucv_sk_list.lock, +drops the lock, and then passes the socket to the afiucv_hs_callback_*() +handlers without holding a reference. AF_IUCV sockets are not +RCU-protected and are freed synchronously by iucv_sock_kill() -> +sock_put(), so a concurrent close can free the socket in the window +between read_unlock() and the handler, which then dereferences freed +memory (for example sk->sk_data_ready() in afiucv_hs_callback_syn()). + +Take a reference with sock_hold() while the socket is still on the list +and release it with sock_put() once the handler has run. + +Fixes: 3881ac441f64 ("af_iucv: add HiperSockets transport") +Signed-off-by: Bryam Vargas +Reviewed-by: Hidayath Khan +Link: https://patch.msgid.link/20260705-b4-disp-fc79c0dc-v1-1-d2cdcb57afa9@proton.me +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/iucv/af_iucv.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c +index c2dc3338670e83..126b58bbc2a5f4 100644 +--- a/net/iucv/af_iucv.c ++++ b/net/iucv/af_iucv.c +@@ -2091,6 +2091,8 @@ static int afiucv_hs_rcv(struct sk_buff *skb, struct net_device *dev, + } + } + } ++ if (sk) ++ sock_hold(sk); + read_unlock(&iucv_sk_list.lock); + if (!iucv) + sk = NULL; +@@ -2140,6 +2142,8 @@ static int afiucv_hs_rcv(struct sk_buff *skb, struct net_device *dev, + kfree_skb(skb); + } + ++ if (sk) ++ sock_put(sk); + return err; + } + +-- +2.53.0 + diff --git a/queue-7.1/net-sched-act_tunnel_key-defer-dst_release-to-rcu-ca.patch b/queue-7.1/net-sched-act_tunnel_key-defer-dst_release-to-rcu-ca.patch new file mode 100644 index 0000000000..f433406a68 --- /dev/null +++ b/queue-7.1/net-sched-act_tunnel_key-defer-dst_release-to-rcu-ca.patch @@ -0,0 +1,176 @@ +From 0988d2c6cd0987a7891006fa3a3a472c9834ad44 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 11 Jul 2026 11:05:37 -0400 +Subject: net/sched: act_tunnel_key: Defer dst_release to RCU callback + +From: Jamal Hadi Salim + +[ Upstream commit f1f5c8a3955f8fda3f84ed883ac8daa1847e724c ] + +Fix a race-condition use-after-free in tunnel_key_release_params(). + +The function releases the metadata_dst of the old params synchronously +via dst_release() while deferring the params struct free with +kfree_rcu(). A concurrent tunnel_key_act() reader on the datapath may +still hold the old params pointer (under rcu_read_lock_bh) and proceed +to call dst_clone(¶ms->tcft_enc_metadata->dst) after the writer's +dst_release has already pushed the dst's rcuref to RCUREF_DEAD. + +zdi-disclosures@trendmicro.com produced a poc which i (and Victor) verified +that KASAN reports: + +================================================================== +BUG: KASAN: slab-use-after-free in instrument_atomic_read_write include/linux/instrumented.h:112 +BUG: KASAN: slab-use-after-free in atomic_sub_return_release include/linux/atomic/atomic-instrumented.h:326 +BUG: KASAN: slab-use-after-free in __rcuref_put include/linux/rcuref.h:109 +BUG: KASAN: slab-use-after-free in rcuref_put include/linux/rcuref.h:173 +BUG: KASAN: slab-use-after-free in dst_release+0x5b/0x370 net/core/dst.c:168 +Write of size 4 at addr ffff88806158de40 by task poc/9388 + +CPU: 0 UID: 0 PID: 9388 Comm: poc Tainted: G W 7.1.0-rc7 #7 PREEMPT(lazy) +Tainted: [W]=WARN +Hardware name: QEMU Ubuntu 25.10 PC v2 (i440FX + PIIX, + 10.1 machine, 1996), BIOS 1.16.3-debian-1.16.3-2 04/01/2014 +Call Trace: + + __dump_stack lib/dump_stack.c:94 + dump_stack_lvl+0x100/0x190 lib/dump_stack.c:120 + print_address_description mm/kasan/report.c:378 + print_report+0x139/0x4ad mm/kasan/report.c:482 + kasan_report+0xe4/0x1d0 mm/kasan/report.c:595 + check_region_inline mm/kasan/generic.c:186 + kasan_check_range+0x125/0x200 mm/kasan/generic.c:200 + instrument_atomic_read_write include/linux/instrumented.h:112 + atomic_sub_return_release include/linux/atomic/atomic-instrumented.h:326 + __rcuref_put include/linux/rcuref.h:109 + rcuref_put include/linux/rcuref.h:173 + dst_release+0x5b/0x370 net/core/dst.c:168 + refdst_drop include/net/dst.h:272 + skb_dst_drop include/net/dst.h:284 + skb_release_head_state+0x293/0x400 net/core/skbuff.c:1163 + skb_release_all net/core/skbuff.c:1187 +[..] +Allocated by task 9391: + kasan_save_stack+0x30/0x50 mm/kasan/common.c:57 + kasan_save_track+0x14/0x30 mm/kasan/common.c:78 + poison_kmalloc_redzone mm/kasan/common.c:398 + __kasan_kmalloc+0x9a/0xb0 mm/kasan/common.c:415 + kasan_kmalloc include/linux/kasan.h:263 + __do_kmalloc_node mm/slub.c:5296 + __kmalloc_noprof+0x2f1/0x830 mm/slub.c:5308 + kmalloc_noprof include/linux/slab.h:954 + kzalloc_noprof include/linux/slab.h:1188 + offload_action_alloc+0x2f/0x130 net/core/flow_offload.c:35 + tcf_action_offload_add_ex+0x1ba/0x880 net/sched/act_api.c:258 + tcf_action_offload_add net/sched/act_api.c:293 + tcf_action_init+0x66e/0xa20 net/sched/act_api.c:1547 + tcf_action_add+0xf6/0x5d0 net/sched/act_api.c:2101 +[..] +Freed by task 9391: + kasan_save_stack+0x30/0x50 mm/kasan/common.c:57 + kasan_save_track+0x14/0x30 mm/kasan/common.c:78 + kasan_save_free_info+0x3b/0x70 mm/kasan/generic.c:584 + poison_slab_object mm/kasan/common.c:253 + __kasan_slab_free+0x6b/0x90 mm/kasan/common.c:285 + kasan_slab_free include/linux/kasan.h:235 + slab_free_hook mm/slub.c:2689 + slab_free mm/slub.c:6251 + kfree+0x21f/0x6b0 mm/slub.c:6566 + tcf_action_offload_add_ex+0x4ad/0x880 net/sched/act_api.c:284 + tcf_action_offload_add net/sched/act_api.c:293 + tcf_action_init+0x66e/0xa20 net/sched/act_api.c:1547 + tcf_action_add+0xf6/0x5d0 net/sched/act_api.c:2101 + +The buggy address belongs to the object at ffff88806158de00 + which belongs to the cache kmalloc-256 of size 256 +The buggy address is located 64 bytes inside of + freed 256-byte region [ffff88806158de00, ffff88806158df00) + +The buggy address belongs to the physical page: +page: refcount:0 mapcount:0 mapping:0000000000000000 index:0xffff88806158d600 pfn:0x6158c +head: order:1 mapcount:0 entire_mapcount:0 nr_pages_mapped:0 pincount:0 +flags: 0x4fff00000000240(workingset|head|node=1|zone=1|lastcpupid=0x7ff) +page_type: f5(slab) +raw: 04fff00000000240 ffff88801c841b40 ffffea0001856290 ffffea0001856190 +raw: ffff88806158d600 0000000800100009 00000000f5000000 0000000000000000 +head: 04fff00000000240 ffff88801c841b40 ffffea0001856290 ffffea0001856190 +head: ffff88806158d600 0000000800100009 00000000f5000000 0000000000000000 +head: 04fff00000000001 ffffffffffffff81 00000000ffffffff 00000000ffffffff +head: ffffffffffffffff 0000000000000000 00000000ffffffff 0000000000000002 +page dumped because: kasan: bad access detected +page_owner tracks the page as allocated +page last allocated via order 1, migratetype Unmovable, gfp_mask 0xd2820(GFP_ATOMIC|__GFP_NOWARN|__GFP_NORETRY|__GFP_COMP|__GFP_NOMEMALLOC), pid 9391, tgid 9378 (poc), ts 123227323196, free_ts 0 + set_page_owner include/linux/page_owner.h:32 + post_alloc_hook+0xfe/0x140 mm/page_alloc.c:1853 + prep_new_page mm/page_alloc.c:1861 + get_page_from_freelist+0x110c/0x2fc0 mm/page_alloc.c:3941 + __alloc_frozen_pages_noprof+0x263/0x2bc0 mm/page_alloc.c:5221 + alloc_slab_page mm/slub.c:3278 + allocate_slab mm/slub.c:3467 + new_slab+0xa6/0x690 mm/slub.c:3525 + refill_objects+0x271/0x420 mm/slub.c:7272 + refill_sheaf mm/slub.c:2816 + __pcs_replace_empty_main+0x373/0x630 mm/slub.c:4652 + alloc_from_pcs mm/slub.c:4750 + slab_alloc_node mm/slub.c:4884 + __do_kmalloc_node mm/slub.c:5295 + __kmalloc_noprof+0x66d/0x830 mm/slub.c:5308 + kmalloc_noprof include/linux/slab.h:954 + metadata_dst_alloc+0x26/0x90 net/core/dst.c:298 + tun_rx_dst include/net/dst_metadata.h:144 + __ip_tun_set_dst include/net/dst_metadata.h:208 + tunnel_key_init+0xb01/0x1b90 net/sched/act_tunnel_key.c:451 + tcf_action_init_1+0x46b/0x6c0 net/sched/act_api.c:1428 + tcf_action_init+0x448/0xa20 net/sched/act_api.c:1503 + tcf_action_add+0xf6/0x5d0 net/sched/act_api.c:2101 +[..] +================================================================== + +Fix by moving dst_release() into a custom RCU callback that runs +after the grace period, matching the lifetime of the containing +params struct. Readers in the datapath therefore always find a live +rcuref when calling dst_clone(). + +Fixes: 9174c3df1cd18 ("net/sched: act_tunnel_key: fix memory leak in case of action replace") +Reported-by: zdi-disclosures@trendmicro.com +Tested-by: Victor Nogueira +Signed-off-by: Jamal Hadi Salim +Reviewed-by: Davide Caratti +Link: https://patch.msgid.link/20260711150537.7946-1-jhs@mojatatu.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/sched/act_tunnel_key.c | 14 ++++++++++---- + 1 file changed, 10 insertions(+), 4 deletions(-) + +diff --git a/net/sched/act_tunnel_key.c b/net/sched/act_tunnel_key.c +index 876b30c5709e1f..b14807761d829e 100644 +--- a/net/sched/act_tunnel_key.c ++++ b/net/sched/act_tunnel_key.c +@@ -342,14 +342,20 @@ static const struct nla_policy tunnel_key_policy[TCA_TUNNEL_KEY_MAX + 1] = { + [TCA_TUNNEL_KEY_ENC_TTL] = { .type = NLA_U8 }, + }; + +-static void tunnel_key_release_params(struct tcf_tunnel_key_params *p) ++static void tunnel_key_release_params_rcu(struct rcu_head *head) + { +- if (!p) +- return; ++ struct tcf_tunnel_key_params *p = container_of(head, typeof(*p), rcu); ++ + if (p->tcft_action == TCA_TUNNEL_KEY_ACT_SET) + dst_release(&p->tcft_enc_metadata->dst); ++ kfree(p); ++} + +- kfree_rcu(p, rcu); ++static void tunnel_key_release_params(struct tcf_tunnel_key_params *p) ++{ ++ if (!p) ++ return; ++ call_rcu(&p->rcu, tunnel_key_release_params_rcu); + } + + static int tunnel_key_init(struct net *net, struct nlattr *nla, +-- +2.53.0 + diff --git a/queue-7.1/powerpc-85xx-add-fsl-ifc-to-common-device-ids.patch b/queue-7.1/powerpc-85xx-add-fsl-ifc-to-common-device-ids.patch new file mode 100644 index 0000000000..7c7e05a801 --- /dev/null +++ b/queue-7.1/powerpc-85xx-add-fsl-ifc-to-common-device-ids.patch @@ -0,0 +1,41 @@ +From 76a5afd98dcb44bba10700b7ed3b01e3c100ab2d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 3 Jun 2026 21:33:09 -0700 +Subject: powerpc/85xx: Add fsl,ifc to common device ids + +From: Rosen Penev + +[ Upstream commit 25957f7c3dac3265332d766b71233e3622f17e14 ] + +Add fsl,ifc to mpc85xx_common_ids so that of_platform_bus_probe +creates a platform device for the IFC node even without 'simple-bus' +in its compatible property. On P1010 and similar platforms the IFC +node is a direct child of the root, so it must be explicitly matched +to be populated. + +Fixes: 0bf51cc9e9e5 ("powerpc: dts: mpc85xx: remove "simple-bus" compatible from ifc node") +Assisted-by: opencode:big-pickle +Signed-off-by: Rosen Penev +Signed-off-by: Madhavan Srinivasan +Link: https://patch.msgid.link/20260604043309.91280-1-rosenp@gmail.com +Signed-off-by: Sasha Levin +--- + arch/powerpc/platforms/85xx/common.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/arch/powerpc/platforms/85xx/common.c b/arch/powerpc/platforms/85xx/common.c +index 757811155587db..c11deb2f50ed45 100644 +--- a/arch/powerpc/platforms/85xx/common.c ++++ b/arch/powerpc/platforms/85xx/common.c +@@ -42,6 +42,8 @@ static const struct of_device_id mpc85xx_common_ids[] __initconst = { + { .compatible = "fsl,qoriq-pcie-v2.3", }, + { .compatible = "fsl,qoriq-pcie-v2.2", }, + { .compatible = "fsl,fman", }, ++ /* IFC NAND and NOR controllers */ ++ { .compatible = "fsl,ifc", }, + {}, + }; + +-- +2.53.0 + diff --git a/queue-7.1/powerpc-time-prepare-to-stop-elapsing-in-dynticks-id.patch b/queue-7.1/powerpc-time-prepare-to-stop-elapsing-in-dynticks-id.patch new file mode 100644 index 0000000000..f6649e9757 --- /dev/null +++ b/queue-7.1/powerpc-time-prepare-to-stop-elapsing-in-dynticks-id.patch @@ -0,0 +1,126 @@ +From 326cb1f90501ee24c19ffa93fe2833296cc9959a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 8 May 2026 15:16:37 +0200 +Subject: powerpc/time: Prepare to stop elapsing in dynticks-idle + +From: Frederic Weisbecker + +[ Upstream commit c8ba971cf8567d49eb5f43ee90c4e50424331c18 ] + +Currently the tick subsystem stores the idle cputime accounting in +private fields, allowing cohabitation with architecture idle vtime +accounting. The former is fetched on online CPUs, the latter on offline +CPUs. + +For consolidation purpose, architecture vtime accounting will continue +to account the cputime but will make a break when the idle tick is +stopped. The dyntick cputime accounting will then be relayed by the tick +subsystem so that the idle cputime is still seen advancing coherently +even when the tick isn't there to flush the idle vtime. + +Prepare for that and introduce three new APIs which will be used in +subsequent patches: + + - vtime_dynticks_start() is deemed to be called when idle enters in + dyntick mode. The idle cputime that elapsed so far is accumulated. + + - vtime_dynticks_stop() is deemed to be called when idle exits from + dyntick mode. The vtime entry clocks are fast-forward to current time + so that idle accounting restarts elapsing from now. + + - vtime_reset() is deemed to be called from dynticks idle IRQ entry to + fast-forward the clock to current time so that the IRQ time is still + accounted by vtime while nohz cputime is paused. + +Also accumulated vtime won't be flushed from dyntick-idle ticks to avoid +accounting twice the idle cputime, along with nohz accounting. + +Signed-off-by: Frederic Weisbecker +Signed-off-by: Thomas Gleixner +Tested-by: Shrikanth Hegde +Reviewed-by: Shrikanth Hegde +Link: https://patch.msgid.link/20260508131647.43868-6-frederic@kernel.org +Stable-dep-of: c1c1ffa490fc ("powerpc/vtime: Initialize starttime at boot for native accounting") +Signed-off-by: Sasha Levin +--- + arch/powerpc/kernel/time.c | 41 ++++++++++++++++++++++++++++++++++++++ + include/linux/vtime.h | 6 ++++++ + 2 files changed, 47 insertions(+) + +diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c +index b4472288e0d434..3460d1a5a97c2a 100644 +--- a/arch/powerpc/kernel/time.c ++++ b/arch/powerpc/kernel/time.c +@@ -376,6 +376,47 @@ void vtime_task_switch(struct task_struct *prev) + acct->starttime = acct0->starttime; + } + } ++ ++#ifdef CONFIG_NO_HZ_COMMON ++/** ++ * vtime_reset - Fast forward vtime entry clocks ++ * ++ * Called from dynticks idle IRQ entry to fast-forward the clocks to current time ++ * so that the IRQ time is still accounted by vtime while nohz cputime is paused. ++ */ ++void vtime_reset(void) ++{ ++ struct cpu_accounting_data *acct = get_accounting(current); ++ ++ acct->starttime = mftb(); ++#ifdef CONFIG_ARCH_HAS_SCALED_CPUTIME ++ acct->startspurr = read_spurr(acct->starttime); ++#endif ++} ++ ++/** ++ * vtime_dyntick_start - Inform vtime about entry to idle-dynticks ++ * ++ * Called when idle enters in dyntick mode. The idle cputime that elapsed so far ++ * is accumulated and the tick subsystem takes over the idle cputime accounting. ++ */ ++void vtime_dyntick_start(void) ++{ ++ vtime_account_idle(current); ++} ++ ++/** ++ * vtime_dyntick_stop - Inform vtime about exit from idle-dynticks ++ * ++ * Called when idle exits from dyntick mode. The vtime entry clocks are ++ * fast-forward to current time so that idle accounting restarts elapsing from ++ * now. ++ */ ++void vtime_dyntick_stop(void) ++{ ++ vtime_reset(); ++} ++#endif /* CONFIG_NO_HZ_COMMON */ + #endif /* CONFIG_VIRT_CPU_ACCOUNTING_NATIVE */ + + void __no_kcsan __delay(unsigned long loops) +diff --git a/include/linux/vtime.h b/include/linux/vtime.h +index 29dd5b91dd7d66..3fc04b849e4e30 100644 +--- a/include/linux/vtime.h ++++ b/include/linux/vtime.h +@@ -32,11 +32,17 @@ extern void vtime_account_irq(struct task_struct *tsk, unsigned int offset); + extern void vtime_account_softirq(struct task_struct *tsk); + extern void vtime_account_hardirq(struct task_struct *tsk); + extern void vtime_flush(struct task_struct *tsk); ++extern void vtime_reset(void); ++extern void vtime_dyntick_start(void); ++extern void vtime_dyntick_stop(void); + #else /* !CONFIG_VIRT_CPU_ACCOUNTING_NATIVE */ + static inline void vtime_account_irq(struct task_struct *tsk, unsigned int offset) { } + static inline void vtime_account_softirq(struct task_struct *tsk) { } + static inline void vtime_account_hardirq(struct task_struct *tsk) { } + static inline void vtime_flush(struct task_struct *tsk) { } ++static inline void vtime_reset(void) { } ++static inline void vtime_dyntick_start(void) { } ++static inline void vtime_dyntick_stop(void) { } + #endif + + /* +-- +2.53.0 + diff --git a/queue-7.1/powerpc-vtime-initialize-starttime-at-boot-for-nativ.patch b/queue-7.1/powerpc-vtime-initialize-starttime-at-boot-for-nativ.patch new file mode 100644 index 0000000000..76179dd248 --- /dev/null +++ b/queue-7.1/powerpc-vtime-initialize-starttime-at-boot-for-nativ.patch @@ -0,0 +1,90 @@ +From 549994e3e6a9e20c7768b8030d66fdf08cee20d4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 5 Jun 2026 18:13:29 +0530 +Subject: powerpc/vtime: Initialize starttime at boot for native accounting + +From: Shrikanth Hegde + +[ Upstream commit c1c1ffa490fc33591e90852ed0d38804dd20bc36 ] + +It was observed that /proc/stat had very large value for one ore more +CPUs. It was more visible after recent code simplifications around +cpustats. + +System has 240 CPUs. + +cat /proc/uptime; +194.18 46500.55 +cat /proc/stat +cpu 5966 39 837032887 4650070 164 185 100 0 0 0 +cpu0 108 0 837030890 19109 24 4 23 0 0 0 + +Since uptime is 194s, system time of each CPU can't be more than 19400. +Sum of system time of all CPUs can't be more than 19400*240 4656000. +In fact huge value is close to mftb(). Note mftb doesn't reset on powerVM +when the LPAR restart. It only resets when whole system resets. The same +issue exists for kexec too. + +This happens since starttime is not setup at init time. Once it is set +then subsequent vtime_delta will return the right delta. + +Fix it by initializing the starttime during CPU initialization. This +fixes the large times seen. + +cat /proc/uptime; cat /proc/stat +15.78 3694.63 +cpu 6035 35 1347 369479 23 144 49 0 0 0 +cpu0 19 0 38 1508 0 1 14 0 0 0 + +Now, system time is reported as expected. + +Fixes: cf9efce0ce31 ("powerpc: Account time using timebase rather than PURR") +Reviewed-by: Christophe Leroy (CS GROUP) +Suggested-by: Christophe Leroy (CS GROUP) +Signed-off-by: Shrikanth Hegde +Signed-off-by: Madhavan Srinivasan +Link: https://patch.msgid.link/20260605124329.377533-1-sshegde@linux.ibm.com +Signed-off-by: Sasha Levin +--- + arch/powerpc/kernel/time.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c +index 3460d1a5a97c2a..11145c40183dd1 100644 +--- a/arch/powerpc/kernel/time.c ++++ b/arch/powerpc/kernel/time.c +@@ -377,7 +377,6 @@ void vtime_task_switch(struct task_struct *prev) + } + } + +-#ifdef CONFIG_NO_HZ_COMMON + /** + * vtime_reset - Fast forward vtime entry clocks + * +@@ -394,6 +393,7 @@ void vtime_reset(void) + #endif + } + ++#ifdef CONFIG_NO_HZ_COMMON + /** + * vtime_dyntick_start - Inform vtime about entry to idle-dynticks + * +@@ -933,6 +933,7 @@ static void __init set_decrementer_max(void) + static void __init init_decrementer_clockevent(void) + { + register_decrementer_clockevent(smp_processor_id()); ++ vtime_reset(); + } + + void secondary_cpu_time_init(void) +@@ -948,6 +949,7 @@ void secondary_cpu_time_init(void) + /* FIME: Should make unrelated change to move snapshot_timebase + * call here ! */ + register_decrementer_clockevent(smp_processor_id()); ++ vtime_reset(); + } + + /* +-- +2.53.0 + diff --git a/queue-7.1/ppp-defer-channel-free-to-an-rcu-grace-period-to-fix.patch b/queue-7.1/ppp-defer-channel-free-to-an-rcu-grace-period-to-fix.patch new file mode 100644 index 0000000000..2b698a1d8b --- /dev/null +++ b/queue-7.1/ppp-defer-channel-free-to-an-rcu-grace-period-to-fix.patch @@ -0,0 +1,104 @@ +From 76e4e6adc75b897bca5e1e852a70bb9b42c5cc22 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 6 Jul 2026 11:01:59 +0200 +Subject: ppp: defer channel free to an RCU grace period to fix pppol2tp RX UAF + +From: Norbert Szetei + +[ Upstream commit ec4215683e47424c9c4762fd3c60f552a3119142 ] + +pppol2tp_recv() runs in the L2TP UDP-encap softirq RX path: + + l2tp_udp_encap_recv() -> l2tp_recv_common() -> pppol2tp_recv() + -> ppp_input(&po->chan) + +It runs under rcu_read_lock() holding only an l2tp_session reference and +takes NO reference on the internal PPP channel (struct channel, +chan->ppp) that ppp_input() dereferences. + +The pppox socket is SOCK_RCU_FREE, so 'po' and the embedded ppp_channel +are RCU-safe. But the internal struct channel is a separate allocation +that ppp_release_channel() frees with a plain kfree(): + + close(data socket) -> pppol2tp_release() -> pppox_unbind_sock() + -> ppp_unregister_channel() -> ppp_release_channel() -> kfree(pch) + +For a channel that is bound (PPPIOCGCHAN) but not attached to a ppp unit +(no PPPIOCCONNECT, pch->ppp == NULL) and not bridged, teardown skips +both ppp_disconnect_channel()'s synchronize_net() and +ppp_unbridge_channels()'s synchronize_rcu(), so the kfree() has no grace +period. rcu_read_lock() in pppol2tp_recv() does not protect against a +plain kfree(), so an in-flight ppp_input() on one CPU can dereference +the channel just freed by close() on another CPU. + +The bug is reachable by an unprivileged user. + +Defer the channel free to an RCU callback via call_rcu() so the grace +period fences any in-flight ppp_input(). The disconnect and unbridge +teardown paths already fence with synchronize_net()/synchronize_rcu(); +call_rcu() does the same here without stalling the close() path. + +Fixes: ee40fb2e1eb5 ("l2tp: protect sock pointer of struct pppol2tp_session with RCU") +Assisted-by: Claude:claude-opus-4-8 +Signed-off-by: Norbert Szetei +Reviewed-by: Qingfang Deng +Link: https://patch.msgid.link/E793FCF2-58DE-4387-A983-C7B4BC3158BD@doyensec.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ppp/ppp_generic.c | 18 +++++++++++++++--- + 1 file changed, 15 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c +index 57c68efa5ff81d..717c1d3aa95380 100644 +--- a/drivers/net/ppp/ppp_generic.c ++++ b/drivers/net/ppp/ppp_generic.c +@@ -184,6 +184,7 @@ struct channel { + struct list_head clist; /* link in list of channels per unit */ + spinlock_t upl; /* protects `ppp' and 'bridge' */ + struct channel __rcu *bridge; /* "bridged" ppp channel */ ++ struct rcu_head rcu; /* for RCU-deferred free of the channel */ + #ifdef CONFIG_PPP_MULTILINK + u8 avail; /* flag used in multilink stuff */ + u8 had_frag; /* >= 1 fragments have been sent */ +@@ -3562,6 +3563,18 @@ ppp_disconnect_channel(struct channel *pch) + return err; + } + ++/* Purge after the grace period: a late ppp_input() may still queue an ++ * skb on pch->file.rq before the last RCU reader drains. ++ */ ++static void ppp_release_channel_free(struct rcu_head *rcu) ++{ ++ struct channel *pch = container_of(rcu, struct channel, rcu); ++ ++ skb_queue_purge(&pch->file.xq); ++ skb_queue_purge(&pch->file.rq); ++ kfree(pch); ++} ++ + /* + * Drop a reference to a ppp channel and free its memory if the refcount reaches + * zero. +@@ -3581,9 +3594,7 @@ static void ppp_release_channel(struct channel *pch) + pr_err("ppp: destroying undead channel %p !\n", pch); + return; + } +- skb_queue_purge(&pch->file.xq); +- skb_queue_purge(&pch->file.rq); +- kfree(pch); ++ call_rcu(&pch->rcu, ppp_release_channel_free); + } + + static void __exit ppp_cleanup(void) +@@ -3596,6 +3607,7 @@ static void __exit ppp_cleanup(void) + device_destroy(&ppp_class, MKDEV(PPP_MAJOR, 0)); + class_unregister(&ppp_class); + unregister_pernet_device(&ppp_net_ops); ++ rcu_barrier(); /* wait for RCU callbacks before module unload */ + } + + /* +-- +2.53.0 + diff --git a/queue-7.1/rdma-cma-fix-hardware-address-comparison-length-in-n.patch b/queue-7.1/rdma-cma-fix-hardware-address-comparison-length-in-n.patch new file mode 100644 index 0000000000..6d5be1d3db --- /dev/null +++ b/queue-7.1/rdma-cma-fix-hardware-address-comparison-length-in-n.patch @@ -0,0 +1,43 @@ +From d645cd636b6bcd8f91d49e1609954a0b6cab8493 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 17 Jun 2026 14:21:05 +0300 +Subject: RDMA/cma: Fix hardware address comparison length in netevent callback + +From: Or Gerlitz + +[ Upstream commit 18313833e2c6de222a4f6c072da759d0d5888528 ] + +The cited commit hardcoded the hardware address comparison len to ETH_ALEN. + +This breaks IPoIB, which uses 20-byte addresses. By truncating the +memcmp, the CMA may incorrectly assume the target address is +unchanged and fails to abort the stalled connection. + +Fix this by replacing ETH_ALEN with the dynamic neigh->dev->addr_len +to correctly evaluate the full address regardless of the link layer. + +Fixes: 925d046e7e52 ("RDMA/core: Add a netevent notifier to cma") +Signed-off-by: Or Gerlitz +Link: https://patch.msgid.link/20260617-fix-cma-ipoib-v1-1-03f869344304@ddn.com +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + drivers/infiniband/core/cma.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c +index 9480d1a51c116e..e88d3efb967b3b 100644 +--- a/drivers/infiniband/core/cma.c ++++ b/drivers/infiniband/core/cma.c +@@ -5270,7 +5270,7 @@ static int cma_netevent_callback(struct notifier_block *self, + + list_for_each_entry(current_id, &ips_node->id_list, id_list_entry) { + if (!memcmp(current_id->id.route.addr.dev_addr.dst_dev_addr, +- neigh->ha, ETH_ALEN)) ++ neigh->ha, neigh->dev->addr_len)) + continue; + cma_id_get(current_id); + if (!queue_work(cma_wq, ¤t_id->id.net_work)) +-- +2.53.0 + diff --git a/queue-7.1/rdma-core-fix-memory-leak-in-__ib_create_cq-on-inval.patch b/queue-7.1/rdma-core-fix-memory-leak-in-__ib_create_cq-on-inval.patch new file mode 100644 index 0000000000..1584de7ae2 --- /dev/null +++ b/queue-7.1/rdma-core-fix-memory-leak-in-__ib_create_cq-on-inval.patch @@ -0,0 +1,46 @@ +From ee0b2558f1b1e76d34ce4ff285e0806b268fae17 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 25 Jun 2026 10:01:48 +0800 +Subject: RDMA/core: Fix memory leak in __ib_create_cq() on invalid cqe + +From: Chenguang Zhao + +[ Upstream commit e939334ea7dd219f100f963dbb1cb43df520c20a ] + +Move the zero CQE validation before rdma_zalloc_drv_obj() to avoid +leaking the CQ object when returning -EINVAL. + +Fixes: a2917582887a ("RDMA/core: Reject zero CQE count") +Link: https://patch.msgid.link/r/20260625020148.224537-1-zhaochenguang@kylinos.cn +Signed-off-by: Chenguang Zhao +Reviewed-by: Kalesh AP +Signed-off-by: Jason Gunthorpe +Signed-off-by: Sasha Levin +--- + drivers/infiniband/core/verbs.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/infiniband/core/verbs.c b/drivers/infiniband/core/verbs.c +index bac87de9cc6735..2f3237e6086b9b 100644 +--- a/drivers/infiniband/core/verbs.c ++++ b/drivers/infiniband/core/verbs.c +@@ -2199,13 +2199,13 @@ struct ib_cq *__ib_create_cq(struct ib_device *device, + struct ib_cq *cq; + int ret; + ++ if (WARN_ON_ONCE(!cq_attr->cqe)) ++ return ERR_PTR(-EINVAL); ++ + cq = rdma_zalloc_drv_obj(device, ib_cq); + if (!cq) + return ERR_PTR(-ENOMEM); + +- if (WARN_ON_ONCE(!cq_attr->cqe)) +- return ERR_PTR(-EINVAL); +- + cq->device = device; + cq->comp_handler = comp_handler; + cq->event_handler = event_handler; +-- +2.53.0 + diff --git a/queue-7.1/rdma-erdma-initialize-ret-for-empty-receive-wr-lists.patch b/queue-7.1/rdma-erdma-initialize-ret-for-empty-receive-wr-lists.patch new file mode 100644 index 0000000000..eb0bee7fb7 --- /dev/null +++ b/queue-7.1/rdma-erdma-initialize-ret-for-empty-receive-wr-lists.patch @@ -0,0 +1,42 @@ +From 29c11b10c4417645f9f3e03c996a0e24651c586b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 18 Jun 2026 12:17:51 +0800 +Subject: RDMA/erdma: initialize ret for empty receive WR lists + +From: Ruoyu Wang + +[ Upstream commit 2815a277c53e9a84784d6410cd55a9da5b33068d ] + +erdma_post_recv() returns ret after walking the receive work request list. +If the caller passes an empty list, the loop is skipped and ret is not +assigned. + +Initialize ret to 0 so an empty receive work request list returns success +instead of stack data. + +Fixes: 155055771704 ("RDMA/erdma: Add verbs implementation") +Link: https://patch.msgid.link/r/20260618041752.481193-1-ruoyuw560@gmail.com +Signed-off-by: Ruoyu Wang +Reviewed-by: Cheng Xu +Signed-off-by: Jason Gunthorpe +Signed-off-by: Sasha Levin +--- + drivers/infiniband/hw/erdma/erdma_qp.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/infiniband/hw/erdma/erdma_qp.c b/drivers/infiniband/hw/erdma/erdma_qp.c +index 25f6c49aec7798..e002343832f74d 100644 +--- a/drivers/infiniband/hw/erdma/erdma_qp.c ++++ b/drivers/infiniband/hw/erdma/erdma_qp.c +@@ -734,7 +734,7 @@ int erdma_post_recv(struct ib_qp *ibqp, const struct ib_recv_wr *recv_wr, + const struct ib_recv_wr *wr = recv_wr; + struct erdma_qp *qp = to_eqp(ibqp); + unsigned long flags; +- int ret; ++ int ret = 0; + + spin_lock_irqsave(&qp->lock, flags); + +-- +2.53.0 + diff --git a/queue-7.1/rdma-hns-fix-potential-integer-overflow-in-mhop-hem-.patch b/queue-7.1/rdma-hns-fix-potential-integer-overflow-in-mhop-hem-.patch new file mode 100644 index 0000000000..18c83fc60a --- /dev/null +++ b/queue-7.1/rdma-hns-fix-potential-integer-overflow-in-mhop-hem-.patch @@ -0,0 +1,52 @@ +From 35d0a2581e62a2889978f587729d711215c7c379 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 27 Jun 2026 09:59:51 +0000 +Subject: RDMA/hns: Fix potential integer overflow in mhop hem cleanup + +From: Danila Chernetsov + +[ Upstream commit 9f0f2d2121f16d420199a82ac5bbc242269133b3 ] + +In hns_roce_cleanup_mhop_hem_table(), the expression: + + obj = i * buf_chunk_size / table->obj_size; + +is evaluated using 32-bit unsigned arithmetic because +'buf_chunk_size' is u32 and the usual arithmetic conversions convert +'i' to unsigned int. The result is assigned to a u64 variable, but the +multiplication may overflow before the assignment. + +For sufficiently large HEM tables, this produces an incorrect object +index passed to hns_roce_table_mhop_put(). + +Cast 'i' to u64 before the multiplication so that the intermediate +calculation is performed with 64-bit arithmetic. + +Found by Linux Verification Center (linuxtesting.org) with SVACE. + +Fixes: a25d13cbe816 ("RDMA/hns: Add the interfaces to support multi hop addressing for the contexts in hip08") +Link: https://patch.msgid.link/r/20260627095951.51378-1-listdansp@mail.ru +Signed-off-by: Danila Chernetsov +Reviewed-by: Junxian Huang +Signed-off-by: Jason Gunthorpe +Signed-off-by: Sasha Levin +--- + drivers/infiniband/hw/hns/hns_roce_hem.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/infiniband/hw/hns/hns_roce_hem.c b/drivers/infiniband/hw/hns/hns_roce_hem.c +index ccb40f8a48b726..a38bfd9a0fe243 100644 +--- a/drivers/infiniband/hw/hns/hns_roce_hem.c ++++ b/drivers/infiniband/hw/hns/hns_roce_hem.c +@@ -836,7 +836,7 @@ static void hns_roce_cleanup_mhop_hem_table(struct hns_roce_dev *hr_dev, + mhop.bt_chunk_size; + + for (i = 0; i < table->num_hem; ++i) { +- obj = i * buf_chunk_size / table->obj_size; ++ obj = (u64)i * buf_chunk_size / table->obj_size; + if (table->hem[i]) + hns_roce_table_mhop_put(hr_dev, table, obj, 0); + } +-- +2.53.0 + diff --git a/queue-7.1/rdma-irdma-prevent-overflows-in-memory-contiguity-ch.patch b/queue-7.1/rdma-irdma-prevent-overflows-in-memory-contiguity-ch.patch new file mode 100644 index 0000000000..48ee94d3fc --- /dev/null +++ b/queue-7.1/rdma-irdma-prevent-overflows-in-memory-contiguity-ch.patch @@ -0,0 +1,64 @@ +From 47707891cb6d5d8b78b0a98b7ed0a80ca41ee122 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 24 Jun 2026 17:48:46 +0300 +Subject: RDMA/irdma: Prevent overflows in memory contiguity checks + +From: Aleksandrova Alyona + +[ Upstream commit 3cda0dfe8c651dcbb9e38977905d3d3b1750c4ab ] + +irdma_check_mem_contiguous() and irdma_check_mr_contiguous() verify that +PBL entries describe physically contiguous memory ranges. + +Both functions calculate byte offsets using 32-bit operands. For example, +with 4 KiB pages, pg_size * pg_idx overflows 32-bit arithmetic when +pg_idx reaches 1048576. In the level-2 check, PBLE_PER_PAGE is 512, so +i * pg_size * PBLE_PER_PAGE overflows when i reaches 2048. + +These values are reachable in the driver. For MRs, palloc->total_cnt +comes from iwmr->page_cnt, which is calculated by +ib_umem_num_dma_blocks(). The MR size is limited by IRDMA_MAX_MR_SIZE, +so a 4 GiB MR with 4 KiB pages can reach page_cnt of 1048576. PBLE +resources do not exclude this value either: for gen3, the limit is based +on avail_sds * MAX_PBLE_PER_SD, and MAX_PBLE_PER_SD is 0x40000, so 4 SDs +are enough for 1048576 PBLEs. + +Cast one operand to u64 before the multiplications so that the offset +calculations are performed in 64-bit arithmetic. + +Found by Linux Verification Center (linuxtesting.org) with SVACE. + +Fixes: b48c24c2d710 ("RDMA/irdma: Implement device supported verb APIs") +Signed-off-by: Aleksandrova Alyona +Link: https://patch.msgid.link/20260624144846.61242-1-aga@itb.spb.ru +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + drivers/infiniband/hw/irdma/verbs.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/infiniband/hw/irdma/verbs.c b/drivers/infiniband/hw/irdma/verbs.c +index e7f6ebd9c9557d..a886029411b81f 100644 +--- a/drivers/infiniband/hw/irdma/verbs.c ++++ b/drivers/infiniband/hw/irdma/verbs.c +@@ -2815,7 +2815,7 @@ static bool irdma_check_mem_contiguous(u64 *arr, u32 npages, u32 pg_size) + u32 pg_idx; + + for (pg_idx = 0; pg_idx < npages; pg_idx++) { +- if ((*arr + (pg_size * pg_idx)) != arr[pg_idx]) ++ if ((*arr + ((u64)pg_size * pg_idx)) != arr[pg_idx]) + return false; + } + +@@ -2848,7 +2848,7 @@ static bool irdma_check_mr_contiguous(struct irdma_pble_alloc *palloc, + + for (i = 0; i < lvl2->leaf_cnt; i++, leaf++) { + arr = leaf->addr; +- if ((*start_addr + (i * pg_size * PBLE_PER_PAGE)) != *arr) ++ if ((*start_addr + ((u64)i * pg_size * PBLE_PER_PAGE)) != *arr) + return false; + ret = irdma_check_mem_contiguous(arr, leaf->cnt, pg_size); + if (!ret) +-- +2.53.0 + diff --git a/queue-7.1/rdma-irdma-prevent-rereg_mr-for-non-mem-regions.patch b/queue-7.1/rdma-irdma-prevent-rereg_mr-for-non-mem-regions.patch new file mode 100644 index 0000000000..8f62f99d86 --- /dev/null +++ b/queue-7.1/rdma-irdma-prevent-rereg_mr-for-non-mem-regions.patch @@ -0,0 +1,51 @@ +From ff24e9ad8c433500ee63795a896a16a4bf78a6a5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 17 Jun 2026 14:19:36 +0000 +Subject: RDMA/irdma: Prevent rereg_mr for non-mem regions + +From: Jacob Moroni + +[ Upstream commit a846aecb931b4d65d5eafa92a0623545af46d4f2 ] + +When a QP/CQ/SRQ is created, a two step process is used +where the buffer is allocated in userspace and explicitly +registered with the normal reg_mr mechanism prior to creating +the actual QP/CQ/SRQ object. + +These special registrations are indicated via an ABI field +so the driver knows that they do not have a valid mkey and +to skip the actual CQP command submission. + +Since these are real MR objects from the core's perspective, +it is possible for a user application to invoke rereg_mr on them +and cause a real CQP op to be emitted with the zero-initialized +mkey value of 0. + +Fix this by preventing rereg_mr on these special regions. + +Fixes: 5ac388db27c4 ("RDMA/irdma: Add support to re-register a memory region") +Signed-off-by: Jacob Moroni +Reviewed-by: David Hu +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + drivers/infiniband/hw/irdma/verbs.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/infiniband/hw/irdma/verbs.c b/drivers/infiniband/hw/irdma/verbs.c +index 7da7a7e8b30ca2..a33bd3c8571247 100644 +--- a/drivers/infiniband/hw/irdma/verbs.c ++++ b/drivers/infiniband/hw/irdma/verbs.c +@@ -3810,6 +3810,9 @@ static struct ib_mr *irdma_rereg_user_mr(struct ib_mr *ib_mr, int flags, + if (flags & ~(IB_MR_REREG_TRANS | IB_MR_REREG_PD | IB_MR_REREG_ACCESS)) + return ERR_PTR(-EOPNOTSUPP); + ++ if (iwmr->type != IRDMA_MEMREG_TYPE_MEM) ++ return ERR_PTR(-EINVAL); ++ + ret = ib_umem_check_rereg(iwmr->region, flags, new_access); + if (ret) + return ERR_PTR(ret); +-- +2.53.0 + diff --git a/queue-7.1/rdma-irdma-prevent-user-triggered-null-deref-on-qp-c.patch b/queue-7.1/rdma-irdma-prevent-user-triggered-null-deref-on-qp-c.patch new file mode 100644 index 0000000000..70b616342d --- /dev/null +++ b/queue-7.1/rdma-irdma-prevent-user-triggered-null-deref-on-qp-c.patch @@ -0,0 +1,66 @@ +From 3f368eb68d82be278d32f668d21f387beecc8b1b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 17 Jun 2026 16:40:13 +0000 +Subject: RDMA/irdma: Prevent user-triggered null deref on QP create + +From: Jacob Moroni + +[ Upstream commit b9b0889071569d43623c260074e159cd8f26adb1 ] + +Previously, the user QP creation path would only attempt to +populate iwqp->iwpbl if the user-provided req.user_wqe_bufs +field was non-zero. The problem is that iwqp->iwpbl is +unconditionally dereferenced later on in irdma_setup_virt_qp. + +While there was a check for iwqp->iwpbl != NULL, this check +would only occur if req.user_wqe_bufs was non-zero. The end +result is that a user could send a zero user_wqe_bufs value +and trigger a null ptr deref. + +Fix this by unconditionally calling irdma_get_pbl and bailing +if it fails, similar to the CQ and SRQ paths. + +Fixes: b48c24c2d710 ("RDMA/irdma: Implement device supported verb APIs") +Link: https://patch.msgid.link/r/20260617164013.280790-1-jmoroni@google.com +Signed-off-by: Jacob Moroni +Reviewed-by: David Hu +Signed-off-by: Jason Gunthorpe +Signed-off-by: Sasha Levin +--- + drivers/infiniband/hw/irdma/verbs.c | 19 +++++++++---------- + 1 file changed, 9 insertions(+), 10 deletions(-) + +diff --git a/drivers/infiniband/hw/irdma/verbs.c b/drivers/infiniband/hw/irdma/verbs.c +index 7ab08f324eb9a2..e7f6ebd9c9557d 100644 +--- a/drivers/infiniband/hw/irdma/verbs.c ++++ b/drivers/infiniband/hw/irdma/verbs.c +@@ -633,17 +633,16 @@ static int irdma_setup_umode_qp(struct ib_udata *udata, + + iwqp->ctx_info.qp_compl_ctx = req.user_compl_ctx; + iwqp->user_mode = 1; +- if (req.user_wqe_bufs) { +- spin_lock_irqsave(&ucontext->qp_reg_mem_list_lock, flags); +- iwqp->iwpbl = irdma_get_pbl((unsigned long)req.user_wqe_bufs, +- &ucontext->qp_reg_mem_list); +- spin_unlock_irqrestore(&ucontext->qp_reg_mem_list_lock, flags); + +- if (!iwqp->iwpbl) { +- ret = -ENODATA; +- ibdev_dbg(&iwdev->ibdev, "VERBS: no pbl info\n"); +- return ret; +- } ++ spin_lock_irqsave(&ucontext->qp_reg_mem_list_lock, flags); ++ iwqp->iwpbl = irdma_get_pbl((unsigned long)req.user_wqe_bufs, ++ &ucontext->qp_reg_mem_list); ++ spin_unlock_irqrestore(&ucontext->qp_reg_mem_list_lock, flags); ++ ++ if (!iwqp->iwpbl) { ++ ret = -ENODATA; ++ ibdev_dbg(&iwdev->ibdev, "VERBS: no pbl info\n"); ++ return ret; + } + + if (!ucontext->use_raw_attrs) { +-- +2.53.0 + diff --git a/queue-7.1/rdma-irdma-remove-redundant-legacy_mode-checks.patch b/queue-7.1/rdma-irdma-remove-redundant-legacy_mode-checks.patch new file mode 100644 index 0000000000..f8430a8a3f --- /dev/null +++ b/queue-7.1/rdma-irdma-remove-redundant-legacy_mode-checks.patch @@ -0,0 +1,110 @@ +From 9f33fc6df425095e54961fb9d061cd345b5f23ff Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 2 Jun 2026 21:44:22 +0000 +Subject: RDMA/irdma: Remove redundant legacy_mode checks + +From: Jacob Moroni + +[ Upstream commit ed8621be482bf18dcd217aa024e95758bf9d28f2 ] + +The driver has the following invariants: + +1. legacy_mode is only allowed on GEN_1 hardware (enforced + in irdma_alloc_ucontext). + +2. GEN_1 hardware does not set IRDMA_FEATURE_CQ_RESIZE or + IRDMA_FEATURE_RTS_AE. These feature flags are only set + for GEN_2 and GEN_3 hardware. + +Therefore, legacy_mode is always false if IRDMA_FEATURE_CQ_RESIZE +or IRDMA_FEATURE_RTS_AE is set, so remove the redundant checks. + +Link: https://patch.msgid.link/r/20260602214423.1315105-1-jmoroni@google.com +Signed-off-by: Jacob Moroni +Signed-off-by: Jason Gunthorpe +Stable-dep-of: b9b088907156 ("RDMA/irdma: Prevent user-triggered null deref on QP create") +Signed-off-by: Sasha Levin +--- + drivers/infiniband/hw/irdma/uk.c | 9 +++------ + drivers/infiniband/hw/irdma/user.h | 1 - + drivers/infiniband/hw/irdma/verbs.c | 7 +------ + 3 files changed, 4 insertions(+), 13 deletions(-) + +diff --git a/drivers/infiniband/hw/irdma/uk.c b/drivers/infiniband/hw/irdma/uk.c +index 4718acf6c6fd00..a34883fe998368 100644 +--- a/drivers/infiniband/hw/irdma/uk.c ++++ b/drivers/infiniband/hw/irdma/uk.c +@@ -1568,15 +1568,12 @@ static const struct irdma_wqe_uk_ops iw_wqe_uk_ops_gen_1 = { + * irdma_setup_connection_wqes - setup WQEs necessary to complete + * connection. + * @qp: hw qp (user and kernel) +- * @info: qp initialization info + */ +-static void irdma_setup_connection_wqes(struct irdma_qp_uk *qp, +- struct irdma_qp_uk_init_info *info) ++static void irdma_setup_connection_wqes(struct irdma_qp_uk *qp) + { + u16 move_cnt = 1; + +- if (!info->legacy_mode && +- (qp->uk_attrs->feature_flags & IRDMA_FEATURE_RTS_AE)) ++ if (qp->uk_attrs->feature_flags & IRDMA_FEATURE_RTS_AE) + move_cnt = 3; + + qp->conn_wqes = move_cnt; +@@ -1727,7 +1724,7 @@ int irdma_uk_qp_init(struct irdma_qp_uk *qp, struct irdma_qp_uk_init_info *info) + sq_ring_size = qp->sq_size << info->sq_shift; + IRDMA_RING_INIT(qp->sq_ring, sq_ring_size); + if (info->first_sq_wq) { +- irdma_setup_connection_wqes(qp, info); ++ irdma_setup_connection_wqes(qp); + qp->swqe_polarity = 1; + qp->first_sq_wq = true; + } else { +diff --git a/drivers/infiniband/hw/irdma/user.h b/drivers/infiniband/hw/irdma/user.h +index 008af1acc92884..4dd3776a4cddb6 100644 +--- a/drivers/infiniband/hw/irdma/user.h ++++ b/drivers/infiniband/hw/irdma/user.h +@@ -563,7 +563,6 @@ struct irdma_qp_uk_init_info { + u8 sq_shift; + u8 rq_shift; + int abi_ver; +- bool legacy_mode; + struct irdma_srq_uk *srq_uk; + }; + +diff --git a/drivers/infiniband/hw/irdma/verbs.c b/drivers/infiniband/hw/irdma/verbs.c +index a33bd3c8571247..7ab08f324eb9a2 100644 +--- a/drivers/infiniband/hw/irdma/verbs.c ++++ b/drivers/infiniband/hw/irdma/verbs.c +@@ -634,7 +634,6 @@ static int irdma_setup_umode_qp(struct ib_udata *udata, + iwqp->ctx_info.qp_compl_ctx = req.user_compl_ctx; + iwqp->user_mode = 1; + if (req.user_wqe_bufs) { +- info->qp_uk_init_info.legacy_mode = ucontext->legacy_mode; + spin_lock_irqsave(&ucontext->qp_reg_mem_list_lock, flags); + iwqp->iwpbl = irdma_get_pbl((unsigned long)req.user_wqe_bufs, + &ucontext->qp_reg_mem_list); +@@ -2074,10 +2073,6 @@ static int irdma_resize_cq(struct ib_cq *ibcq, unsigned int entries, + rdma_udata_to_drv_context(udata, struct irdma_ucontext, + ibucontext); + +- /* CQ resize not supported with legacy GEN_1 libi40iw */ +- if (ucontext->legacy_mode) +- return -EOPNOTSUPP; +- + if (ib_copy_from_udata(&req, udata, + min(sizeof(req), udata->inlen))) + return -EINVAL; +@@ -2559,7 +2554,7 @@ static int irdma_create_cq(struct ib_cq *ibcq, + cqmr = &iwpbl->cq_mr; + + if (rf->sc_dev.hw_attrs.uk_attrs.feature_flags & +- IRDMA_FEATURE_CQ_RESIZE && !ucontext->legacy_mode) { ++ IRDMA_FEATURE_CQ_RESIZE) { + spin_lock_irqsave(&ucontext->cq_reg_mem_list_lock, flags); + iwpbl_shadow = irdma_get_pbl( + (unsigned long)req.user_shadow_area, +-- +2.53.0 + diff --git a/queue-7.1/rdma-mana_ib-initialize-err-for-empty-send-wr-lists.patch b/queue-7.1/rdma-mana_ib-initialize-err-for-empty-send-wr-lists.patch new file mode 100644 index 0000000000..1ca2eef59c --- /dev/null +++ b/queue-7.1/rdma-mana_ib-initialize-err-for-empty-send-wr-lists.patch @@ -0,0 +1,42 @@ +From 0f10d4ac619a720c8b3e214bd41ee6cca3c5dc97 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 18 Jun 2026 12:17:52 +0800 +Subject: RDMA/mana_ib: initialize err for empty send WR lists + +From: Ruoyu Wang + +[ Upstream commit 155fd5ce2382b0ffbec0d7ee7b3a6818a27a5aed ] + +mana_ib_post_send() returns err after walking the send work request list. +If the caller passes an empty list, the loop is skipped and err is not +assigned. + +Initialize err to 0 so an empty send work request list returns success +instead of stack data. + +Fixes: c8017f5b4856 ("RDMA/mana_ib: UD/GSI work requests") +Link: https://patch.msgid.link/r/20260618041752.481193-2-ruoyuw560@gmail.com +Signed-off-by: Ruoyu Wang +Reviewed-by: Long Li +Signed-off-by: Jason Gunthorpe +Signed-off-by: Sasha Levin +--- + drivers/infiniband/hw/mana/wr.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/infiniband/hw/mana/wr.c b/drivers/infiniband/hw/mana/wr.c +index 1813567d3b16c9..36a1d506f08f65 100644 +--- a/drivers/infiniband/hw/mana/wr.c ++++ b/drivers/infiniband/hw/mana/wr.c +@@ -144,7 +144,7 @@ static int mana_ib_post_send_ud(struct mana_ib_qp *qp, const struct ib_ud_wr *wr + int mana_ib_post_send(struct ib_qp *ibqp, const struct ib_send_wr *wr, + const struct ib_send_wr **bad_wr) + { +- int err; ++ int err = 0; + struct mana_ib_qp *qp = container_of(ibqp, struct mana_ib_qp, ibqp); + + for (; wr; wr = wr->next) { +-- +2.53.0 + diff --git a/queue-7.1/rdma-siw-publish-qp-after-initialization.patch b/queue-7.1/rdma-siw-publish-qp-after-initialization.patch new file mode 100644 index 0000000000..d7463a656c --- /dev/null +++ b/queue-7.1/rdma-siw-publish-qp-after-initialization.patch @@ -0,0 +1,153 @@ +From 4befd8f93b4b7d8c7387e143d07e06f29b582f4a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 30 Jun 2026 14:00:40 +0800 +Subject: RDMA/siw: publish QP after initialization + +From: Ruoyu Wang + +[ Upstream commit bb27fcc67c429d97f785c92c35a6c5adebb05d7f ] + +siw_create_qp() currently calls siw_qp_add() before the queues, CQ +pointers, state, completion, and device list entry are ready. A QPN +lookup can therefore reach a QP that is still being constructed. + +Move siw_qp_add() to the end of siw_create_qp(), after QP +initialization and before adding the QP to the siw device list. + +Fixes: f29dd55b0236 ("rdma/siw: queue pair methods") +Link: https://patch.msgid.link/r/20260630060040.966461-1-ruoyuw560@gmail.com +Suggested-by: Bernard Metzler +Signed-off-by: Ruoyu Wang +Acked-by: Bernard Metzler +Signed-off-by: Jason Gunthorpe +Signed-off-by: Sasha Levin +--- + drivers/infiniband/sw/siw/siw_verbs.c | 44 +++++++++++++++------------ + 1 file changed, 24 insertions(+), 20 deletions(-) + +diff --git a/drivers/infiniband/sw/siw/siw_verbs.c b/drivers/infiniband/sw/siw/siw_verbs.c +index 1e1d262a4ae2db..a513ca96259fd2 100644 +--- a/drivers/infiniband/sw/siw/siw_verbs.c ++++ b/drivers/infiniband/sw/siw/siw_verbs.c +@@ -316,6 +316,7 @@ int siw_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attrs, + struct siw_ucontext *uctx = + rdma_udata_to_drv_context(udata, struct siw_ucontext, + base_ucontext); ++ struct siw_uresp_create_qp uresp = {}; + unsigned long flags; + int num_sqe, num_rqe, rv = 0; + size_t length; +@@ -369,11 +370,6 @@ int siw_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attrs, + spin_lock_init(&qp->rq_lock); + spin_lock_init(&qp->orq_lock); + +- rv = siw_qp_add(sdev, qp); +- if (rv) +- goto err_atomic; +- +- + /* All queue indices are derived from modulo operations + * on a free running 'get' (consumer) and 'put' (producer) + * unsigned counter. Having queue sizes at power of two +@@ -391,14 +387,14 @@ int siw_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attrs, + + if (qp->sendq == NULL) { + rv = -ENOMEM; +- goto err_out_xa; ++ goto err_out; + } + if (attrs->sq_sig_type != IB_SIGNAL_REQ_WR) { + if (attrs->sq_sig_type == IB_SIGNAL_ALL_WR) + qp->attrs.flags |= SIW_SIGNAL_ALL_WR; + else { + rv = -EINVAL; +- goto err_out_xa; ++ goto err_out; + } + } + qp->pd = pd; +@@ -424,7 +420,7 @@ int siw_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attrs, + + if (qp->recvq == NULL) { + rv = -ENOMEM; +- goto err_out_xa; ++ goto err_out; + } + qp->attrs.rq_size = num_rqe; + } +@@ -439,11 +435,8 @@ int siw_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attrs, + qp->attrs.state = SIW_QP_STATE_IDLE; + + if (udata) { +- struct siw_uresp_create_qp uresp = {}; +- + uresp.num_sqe = num_sqe; + uresp.num_rqe = num_rqe; +- uresp.qp_id = qp_id(qp); + + if (qp->sendq) { + length = num_sqe * sizeof(struct siw_sqe); +@@ -452,7 +445,7 @@ int siw_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attrs, + length, &uresp.sq_key); + if (!qp->sq_entry) { + rv = -ENOMEM; +- goto err_out_xa; ++ goto err_out; + } + } + +@@ -464,9 +457,23 @@ int siw_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attrs, + if (!qp->rq_entry) { + uresp.sq_key = SIW_INVAL_UOBJ_KEY; + rv = -ENOMEM; +- goto err_out_xa; ++ goto err_out; + } + } ++ } ++ qp->tx_cpu = siw_get_tx_cpu(sdev); ++ if (qp->tx_cpu < 0) { ++ rv = -EINVAL; ++ goto err_out; ++ } ++ init_completion(&qp->qp_free); ++ ++ rv = siw_qp_add(sdev, qp); ++ if (rv) ++ goto err_out_tx; ++ ++ if (udata) { ++ uresp.qp_id = qp_id(qp); + + if (udata->outlen < sizeof(uresp)) { + rv = -EINVAL; +@@ -476,22 +483,19 @@ int siw_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attrs, + if (rv) + goto err_out_xa; + } +- qp->tx_cpu = siw_get_tx_cpu(sdev); +- if (qp->tx_cpu < 0) { +- rv = -EINVAL; +- goto err_out_xa; +- } ++ + INIT_LIST_HEAD(&qp->devq); + spin_lock_irqsave(&sdev->lock, flags); + list_add_tail(&qp->devq, &sdev->qp_list); + spin_unlock_irqrestore(&sdev->lock, flags); + +- init_completion(&qp->qp_free); +- + return 0; + + err_out_xa: + xa_erase(&sdev->qp_xa, qp_id(qp)); ++err_out_tx: ++ siw_put_tx_cpu(qp->tx_cpu); ++err_out: + if (uctx) { + rdma_user_mmap_entry_remove(qp->sq_entry); + rdma_user_mmap_entry_remove(qp->rq_entry); +-- +2.53.0 + diff --git a/queue-7.1/reset-spacemit-k3-fix-usb2-ahb-reset.patch b/queue-7.1/reset-spacemit-k3-fix-usb2-ahb-reset.patch new file mode 100644 index 0000000000..b6c0865d9c --- /dev/null +++ b/queue-7.1/reset-spacemit-k3-fix-usb2-ahb-reset.patch @@ -0,0 +1,42 @@ +From 797a4676ed8f5e91b33f9f756e4dcbd0e5cd2cbc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 18 May 2026 02:58:37 +0000 +Subject: reset: spacemit: k3: fix USB2 ahb reset + +From: Yixun Lan + +[ Upstream commit 1ca22c6aa006b05143367268066fb74e32cfe66b ] + +According to SpacemiT K3's updated docs, the USB2 ahb reset and USB2 bus +clock enable bit was wrongly swapped, the correct one should be: + +Register : APMU_USB_CLK_RES_CTRL +bit[1] : usb2_port_bus_clk_en +bit[0] : usb2_port_ahb_rstn + +Fixes: a0e0c2f8c5f3 ("reset: spacemit: k3: Decouple composite reset lines") +Reported-by: Junzhong Pan +Signed-off-by: Yixun Lan +Reviewed-by: Philipp Zabel +Signed-off-by: Philipp Zabel +Signed-off-by: Sasha Levin +--- + drivers/reset/spacemit/reset-spacemit-k3.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/reset/spacemit/reset-spacemit-k3.c b/drivers/reset/spacemit/reset-spacemit-k3.c +index 9841f5e057b2a0..2e87f320cf1184 100644 +--- a/drivers/reset/spacemit/reset-spacemit-k3.c ++++ b/drivers/reset/spacemit/reset-spacemit-k3.c +@@ -112,7 +112,7 @@ static const struct ccu_reset_data k3_apmu_resets[] = { + [RESET_APMU_SDH0] = RESET_DATA(APMU_SDH0_CLK_RES_CTRL, 0, BIT(1)), + [RESET_APMU_SDH1] = RESET_DATA(APMU_SDH1_CLK_RES_CTRL, 0, BIT(1)), + [RESET_APMU_SDH2] = RESET_DATA(APMU_SDH2_CLK_RES_CTRL, 0, BIT(1)), +- [RESET_APMU_USB2_AHB] = RESET_DATA(APMU_USB_CLK_RES_CTRL, 0, BIT(1)), ++ [RESET_APMU_USB2_AHB] = RESET_DATA(APMU_USB_CLK_RES_CTRL, 0, BIT(0)), + [RESET_APMU_USB2_VCC] = RESET_DATA(APMU_USB_CLK_RES_CTRL, 0, BIT(2)), + [RESET_APMU_USB2_PHY] = RESET_DATA(APMU_USB_CLK_RES_CTRL, 0, BIT(3)), + [RESET_APMU_USB3_A_AHB] = RESET_DATA(APMU_USB_CLK_RES_CTRL, 0, BIT(5)), +-- +2.53.0 + diff --git a/queue-7.1/riscv-gate-function_alignment_4b-on-dynamic_ftrace.patch b/queue-7.1/riscv-gate-function_alignment_4b-on-dynamic_ftrace.patch new file mode 100644 index 0000000000..af26e34c7e --- /dev/null +++ b/queue-7.1/riscv-gate-function_alignment_4b-on-dynamic_ftrace.patch @@ -0,0 +1,53 @@ +From cae581b9743fc95c76c2c99da12f3737663eedf5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 6 Jul 2026 21:04:14 +0800 +Subject: riscv: Gate FUNCTION_ALIGNMENT_4B on DYNAMIC_FTRACE + +From: Rui Qi + +[ Upstream commit 3a2694bf6ac8e47b3814293e80343f58fc72937f ] + +The FUNCTION_ALIGNMENT_4B select forces the whole kernel to be built +with -fmin-function-alignment=4. This alignment is only needed so the +patchable-function-entry NOPs, which arch/riscv/Makefile emits under +CONFIG_DYNAMIC_FTRACE, can be patched reliably on RISCV_ISA_C=y builds +where compressed instructions otherwise allow 2-byte function +alignment. + +The select is currently gated on HAVE_DYNAMIC_FTRACE, a capability bit +that is selected whenever the toolchain supports dynamic ftrace, rather +than on whether tracing is actually enabled. As a result every +RISCV_ISA_C=y build gets 4-byte function alignment across the entire +kernel even when function tracing is disabled, needlessly growing the +kernel image and wasting instruction cache for a feature that is not +in use. + +Gate the select on DYNAMIC_FTRACE instead, matching the condition under +which arch/riscv/Makefile emits -fpatchable-function-entry, so the +alignment is only applied when it is actually needed. + +Fixes: c41bf4326c7b ("riscv: ftrace: align patchable functions to 4 Byte boundary") +Signed-off-by: Rui Qi +Link: https://patch.msgid.link/20260706130415.463682-1-qirui.001@bytedance.com +Signed-off-by: Paul Walmsley +Signed-off-by: Sasha Levin +--- + arch/riscv/Kconfig | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig +index c5754942cf85a4..e73f556720c1cf 100644 +--- a/arch/riscv/Kconfig ++++ b/arch/riscv/Kconfig +@@ -155,7 +155,7 @@ config RISCV + select HAVE_DEBUG_KMEMLEAK + select HAVE_DMA_CONTIGUOUS if MMU + select HAVE_DYNAMIC_FTRACE if MMU && (CLANG_SUPPORTS_DYNAMIC_FTRACE || GCC_SUPPORTS_DYNAMIC_FTRACE) +- select FUNCTION_ALIGNMENT_4B if HAVE_DYNAMIC_FTRACE && RISCV_ISA_C ++ select FUNCTION_ALIGNMENT_4B if DYNAMIC_FTRACE && RISCV_ISA_C + select HAVE_DYNAMIC_FTRACE_WITH_DIRECT_CALLS if HAVE_DYNAMIC_FTRACE_WITH_CALL_OPS + select HAVE_DYNAMIC_FTRACE_WITH_CALL_OPS if (DYNAMIC_FTRACE_WITH_ARGS && !CFI) + select HAVE_DYNAMIC_FTRACE_WITH_ARGS if HAVE_DYNAMIC_FTRACE +-- +2.53.0 + diff --git a/queue-7.1/riscv-hwprobe-avoid-uninitialized-read-in-hwprobe_ge.patch b/queue-7.1/riscv-hwprobe-avoid-uninitialized-read-in-hwprobe_ge.patch new file mode 100644 index 0000000000..fc7f2a52bc --- /dev/null +++ b/queue-7.1/riscv-hwprobe-avoid-uninitialized-read-in-hwprobe_ge.patch @@ -0,0 +1,41 @@ +From dc3c4ec4c3f42ed2b8d63e703a1a710a686d3fc4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 13 Jul 2026 17:30:56 -0700 +Subject: riscv: hwprobe: Avoid uninitialized read in hwprobe_get_cpus() + +From: Mark Harris + +[ Upstream commit 5caae1deee89a6582c761d5dcd4b924b744426cc ] + +When cpusetsize < cpumask_size(), hwprobe_get_cpus() did not fully +initialize its copy of the cpu mask, which could cause non-deterministic +results from the riscv_hwprobe syscall on a system with more than 8 CPUs +when the supplied cpu mask is empty. Address this by fully initializing +the cpu mask. + +Fixes: e178bf146e4b ("RISC-V: hwprobe: Introduce which-cpus flag") +Signed-off-by: Mark Harris +Reviewed-by: Nam Cao +Reviewed-by: Michael Ellerman +Link: https://patch.msgid.link/20260714003056.73707-1-mark.hsj@gmail.com +Signed-off-by: Paul Walmsley +Signed-off-by: Sasha Levin +--- + arch/riscv/kernel/sys_hwprobe.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/arch/riscv/kernel/sys_hwprobe.c b/arch/riscv/kernel/sys_hwprobe.c +index 1659d31fd288fc..caf6762427c87e 100644 +--- a/arch/riscv/kernel/sys_hwprobe.c ++++ b/arch/riscv/kernel/sys_hwprobe.c +@@ -450,6 +450,7 @@ static int hwprobe_get_cpus(struct riscv_hwprobe __user *pairs, + if (cpusetsize > cpumask_size()) + cpusetsize = cpumask_size(); + ++ cpumask_clear(&cpus); + ret = copy_from_user(&cpus, cpus_user, cpusetsize); + if (ret) + return -EFAULT; +-- +2.53.0 + diff --git a/queue-7.1/s390-checksum-fix-csum_partial-without-vector-facili.patch b/queue-7.1/s390-checksum-fix-csum_partial-without-vector-facili.patch new file mode 100644 index 0000000000..2da6d9a298 --- /dev/null +++ b/queue-7.1/s390-checksum-fix-csum_partial-without-vector-facili.patch @@ -0,0 +1,41 @@ +From 87c3655f8900c9bc6a2e68b7cdf559768b22a185 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 8 Jul 2026 12:02:14 +0200 +Subject: s390/checksum: Fix csum_partial() without vector facility + +From: Vasily Gorbik + +[ Upstream commit 4bb06b60d982355e22647b3d12d6619419f8c1fa ] + +Currently csum_partial() calls csum_copy() with copy=false and dst=NULL. +On machines without the vector facility, csum_copy() falls back to +cksm(dst, ...), causing the checksum to be calculated from address zero +instead of the source buffer. + +The VX implementation already checksums data loaded from src. Make the +fallback do the same by passing src to cksm(). + +Fixes: dcd3e1de9d17 ("s390/checksum: provide csum_partial_copy_nocheck()") +Reviewed-by: Heiko Carstens +Signed-off-by: Vasily Gorbik +Signed-off-by: Sasha Levin +--- + arch/s390/lib/csum-partial.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/s390/lib/csum-partial.c b/arch/s390/lib/csum-partial.c +index 458abd9bac7025..9d74ceff136c54 100644 +--- a/arch/s390/lib/csum-partial.c ++++ b/arch/s390/lib/csum-partial.c +@@ -23,7 +23,7 @@ static __always_inline __wsum csum_copy(void *dst, const void *src, int len, __w + if (!cpu_has_vx()) { + if (copy) + memcpy(dst, src, len); +- return cksm(dst, len, sum); ++ return cksm(src, len, sum); + } + kernel_fpu_begin(&vxstate, KERNEL_VXR_V16V23); + fpu_vlvgf(16, (__force u32)sum, 1); +-- +2.53.0 + diff --git a/queue-7.1/sched_ext-annotate-ksyncs-with-__rcu-in-alloc-free_k.patch b/queue-7.1/sched_ext-annotate-ksyncs-with-__rcu-in-alloc-free_k.patch new file mode 100644 index 0000000000..323b0a37a0 --- /dev/null +++ b/queue-7.1/sched_ext-annotate-ksyncs-with-__rcu-in-alloc-free_k.patch @@ -0,0 +1,49 @@ +From 69f5da0b892c4cb9bd92ba737e63d37806124566 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 24 Jun 2026 12:40:51 -1000 +Subject: sched_ext: Annotate ksyncs with __rcu in alloc/free_kick_syncs() + +From: Tejun Heo + +[ Upstream commit 115d1ce989747045bd7745c7ab020982660c7e42 ] + +scx_kick_syncs is a per-CPU __rcu pointer, so per_cpu_ptr() returns struct +scx_kick_syncs __rcu **. alloc_kick_syncs() and free_kick_syncs() stored it +in a plain struct scx_kick_syncs **ksyncs, which sparse flags as an __rcu +address-space mismatch. Annotate ksyncs to match. Its accesses already go +through rcu_*_pointer(). + +Fixes: 987e00035c0e ("sched_ext: Rename pnt_seq to kick_sync") +Reported-by: kernel test robot +Closes: https://lore.kernel.org/oe-kbuild-all/202606122315.pbnDHP0n-lkp@intel.com/ +Signed-off-by: Tejun Heo +Signed-off-by: Sasha Levin +--- + kernel/sched/ext.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/kernel/sched/ext.c b/kernel/sched/ext.c +index 8429bebc21a19a..0e13139a7f27b9 100644 +--- a/kernel/sched/ext.c ++++ b/kernel/sched/ext.c +@@ -5615,7 +5615,7 @@ static void free_kick_syncs(void) + int cpu; + + for_each_possible_cpu(cpu) { +- struct scx_kick_syncs **ksyncs = per_cpu_ptr(&scx_kick_syncs, cpu); ++ struct scx_kick_syncs __rcu **ksyncs = per_cpu_ptr(&scx_kick_syncs, cpu); + struct scx_kick_syncs *to_free; + + to_free = rcu_replace_pointer(*ksyncs, NULL, true); +@@ -6538,7 +6538,7 @@ static int alloc_kick_syncs(void) + * can exceed percpu allocator limits on large machines. + */ + for_each_possible_cpu(cpu) { +- struct scx_kick_syncs **ksyncs = per_cpu_ptr(&scx_kick_syncs, cpu); ++ struct scx_kick_syncs __rcu **ksyncs = per_cpu_ptr(&scx_kick_syncs, cpu); + struct scx_kick_syncs *new_ksyncs; + + WARN_ON_ONCE(rcu_access_pointer(*ksyncs)); +-- +2.53.0 + diff --git a/queue-7.1/sched_ext-don-t-warn-on-core-sched-forced-idle-in-pu.patch b/queue-7.1/sched_ext-don-t-warn-on-core-sched-forced-idle-in-pu.patch new file mode 100644 index 0000000000..9ed2db22f8 --- /dev/null +++ b/queue-7.1/sched_ext-don-t-warn-on-core-sched-forced-idle-in-pu.patch @@ -0,0 +1,52 @@ +From f10c175e6eb42f587ca4e64f41ca4942096aec9c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 29 Jun 2026 12:55:48 -1000 +Subject: sched_ext: Don't warn on core-sched forced idle in + put_prev_task_scx() + +From: Tejun Heo + +[ Upstream commit b7d9c359e5cf867f7eb23df3bb1c6b9e58af24da ] + +put_prev_task_scx() warns when a runnable task drops to a lower sched_class +without SCX_OPS_ENQ_LAST, on the assumption that balance_one() would have +kept it running. Core scheduling breaks that: a forced-idle SMT sibling +reschedules through the core_pick fast path in pick_next_task(), which skips +pick_task_scx() and thus balance_one(), so a runnable task can drop to idle +with ENQ_LAST unset. + +Gate the warning on sched_cpu_cookie_match(): a cookie mismatch means core +scheduling forced the idle, while a match (or core scheduling off) still +catches a genuine missing-ENQ_LAST drop. + +Fixes: 7c65ae81ea86 ("sched_ext: Don't call put_prev_task_scx() before picking the next task") +Signed-off-by: Tejun Heo +Reviewed-by: Andrea Righi +Signed-off-by: Sasha Levin +--- + kernel/sched/ext.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/kernel/sched/ext.c b/kernel/sched/ext.c +index 0e13139a7f27b9..5f1accb092e30b 100644 +--- a/kernel/sched/ext.c ++++ b/kernel/sched/ext.c +@@ -3097,9 +3097,14 @@ static void put_prev_task_scx(struct rq *rq, struct task_struct *p, + * sched_class, %SCX_OPS_ENQ_LAST must be set. Tell + * ops.enqueue() that @p is the only one available for this cpu, + * which should trigger an explicit follow-up scheduling event. ++ * ++ * Core scheduling can force this CPU idle while @p stays ++ * runnable. @p's cookie then won't match the core's, so skip ++ * the warning in that case. + */ + if (next && sched_class_above(&ext_sched_class, next->sched_class)) { +- WARN_ON_ONCE(!(sch->ops.flags & SCX_OPS_ENQ_LAST)); ++ WARN_ON_ONCE(sched_cpu_cookie_match(rq, p) && ++ !(sch->ops.flags & SCX_OPS_ENQ_LAST)); + do_enqueue_task(rq, p, SCX_ENQ_LAST, -1); + } else { + do_enqueue_task(rq, p, 0, -1); +-- +2.53.0 + diff --git a/queue-7.1/sched_ext-enable-tick-for-finite-slices-on-nohz_full.patch b/queue-7.1/sched_ext-enable-tick-for-finite-slices-on-nohz_full.patch new file mode 100644 index 0000000000..2be95dd8b9 --- /dev/null +++ b/queue-7.1/sched_ext-enable-tick-for-finite-slices-on-nohz_full.patch @@ -0,0 +1,113 @@ +From 3f414202e8855beec0f3f3cef546264d1a88497b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 8 Jul 2026 09:46:48 +0200 +Subject: sched_ext: Enable tick for finite slices on nohz_full + +From: Andrea Righi + +[ Upstream commit 4ec10f38ff901dc10503d57cbdcf941248419ac1 ] + +set_next_task_scx() updates the tick dependency before __schedule() +updates rq->curr. When switching from a non-EXT task, such as idle, to +an EXT task with a finite slice, sched_update_tick_dependency() checks +the outgoing task and can allow the tick to remain stopped. + +The dependency can also be lost without a slice-type transition. After a +finite-slice task leaves the CPU idle, the enqueue path can clear the +dependency against the idle rq->curr. SCX_RQ_CAN_STOP_TICK still records +a finite slice, so another finite task skips the transition block and +can run without the ticks needed to expire its slice. + +The reverse mismatch can also happen when the last finite-slice EXT task +is dequeued: sub_nr_running() updates the dependency before rq->curr +changes, so the outgoing task state can keep the dependency set after +the CPU goes idle. + +Fix this by unconditionally enabling the scheduler tick whenever a +finite-slice EXT task is selected on a nohz_full CPU. Moreover, when the +last runnable EXT task leaves, ignore the outgoing EXT slice state so +the generic scheduler can correctly re-evaluate and clear the tick +dependency. + +Fixes: 22a920209ab6 ("sched_ext: Implement tickless support") +Signed-off-by: Andrea Righi +Signed-off-by: Tejun Heo +Signed-off-by: Sasha Levin +--- + kernel/sched/ext.c | 47 ++++++++++++++++++++++++++++++++++------------ + 1 file changed, 35 insertions(+), 12 deletions(-) + +diff --git a/kernel/sched/ext.c b/kernel/sched/ext.c +index 5f1accb092e30b..432c4c68a2c010 100644 +--- a/kernel/sched/ext.c ++++ b/kernel/sched/ext.c +@@ -2985,24 +2985,38 @@ static void set_next_task_scx(struct rq *rq, struct task_struct *p, bool first) + + /* + * @p is getting newly scheduled or got kicked after someone updated its +- * slice. Refresh whether tick can be stopped. See scx_can_stop_tick(). ++ * slice. Update SCX_RQ_CAN_STOP_TICK to reflect whether the tick can be ++ * stopped. See scx_can_stop_tick(). ++ * ++ * Moreover, refresh the load_avgs just when transitioning in and out of ++ * nohz. In the future, we might want to add a mechanism to update ++ * load_avgs periodically on tick-stopped CPUs. + */ +- if ((p->scx.slice == SCX_SLICE_INF) != +- (bool)(rq->scx.flags & SCX_RQ_CAN_STOP_TICK)) { +- if (p->scx.slice == SCX_SLICE_INF) ++ if (p->scx.slice == SCX_SLICE_INF) { ++ if (!(rq->scx.flags & SCX_RQ_CAN_STOP_TICK)) { ++ /* ++ * Bypass mode always assigns finite slices, so @p ++ * can't have an infinite slice while bypassing. ++ * Therefore, sched_update_tick_dependency() can safely ++ * evaluate the outgoing task. ++ */ + rq->scx.flags |= SCX_RQ_CAN_STOP_TICK; +- else +- rq->scx.flags &= ~SCX_RQ_CAN_STOP_TICK; ++ sched_update_tick_dependency(rq); + +- sched_update_tick_dependency(rq); ++ update_other_load_avgs(rq); ++ } ++ } else { ++ if (rq->scx.flags & SCX_RQ_CAN_STOP_TICK) { ++ rq->scx.flags &= ~SCX_RQ_CAN_STOP_TICK; ++ update_other_load_avgs(rq); ++ } + + /* +- * For now, let's refresh the load_avgs just when transitioning +- * in and out of nohz. In the future, we might want to add a +- * mechanism which calls the following periodically on +- * tick-stopped CPUs. ++ * @rq still references the outgoing scheduling context. A finite ++ * slice is sufficient by itself to require the tick. + */ +- update_other_load_avgs(rq); ++ if (tick_nohz_full_cpu(cpu_of(rq))) ++ tick_nohz_dep_set_cpu(cpu_of(rq), TICK_DEP_BIT_SCHED); + } + } + +@@ -4296,6 +4310,15 @@ bool scx_can_stop_tick(struct rq *rq) + if (p->sched_class != &ext_sched_class) + return true; + ++ /* ++ * @rq->curr may still reference an outgoing EXT task after it has been ++ * dequeued. If no EXT tasks are accounted on @rq, ignore its stale ++ * slice state. If another task is dispatched from a DSQ, ++ * set_next_task_scx() will update the dependency for the incoming task. ++ */ ++ if (!rq->scx.nr_running) ++ return true; ++ + if (scx_bypassing(sch, cpu_of(rq))) + return false; + +-- +2.53.0 + diff --git a/queue-7.1/sched_ext-record-an-error-on-errno-only-sub-enable-f.patch b/queue-7.1/sched_ext-record-an-error-on-errno-only-sub-enable-f.patch new file mode 100644 index 0000000000..18edbaace7 --- /dev/null +++ b/queue-7.1/sched_ext-record-an-error-on-errno-only-sub-enable-f.patch @@ -0,0 +1,46 @@ +From 00994572199d328af60b9a06acea5e225eeaf7d8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 9 Jul 2026 11:08:13 -1000 +Subject: sched_ext: Record an error on errno-only sub-enable failure + +From: Tejun Heo + +[ Upstream commit db4e9defd2e8620abee04cfe5809c0bcd6ecf06a ] + +scx_sub_enable_workfn() has several failure paths that only return an errno +(e.g. -ENOMEM from an allocation) and jump to err_disable without calling +scx_error(). scx_flush_disable_work() runs the disable, and thus ops.exit(), +only when an error has been recorded, so an errno-only failure leaves the +half-initialized sub-scheduler linked. + +Record an error at the err_disable sink so every errno-only failure runs the +disable path. + +Fixes: ebeca1f930ea ("sched_ext: Introduce cgroup sub-sched support") +Signed-off-by: Tejun Heo +Reviewed-by: Andrea Righi +Signed-off-by: Sasha Levin +--- + kernel/sched/ext.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/kernel/sched/ext.c b/kernel/sched/ext.c +index 432c4c68a2c010..46f7b33b565ba3 100644 +--- a/kernel/sched/ext.c ++++ b/kernel/sched/ext.c +@@ -7440,6 +7440,12 @@ static void scx_sub_enable_workfn(struct kthread_work *work) + percpu_up_write(&scx_fork_rwsem); + err_disable: + mutex_unlock(&scx_enable_mutex); ++ /* ++ * Some enable failures only return an errno (e.g. -ENOMEM from an ++ * allocation) without calling scx_error(). Record it so ++ * scx_flush_disable_work() runs the disable and ops.exit() fires. ++ */ ++ scx_error(sch, "scx_sub_enable() failed (%d)", ret); + scx_flush_disable_work(sch); + cmd->ret = 0; + } +-- +2.53.0 + diff --git a/queue-7.1/scsi-core-wake-eh-reliably-when-using-scsi_schedule_.patch b/queue-7.1/scsi-core-wake-eh-reliably-when-using-scsi_schedule_.patch new file mode 100644 index 0000000000..427b1eca8a --- /dev/null +++ b/queue-7.1/scsi-core-wake-eh-reliably-when-using-scsi_schedule_.patch @@ -0,0 +1,123 @@ +From fe244be3b03220ff6d4bace6559b6b46fffa982d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 15 Jun 2026 13:46:30 -0400 +Subject: scsi: core: wake eh reliably when using scsi_schedule_eh + +From: David Jeffery + +[ Upstream commit dccf3b1798b70f94e958b3d00b83010399e6fb05 ] + +Drivers which use the scsi_schedule_eh function to run the error handler +currently risk the error handler thread never waking once all commands are +timed out or inactive. There is no enforced memory order between setting +the host into error recovery state and counting busy commands. This can +result in a race with scsi_dec_host_busy where neither CPU sees both +conditions of all commands inactive and the host error state to request +waking the error handler. + +To fix this, run the scsi_schedule_eh's scsi_eh_wakeup from a new work item +which will use rcu to ensure scsi_schedule_eh's call to scsi_host_busy will +occur after the error state is globally visible and will be seen by any +current scsi_dec_host_busy callers. + +Fixes: 6eb045e092ef ("scsi: core: avoid host-wide host_busy counter for scsi_mq") +Signed-off-by: David Jeffery +Link: https://patch.msgid.link/20260615174630.11492-1-djeffery@redhat.com +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +--- + drivers/scsi/hosts.c | 2 ++ + drivers/scsi/scsi_error.c | 22 +++++++++++++++++++++- + drivers/scsi/scsi_priv.h | 1 + + include/scsi/scsi_host.h | 3 +++ + 4 files changed, 27 insertions(+), 1 deletion(-) + +diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c +index e047747d4ecf81..46cc8e3c79a26e 100644 +--- a/drivers/scsi/hosts.c ++++ b/drivers/scsi/hosts.c +@@ -357,6 +357,7 @@ static void scsi_host_dev_release(struct device *dev) + /* Wait for functions invoked through call_rcu(&scmd->rcu, ...) */ + rcu_barrier(); + ++ cancel_work_sync(&shost->eh_work); + if (shost->tmf_work_q) + destroy_workqueue(shost->tmf_work_q); + if (shost->ehandler) +@@ -422,6 +423,7 @@ struct Scsi_Host *scsi_host_alloc(const struct scsi_host_template *sht, int priv + INIT_LIST_HEAD(&shost->starved_list); + init_waitqueue_head(&shost->host_wait); + mutex_init(&shost->scan_mutex); ++ INIT_WORK(&shost->eh_work, scsi_rcu_eh_wakeup); + + index = ida_alloc(&host_index_ida, GFP_KERNEL); + if (index < 0) { +diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c +index 147127fb4db9cc..453a2232452dba 100644 +--- a/drivers/scsi/scsi_error.c ++++ b/drivers/scsi/scsi_error.c +@@ -73,6 +73,26 @@ void scsi_eh_wakeup(struct Scsi_Host *shost, unsigned int busy) + } + } + ++void scsi_rcu_eh_wakeup(struct work_struct *work) ++{ ++ struct Scsi_Host *shost = container_of(work, struct Scsi_Host, eh_work); ++ unsigned long flags; ++ unsigned int busy; ++ ++ /* ++ * Ensure any running scsi_dec_host_busy has completed its rcu section ++ * so changes to host state and host_eh_scheduled are visible to all ++ * future calls of scsi_dec_host_busy ++ */ ++ synchronize_rcu(); ++ ++ busy = scsi_host_busy(shost); ++ ++ spin_lock_irqsave(shost->host_lock, flags); ++ scsi_eh_wakeup(shost, busy); ++ spin_unlock_irqrestore(shost->host_lock, flags); ++} ++ + /** + * scsi_schedule_eh - schedule EH for SCSI host + * @shost: SCSI host to invoke error handling on. +@@ -88,7 +108,7 @@ void scsi_schedule_eh(struct Scsi_Host *shost) + if (scsi_host_set_state(shost, SHOST_RECOVERY) == 0 || + scsi_host_set_state(shost, SHOST_CANCEL_RECOVERY) == 0) { + shost->host_eh_scheduled++; +- scsi_eh_wakeup(shost, scsi_host_busy(shost)); ++ queue_work(shost->tmf_work_q, &shost->eh_work); + } + + spin_unlock_irqrestore(shost->host_lock, flags); +diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h +index 7a193cc04e5b6f..304e8e79bd91a9 100644 +--- a/drivers/scsi/scsi_priv.h ++++ b/drivers/scsi/scsi_priv.h +@@ -91,6 +91,7 @@ extern enum blk_eh_timer_return scsi_timeout(struct request *req); + extern int scsi_error_handler(void *host); + extern enum scsi_disposition scsi_decide_disposition(struct scsi_cmnd *cmd); + extern void scsi_eh_wakeup(struct Scsi_Host *shost, unsigned int busy); ++extern void scsi_rcu_eh_wakeup(struct work_struct *work); + extern void scsi_eh_scmd_add(struct scsi_cmnd *); + void scsi_eh_ready_devs(struct Scsi_Host *shost, + struct list_head *work_q, +diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h +index 7e2011830ba4bd..f6b286fa59f214 100644 +--- a/include/scsi/scsi_host.h ++++ b/include/scsi/scsi_host.h +@@ -750,6 +750,9 @@ struct Scsi_Host { + */ + struct device *dma_dev; + ++ /* Used for an rcu-synchronizing eh wakeup */ ++ struct work_struct eh_work; ++ + /* Delay for runtime autosuspend */ + int rpm_autosuspend_delay; + +-- +2.53.0 + diff --git a/queue-7.1/sctp-fix-auth_hmacs-array-size-in-struct-sctp_cookie.patch b/queue-7.1/sctp-fix-auth_hmacs-array-size-in-struct-sctp_cookie.patch new file mode 100644 index 0000000000..6376e6a6f5 --- /dev/null +++ b/queue-7.1/sctp-fix-auth_hmacs-array-size-in-struct-sctp_cookie.patch @@ -0,0 +1,56 @@ +From fc2430fcae93a99e8d62eb9923387331c6f6b78a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 10 Jul 2026 14:12:35 -0400 +Subject: sctp: fix auth_hmacs array size in struct sctp_cookie + +From: Xin Long + +[ Upstream commit e0b5252a59383b77d1b8dbeda00b7184dd95f4d3 ] + +The auth_hmacs array in struct sctp_cookie is supposed to store a complete +SCTP_AUTH_HMAC_ALGO parameter, which consists of a struct sctp_paramhdr +followed by N HMAC identifiers. + +However, the array size was calculated using an extra 2 bytes instead of +sizeof(struct sctp_paramhdr), which is 4 bytes. When four HMAC identifiers +are configured, the HMAC-ALGO parameter stored in the endpoint is larger +than the auth_hmacs buffer in the cookie. + +As a result, sctp_association_init() copies beyond the end of auth_hmacs +when initializing the association, corrupting the adjacent auth_chunks +field. This can lead to an invalid HMAC identifier being accepted and later +cause an out-of-bounds read in sctp_auth_get_hmac(). + +Fix the array size calculation by including the full SCTP parameter header +size. + +Fixes: 1f485649f529 ("[SCTP]: Implement SCTP-AUTH internals") +Reported-by: Yuan Tan +Reported-by: Xin Liu +Reported-by: Zihan Xi +Reported-by: Ren Wei +Signed-off-by: Xin Long +Link: https://patch.msgid.link/634a0de0d5de29532915e6d47c92a0cbc206e03f.1783707155.git.lucien.xin@gmail.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + include/net/sctp/structs.h | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h +index affee44bd38e31..cccc662561aac3 100644 +--- a/include/net/sctp/structs.h ++++ b/include/net/sctp/structs.h +@@ -312,7 +312,8 @@ struct sctp_cookie { + + __u8 auth_random[sizeof(struct sctp_paramhdr) + + SCTP_AUTH_RANDOM_LENGTH]; +- __u8 auth_hmacs[SCTP_AUTH_NUM_HMACS * sizeof(__u16) + 2]; ++ __u8 auth_hmacs[sizeof(struct sctp_paramhdr) + ++ SCTP_AUTH_NUM_HMACS * sizeof(__u16)]; + __u8 auth_chunks[sizeof(struct sctp_paramhdr) + SCTP_AUTH_MAX_CHUNKS]; + + /* This is a shim for my peer's INIT packet, followed by +-- +2.53.0 + diff --git a/queue-7.1/selftests-alsa-fix-memory-leak-in-find_controls-erro.patch b/queue-7.1/selftests-alsa-fix-memory-leak-in-find_controls-erro.patch new file mode 100644 index 0000000000..8f6ec6d4ac --- /dev/null +++ b/queue-7.1/selftests-alsa-fix-memory-leak-in-find_controls-erro.patch @@ -0,0 +1,41 @@ +From 7f05b4c9d464c9baf7d83420df971518ceb3ed2d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 4 Jul 2026 16:27:36 +0530 +Subject: selftests/alsa: Fix memory leak in find_controls error path + +From: Malaya Kumar Rout + +[ Upstream commit cb89f0c1aed02eb233c4271f76f830b37e222ff6 ] + +In find_controls(), card_data is allocated with malloc() but when +snd_ctl_open_lconf() fails, the code jumps to next_card without +freeing the allocated memory. This results in a memory leak for +each card where snd_ctl_open_lconf() fails. + +Add free(card_data) before goto next_card to ensure proper cleanup +of the allocated memory in the error path. + +Fixes: 5aaf9efffc57 ("kselftest: alsa: Add simplistic test for ALSA mixer controls kselftest") +Signed-off-by: Malaya Kumar Rout +Link: https://patch.msgid.link/20260704105736.94874-1-malayarout91@gmail.com +Signed-off-by: Takashi Iwai +Signed-off-by: Sasha Levin +--- + tools/testing/selftests/alsa/mixer-test.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/tools/testing/selftests/alsa/mixer-test.c b/tools/testing/selftests/alsa/mixer-test.c +index d4f845c3280456..c5ae2a026ce919 100644 +--- a/tools/testing/selftests/alsa/mixer-test.c ++++ b/tools/testing/selftests/alsa/mixer-test.c +@@ -84,6 +84,7 @@ static void find_controls(void) + if (err < 0) { + ksft_print_msg("Failed to get hctl for card %d: %s\n", + card, snd_strerror(err)); ++ free(card_data); + goto next_card; + } + +-- +2.53.0 + diff --git a/queue-7.1/selftests-netconsole-only-restore-mac-when-it-change.patch b/queue-7.1/selftests-netconsole-only-restore-mac-when-it-change.patch new file mode 100644 index 0000000000..17005ee454 --- /dev/null +++ b/queue-7.1/selftests-netconsole-only-restore-mac-when-it-change.patch @@ -0,0 +1,49 @@ +From 42a9a02906eb1a6ad5647b0c8d61c1e3af00edfc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 10 Jul 2026 23:19:17 +0100 +Subject: selftests: netconsole: only restore MAC when it changed on resume + +From: Andre Carvalho + +[ Upstream commit 04aeddf2dadd0eb7ad016a766dcbe9c983311f09 ] + +The "mac" bind mode reactivation downs the interface, restores the saved +MAC and renames it to trigger a target resume. This assumes the recreated +interface comes back with a different MAC, which is true under +MACAddressPolicy=none (as on the Netdev CI) but not when MACs are +persistent. In the persistent case netconsole resumes the target on its +own, and the down/restore/rename flow instead drops it and fails the test. + +Guard the block on the MAC having actually changed so the test passes +under both policies. + +Fixes: 6ecc08329bab ("selftests: netconsole: validate target resume") +Reported-by: Matthieu Baerts (NGI0) +Closes: https://lore.kernel.org/netdev/f398373e-2cb4-4649-a491-9763df94d98b@kernel.org/ +Signed-off-by: Andre Carvalho +Tested-by: Matthieu Baerts (NGI0) +Reviewed-by: Breno Leitao +Link: https://patch.msgid.link/20260710-netcons-mac-reload-v1-1-3fb1bcc70b4a@gmail.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + .../testing/selftests/drivers/net/netconsole/netcons_resume.sh | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/tools/testing/selftests/drivers/net/netconsole/netcons_resume.sh b/tools/testing/selftests/drivers/net/netconsole/netcons_resume.sh +index cb59cf436dd0a3..d9111f2102bcd1 100755 +--- a/tools/testing/selftests/drivers/net/netconsole/netcons_resume.sh ++++ b/tools/testing/selftests/drivers/net/netconsole/netcons_resume.sh +@@ -44,7 +44,8 @@ function trigger_reactivation() { + # Restore MACs + ip netns exec "${NAMESPACE}" ip link set "${DSTIF}" \ + address "${SAVED_DSTMAC}" +- if [ "${BINDMODE}" == "mac" ]; then ++ if [ "${BINDMODE}" == "mac" ] && ++ [ "$(mac_get "${SRCIF}")" != "${SAVED_SRCMAC}" ]; then + ip link set dev "${SRCIF}" down + ip link set dev "${SRCIF}" address "${SAVED_SRCMAC}" + # Rename device in order to trigger target resume, as initial +-- +2.53.0 + diff --git a/queue-7.1/series b/queue-7.1/series index b1e281a171..e93c6e3dcd 100644 --- a/queue-7.1/series +++ b/queue-7.1/series @@ -10,3 +10,128 @@ kvm-x86-mmu-fix-use-after-free-on-vendor-module-reload.patch gpu-host1x-fix-use-after-free-in-host1x_bo_clear_cac.patch crypto-tegra-don-t-touch-bo-refcount-in-host1x-bo-pi.patch xprtrdma-clear-receive-side-ownership-pointers-on-re.patch +arm64-tegra-remove-fallback-compatible-for-gpcdma.patch +docs-admin-guide-cgroup-v2-fix-memory.stat-doc-detai.patch +sched_ext-annotate-ksyncs-with-__rcu-in-alloc-free_k.patch +arm64-tegra-fix-cpu-compatible-string-to-cortex-a78a.patch +xfrm-propagate-einprogress-from-validate_xmit_xfrm.patch +xfrm-fix-stale-skb-prev-after-async-crypto-steals-a-.patch +firmware-arm_ffa-respect-firmware-advertised-rx-tx-b.patch +ib-mad-drop-unmatched-rmpp-responses-before-reassemb.patch +mtd-virt_concat-fix-use-after-free-in-mtd_virt_conca.patch +mtd-virt_concat-fix-use-after-free-in-mtd_virt_conca.patch-15214 +mtd-mtdswap-remove-debugfs-stats-file-on-teardown.patch +mtd-nand-mtk-ecc-stop-on-ecc-idle-timeouts.patch +btrfs-reject-free-space-cache-with-more-entries-than.patch +btrfs-fix-root-leak-if-its-reloc-root-is-unexpected-.patch +btrfs-fallback-to-transaction-csum-tree-on-a-commit-.patch +firmware-arm_ffa-fix-null-dereference-in-ffa_partiti.patch +sched_ext-don-t-warn-on-core-sched-forced-idle-in-pu.patch +reset-spacemit-k3-fix-usb2-ahb-reset.patch +xfrm-fix-sk_dst_cache-double-free-in-xfrm_user_polic.patch +xfrm-reject-optional-iptfs-templates-in-outbound-pol.patch +rdma-cma-fix-hardware-address-comparison-length-in-n.patch +rdma-irdma-prevent-rereg_mr-for-non-mem-regions.patch +rdma-irdma-remove-redundant-legacy_mode-checks.patch +rdma-irdma-prevent-user-triggered-null-deref-on-qp-c.patch +rdma-erdma-initialize-ret-for-empty-receive-wr-lists.patch +rdma-mana_ib-initialize-err-for-empty-send-wr-lists.patch +rdma-core-fix-memory-leak-in-__ib_create_cq-on-inval.patch +rdma-hns-fix-potential-integer-overflow-in-mhop-hem-.patch +rdma-siw-publish-qp-after-initialization.patch +mtd-fix-double-free-and-warn_on-in-add_mtd_device-er.patch +selftests-alsa-fix-memory-leak-in-find_controls-erro.patch +rdma-irdma-prevent-overflows-in-memory-contiguity-ch.patch +xfrm-clear-mode-callbacks-after-failed-mode-setup.patch +xfrm-iptfs-propagate-skbfl_shared_frag-in-iptfs_skb_.patch +xfrm6-clear-dst.dev-on-error-to-avoid-double-netdev_.patch +xfrm-policy-preallocate-inexact-bins-before-xfrm_has.patch +wifi-mac80211-allocate-backup-ieee80211_nan_sched_cf.patch +alsa-usb-audio-fix-imbalance-per-channel-volume-of-s.patch +wifi-cfg80211-cancel-sched-scan-results-work-on-unre.patch +wifi-ipw2100-fix-potential-memory-leak-in-ipw2100_pc.patch +wifi-cfg80211-fix-an-error-handling-path-in-cfg80211.patch +wifi-mac80211_hwsim-clamp-virtio-rx-length-before-sk.patch +wifi-mac80211-fix-unsol_bcast_probe_resp-double-free.patch +wifi-mac80211-fix-fils_discovery-double-free-on-allo.patch +wifi-libertas-fix-memory-leak-in-helper_firmware_cb.patch +wifi-mac80211-defer-link-rx-stats-percpu-free-to-rcu.patch +wifi-p54-validate-rx-frame-length-in-p54_rx_eeprom_r.patch +wifi-cfg80211-convert-pmsr_free_wk-to-wiphy_work-to-.patch +wifi-nl80211-free-rnr-data-on-mbssid-mismatch.patch +wifi-cfg80211-derive-s1g-beacon-tsf-from-s1g-fields.patch +wifi-nl80211-validate-nested-mbssid-ie-blobs.patch +wifi-nl80211-constrain-mbssid-tx-link-id-range.patch +wifi-cfg80211-validate-pmsr-measurement-type-data.patch +wifi-cfg80211-validate-pmsr-ftm-preamble-range.patch +wifi-cfg80211-reject-unsupported-pmsr-ftm-location-r.patch +wifi-cfg80211-reject-empty-pmsr-peer-lists.patch +wifi-mac80211-avoid-non-s1g-aid-fallback-for-s1g-ass.patch +asoc-amd-acp-fix-linker-error-with-sdca-quirks.patch +wifi-mac80211-free-ap_vlan-bc_buf-skbs-outside-irq-l.patch +wifi-cfg80211-use-wiphy-work-for-socket-owner-autodi.patch +wifi-brcmfmac-initialize-sdio-data-work-before-clean.patch +wifi-cfg80211-bound-element-id-read-when-checking-no.patch +firmware-arm_ffa-fix-out-of-bound-writes-in-ffa_setu.patch +firmware-arm_ffa-fix-endpoint-memory-access-descript.patch +asoc-meson-aiu-fifo-spdif-soft-reset-the-s-pdif-data.patch +asoc-amd-ps-disable-msi-on-resume-in-acp-pci-driver.patch +asoc-amd-ps-fix-wrong-acp-version-string-in-pci_requ.patch +asoc-amd-ps-replace-bitwise-or-with-logical-or-in-ir.patch +erofs-relax-sanity-check-for-tail-pclusters-due-to-z.patch +asoc-cs42l43-correct-report-for-forced-microphone-ja.patch +sched_ext-enable-tick-for-finite-slices-on-nohz_full.patch +asoc-tas2562-fix-deprecated-shut-down-gpio-always-cl.patch +firmware-arm_scmi-rate-limit-queue-full-warnings-in-.patch +bpf-fix-uaf-in-sock-clone-early-bailouts.patch +cpufreq-make-cpufreq_update_pressure-fall-back-to-cp.patch +sched_ext-record-an-error-on-errno-only-sub-enable-f.patch +ppp-defer-channel-free-to-an-rcu-grace-period-to-fix.patch +ipv4-fib-free-fib_alias-with-kfree_rcu-on-insert-err.patch +net-iucv-take-a-reference-on-the-socket-found-in-afi.patch +udmabuf-ensure-to-perform-cache-synchronisation-in-b.patch +scsi-core-wake-eh-reliably-when-using-scsi_schedule_.patch +ata-sata_dwc_460ex-enable-sata-interrupts-only-after.patch +ata-sata_dwc_460ex-use-platform_get_irq.patch +ata-sata_dwc_460ex-fix-clear_interrupt_bit-clearing-.patch +ata-sata_dwc_460ex-fix-infinite-loop-in-ncq-tag-comp.patch +accel-ivpu-fix-wrong-register-read-in-lnl-failure-di.patch +alsa-usb-audio-skip-dsd-quirk-for-musical-fidelity-m.patch +bluetooth-qca-fix-nvm-tag-length-underflow-in-tlv-pa.patch +bluetooth-mgmt-revalidate-load_conn_param-queued-upd.patch +bluetooth-hci_sync-extend-conn_hash-lookup-critical-.patch +bluetooth-mgmt-fix-locking-in-unpair_device-disconne.patch +bluetooth-mgmt-hold-reference-for-hci_conn-in-mgmt_p.patch +bluetooth-hci_sync-hold-hdev-lock-for-hci_conn_param.patch +bluetooth-hci_qca-clear-memdump-state-on-invalid-dum.patch +bluetooth-mgmt-translate-hci-reason-in-device-discon.patch +smb-client-handle-overlapping-allocated-ranges-in-fa.patch +riscv-gate-function_alignment_4b-on-dynamic_ftrace.patch +drm-i915-gt-use-correct-selftest-config-symbol.patch +can-raw-add-locking-for-raw-flags-bitfield.patch +spi-cadence-quadspi-fix-indirect-write-timeout-when-.patch +powerpc-85xx-add-fsl-ifc-to-common-device-ids.patch +powerpc-time-prepare-to-stop-elapsing-in-dynticks-id.patch +powerpc-vtime-initialize-starttime-at-boot-for-nativ.patch +bpf-sockmap-reject-unhashed-udp-sockets-on-sockmap-u.patch +drm-panthor-check-debugfs-gem-lock-initialization.patch +s390-checksum-fix-csum_partial-without-vector-facili.patch +riscv-hwprobe-avoid-uninitialized-read-in-hwprobe_ge.patch +can-j1939-fix-lockless-local-destination-check.patch +drm-xe-vf-fix-vf-ccs-attach-detach-race-with-in-flig.patch +drm-xe-wopcm-fix-wopcm-size-for-lnl.patch +drm-xe-assign-queue-name-in-time-for-drm_sched_init.patch +drm-xe-guc-keep-scheduler-timeline-name-alive.patch +drm-xe-guc-hold-device-ref-until-queue-teardown-comp.patch +ksmbd-pin-conn-during-async-oplock-break-notificatio.patch +ksmbd-validate-compound-request-size-before-reading-.patch +drm-i915-wm-clear-the-plane-ddb_y-entries-on-plane-d.patch +drm-i915-selftests-fix-gt-pm-sort-comparators.patch +accel-amdxdna-fix-use-after-free-of-mm_struct-in-job.patch +tcp-fix-time_wait-socket-reference-leak-on-psp-polic.patch +dpll-fix-null-pointer-dereference-in-dpll_msg_add_pi.patch +net-sched-act_tunnel_key-defer-dst_release-to-rcu-ca.patch +sctp-fix-auth_hmacs-array-size-in-struct-sctp_cookie.patch +bnxt_en-handle-partially-initialized-auxiliary-devic.patch +selftests-netconsole-only-restore-mac-when-it-change.patch +mpls-fix-null-deref-in-mpls_valid_fib_dump_req-on-co.patch diff --git a/queue-7.1/smb-client-handle-overlapping-allocated-ranges-in-fa.patch b/queue-7.1/smb-client-handle-overlapping-allocated-ranges-in-fa.patch new file mode 100644 index 0000000000..98adfad061 --- /dev/null +++ b/queue-7.1/smb-client-handle-overlapping-allocated-ranges-in-fa.patch @@ -0,0 +1,110 @@ +From cda1d427034c9600382bcf930e8f1a68094565af Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 3 Jul 2026 13:32:56 +0800 +Subject: smb/client: handle overlapping allocated ranges in fallocate + +From: Huiwen He + +[ Upstream commit b09ae45d85dc816987a71db9eebc54b0ae288e94 ] + +smb3_simple_fallocate_range() can skip holes when an allocated range +returned by the server starts before the current fallocate offset. The +skipped hole is not zero-filled, but fallocate still returns success. A +later write to that hole may therefore fail with ENOSPC. + +The function queries allocated ranges so that it can preserve existing +contents and write zeroes only into holes. However, the server may return +a range that starts before the current fallocate offset. + +For example, assume the fallocate request is [100, 400) and the only +allocated range returned by the server is [0, 200): + + Request: [100, 400) + Server range: [ 0, 200) allocated + + Correct: + [100, 200) allocated data, skip + [200, 400) hole, zero-fill + + Current: + [100, 300) skipped + [300, 400) zero-filled afterwards + +The current code adds the full server range length, 200, to the current +offset 100 and moves to 300. As a result, the hole in [200, 300) is +skipped without being zero-filled. + +Fix this by advancing only over the part of the allocated range that +overlaps the current fallocate offset. Ignore ranges that end before the +current offset and reject ranges whose end offset overflows. + +This also prevents a malformed range length from causing an out-of-bounds +zero-buffer read. + +Fixes: 966a3cb7c7db ("cifs: improve fallocate emulation") +Signed-off-by: Huiwen He +Reviewed-by: ChenXiaoSong +Signed-off-by: Steve French +Signed-off-by: Sasha Levin +--- + fs/smb/client/smb2ops.c | 25 ++++++++++++++++++------- + 1 file changed, 18 insertions(+), 7 deletions(-) + +diff --git a/fs/smb/client/smb2ops.c b/fs/smb/client/smb2ops.c +index 02c2f83353e27a..6f843c8b83f3a8 100644 +--- a/fs/smb/client/smb2ops.c ++++ b/fs/smb/client/smb2ops.c +@@ -3581,6 +3581,7 @@ static int smb3_simple_fallocate_range(unsigned int xid, + struct file_allocated_range_buffer in_data, *out_data = NULL, *tmp_data; + u32 out_data_len; + char *buf = NULL; ++ u64 range_start, range_len, range_end; + loff_t l; + int rc; + +@@ -3617,13 +3618,21 @@ static int smb3_simple_fallocate_range(unsigned int xid, + goto out; + } + +- if (off < le64_to_cpu(tmp_data->file_offset)) { ++ range_start = le64_to_cpu(tmp_data->file_offset); ++ range_len = le64_to_cpu(tmp_data->length); ++ if (check_add_overflow(range_start, range_len, &range_end) || ++ range_end > S64_MAX) { ++ rc = -EINVAL; ++ goto out; ++ } ++ ++ if (off < range_start) { + /* + * We are at a hole. Write until the end of the region + * or until the next allocated data, + * whichever comes next. + */ +- l = le64_to_cpu(tmp_data->file_offset) - off; ++ l = range_start - off; + if (len < l) + l = len; + rc = smb3_simple_fallocate_write_range(xid, tcon, +@@ -3640,11 +3649,13 @@ static int smb3_simple_fallocate_range(unsigned int xid, + * until the end of the data or the end of the region + * we are supposed to fallocate, whichever comes first. + */ +- l = le64_to_cpu(tmp_data->length); +- if (len < l) +- l = len; +- off += l; +- len -= l; ++ if (off < range_end) { ++ l = range_end - off; ++ if (len < l) ++ l = len; ++ off += l; ++ len -= l; ++ } + + tmp_data = &tmp_data[1]; + out_data_len -= sizeof(struct file_allocated_range_buffer); +-- +2.53.0 + diff --git a/queue-7.1/spi-cadence-quadspi-fix-indirect-write-timeout-when-.patch b/queue-7.1/spi-cadence-quadspi-fix-indirect-write-timeout-when-.patch new file mode 100644 index 0000000000..5aaabc057e --- /dev/null +++ b/queue-7.1/spi-cadence-quadspi-fix-indirect-write-timeout-when-.patch @@ -0,0 +1,62 @@ +From 4e88e3535cd1bc3972789d93484f77fee45febf0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 8 Jul 2026 10:21:48 +0530 +Subject: spi: cadence-quadspi: Fix indirect write timeout when DMA read mode + is enabled + +From: Srikanth Boyapally + +[ Upstream commit e919ca35a6e84b5adf085da9ffa1544c01d4ce1e ] + +When use_dma_read is enabled, the IRQ handler unconditionally overwrites +irq_status with the return value of get_dma_status(). For write operations, +DMA status returns 0 since no DMA read is in progress, causing irq_status +to become 0. The subsequent completion signal is never triggered and the +write operation times out with -ETIMEDOUT: + + cadence-qspi f1010000.spi: Indirect write timeout + spi-nor spi0.1: operation failed with -110 + +Fix this by separating the DMA completion path from the write interrupt +path. If get_dma_status() indicates DMA read completion, signal completion +and return immediately. Otherwise, preserve the original irq_status so that +write completion interrupts are correctly recognized and signalled. + +Fixes: aac733a96636 ("spi: cadence-qspi: Fix style and improve readability") +Signed-off-by: Srikanth Boyapally +Reviewed-by: Radhey Shyam Pandey +Link: https://patch.msgid.link/20260708045148.2993313-1-srikanth.boyapally@amd.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + drivers/spi/spi-cadence-quadspi.c | 12 ++++++++---- + 1 file changed, 8 insertions(+), 4 deletions(-) + +diff --git a/drivers/spi/spi-cadence-quadspi.c b/drivers/spi/spi-cadence-quadspi.c +index 057381e56a7fd5..38aa83375c1896 100644 +--- a/drivers/spi/spi-cadence-quadspi.c ++++ b/drivers/spi/spi-cadence-quadspi.c +@@ -382,12 +382,16 @@ static irqreturn_t cqspi_irq_handler(int this_irq, void *dev) + /* Clear interrupt */ + writel(irq_status, cqspi->iobase + CQSPI_REG_IRQSTATUS); + +- if (cqspi->use_dma_read && ddata && ddata->get_dma_status) +- irq_status = ddata->get_dma_status(cqspi); +- else if (cqspi->slow_sram) ++ if (cqspi->use_dma_read && ddata && ddata->get_dma_status) { ++ if (ddata->get_dma_status(cqspi)) { ++ complete(&cqspi->transfer_complete); ++ return IRQ_HANDLED; ++ } ++ } else if (cqspi->slow_sram) { + irq_status &= CQSPI_IRQ_MASK_RD_SLOW_SRAM | CQSPI_IRQ_MASK_WR; +- else ++ } else { + irq_status &= CQSPI_IRQ_MASK_RD | CQSPI_IRQ_MASK_WR; ++ } + + if (irq_status) + complete(&cqspi->transfer_complete); +-- +2.53.0 + diff --git a/queue-7.1/tcp-fix-time_wait-socket-reference-leak-on-psp-polic.patch b/queue-7.1/tcp-fix-time_wait-socket-reference-leak-on-psp-polic.patch new file mode 100644 index 0000000000..a5a38c5f6c --- /dev/null +++ b/queue-7.1/tcp-fix-time_wait-socket-reference-leak-on-psp-polic.patch @@ -0,0 +1,62 @@ +From ce7a35f7f03c998b78383b61f6c9dd9fa9fcf3cf Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 10 Jul 2026 18:13:17 +0000 +Subject: tcp: fix TIME_WAIT socket reference leak on PSP policy failure + +From: Eric Dumazet + +[ Upstream commit 2c1931a81122c3cdc4c89448fe0442c69e21c0d5 ] + +Release the TIME_WAIT socket reference and jump to discard_it +upon PSP policy failure in both IPv4 and IPv6 receive paths. +This prevents a memory leak of tcp_tw_bucket structures. + +Fixes: 659a2899a57d ("tcp: add datapath logic for PSP with inline key exchange") +Signed-off-by: Eric Dumazet +Reviewed-by: Kuniyuki Iwashima +Reviewed-by: Daniel Zahka +Link: https://patch.msgid.link/20260710181317.4060230-1-edumazet@google.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/ipv4/tcp_ipv4.c | 6 ++++-- + net/ipv6/tcp_ipv6.c | 6 ++++-- + 2 files changed, 8 insertions(+), 4 deletions(-) + +diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c +index bfdabad01fa765..d5cd238358ef04 100644 +--- a/net/ipv4/tcp_ipv4.c ++++ b/net/ipv4/tcp_ipv4.c +@@ -2319,8 +2319,10 @@ int tcp_v4_rcv(struct sk_buff *skb) + } + + drop_reason = psp_twsk_rx_policy_check(inet_twsk(sk), skb); +- if (drop_reason) +- break; ++ if (drop_reason) { ++ inet_twsk_put(inet_twsk(sk)); ++ goto discard_it; ++ } + } + /* to ACK */ + fallthrough; +diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c +index 36d75fb50a70b7..71cca3c74423f5 100644 +--- a/net/ipv6/tcp_ipv6.c ++++ b/net/ipv6/tcp_ipv6.c +@@ -1962,8 +1962,10 @@ INDIRECT_CALLABLE_SCOPE int tcp_v6_rcv(struct sk_buff *skb) + } + + drop_reason = psp_twsk_rx_policy_check(inet_twsk(sk), skb); +- if (drop_reason) +- break; ++ if (drop_reason) { ++ inet_twsk_put(inet_twsk(sk)); ++ goto discard_it; ++ } + } + /* to ACK */ + fallthrough; +-- +2.53.0 + diff --git a/queue-7.1/udmabuf-ensure-to-perform-cache-synchronisation-in-b.patch b/queue-7.1/udmabuf-ensure-to-perform-cache-synchronisation-in-b.patch new file mode 100644 index 0000000000..1a9e8fa55d --- /dev/null +++ b/queue-7.1/udmabuf-ensure-to-perform-cache-synchronisation-in-b.patch @@ -0,0 +1,68 @@ +From bc11f9a8c541293f50c15e29197ce62236b64e3f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 27 Jun 2026 12:57:25 +0200 +Subject: udmabuf: Ensure to perform cache synchronisation in + begin_cpu_udmabuf() + +From: Robert Mader + +[ Upstream commit 1d0e25c1ddf2063c499264fb2ba0fa6a3e4f8a00 ] + +The message of commit 504e2b4ab97a ("dma-buf/udmabuf: skip redundant cpu sync to +fix cacheline EEXIST warning") says: + +> The CPU sync at map/unmap time is also redundant for udmabuf: +> begin_cpu_udmabuf() and end_cpu_udmabuf() already perform explicit +> cache synchronization via dma_sync_sgtable_for_cpu/device() when CPU +> access is requested through the dma-buf interface. + +This, however, does not apply to the first time begin_cpu_udmabuf() is +called on an udmabuf, in which case the implementation previously relied on +get_sg_table() to perform the cache synchronisation. + +Ensure to call dma_sync_sgtable_for_cpu() in that case as well. + +Fixes: 504e2b4ab97a ("dma-buf/udmabuf: skip redundant cpu sync to fix cacheline EEXIST warning") +Signed-off-by: Robert Mader +Reviewed-by: Mikhail Gavrilov +Signed-off-by: Vivek Kasireddy +Link: https://patch.msgid.link/20260627105725.9083-1-robert.mader@collabora.com +Signed-off-by: Sasha Levin +--- + drivers/dma-buf/udmabuf.c | 9 +++++---- + 1 file changed, 5 insertions(+), 4 deletions(-) + +diff --git a/drivers/dma-buf/udmabuf.c b/drivers/dma-buf/udmabuf.c +index 2f94be1df525aa..2e7b5d4d11f429 100644 +--- a/drivers/dma-buf/udmabuf.c ++++ b/drivers/dma-buf/udmabuf.c +@@ -247,21 +247,22 @@ static int begin_cpu_udmabuf(struct dma_buf *buf, + { + struct udmabuf *ubuf = buf->priv; + struct device *dev = ubuf->device->this_device; +- int ret = 0; + + if (!ubuf->sg) { + ubuf->sg = get_sg_table(dev, buf, direction); + if (IS_ERR(ubuf->sg)) { ++ int ret; ++ + ret = PTR_ERR(ubuf->sg); + ubuf->sg = NULL; ++ return ret; + } else { + ubuf->sg_dir = direction; + } +- } else { +- dma_sync_sgtable_for_cpu(dev, ubuf->sg, direction); + } + +- return ret; ++ dma_sync_sgtable_for_cpu(dev, ubuf->sg, direction); ++ return 0; + } + + static int end_cpu_udmabuf(struct dma_buf *buf, +-- +2.53.0 + diff --git a/queue-7.1/wifi-brcmfmac-initialize-sdio-data-work-before-clean.patch b/queue-7.1/wifi-brcmfmac-initialize-sdio-data-work-before-clean.patch new file mode 100644 index 0000000000..e6c7c8a6fe --- /dev/null +++ b/queue-7.1/wifi-brcmfmac-initialize-sdio-data-work-before-clean.patch @@ -0,0 +1,61 @@ +From 4d2ad3756413fc9889aa75b6558a10a509a9cfa1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 19 Jun 2026 14:44:01 +0800 +Subject: wifi: brcmfmac: initialize SDIO data work before cleanup + +From: Runyu Xiao + +[ Upstream commit 2a665946e0407a05a3f81bd56a08553c446498e0 ] + +brcmf_sdio_probe() stores the newly allocated bus in sdiodev->bus before +allocating the ordered workqueue. If that allocation fails, the function +jumps to fail and calls brcmf_sdio_remove(). + +brcmf_sdio_remove() unconditionally cancels bus->datawork. Initialize the +work item before the first failure path that can reach brcmf_sdio_remove(), +so the cleanup path always observes a valid work object. + +This issue was found by our static analysis tool and then confirmed by +manual review of the probe error path and the remove-time work drain. The +problem pattern is an early setup failure that reaches a cleanup helper +which cancels an embedded work item before its initializer has run. + +A QEMU PoC forced alloc_ordered_workqueue() to fail at the same point in +brcmf_sdio_probe(), before INIT_WORK(&bus->datawork) is reached. The +resulting fail path calls brcmf_sdio_remove(), and DEBUG_OBJECTS reports +the invalid work drain with brcmf_sdio_probe() and brcmf_sdio_remove() in +the stack. + +Fixes: 9982464379e8 ("brcmfmac: make sdio suspend wait for threads to freeze") +Signed-off-by: Runyu Xiao +Acked-by: Arend van Spriel +Link: https://patch.msgid.link/20260619064401.1048976-1-runyu.xiao@seu.edu.cn +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c +index 8fb595733b9c36..b725c64e5b5c63 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c +@@ -4465,6 +4465,7 @@ int brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev) + bus->sdiodev = sdiodev; + sdiodev->bus = bus; + skb_queue_head_init(&bus->glom); ++ INIT_WORK(&bus->datawork, brcmf_sdio_dataworker); + bus->txbound = BRCMF_TXBOUND; + bus->rxbound = BRCMF_RXBOUND; + bus->txminmax = BRCMF_TXMINMAX; +@@ -4479,7 +4480,6 @@ int brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev) + goto fail; + } + brcmf_sdiod_freezer_count(sdiodev); +- INIT_WORK(&bus->datawork, brcmf_sdio_dataworker); + bus->brcmf_wq = wq; + + /* attempt to attach to the dongle */ +-- +2.53.0 + diff --git a/queue-7.1/wifi-cfg80211-bound-element-id-read-when-checking-no.patch b/queue-7.1/wifi-cfg80211-bound-element-id-read-when-checking-no.patch new file mode 100644 index 0000000000..143ece7cf0 --- /dev/null +++ b/queue-7.1/wifi-cfg80211-bound-element-id-read-when-checking-no.patch @@ -0,0 +1,58 @@ +From 3e1a163b3b2ea25063e7cd1bdb1398fe5487ef07 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 7 Jul 2026 18:48:28 +0900 +Subject: wifi: cfg80211: bound element ID read when checking non-inheritance +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: HE WEI (ギカク) + +[ Upstream commit cb8afea4655ff004fa7feee825d5c79783525383 ] + +cfg80211_is_element_inherited() reads the first data octet of the +candidate element (id = elem->data[0]) to look it up in an extension +non-inheritance list. It does so after testing elem->id, but without +verifying that the element actually has a data octet. A zero-length +extension element (WLAN_EID_EXTENSION with length 0) therefore makes it +read one octet past the end of the element. + +_ieee802_11_parse_elems_full() runs this check for every element of a +frame once a non-inheritance context exists -- e.g. while parsing a +per-STA profile of a Multi-Link element in a (re)association response, +or a non-transmitted BSS profile -- so a crafted frame from an AP can +trigger a one-octet slab-out-of-bounds read during element parsing: + + BUG: KASAN: slab-out-of-bounds in cfg80211_is_element_inherited + Read of size 1 ... in net/wireless/scan.c + +Return early (treat the element as inherited) when an extension element +carries no data, mirroring the existing handling of empty ID lists. + +The bug was found by fuzzing ieee802_11_parse_elems_full() under KASAN. + +Fixes: f7dacfb11475 ("cfg80211: support non-inheritance element") +Signed-off-by: HE WEI (ギカク) +Link: https://patch.msgid.link/20260707094828.16465-1-skyexpoc@gmail.com +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + net/wireless/scan.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/wireless/scan.c b/net/wireless/scan.c +index 4b7d4c576763ba..8ea6946eb0a353 100644 +--- a/net/wireless/scan.c ++++ b/net/wireless/scan.c +@@ -205,7 +205,7 @@ bool cfg80211_is_element_inherited(const struct element *elem, + return true; + + if (elem->id == WLAN_EID_EXTENSION) { +- if (!ext_id_len) ++ if (!ext_id_len || !elem->datalen) + return true; + loop_len = ext_id_len; + list = &non_inherit_elem->data[3 + id_len]; +-- +2.53.0 + diff --git a/queue-7.1/wifi-cfg80211-cancel-sched-scan-results-work-on-unre.patch b/queue-7.1/wifi-cfg80211-cancel-sched-scan-results-work-on-unre.patch new file mode 100644 index 0000000000..650aef7ad7 --- /dev/null +++ b/queue-7.1/wifi-cfg80211-cancel-sched-scan-results-work-on-unre.patch @@ -0,0 +1,83 @@ +From 4352bc04c076fe4583894ec1b8fb300eecada557 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 20 Jun 2026 00:25:42 +0800 +Subject: wifi: cfg80211: cancel sched scan results work on unregister + +From: Cen Zhang + +[ Upstream commit edf0730be33696a1bd142792830d392129e495cc ] + +cfg80211_sched_scan_results() can queue rdev->sched_scan_res_wk from a +driver result notification while a scheduled scan request is present. The +work callback recovers the containing cfg80211_registered_device and then +locks the wiphy and walks the scheduled-scan request list. + +wiphy_unregister() already makes the wiphy unreachable and drains rdev work +items before cfg80211_dev_free() can release the object, but it does not +drain sched_scan_res_wk. A queued or running result work item can therefore +cross the unregister/free boundary and access freed rdev state. + +The buggy scenario involves two paths, with each column showing the order +within that path: + +scheduled-scan result path: unregister/free path: +1. cfg80211_sched_scan_results() 1. interface teardown stops and + queues rdev->sched_scan_res_wk. removes the scheduled scan request. +2. cfg80211_wq starts the work 2. wiphy_unregister() drains other + item and recovers rdev. rdev work items. +3. The worker locks rdev->wiphy 3. cfg80211_dev_free() destroys and + and walks rdev state. frees rdev. + +Cancel sched_scan_res_wk in wiphy_unregister() alongside the other rdev +work items. cancel_work_sync() removes a pending result notification and +waits for an already running callback, so cfg80211_dev_free() cannot free +rdev while this work item is still active. + +Validation reproduced this kernel report: +BUG: KASAN: use-after-free in cfg80211_sched_scan_results_wk+0x4a6/0x530 +Workqueue: cfg80211 cfg80211_sched_scan_results_wk [cfg80211] +Read of size 8 +Call trace: + dump_stack_lvl+0x66/0xa0 + print_report+0xce/0x630 + cfg80211_sched_scan_results_wk+0x4a6/0x530 + srso_alias_return_thunk+0x5/0xfbef5 + __virt_addr_valid+0x224/0x430 + kasan_report+0xac/0xe0 + lockdep_hardirqs_on_prepare+0xea/0x1a0 + process_one_work+0x8d0/0x18f0 (kernel/workqueue.c:3212) + lock_is_held_type+0x8f/0x100 + worker_thread+0x5ad/0xfd0 + __kthread_parkme+0xc6/0x200 + kthread+0x31e/0x410 + trace_hardirqs_on+0x1a/0x170 + ret_from_fork+0x576/0x810 + __switch_to+0x57e/0xe20 + __switch_to_asm+0x33/0x70 + ret_from_fork_asm+0x1a/0x30 + +Fixes: 807f8a8c3004 ("cfg80211/nl80211: add support for scheduled scans") +Assisted-by: Codex:gpt-5.5 +Signed-off-by: Cen Zhang +Link: https://patch.msgid.link/20260619162542.3878296-1-zzzccc427@gmail.com +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + net/wireless/core.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/net/wireless/core.c b/net/wireless/core.c +index 6783e0672dcb71..2743a8a50fe3e4 100644 +--- a/net/wireless/core.c ++++ b/net/wireless/core.c +@@ -1288,6 +1288,7 @@ void wiphy_unregister(struct wiphy *wiphy) + /* this has nothing to do now but make sure it's gone */ + cancel_work_sync(&rdev->wiphy_work); + ++ cancel_work_sync(&rdev->sched_scan_res_wk); + cancel_work_sync(&rdev->rfkill_block); + cancel_work_sync(&rdev->conn_work); + flush_work(&rdev->event_work); +-- +2.53.0 + diff --git a/queue-7.1/wifi-cfg80211-convert-pmsr_free_wk-to-wiphy_work-to-.patch b/queue-7.1/wifi-cfg80211-convert-pmsr_free_wk-to-wiphy_work-to-.patch new file mode 100644 index 0000000000..5983c9e5a1 --- /dev/null +++ b/queue-7.1/wifi-cfg80211-convert-pmsr_free_wk-to-wiphy_work-to-.patch @@ -0,0 +1,138 @@ +From 0d2dbe0f63473ca3e83c831927711aa13f3b0e23 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 3 Jul 2026 13:55:23 +0530 +Subject: wifi: cfg80211: convert pmsr_free_wk to wiphy_work to fix deadlock + +From: Peddolla Harshavardhan Reddy + +[ Upstream commit 2b0eab425e1f658d8fe1df7590e3b9af5959505e ] + +When a netlink socket that owns a PMSR session is closed, +cfg80211_release_pmsr() clears the request's nl_portid and queues +pmsr_free_wk to call cfg80211_pmsr_process_abort() asynchronously. + +If the interface tears down concurrently, cfg80211_pmsr_wdev_down() +is called under wiphy_lock and calls cancel_work_sync(&pmsr_free_wk) +to wait for any running work. The work function acquires wiphy_lock +via guard(wiphy) before calling process_abort. + +This is a deadlock: wdev_down holds wiphy_lock and blocks inside +cancel_work_sync(); pmsr_free_wk blocks trying to acquire that same +wiphy_lock. Neither thread can proceed. + +The same deadlock is reachable from cfg80211_leave_locked(), which +calls cfg80211_pmsr_wdev_down() for all interface types under +wiphy_lock. + +Fix this by converting pmsr_free_wk from a plain work_struct to a +wiphy_work. The wiphy_work dispatcher holds wiphy_lock when running +work items, so the explicit guard(wiphy) in the work function is no +longer needed. wiphy_work_cancel() can be called safely while holding +wiphy_lock - since wiphy_lock prevents the work from running +concurrently, wiphy_work_cancel() never blocks, eliminating the +deadlock. + +Remove the cancel_work_sync() for pmsr_free_wk from the +NETDEV_GOING_DOWN handler. cfg80211_leave(), called unconditionally +just before it, already cancels any pending work under wiphy_lock +via wiphy_work_cancel() inside cfg80211_pmsr_wdev_down(). + +Fixes: 6dccbc9f3e1d ("wifi: cfg80211: cancel pmsr_free_wk in cfg80211_pmsr_wdev_down") +Signed-off-by: Peddolla Harshavardhan Reddy +Link: https://patch.msgid.link/20260703082523.2629324-1-peddolla.reddy@oss.qualcomm.com +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + include/net/cfg80211.h | 2 +- + net/wireless/core.c | 3 +-- + net/wireless/core.h | 2 +- + net/wireless/pmsr.c | 8 +++----- + 4 files changed, 6 insertions(+), 9 deletions(-) + +diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h +index 9d3639ff9c28e7..e7441414909cce 100644 +--- a/include/net/cfg80211.h ++++ b/include/net/cfg80211.h +@@ -7027,7 +7027,7 @@ struct wireless_dev { + + struct list_head pmsr_list; + spinlock_t pmsr_lock; +- struct work_struct pmsr_free_wk; ++ struct wiphy_work pmsr_free_wk; + + unsigned long unprot_beacon_reported; + +diff --git a/net/wireless/core.c b/net/wireless/core.c +index 2743a8a50fe3e4..6dd24115177112 100644 +--- a/net/wireless/core.c ++++ b/net/wireless/core.c +@@ -1561,7 +1561,7 @@ void cfg80211_init_wdev(struct wireless_dev *wdev) + INIT_LIST_HEAD(&wdev->mgmt_registrations); + INIT_LIST_HEAD(&wdev->pmsr_list); + spin_lock_init(&wdev->pmsr_lock); +- INIT_WORK(&wdev->pmsr_free_wk, cfg80211_pmsr_free_wk); ++ wiphy_work_init(&wdev->pmsr_free_wk, cfg80211_pmsr_free_wk); + + #ifdef CONFIG_CFG80211_WEXT + wdev->wext.default_key = -1; +@@ -1695,7 +1695,6 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb, + cfg80211_remove_links(wdev); + /* since we just did cfg80211_leave() nothing to do there */ + cancel_work_sync(&wdev->disconnect_wk); +- cancel_work_sync(&wdev->pmsr_free_wk); + break; + case NETDEV_DOWN: + wiphy_lock(&rdev->wiphy); +diff --git a/net/wireless/core.h b/net/wireless/core.h +index ae2d56d3ad9083..5ad38519d8a64b 100644 +--- a/net/wireless/core.h ++++ b/net/wireless/core.h +@@ -583,7 +583,7 @@ cfg80211_get_6ghz_power_type(const u8 *elems, size_t elems_len, + + void cfg80211_release_pmsr(struct wireless_dev *wdev, u32 portid); + void cfg80211_pmsr_wdev_down(struct wireless_dev *wdev); +-void cfg80211_pmsr_free_wk(struct work_struct *work); ++void cfg80211_pmsr_free_wk(struct wiphy *wiphy, struct wiphy_work *work); + + void cfg80211_remove_link(struct wireless_dev *wdev, unsigned int link_id); + void cfg80211_remove_links(struct wireless_dev *wdev); +diff --git a/net/wireless/pmsr.c b/net/wireless/pmsr.c +index 0ca93fd7d46f8d..1ee7a9e2cdef21 100644 +--- a/net/wireless/pmsr.c ++++ b/net/wireless/pmsr.c +@@ -645,13 +645,11 @@ static void cfg80211_pmsr_process_abort(struct wireless_dev *wdev) + } + } + +-void cfg80211_pmsr_free_wk(struct work_struct *work) ++void cfg80211_pmsr_free_wk(struct wiphy *wiphy, struct wiphy_work *work) + { + struct wireless_dev *wdev = container_of(work, struct wireless_dev, + pmsr_free_wk); + +- guard(wiphy)(wdev->wiphy); +- + cfg80211_pmsr_process_abort(wdev); + } + +@@ -667,7 +665,7 @@ void cfg80211_pmsr_wdev_down(struct wireless_dev *wdev) + } + spin_unlock_bh(&wdev->pmsr_lock); + +- cancel_work_sync(&wdev->pmsr_free_wk); ++ wiphy_work_cancel(wdev->wiphy, &wdev->pmsr_free_wk); + if (found) + cfg80211_pmsr_process_abort(wdev); + +@@ -682,7 +680,7 @@ void cfg80211_release_pmsr(struct wireless_dev *wdev, u32 portid) + list_for_each_entry(req, &wdev->pmsr_list, list) { + if (req->nl_portid == portid) { + req->nl_portid = 0; +- schedule_work(&wdev->pmsr_free_wk); ++ wiphy_work_queue(wdev->wiphy, &wdev->pmsr_free_wk); + } + } + spin_unlock_bh(&wdev->pmsr_lock); +-- +2.53.0 + diff --git a/queue-7.1/wifi-cfg80211-derive-s1g-beacon-tsf-from-s1g-fields.patch b/queue-7.1/wifi-cfg80211-derive-s1g-beacon-tsf-from-s1g-fields.patch new file mode 100644 index 0000000000..160d822390 --- /dev/null +++ b/queue-7.1/wifi-cfg80211-derive-s1g-beacon-tsf-from-s1g-fields.patch @@ -0,0 +1,54 @@ +From 779f4bc43ff8ed8edb9417c90d0d728f71b0e6ac Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 12 Jun 2026 00:19:46 +0800 +Subject: wifi: cfg80211: derive S1G beacon TSF from S1G fields + +From: Zhao Li + +[ Upstream commit 4e5a4641e7b4763656336b7891d01359aaf363cd ] + +cfg80211_inform_bss_frame_data() parses S1G beacons with the extension +frame layout, but still reads the TSF from the regular probe response +layout after the S1G branch. For S1G beacons that reads bytes at the +regular management-frame timestamp offset instead of the S1G timestamp. + +Use the 32-bit S1G beacon timestamp and the S1G Beacon Compatibility +element's TSF completion field when informing an S1G BSS. Keep the +regular management-frame timestamp read in the non-S1G branch. + +Fixes: 9eaffe5078ca ("cfg80211: convert S1G beacon to scan results") +Signed-off-by: Zhao Li +Tested-by: Lachlan Hodges +Reviewed-by: Lachlan Hodges +Link: https://patch.msgid.link/20260611161943.91069-6-enderaoelyther@gmail.com +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + net/wireless/scan.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/net/wireless/scan.c b/net/wireless/scan.c +index 654f3300912dab..4b7d4c576763ba 100644 +--- a/net/wireless/scan.c ++++ b/net/wireless/scan.c +@@ -3312,14 +3312,15 @@ cfg80211_inform_bss_frame_data(struct wiphy *wiphy, + bssid = ext->u.s1g_beacon.sa; + capability = le16_to_cpu(compat->compat_info); + beacon_interval = le16_to_cpu(compat->beacon_int); ++ tsf = le32_to_cpu(ext->u.s1g_beacon.timestamp); ++ tsf |= (u64)le32_to_cpu(compat->tsf_completion) << 32; + } else { + bssid = mgmt->bssid; + beacon_interval = le16_to_cpu(mgmt->u.probe_resp.beacon_int); + capability = le16_to_cpu(mgmt->u.probe_resp.capab_info); ++ tsf = le64_to_cpu(mgmt->u.probe_resp.timestamp); + } + +- tsf = le64_to_cpu(mgmt->u.probe_resp.timestamp); +- + if (ieee80211_is_probe_resp(mgmt->frame_control)) + ftype = CFG80211_BSS_FTYPE_PRESP; + else if (ext) +-- +2.53.0 + diff --git a/queue-7.1/wifi-cfg80211-fix-an-error-handling-path-in-cfg80211.patch b/queue-7.1/wifi-cfg80211-fix-an-error-handling-path-in-cfg80211.patch new file mode 100644 index 0000000000..fc60e55476 --- /dev/null +++ b/queue-7.1/wifi-cfg80211-fix-an-error-handling-path-in-cfg80211.patch @@ -0,0 +1,41 @@ +From f75a0436c5451eda35070d81ad2ced9bb498c912 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 20 Jun 2026 21:48:56 +0200 +Subject: wifi: cfg80211: Fix an error handling path in cfg80211_wext_siwscan() + +From: Christophe JAILLET + +[ Upstream commit c6659f66d4ee4841aafae5659d2ef5e4c5c63cb6 ] + +If the test against IEEE80211_MAX_SSID_LEN fails, then 'creq' leaks. +Use the existing error handling path to fix it. + +Fixes: 2a5193119269 ("cfg80211/nl80211: scanning (and mac80211 update to use it)") +Signed-off-by: Christophe JAILLET +Link: https://patch.msgid.link/a1be7eea4da0da18f90589af252bb76a18a61978.1781984889.git.christophe.jaillet@wanadoo.fr +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + net/wireless/scan.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/net/wireless/scan.c b/net/wireless/scan.c +index d9f2a77e127ce8..654f3300912dab 100644 +--- a/net/wireless/scan.c ++++ b/net/wireless/scan.c +@@ -3613,8 +3613,10 @@ int cfg80211_wext_siwscan(struct net_device *dev, + /* translate "Scan for SSID" request */ + if (wreq) { + if (wrqu->data.flags & IW_SCAN_THIS_ESSID) { +- if (wreq->essid_len > IEEE80211_MAX_SSID_LEN) +- return -EINVAL; ++ if (wreq->essid_len > IEEE80211_MAX_SSID_LEN) { ++ err = -EINVAL; ++ goto out; ++ } + memcpy(creq->req.ssids[0].ssid, wreq->essid, + wreq->essid_len); + creq->req.ssids[0].ssid_len = wreq->essid_len; +-- +2.53.0 + diff --git a/queue-7.1/wifi-cfg80211-reject-empty-pmsr-peer-lists.patch b/queue-7.1/wifi-cfg80211-reject-empty-pmsr-peer-lists.patch new file mode 100644 index 0000000000..0535d55e51 --- /dev/null +++ b/queue-7.1/wifi-cfg80211-reject-empty-pmsr-peer-lists.patch @@ -0,0 +1,46 @@ +From ada7e6abb0ebaff356c9e567b7b82f4b45cafd9c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 12 Jun 2026 21:37:18 +0800 +Subject: wifi: cfg80211: reject empty PMSR peer lists + +From: Zhao Li + +[ Upstream commit 57c05ce14fea03df01288fe1250f49197e161710 ] + +A PMSR request with an empty peers array is not a useful request and +weakens the cfg80211-to-driver contract by allowing start_pmsr() with +no target peer. + +Reject empty peer lists before allocating the request object or calling +into the driver. + +Fixes: 9bb7e0f24e7e7 ("cfg80211: add peer measurement with FTM initiator API") +Assisted-by: Codex:gpt-5.5 +Assisted-by: Claude:claude-opus-4.8 +Signed-off-by: Zhao Li +Link: https://patch.msgid.link/20260612133717.93783-2-enderaoelyther@gmail.com +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + net/wireless/pmsr.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/net/wireless/pmsr.c b/net/wireless/pmsr.c +index 9246640d2eedfd..feced0f762e01d 100644 +--- a/net/wireless/pmsr.c ++++ b/net/wireless/pmsr.c +@@ -332,6 +332,11 @@ int nl80211_pmsr_start(struct sk_buff *skb, struct genl_info *info) + } + } + ++ if (!count) { ++ NL_SET_ERR_MSG_ATTR(info->extack, peers, "No peers specified"); ++ return -EINVAL; ++ } ++ + req = kzalloc_flex(*req, peers, count); + if (!req) + return -ENOMEM; +-- +2.53.0 + diff --git a/queue-7.1/wifi-cfg80211-reject-unsupported-pmsr-ftm-location-r.patch b/queue-7.1/wifi-cfg80211-reject-unsupported-pmsr-ftm-location-r.patch new file mode 100644 index 0000000000..4db3bdfa6b --- /dev/null +++ b/queue-7.1/wifi-cfg80211-reject-unsupported-pmsr-ftm-location-r.patch @@ -0,0 +1,50 @@ +From 870c78b7746f29ae4d52963a277bbaac3b174dcc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 12 Jun 2026 21:37:11 +0800 +Subject: wifi: cfg80211: reject unsupported PMSR FTM location requests + +From: Zhao Li + +[ Upstream commit 69ef6a7ec277f16d216be8da2b3cbe872786c999 ] + +PMSR FTM location request flags are syntactically valid, but they must +be rejected when the device capability does not advertise support for +them. + +Return an error immediately after rejecting unsupported LCI or civic +location request bits so the request cannot reach the driver. + +Fixes: 9bb7e0f24e7e7 ("cfg80211: add peer measurement with FTM initiator API") +Assisted-by: Codex:gpt-5.5 +Assisted-by: Claude:claude-opus-4.8 +Signed-off-by: Zhao Li +Link: https://patch.msgid.link/20260612133710.93544-2-enderaoelyther@gmail.com +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + net/wireless/pmsr.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/net/wireless/pmsr.c b/net/wireless/pmsr.c +index 4b10ce0486f4a6..9246640d2eedfd 100644 +--- a/net/wireless/pmsr.c ++++ b/net/wireless/pmsr.c +@@ -109,6 +109,7 @@ static int pmsr_parse_ftm(struct cfg80211_registered_device *rdev, + NL_SET_ERR_MSG_ATTR(info->extack, + tb[NL80211_PMSR_FTM_REQ_ATTR_REQUEST_LCI], + "FTM: LCI request not supported"); ++ return -EOPNOTSUPP; + } + + out->ftm.request_civicloc = +@@ -117,6 +118,7 @@ static int pmsr_parse_ftm(struct cfg80211_registered_device *rdev, + NL_SET_ERR_MSG_ATTR(info->extack, + tb[NL80211_PMSR_FTM_REQ_ATTR_REQUEST_CIVICLOC], + "FTM: civic location request not supported"); ++ return -EOPNOTSUPP; + } + + out->ftm.trigger_based = +-- +2.53.0 + diff --git a/queue-7.1/wifi-cfg80211-use-wiphy-work-for-socket-owner-autodi.patch b/queue-7.1/wifi-cfg80211-use-wiphy-work-for-socket-owner-autodi.patch new file mode 100644 index 0000000000..36cff755b9 --- /dev/null +++ b/queue-7.1/wifi-cfg80211-use-wiphy-work-for-socket-owner-autodi.patch @@ -0,0 +1,142 @@ +From 71458167bd932aa56c84d82966267da3bb745b1b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 6 Jul 2026 23:24:18 +0800 +Subject: wifi: cfg80211: use wiphy work for socket owner autodisconnect + +From: Cen Zhang + +[ Upstream commit 0c2ed186bbe14304415476d6707b747dddcd8583 ] + +nl80211_netlink_notify() walks the cfg80211 wireless device list when a +NETLINK_GENERIC socket is released. If the socket owns a connection, the +notifier queues the embedded wdev->disconnect_wk work item. + +That work is a plain work_struct today. NETDEV_GOING_DOWN cancels it, but a +NETLINK_URELEASE notifier that already observed conn_owner_nlportid can +queue it after that cancel returns. _cfg80211_unregister_wdev() then +removes the wdev from the list and waits for RCU readers, but +synchronize_net() does not drain work queued by such a reader. + +Make the autodisconnect work a wiphy_work instead. The callback already +needs the wiphy mutex, and wiphy_work runs under that mutex. This lets +teardown cancel pending autodisconnect work while holding the mutex, +without a cancel_work_sync() vs. worker locking concern. + +Also cancel the wiphy work after list_del_rcu() and synchronize_net(). Any +NETLINK_URELEASE notifier that had already reached the wdev list has then +either queued the work and it is removed, or can no longer find the wdev. + +Fixes: bd2522b16884 ("cfg80211: NL80211_ATTR_SOCKET_OWNER support for CMD_CONNECT") +Suggested-by: Johannes Berg +Assisted-by: Codex:gpt-5.5 +Signed-off-by: Cen Zhang +Link: https://patch.msgid.link/20260706152418.779226-1-zzzccc427@gmail.com +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + include/net/cfg80211.h | 2 +- + net/wireless/core.c | 10 ++++++---- + net/wireless/core.h | 2 +- + net/wireless/nl80211.c | 3 ++- + net/wireless/sme.c | 6 ++---- + 5 files changed, 12 insertions(+), 11 deletions(-) + +diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h +index e7441414909cce..909fb76751c508 100644 +--- a/include/net/cfg80211.h ++++ b/include/net/cfg80211.h +@@ -6990,7 +6990,7 @@ struct wireless_dev { + enum ieee80211_bss_type conn_bss_type; + u32 conn_owner_nlportid; + +- struct work_struct disconnect_wk; ++ struct wiphy_work disconnect_wk; + u8 disconnect_bssid[ETH_ALEN]; + + struct list_head event_list; +diff --git a/net/wireless/core.c b/net/wireless/core.c +index 6dd24115177112..7f6a0418d83018 100644 +--- a/net/wireless/core.c ++++ b/net/wireless/core.c +@@ -1378,6 +1378,7 @@ static void _cfg80211_unregister_wdev(struct wireless_dev *wdev, + list_del_rcu(&wdev->list); + synchronize_net(); + rdev->devlist_generation++; ++ wiphy_work_cancel(wdev->wiphy, &wdev->disconnect_wk); + + cfg80211_mlme_purge_registrations(wdev); + +@@ -1585,7 +1586,7 @@ void cfg80211_init_wdev(struct wireless_dev *wdev) + wdev->iftype == NL80211_IFTYPE_ADHOC) && !wdev->use_4addr) + wdev->netdev->priv_flags |= IFF_DONT_BRIDGE; + +- INIT_WORK(&wdev->disconnect_wk, cfg80211_autodisconnect_wk); ++ wiphy_work_init(&wdev->disconnect_wk, cfg80211_autodisconnect_wk); + } + + void cfg80211_register_wdev(struct cfg80211_registered_device *rdev, +@@ -1691,10 +1692,11 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb, + break; + case NETDEV_GOING_DOWN: + cfg80211_leave(rdev, wdev, -1); +- scoped_guard(wiphy, &rdev->wiphy) ++ scoped_guard(wiphy, &rdev->wiphy) { + cfg80211_remove_links(wdev); +- /* since we just did cfg80211_leave() nothing to do there */ +- cancel_work_sync(&wdev->disconnect_wk); ++ /* since we just did cfg80211_leave() nothing to do there */ ++ wiphy_work_cancel(wdev->wiphy, &wdev->disconnect_wk); ++ } + break; + case NETDEV_DOWN: + wiphy_lock(&rdev->wiphy); +diff --git a/net/wireless/core.h b/net/wireless/core.h +index 5ad38519d8a64b..8d40f1e6538bca 100644 +--- a/net/wireless/core.h ++++ b/net/wireless/core.h +@@ -428,7 +428,7 @@ void __cfg80211_port_authorized(struct wireless_dev *wdev, const u8 *peer_addr, + const u8 *td_bitmap, u8 td_bitmap_len); + int cfg80211_mgd_wext_connect(struct cfg80211_registered_device *rdev, + struct wireless_dev *wdev); +-void cfg80211_autodisconnect_wk(struct work_struct *work); ++void cfg80211_autodisconnect_wk(struct wiphy *wiphy, struct wiphy_work *work); + + /* SME implementation */ + void cfg80211_conn_work(struct work_struct *work); +diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c +index 3476681ecd7aa8..68f9219796e199 100644 +--- a/net/wireless/nl80211.c ++++ b/net/wireless/nl80211.c +@@ -22557,7 +22557,8 @@ static int nl80211_netlink_notify(struct notifier_block * nb, + wdev->nl_owner_dead = true; + schedule_work(&rdev->destroy_work); + } else if (wdev->conn_owner_nlportid == notify->portid) { +- schedule_work(&wdev->disconnect_wk); ++ wiphy_work_queue(wdev->wiphy, ++ &wdev->disconnect_wk); + } + + cfg80211_release_pmsr(wdev, notify->portid); +diff --git a/net/wireless/sme.c b/net/wireless/sme.c +index 86e2ccaa678ce5..1ddaadbed74c82 100644 +--- a/net/wireless/sme.c ++++ b/net/wireless/sme.c +@@ -1577,13 +1577,11 @@ int cfg80211_disconnect(struct cfg80211_registered_device *rdev, + * Used to clean up after the connection / connection attempt owner socket + * disconnects + */ +-void cfg80211_autodisconnect_wk(struct work_struct *work) ++void cfg80211_autodisconnect_wk(struct wiphy *wiphy, struct wiphy_work *work) + { + struct wireless_dev *wdev = + container_of(work, struct wireless_dev, disconnect_wk); +- struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy); +- +- guard(wiphy)(wdev->wiphy); ++ struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy); + + if (wdev->conn_owner_nlportid) { + switch (wdev->iftype) { +-- +2.53.0 + diff --git a/queue-7.1/wifi-cfg80211-validate-pmsr-ftm-preamble-range.patch b/queue-7.1/wifi-cfg80211-validate-pmsr-ftm-preamble-range.patch new file mode 100644 index 0000000000..a13985109a --- /dev/null +++ b/queue-7.1/wifi-cfg80211-validate-pmsr-ftm-preamble-range.patch @@ -0,0 +1,45 @@ +From cb2413b1088da94ee10aa5fca3657418d3ab95d3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 12 Jun 2026 21:37:04 +0800 +Subject: wifi: cfg80211: validate PMSR FTM preamble range + +From: Zhao Li + +[ Upstream commit 36230936468f0ba4930e94aef496fc229d4bb951 ] + +PMSR FTM request parsing accepts preamble values outside the +enumerated nl80211 preamble range. + +Reject out-of-range values before using them in the parser capability +bit test using the policy. + +Fixes: 9bb7e0f24e7e7 ("cfg80211: add peer measurement with FTM initiator API") +Assisted-by: Codex:gpt-5.5 +Assisted-by: Claude:claude-opus-4.8 +Signed-off-by: Zhao Li +Link: https://patch.msgid.link/20260612133703.93274-2-enderaoelyther@gmail.com +[drop unnecessary check] +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + net/wireless/nl80211.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c +index 3024fa8dd78021..3476681ecd7aa8 100644 +--- a/net/wireless/nl80211.c ++++ b/net/wireless/nl80211.c +@@ -461,7 +461,9 @@ nl80211_ftm_responder_policy[NL80211_FTM_RESP_ATTR_MAX + 1] = { + static const struct nla_policy + nl80211_pmsr_ftm_req_attr_policy[NL80211_PMSR_FTM_REQ_ATTR_MAX + 1] = { + [NL80211_PMSR_FTM_REQ_ATTR_ASAP] = { .type = NLA_FLAG }, +- [NL80211_PMSR_FTM_REQ_ATTR_PREAMBLE] = { .type = NLA_U32 }, ++ [NL80211_PMSR_FTM_REQ_ATTR_PREAMBLE] = ++ NLA_POLICY_RANGE(NLA_U32, NL80211_PREAMBLE_LEGACY, ++ NL80211_PREAMBLE_HE), + [NL80211_PMSR_FTM_REQ_ATTR_NUM_BURSTS_EXP] = + NLA_POLICY_MAX(NLA_U8, 15), + [NL80211_PMSR_FTM_REQ_ATTR_BURST_PERIOD] = { .type = NLA_U16 }, +-- +2.53.0 + diff --git a/queue-7.1/wifi-cfg80211-validate-pmsr-measurement-type-data.patch b/queue-7.1/wifi-cfg80211-validate-pmsr-measurement-type-data.patch new file mode 100644 index 0000000000..76709e8136 --- /dev/null +++ b/queue-7.1/wifi-cfg80211-validate-pmsr-measurement-type-data.patch @@ -0,0 +1,76 @@ +From 6c04fd4c66a5b04450c49b74a79e8a8904b36395 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 12 Jun 2026 21:36:57 +0800 +Subject: wifi: cfg80211: validate PMSR measurement type data + +From: Zhao Li + +[ Upstream commit 41aa973eb05922848dded26875c55ef982ac1c49 ] + +PMSR request parsing accepts missing or duplicated measurement type +entries in NL80211_PMSR_REQ_ATTR_DATA. + +Track whether one measurement type was already provided, reject a +second one immediately, and return an error if the request data block +contains no measurement type at all. + +Fixes: 9bb7e0f24e7e7 ("cfg80211: add peer measurement with FTM initiator API") +Assisted-by: Codex:gpt-5.5 +Assisted-by: Claude:claude-opus-4.8 +Signed-off-by: Zhao Li +Link: https://patch.msgid.link/20260612133656.92900-2-enderaoelyther@gmail.com +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + net/wireless/pmsr.c | 19 +++++++++++++++++-- + 1 file changed, 17 insertions(+), 2 deletions(-) + +diff --git a/net/wireless/pmsr.c b/net/wireless/pmsr.c +index 1ee7a9e2cdef21..4b10ce0486f4a6 100644 +--- a/net/wireless/pmsr.c ++++ b/net/wireless/pmsr.c +@@ -214,6 +214,7 @@ static int pmsr_parse_peer(struct cfg80211_registered_device *rdev, + { + struct nlattr *tb[NL80211_PMSR_PEER_ATTR_MAX + 1]; + struct nlattr *req[NL80211_PMSR_REQ_ATTR_MAX + 1]; ++ bool have_measurement_type = false; + struct nlattr *treq; + int err, rem; + +@@ -267,6 +268,14 @@ static int pmsr_parse_peer(struct cfg80211_registered_device *rdev, + } + + nla_for_each_nested(treq, req[NL80211_PMSR_REQ_ATTR_DATA], rem) { ++ if (have_measurement_type) { ++ NL_SET_ERR_MSG_ATTR(info->extack, treq, ++ "multiple measurement types in request data"); ++ return -EINVAL; ++ } ++ ++ have_measurement_type = true; ++ + switch (nla_type(treq)) { + case NL80211_PMSR_TYPE_FTM: + err = pmsr_parse_ftm(rdev, treq, out, info); +@@ -276,10 +285,16 @@ static int pmsr_parse_peer(struct cfg80211_registered_device *rdev, + "unsupported measurement type"); + err = -EINVAL; + } ++ if (err) ++ return err; + } + +- if (err) +- return err; ++ if (!have_measurement_type) { ++ NL_SET_ERR_MSG_ATTR(info->extack, ++ req[NL80211_PMSR_REQ_ATTR_DATA], ++ "missing measurement type in request data"); ++ return -EINVAL; ++ } + + return 0; + } +-- +2.53.0 + diff --git a/queue-7.1/wifi-ipw2100-fix-potential-memory-leak-in-ipw2100_pc.patch b/queue-7.1/wifi-ipw2100-fix-potential-memory-leak-in-ipw2100_pc.patch new file mode 100644 index 0000000000..3991d2ca8b --- /dev/null +++ b/queue-7.1/wifi-ipw2100-fix-potential-memory-leak-in-ipw2100_pc.patch @@ -0,0 +1,60 @@ +From 41cb149410a0c1b25c0b7753b458e190354b5a93 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 20 Jun 2026 12:22:39 +0530 +Subject: wifi: ipw2100: fix potential memory leak in ipw2100_pci_init_one() + +From: Abdun Nihaal + +[ Upstream commit 0d388f62031dbabcba0f44bb91b59f10e88cac17 ] + +The memory allocated in the ipw2100_alloc_device() function is not freed +in some of the error paths in ipw2100_pci_init_one(). Fix that by +converting the direct return into a goto to the error path return. + +The error path when pci_enable_device() fails cannot jump to fail, since +at this point priv is not set, so perform error handling inline. + +Fixes: 2c86c275015c ("Add ipw2100 wireless driver.") +Signed-off-by: Abdun Nihaal +Link: https://patch.msgid.link/20260620065242.93798-1-nihaal@cse.iitm.ac.in +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/intel/ipw2x00/ipw2100.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/drivers/net/wireless/intel/ipw2x00/ipw2100.c b/drivers/net/wireless/intel/ipw2x00/ipw2100.c +index c11428485dccf5..2b8a23865bfb29 100644 +--- a/drivers/net/wireless/intel/ipw2x00/ipw2100.c ++++ b/drivers/net/wireless/intel/ipw2x00/ipw2100.c +@@ -6157,6 +6157,8 @@ static int ipw2100_pci_init_one(struct pci_dev *pci_dev, + if (err) { + printk(KERN_WARNING DRV_NAME + "Error calling pci_enable_device.\n"); ++ free_libipw(dev, 0); ++ pci_iounmap(pci_dev, ioaddr); + return err; + } + +@@ -6169,16 +6171,14 @@ static int ipw2100_pci_init_one(struct pci_dev *pci_dev, + if (err) { + printk(KERN_WARNING DRV_NAME + "Error calling pci_set_dma_mask.\n"); +- pci_disable_device(pci_dev); +- return err; ++ goto fail; + } + + err = pci_request_regions(pci_dev, DRV_NAME); + if (err) { + printk(KERN_WARNING DRV_NAME + "Error calling pci_request_regions.\n"); +- pci_disable_device(pci_dev); +- return err; ++ goto fail; + } + + /* We disable the RETRY_TIMEOUT register (0x41) to keep +-- +2.53.0 + diff --git a/queue-7.1/wifi-libertas-fix-memory-leak-in-helper_firmware_cb.patch b/queue-7.1/wifi-libertas-fix-memory-leak-in-helper_firmware_cb.patch new file mode 100644 index 0000000000..6ac09f487a --- /dev/null +++ b/queue-7.1/wifi-libertas-fix-memory-leak-in-helper_firmware_cb.patch @@ -0,0 +1,50 @@ +From ffe4d22c52c80de99b93c790ee690cd74b21bbcc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 24 Jun 2026 16:53:43 +0800 +Subject: wifi: libertas: fix memory leak in helper_firmware_cb() + +From: Dawei Feng + +[ Upstream commit 63c2391deefb31e1b801b7f32bd502ca4808639b ] + +helper_firmware_cb() neglects to free the single-stage firmware image +after a successful async load, leading to a memory leak in the USB +firmware-download path. + +Fix this memory leak by calling release_firmware() immediately after +lbs_fw_loaded() returns. + +The bug was first flagged by an experimental analysis tool we are +developing for kernel memory-management bugs while analyzing +v6.13-rc1. The tool is still under development and is not yet publicly +available. Manual inspection confirms that the bug is still present in +the current wireless tree. + +An x86_64 allyesconfig build showed no new warnings. As we do not have +compatible Libertas USB hardware for exercising this firmware-download +path, no runtime testing was able to be performed. + +Fixes: 1dfba3060fe7 ("libertas: move firmware lifetime handling to firmware.c") +Signed-off-by: Dawei Feng +Link: https://patch.msgid.link/20260624085343.575508-1-dawei.feng@seu.edu.cn +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/marvell/libertas/firmware.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/net/wireless/marvell/libertas/firmware.c b/drivers/net/wireless/marvell/libertas/firmware.c +index f124110944b7e9..9bf7d4c207b9ed 100644 +--- a/drivers/net/wireless/marvell/libertas/firmware.c ++++ b/drivers/net/wireless/marvell/libertas/firmware.c +@@ -78,6 +78,7 @@ static void helper_firmware_cb(const struct firmware *firmware, void *context) + } else { + /* No main firmware needed for this helper --> success! */ + lbs_fw_loaded(priv, 0, firmware, NULL); ++ release_firmware(firmware); + } + } + +-- +2.53.0 + diff --git a/queue-7.1/wifi-mac80211-allocate-backup-ieee80211_nan_sched_cf.patch b/queue-7.1/wifi-mac80211-allocate-backup-ieee80211_nan_sched_cf.patch new file mode 100644 index 0000000000..3c645d75bf --- /dev/null +++ b/queue-7.1/wifi-mac80211-allocate-backup-ieee80211_nan_sched_cf.patch @@ -0,0 +1,108 @@ +From e216efebf4bebb3f0ff0452f0d7aeeba8c18dba7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 11 Jun 2026 15:00:54 +0200 +Subject: wifi: mac80211: allocate backup ieee80211_nan_sched_cfg off stack + +From: Arnd Bergmann + +[ Upstream commit 44494b0d1d16e76ae805817579eacc801b10ed37 ] + +The ieee80211_nan_sched_cfg structure is too large to keep on the +per thread stack: + +net/mac80211/nan.c:251:5: error: stack frame size (1560) exceeds limit (1536) in 'ieee80211_nan_set_local_sched' [-Werror,-Wframe-larger-than] + 251 | int ieee80211_nan_set_local_sched(struct ieee80211_sub_if_data *sdata, + +Allocate this dynamically using kmalloc_obj() to reduce the stack +usage of this function to a manageable 344 bytes for the same +configuration. + +Fixes: 589c06e8fdee ("wifi: mac80211: add NAN local schedule support") +Signed-off-by: Arnd Bergmann +Link: https://patch.msgid.link/20260611130100.3387714-1-arnd@kernel.org +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + net/mac80211/nan.c | 35 +++++++++++++++++++---------------- + 1 file changed, 19 insertions(+), 16 deletions(-) + +diff --git a/net/mac80211/nan.c b/net/mac80211/nan.c +index 4e262b624521d2..d089b18321e44c 100644 +--- a/net/mac80211/nan.c ++++ b/net/mac80211/nan.c +@@ -253,9 +253,12 @@ int ieee80211_nan_set_local_sched(struct ieee80211_sub_if_data *sdata, + { + struct ieee80211_nan_channel *sched_idx_to_chan[IEEE80211_NAN_MAX_CHANNELS] = {}; + struct ieee80211_nan_sched_cfg *sched_cfg = &sdata->vif.cfg.nan_sched; +- struct ieee80211_nan_sched_cfg backup_sched; ++ struct ieee80211_nan_sched_cfg *backup_sched __free(kfree) = kmalloc_obj(*backup_sched); + int ret; + ++ if (!backup_sched) ++ return -ENOMEM; ++ + if (sched->n_channels > IEEE80211_NAN_MAX_CHANNELS) + return -EOPNOTSUPP; + +@@ -275,13 +278,13 @@ int ieee80211_nan_set_local_sched(struct ieee80211_sub_if_data *sdata, + + bitmap_zero(sdata->u.nan.removed_channels, IEEE80211_NAN_MAX_CHANNELS); + +- memcpy(backup_sched.schedule, sched_cfg->schedule, +- sizeof(backup_sched.schedule)); +- memcpy(backup_sched.channels, sched_cfg->channels, +- sizeof(backup_sched.channels)); +- memcpy(backup_sched.avail_blob, sched_cfg->avail_blob, +- sizeof(backup_sched.avail_blob)); +- backup_sched.avail_blob_len = sched_cfg->avail_blob_len; ++ memcpy(backup_sched->schedule, sched_cfg->schedule, ++ sizeof(backup_sched->schedule)); ++ memcpy(backup_sched->channels, sched_cfg->channels, ++ sizeof(backup_sched->channels)); ++ memcpy(backup_sched->avail_blob, sched_cfg->avail_blob, ++ sizeof(backup_sched->avail_blob)); ++ backup_sched->avail_blob_len = sched_cfg->avail_blob_len; + + memcpy(sched_cfg->avail_blob, sched->nan_avail_blob, + sched->nan_avail_blob_len); +@@ -377,17 +380,17 @@ int ieee80211_nan_set_local_sched(struct ieee80211_sub_if_data *sdata, + if (!chan_def->chan) + continue; + +- if (!cfg80211_chandef_identical(&backup_sched.channels[i].chanreq.oper, ++ if (!cfg80211_chandef_identical(&backup_sched->channels[i].chanreq.oper, + chan_def)) + ieee80211_nan_remove_channel(sdata, + &sched_cfg->channels[i]); + } + + /* Re-add all backed up channels */ +- for (int i = 0; i < ARRAY_SIZE(backup_sched.channels); i++) { ++ for (int i = 0; i < ARRAY_SIZE(backup_sched->channels); i++) { + struct ieee80211_nan_channel *chan = &sched_cfg->channels[i]; + +- *chan = backup_sched.channels[i]; ++ *chan = backup_sched->channels[i]; + + /* + * For deferred update, no channels were removed and the channel +@@ -418,11 +421,11 @@ int ieee80211_nan_set_local_sched(struct ieee80211_sub_if_data *sdata, + } + } + +- memcpy(sched_cfg->schedule, backup_sched.schedule, +- sizeof(backup_sched.schedule)); +- memcpy(sched_cfg->avail_blob, backup_sched.avail_blob, +- sizeof(backup_sched.avail_blob)); +- sched_cfg->avail_blob_len = backup_sched.avail_blob_len; ++ memcpy(sched_cfg->schedule, backup_sched->schedule, ++ sizeof(backup_sched->schedule)); ++ memcpy(sched_cfg->avail_blob, backup_sched->avail_blob, ++ sizeof(backup_sched->avail_blob)); ++ sched_cfg->avail_blob_len = backup_sched->avail_blob_len; + sched_cfg->deferred = false; + bitmap_zero(sdata->u.nan.removed_channels, IEEE80211_NAN_MAX_CHANNELS); + +-- +2.53.0 + diff --git a/queue-7.1/wifi-mac80211-avoid-non-s1g-aid-fallback-for-s1g-ass.patch b/queue-7.1/wifi-mac80211-avoid-non-s1g-aid-fallback-for-s1g-ass.patch new file mode 100644 index 0000000000..19a3eecaa2 --- /dev/null +++ b/queue-7.1/wifi-mac80211-avoid-non-s1g-aid-fallback-for-s1g-ass.patch @@ -0,0 +1,58 @@ +From 967ea4f633fcc48c1acfd5ea026fa45b721aceef Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 12 Jun 2026 23:24:41 +0800 +Subject: wifi: mac80211: avoid non-S1G AID fallback for S1G assoc + +From: Zhao Li + +[ Upstream commit 035ed430ce6a2c35b01e211844a9f0a7643e57a4 ] + +When assoc_data->s1g is set and no AID Response element is present, +falling back to mgmt->u.assoc_resp.aid reads the non-S1G +association-response layout. + +Keep the fallback for non-S1G only. If a successful S1G association +response omits the AID Response element, abandon the association +instead of proceeding with AID 0. Initialize aid to 0 for other S1G +responses so the later mask and logging flow keeps a defined value +without reading the non-S1G layout. + +Fixes: 2a8a6b7c4cb0 ("wifi: mac80211: handle station association response with S1G") +Assisted-by: Codex:gpt-5.5 +Assisted-by: Claude:claude-opus-4.8 +Signed-off-by: Zhao Li +Link: https://patch.msgid.link/20260612152440.25955-2-enderaoelyther@gmail.com +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + net/mac80211/mlme.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c +index b98ddfa3003e16..ddd3479f0b4034 100644 +--- a/net/mac80211/mlme.c ++++ b/net/mac80211/mlme.c +@@ -6659,7 +6659,7 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, + { + struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; + struct ieee80211_mgd_assoc_data *assoc_data = ifmgd->assoc_data; +- u16 capab_info, status_code, aid; ++ u16 capab_info, status_code, aid = 0; + struct ieee80211_elems_parse_params parse_params = { + .bss = NULL, + .link_id = -1, +@@ -6737,8 +6737,10 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, + + if (elems->aid_resp) + aid = le16_to_cpu(elems->aid_resp->aid); +- else ++ else if (!assoc_data->s1g) + aid = le16_to_cpu(mgmt->u.assoc_resp.aid); ++ else if (status_code == WLAN_STATUS_SUCCESS) ++ goto abandon_assoc; + + /* + * The 5 MSB of the AID field are reserved for a non-S1G STA. For +-- +2.53.0 + diff --git a/queue-7.1/wifi-mac80211-defer-link-rx-stats-percpu-free-to-rcu.patch b/queue-7.1/wifi-mac80211-defer-link-rx-stats-percpu-free-to-rcu.patch new file mode 100644 index 0000000000..163bf8a2aa --- /dev/null +++ b/queue-7.1/wifi-mac80211-defer-link-rx-stats-percpu-free-to-rcu.patch @@ -0,0 +1,77 @@ +From a5e76621b3a13d2401766e6d51a1a56193888202 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 27 Jun 2026 16:30:28 +0800 +Subject: wifi: mac80211: defer link RX stats percpu free to RCU + +From: Maoyi Xie + +[ Upstream commit aa2eb62525188269cdd402a583b9a8ed94657ff0 ] + +sta_remove_link() frees a removed MLO link's RX stats percpu buffer right +away, but defers only the link container to RCU: + + sta_info_free_link(&alloc->info); + kfree_rcu(alloc, rcu_head); + +The RX fast path reads link_sta under rcu_read_lock and writes the percpu +stats. A reader that resolved link_sta before the removal keeps the +pointer. The container stays alive from the kfree_rcu, so the read still +works. But the percpu block it points to is already freed. This needs +uses_rss. That is when pcpu_rx_stats exists. + +The full STA teardown frees the deflink stats only after +synchronize_net(). The link removal path had no such barrier. The race is +hard to win in practice, but the free should still wait for RCU. + +Free the link together with its data from a single RCU callback, so the +percpu block is reclaimed only after readers drain. + +Fixes: c71420db653a ("wifi: mac80211: RCU-ify link STA pointers") +Link: https://lore.kernel.org/r/20260626080158.3589711-1-maoyixie.tju@gmail.com +Suggested-by: Johannes Berg +Co-developed-by: Kaixuan Li +Signed-off-by: Kaixuan Li +Signed-off-by: Maoyi Xie +Link: https://patch.msgid.link/20260627083028.3826810-1-maoyixie.tju@gmail.com +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + net/mac80211/sta_info.c | 15 +++++++++++---- + 1 file changed, 11 insertions(+), 4 deletions(-) + +diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c +index 4c31ef8817ce07..6d58571a364d14 100644 +--- a/net/mac80211/sta_info.c ++++ b/net/mac80211/sta_info.c +@@ -355,6 +355,15 @@ static void sta_info_free_link(struct link_sta_info *link_sta) + free_percpu(link_sta->pcpu_rx_stats); + } + ++static void sta_link_free_rcu(struct rcu_head *head) ++{ ++ struct sta_link_alloc *alloc = ++ container_of(head, struct sta_link_alloc, rcu_head); ++ ++ sta_info_free_link(&alloc->info); ++ kfree(alloc); ++} ++ + static void sta_accumulate_removed_link_stats(struct sta_info *sta, int link_id) + { + struct link_sta_info *link_sta = wiphy_dereference(sta->local->hw.wiphy, +@@ -439,10 +448,8 @@ static void sta_remove_link(struct sta_info *sta, unsigned int link_id, + + RCU_INIT_POINTER(sta->link[link_id], NULL); + RCU_INIT_POINTER(sta->sta.link[link_id], NULL); +- if (alloc) { +- sta_info_free_link(&alloc->info); +- kfree_rcu(alloc, rcu_head); +- } ++ if (alloc) ++ call_rcu(&alloc->rcu_head, sta_link_free_rcu); + + ieee80211_sta_recalc_aggregates(&sta->sta); + } +-- +2.53.0 + diff --git a/queue-7.1/wifi-mac80211-fix-fils_discovery-double-free-on-allo.patch b/queue-7.1/wifi-mac80211-fix-fils_discovery-double-free-on-allo.patch new file mode 100644 index 0000000000..1626f03937 --- /dev/null +++ b/queue-7.1/wifi-mac80211-fix-fils_discovery-double-free-on-allo.patch @@ -0,0 +1,66 @@ +From d6fd20a3b57868e5313d75a8916bce92503f16e3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 21 Jun 2026 02:35:32 -0700 +Subject: wifi: mac80211: fix fils_discovery double free on alloc failure + +From: Xiang Mei + +[ Upstream commit 286e52a799fa158bdbd77da1426c4d93f9a6e7ad ] + +ieee80211_set_fils_discovery() calls kfree_rcu() on the old template +before allocating the replacement. If the kzalloc() then fails, it +returns -ENOMEM while link->u.ap.fils_discovery still points at the +object already queued for freeing. A later update or AP teardown +(ieee80211_stop_ap()) re-queues that same rcu_head; the second free is +caught by KASAN when the RCU sheaf is processed in softirq: + + BUG: KASAN: double-free in rcu_free_sheaf (mm/slub.c:5850) + Free of addr ffff88800c065280 by task swapper/0/0 + ... + __rcu_free_sheaf_prepare (mm/slub.c:2634 mm/slub.c:2940) + rcu_free_sheaf (mm/slub.c:5850) + rcu_core (kernel/rcu/tree.c:2617 kernel/rcu/tree.c:2869) + handle_softirqs (kernel/softirq.c:622) + The buggy address belongs to the cache kmalloc-96 of size 96 + +Queue the old object for kfree_rcu() only after the new one is published, +matching ieee80211_set_probe_resp() and ieee80211_set_s1g_short_beacon(). + +Fixes: 3b1c256eb4ae ("wifi: mac80211: fixes in FILS discovery updates") +Reported-by: Weiming Shi +Assisted-by: Claude:claude-opus-4-8 +Signed-off-by: Xiang Mei +Link: https://patch.msgid.link/20260621093532.884188-2-xmei5@asu.edu +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + net/mac80211/cfg.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c +index e926bced6a313d..0bc10136b816ef 100644 +--- a/net/mac80211/cfg.c ++++ b/net/mac80211/cfg.c +@@ -1145,9 +1145,6 @@ static int ieee80211_set_fils_discovery(struct ieee80211_sub_if_data *sdata, + fd->max_interval = params->max_interval; + + old = sdata_dereference(link->u.ap.fils_discovery, sdata); +- if (old) +- kfree_rcu(old, rcu_head); +- + if (params->tmpl && params->tmpl_len) { + new = kzalloc(sizeof(*new) + params->tmpl_len, GFP_KERNEL); + if (!new) +@@ -1159,6 +1156,9 @@ static int ieee80211_set_fils_discovery(struct ieee80211_sub_if_data *sdata, + RCU_INIT_POINTER(link->u.ap.fils_discovery, NULL); + } + ++ if (old) ++ kfree_rcu(old, rcu_head); ++ + *changed |= BSS_CHANGED_FILS_DISCOVERY; + return 0; + } +-- +2.53.0 + diff --git a/queue-7.1/wifi-mac80211-fix-unsol_bcast_probe_resp-double-free.patch b/queue-7.1/wifi-mac80211-fix-unsol_bcast_probe_resp-double-free.patch new file mode 100644 index 0000000000..465233bafd --- /dev/null +++ b/queue-7.1/wifi-mac80211-fix-unsol_bcast_probe_resp-double-free.patch @@ -0,0 +1,66 @@ +From aa388d2ecef303b1fa24fa8d8051ab76d5265562 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 21 Jun 2026 02:35:31 -0700 +Subject: wifi: mac80211: fix unsol_bcast_probe_resp double free on alloc + failure + +From: Xiang Mei + +[ Upstream commit 1d067abcd37062426c59ec73dbc4e87a63f33fea ] + +ieee80211_set_unsol_bcast_probe_resp() calls kfree_rcu() on the old +template before allocating the replacement. If the kzalloc() then fails, +it returns -ENOMEM while link->u.ap.unsol_bcast_probe_resp still points +at the object already queued for freeing. A later update or AP teardown +re-queues that same rcu_head; the second free is caught by KASAN when the +RCU sheaf is processed in softirq: + + BUG: KASAN: double-free in rcu_free_sheaf (mm/slub.c:5850) + Free of addr ffff88800d06f300 by task exploit/145 + ... + __rcu_free_sheaf_prepare (mm/slub.c:2634 mm/slub.c:2940) + rcu_free_sheaf (mm/slub.c:5850) + rcu_core (kernel/rcu/tree.c:2617 kernel/rcu/tree.c:2869) + handle_softirqs (kernel/softirq.c:622) + The buggy address belongs to the cache kmalloc-128 of size 128 + +Queue the old object for kfree_rcu() only after the new one is published, +matching ieee80211_set_probe_resp() and ieee80211_set_s1g_short_beacon(). + +Fixes: 3b1c256eb4ae ("wifi: mac80211: fixes in FILS discovery updates") +Reported-by: Weiming Shi +Assisted-by: Claude:claude-opus-4-8 +Signed-off-by: Xiang Mei +Link: https://patch.msgid.link/20260621093532.884188-1-xmei5@asu.edu +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + net/mac80211/cfg.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c +index f9ee9947a94d66..e926bced6a313d 100644 +--- a/net/mac80211/cfg.c ++++ b/net/mac80211/cfg.c +@@ -1178,8 +1178,6 @@ ieee80211_set_unsol_bcast_probe_resp(struct ieee80211_sub_if_data *sdata, + link_conf->unsol_bcast_probe_resp_interval = params->interval; + + old = sdata_dereference(link->u.ap.unsol_bcast_probe_resp, sdata); +- if (old) +- kfree_rcu(old, rcu_head); + + if (params->tmpl && params->tmpl_len) { + new = kzalloc(sizeof(*new) + params->tmpl_len, GFP_KERNEL); +@@ -1192,6 +1190,9 @@ ieee80211_set_unsol_bcast_probe_resp(struct ieee80211_sub_if_data *sdata, + RCU_INIT_POINTER(link->u.ap.unsol_bcast_probe_resp, NULL); + } + ++ if (old) ++ kfree_rcu(old, rcu_head); ++ + *changed |= BSS_CHANGED_UNSOL_BCAST_PROBE_RESP; + return 0; + } +-- +2.53.0 + diff --git a/queue-7.1/wifi-mac80211-free-ap_vlan-bc_buf-skbs-outside-irq-l.patch b/queue-7.1/wifi-mac80211-free-ap_vlan-bc_buf-skbs-outside-irq-l.patch new file mode 100644 index 0000000000..7a00b64acf --- /dev/null +++ b/queue-7.1/wifi-mac80211-free-ap_vlan-bc_buf-skbs-outside-irq-l.patch @@ -0,0 +1,77 @@ +From a00403bc65620a89975c590996e5bf5111f12bad Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 6 Jul 2026 22:08:41 +0800 +Subject: wifi: mac80211: free AP_VLAN bc_buf SKBs outside IRQ lock + +From: Cen Zhang + +[ Upstream commit f3858d5b1432098c1936e03d6e03dd0e33facf60 ] + +ieee80211_do_stop() removes AP_VLAN packets from the parent AP +ps->bc_buf while holding ps->bc_buf.lock with IRQs disabled. It then +calls ieee80211_free_txskb() before dropping the lock. + +ieee80211_free_txskb() is not just a passive SKB release. For SKBs with +TX status state it can report a dropped frame through cfg80211/nl80211, +and that path can reach netlink tap transmit. This is the same reason +the pending queue cleanup in ieee80211_do_stop() already unlinks SKBs +under the queue lock and frees them after IRQ state is restored. + +The buggy scenario involves two paths, with each column showing the +order within that path: + +AP_VLAN management TX: AP_VLAN stop: +1. attach ACK-status state 1. clear the running state +2. queue a multicast SKB on 2. take ps->bc_buf.lock with IRQs + parent ps->bc_buf disabled + 3. unlink the AP_VLAN SKB + 4. call ieee80211_free_txskb() + +Unlink matching AP_VLAN SKBs from ps->bc_buf under the existing lock, +but move them to a local free queue. Drop the lock and restore IRQ state +before calling ieee80211_free_txskb(). + +WARNING: kernel/softirq.c:430 at __local_bh_enable_ip + +Fixes: 397a7a24ef8c ("mac80211: free ps->bc_buf skbs on vlan device stop") +Assisted-by: Codex:gpt-5.5 +Signed-off-by: Cen Zhang +Link: https://patch.msgid.link/20260706140841.581566-1-zzzccc427@gmail.com +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + net/mac80211/iface.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c +index 95b779c4d627e8..a3a3b9f247214a 100644 +--- a/net/mac80211/iface.c ++++ b/net/mac80211/iface.c +@@ -588,6 +588,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, bool going_do + WARN_ON(!list_empty(&sdata->u.ap.vlans)); + } else if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) { + /* remove all packets in parent bc_buf pointing to this dev */ ++ __skb_queue_head_init(&freeq); + ps = &sdata->bss->ps; + + spin_lock_irqsave(&ps->bc_buf.lock, flags); +@@ -595,10 +596,15 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, bool going_do + if (skb->dev == sdata->dev) { + __skb_unlink(skb, &ps->bc_buf); + local->total_ps_buffered--; +- ieee80211_free_txskb(&local->hw, skb); ++ __skb_queue_tail(&freeq, skb); + } + } + spin_unlock_irqrestore(&ps->bc_buf.lock, flags); ++ ++ skb_queue_walk_safe(&freeq, skb, tmp) { ++ __skb_unlink(skb, &freeq); ++ ieee80211_free_txskb(&local->hw, skb); ++ } + } + + if (going_down) +-- +2.53.0 + diff --git a/queue-7.1/wifi-mac80211_hwsim-clamp-virtio-rx-length-before-sk.patch b/queue-7.1/wifi-mac80211_hwsim-clamp-virtio-rx-length-before-sk.patch new file mode 100644 index 0000000000..403b49b5e5 --- /dev/null +++ b/queue-7.1/wifi-mac80211_hwsim-clamp-virtio-rx-length-before-sk.patch @@ -0,0 +1,46 @@ +From e2c97adcb6271221994f9c00eb3691cc317158e4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 20 Jun 2026 21:45:18 -0500 +Subject: wifi: mac80211_hwsim: clamp virtio RX length before skb_put + +From: Bryam Vargas + +[ Upstream commit 10a2b430f8f06ae14b9590b6f6faa6b588ef0654 ] + +hwsim_virtio_rx_work() passes the virtqueue used-ring length reported by +the device straight to skb_put() on a fixed-size receive skb. A backend +reporting a length larger than the skb tailroom drives skb_put() past the +buffer end and hits skb_over_panic() -- a host-triggerable guest panic +(denial of service). + +Clamp the length to the skb's available room before skb_put(). A +conforming device never reports more than the posted buffer size, so valid +frames are unaffected; a truncated over-report then fails the +length/header checks in hwsim_virtio_handle_cmd() and is dropped, so +truncating rather than dropping here cannot be turned into a parsing +problem. + +Fixes: 5d44fe7c9808 ("mac80211_hwsim: add frame transmission support over virtio") +Signed-off-by: Bryam Vargas +Link: https://patch.msgid.link/20260620-b4-disp-474bee37-v1-1-1a4d37f3e2d4@proton.me +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/virtual/mac80211_hwsim.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/net/wireless/virtual/mac80211_hwsim.c b/drivers/net/wireless/virtual/mac80211_hwsim.c +index 1fcf5d0d2e13fe..17bf8e547b25be 100644 +--- a/drivers/net/wireless/virtual/mac80211_hwsim.c ++++ b/drivers/net/wireless/virtual/mac80211_hwsim.c +@@ -7122,6 +7122,7 @@ static void hwsim_virtio_rx_work(struct work_struct *work) + + skb->data = skb->head; + skb_reset_tail_pointer(skb); ++ len = min(len, skb_end_offset(skb)); + skb_put(skb, len); + hwsim_virtio_handle_cmd(skb); + +-- +2.53.0 + diff --git a/queue-7.1/wifi-nl80211-constrain-mbssid-tx-link-id-range.patch b/queue-7.1/wifi-nl80211-constrain-mbssid-tx-link-id-range.patch new file mode 100644 index 0000000000..9752317d89 --- /dev/null +++ b/queue-7.1/wifi-nl80211-constrain-mbssid-tx-link-id-range.patch @@ -0,0 +1,40 @@ +From c13adac32434d3ae6a4e5fd717cfd3b1e4cb7ce9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 12 Jun 2026 21:18:56 +0800 +Subject: wifi: nl80211: constrain MBSSID TX link ID range + +From: Zhao Li + +[ Upstream commit 172f06023669f0a96d32511669ff45c600731380 ] + +MBSSID transmitted-profile link IDs are valid only in the range +0..IEEE80211_MLD_MAX_NUM_LINKS - 1. Constrain the nl80211 policy to +reject out-of-range values during attribute validation. + +Fixes: 37523c3c47b3 ("wifi: nl80211: add link id of transmitted profile for MLO MBSSID") +Assisted-by: Codex:gpt-5.5 +Assisted-by: Claude:claude-opus-4.8 +Signed-off-by: Zhao Li +Link: https://patch.msgid.link/20260612131854.43575-4-enderaoelyther@gmail.com +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + net/wireless/nl80211.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c +index 264ae4e742a1c4..3024fa8dd78021 100644 +--- a/net/wireless/nl80211.c ++++ b/net/wireless/nl80211.c +@@ -616,7 +616,7 @@ nl80211_mbssid_config_policy[NL80211_MBSSID_CONFIG_ATTR_MAX + 1] = { + [NL80211_MBSSID_CONFIG_ATTR_TX_IFINDEX] = { .type = NLA_U32 }, + [NL80211_MBSSID_CONFIG_ATTR_EMA] = { .type = NLA_FLAG }, + [NL80211_MBSSID_CONFIG_ATTR_TX_LINK_ID] = +- NLA_POLICY_MAX(NLA_U8, IEEE80211_MLD_MAX_NUM_LINKS), ++ NLA_POLICY_RANGE(NLA_U8, 0, IEEE80211_MLD_MAX_NUM_LINKS - 1), + }; + + static const struct nla_policy +-- +2.53.0 + diff --git a/queue-7.1/wifi-nl80211-free-rnr-data-on-mbssid-mismatch.patch b/queue-7.1/wifi-nl80211-free-rnr-data-on-mbssid-mismatch.patch new file mode 100644 index 0000000000..564313ce11 --- /dev/null +++ b/queue-7.1/wifi-nl80211-free-rnr-data-on-mbssid-mismatch.patch @@ -0,0 +1,43 @@ +From a85b10763ce26921dc519309293c18100341f853 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 10 Jun 2026 19:22:09 +0800 +Subject: wifi: nl80211: free RNR data on MBSSID mismatch + +From: Zhao Li + +[ Upstream commit 07a95ec2b54774201fdf4ef7ffb0ca2ab19ed29c ] + +nl80211_parse_beacon() rejects EMA RNR data when there are fewer RNR +entries than MBSSID entries. + +The rejected RNR allocation has not been attached to the beacon data yet, +so free it before returning the error. + +Fixes: dbbb27e183b1 ("cfg80211: support RNR for EMA AP") +Signed-off-by: Zhao Li +Link: https://patch.msgid.link/20260610112208.1308-2-enderaoelyther@gmail.com +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + net/wireless/nl80211.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c +index 21e43e08b5d795..c7edaea9873e0a 100644 +--- a/net/wireless/nl80211.c ++++ b/net/wireless/nl80211.c +@@ -6519,8 +6519,10 @@ static int nl80211_parse_beacon(struct cfg80211_registered_device *rdev, + if (IS_ERR(rnr)) + return PTR_ERR(rnr); + +- if (rnr && rnr->cnt < bcn->mbssid_ies->cnt) ++ if (rnr && rnr->cnt < bcn->mbssid_ies->cnt) { ++ kfree(rnr); + return -EINVAL; ++ } + + bcn->rnr_ies = rnr; + } +-- +2.53.0 + diff --git a/queue-7.1/wifi-nl80211-validate-nested-mbssid-ie-blobs.patch b/queue-7.1/wifi-nl80211-validate-nested-mbssid-ie-blobs.patch new file mode 100644 index 0000000000..0881d43a0c --- /dev/null +++ b/queue-7.1/wifi-nl80211-validate-nested-mbssid-ie-blobs.patch @@ -0,0 +1,67 @@ +From cc239f885f9fbafde4f25767b112e59e37afe7cf Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 12 Jun 2026 21:18:55 +0800 +Subject: wifi: nl80211: validate nested MBSSID IE blobs + +From: Zhao Li + +[ Upstream commit 7f4b01812323443b55e4c65381c9dc851ff009e3 ] + +Validate each nested NL80211_ATTR_MBSSID_ELEMS entry as a well-formed +information-element stream before storing it for beacon construction. + +RNR parsing already validates each nested blob with validate_ie_attr() +before storing it. Apply the same syntactic IE validation to MBSSID +entries before counting and copying their data and length pointers. + +Fixes: dc1e3cb8da8b ("nl80211: MBSSID and EMA support in AP mode") +Assisted-by: Codex:gpt-5.5 +Assisted-by: Claude:claude-opus-4.8 +Signed-off-by: Zhao Li +Link: https://patch.msgid.link/20260612131854.43575-3-enderaoelyther@gmail.com +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + net/wireless/nl80211.c | 12 ++++++++++-- + 1 file changed, 10 insertions(+), 2 deletions(-) + +diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c +index c7edaea9873e0a..264ae4e742a1c4 100644 +--- a/net/wireless/nl80211.c ++++ b/net/wireless/nl80211.c +@@ -6321,7 +6321,8 @@ static int nl80211_parse_mbssid_config(struct wiphy *wiphy, + } + + static struct cfg80211_mbssid_elems * +-nl80211_parse_mbssid_elems(struct wiphy *wiphy, struct nlattr *attrs) ++nl80211_parse_mbssid_elems(struct wiphy *wiphy, struct nlattr *attrs, ++ struct netlink_ext_ack *extack) + { + struct nlattr *nl_elems; + struct cfg80211_mbssid_elems *elems; +@@ -6332,6 +6333,12 @@ nl80211_parse_mbssid_elems(struct wiphy *wiphy, struct nlattr *attrs) + return ERR_PTR(-EINVAL); + + nla_for_each_nested(nl_elems, attrs, rem_elems) { ++ int ret; ++ ++ ret = validate_ie_attr(nl_elems, extack); ++ if (ret) ++ return ERR_PTR(ret); ++ + if (num_elems >= 255) + return ERR_PTR(-EINVAL); + num_elems++; +@@ -6503,7 +6510,8 @@ static int nl80211_parse_beacon(struct cfg80211_registered_device *rdev, + if (attrs[NL80211_ATTR_MBSSID_ELEMS]) { + struct cfg80211_mbssid_elems *mbssid = + nl80211_parse_mbssid_elems(&rdev->wiphy, +- attrs[NL80211_ATTR_MBSSID_ELEMS]); ++ attrs[NL80211_ATTR_MBSSID_ELEMS], ++ extack); + + if (IS_ERR(mbssid)) + return PTR_ERR(mbssid); +-- +2.53.0 + diff --git a/queue-7.1/wifi-p54-validate-rx-frame-length-in-p54_rx_eeprom_r.patch b/queue-7.1/wifi-p54-validate-rx-frame-length-in-p54_rx_eeprom_r.patch new file mode 100644 index 0000000000..e9f6e0d6e5 --- /dev/null +++ b/queue-7.1/wifi-p54-validate-rx-frame-length-in-p54_rx_eeprom_r.patch @@ -0,0 +1,80 @@ +From e5d8b09f61d89563cf7e9589dd76c9d79d57d6d4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 27 Jun 2026 17:05:10 -0700 +Subject: wifi: p54: validate RX frame length in p54_rx_eeprom_readback() + +From: Xiang Mei + +[ Upstream commit ebd6d37fa94bee929e0b4c9ca19fdf9b1dcf6cea ] + +p54_rx_eeprom_readback() copies the requested EEPROM slice out of a +device-supplied readback frame without checking that the skb actually holds +that many bytes. Commit da1b9a55ff11 ("wifi: p54: prevent buffer-overflow in +p54_rx_eeprom_readback()") closed the destination overflow by copying a +fixed priv->eeprom_slice_size (and rejecting a mismatched advertised len), +but the source side is still unbounded: nothing verifies the frame is long +enough to supply that many bytes. + +A malicious USB device can send a short frame whose advertised len matches +priv->eeprom_slice_size while the payload is truncated. The equality check +passes and memcpy() reads past the end of the skb, leaking adjacent heap: + + BUG: KASAN: slab-out-of-bounds in p54_rx (drivers/net/wireless/intersil/p54/txrx.c:507) + Read of size 1016 at addr ffff88800f077114 by task swapper/0/0 + Call Trace: + + ... + __asan_memcpy (mm/kasan/shadow.c:105) + p54_rx (drivers/net/wireless/intersil/p54/txrx.c:507) + p54u_rx_cb (drivers/net/wireless/intersil/p54/p54usb.c:163) + __usb_hcd_giveback_urb (drivers/usb/core/hcd.c:1657) + dummy_timer (drivers/usb/gadget/udc/dummy_hcd.c:2005) + ... + + + The buggy address belongs to the object at ffff88800f0770c0 + which belongs to the cache skbuff_small_head of size 704 + The buggy address is located 84 bytes inside of + allocated 704-byte region [ffff88800f0770c0, ffff88800f077380) + +Check that the slice fits in the skb before copying. + +Fixes: 7cb770729ba8 ("p54: move eeprom code into common library") +Reported-by: Weiming Shi +Assisted-by: Claude:claude-opus-4-8 +Signed-off-by: Xiang Mei +Acked-by: Christian Lamparter +Link: https://patch.msgid.link/20260628000510.4152481-1-xmei5@asu.edu +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/intersil/p54/txrx.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/drivers/net/wireless/intersil/p54/txrx.c b/drivers/net/wireless/intersil/p54/txrx.c +index 1294a1d6528e2c..9f491334c8d043 100644 +--- a/drivers/net/wireless/intersil/p54/txrx.c ++++ b/drivers/net/wireless/intersil/p54/txrx.c +@@ -499,11 +499,19 @@ static void p54_rx_eeprom_readback(struct p54_common *priv, + if (le16_to_cpu(eeprom->v2.len) != priv->eeprom_slice_size) + return; + ++ if (eeprom->v2.data + priv->eeprom_slice_size > ++ skb_tail_pointer(skb)) ++ return; ++ + memcpy(priv->eeprom, eeprom->v2.data, priv->eeprom_slice_size); + } else { + if (le16_to_cpu(eeprom->v1.len) != priv->eeprom_slice_size) + return; + ++ if (eeprom->v1.data + priv->eeprom_slice_size > ++ skb_tail_pointer(skb)) ++ return; ++ + memcpy(priv->eeprom, eeprom->v1.data, priv->eeprom_slice_size); + } + +-- +2.53.0 + diff --git a/queue-7.1/xfrm-clear-mode-callbacks-after-failed-mode-setup.patch b/queue-7.1/xfrm-clear-mode-callbacks-after-failed-mode-setup.patch new file mode 100644 index 0000000000..5d017a40e6 --- /dev/null +++ b/queue-7.1/xfrm-clear-mode-callbacks-after-failed-mode-setup.patch @@ -0,0 +1,90 @@ +From d7f44c5eea8778f994a6e2d95d27785944da5e89 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 27 Jun 2026 11:01:17 +0800 +Subject: xfrm: clear mode callbacks after failed mode setup + +From: Cen Zhang + +[ Upstream commit 2538bd3cd1ff5af655908469544ac7b7ae259386 ] + +xfrm_state_gc_task can run long after a failed IPTFS state setup. In the +reproduced case, __xfrm_init_state() cached x->mode_cbs, IPTFS setup +returned -ENOMEM before publishing mode_data, and the temporary module +reference from xfrm_get_mode_cbs() was dropped immediately. The dead state +then kept x->mode_cbs until deferred GC ran after xfrm_iptfs had been +unloaded. + +Clear x->mode_cbs when mode init or clone fails before publishing +mode_data. Those states never installed mode-specific state or the +long-term IPTFS module pin, so deferred GC has nothing mode-specific to +destroy and must not retain a callback table pointer past the temporary +lookup reference. + +The buggy scenario involves two paths, with each column showing the order +within that path: + +failed setup path: +1. cache x->mode_cbs +2. mode setup fails before mode_data +3. drop the temporary module ref +4. dead state keeps x->mode_cbs cached + +GC/unload path: +1. xfrm_state_put() queues GC work +2. xfrm_iptfs unloads later +3. xfrm_state_gc_task runs +4. GC dereferences stale x->mode_cbs + +This also covers the failed clone path where clone_state() returns before +publishing mode_data. + +Validation reproduced this kernel report: +Kernel panic - not syncing: Fatal exception +CONFIG_FAULT_INJECTION_STACKTRACE_FILTER=y +failslab_stacktrace_filter matched xfrm_iptfs frames +ack_error=-12 +FAULT_INJECTION: forcing a failure +BUG: unable to handle page fault +Workqueue: events xfrm_state_gc_task +RIP: xfrm_state_gc_task+0x142/0x650 +Modules linked in: esp4_offload xfrm_user [last unloaded: xfrm_iptfs] +Kernel panic - not syncing: Fatal exception + +Fixes: 4b3faf610cc6 ("xfrm: iptfs: add new iptfs xfrm mode impl") +Assisted-by: Codex:gpt-5.5 +Signed-off-by: Cen Zhang +Signed-off-by: Steffen Klassert +Signed-off-by: Sasha Levin +--- + net/xfrm/xfrm_state.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c +index 511a7402ada41b..37193d2fcc2f2b 100644 +--- a/net/xfrm/xfrm_state.c ++++ b/net/xfrm/xfrm_state.c +@@ -2070,8 +2070,11 @@ static struct xfrm_state *xfrm_state_clone_and_setup(struct xfrm_state *orig, + + x->mode_cbs = orig->mode_cbs; + if (x->mode_cbs && x->mode_cbs->clone_state) { +- if (x->mode_cbs->clone_state(x, orig)) ++ if (x->mode_cbs->clone_state(x, orig)) { ++ if (!x->mode_data) ++ x->mode_cbs = NULL; + goto error; ++ } + } + + +@@ -3254,6 +3257,8 @@ int __xfrm_init_state(struct xfrm_state *x, struct netlink_ext_ack *extack) + if (x->mode_cbs->init_state) + err = x->mode_cbs->init_state(x); + module_put(x->mode_cbs->owner); ++ if (err && !x->mode_data) ++ x->mode_cbs = NULL; + } + error: + return err; +-- +2.53.0 + diff --git a/queue-7.1/xfrm-fix-sk_dst_cache-double-free-in-xfrm_user_polic.patch b/queue-7.1/xfrm-fix-sk_dst_cache-double-free-in-xfrm_user_polic.patch new file mode 100644 index 0000000000..a72466b66a --- /dev/null +++ b/queue-7.1/xfrm-fix-sk_dst_cache-double-free-in-xfrm_user_polic.patch @@ -0,0 +1,76 @@ +From fbe704d9f52f1403485d2ba84e01101523cd8bb2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 27 Jun 2026 02:40:23 +0000 +Subject: xfrm: fix sk_dst_cache double-free in xfrm_user_policy() + +From: Xiang Mei (Microsoft) + +[ Upstream commit c283e9ada7fcb7dd4b10592623086b2e6d2f9925 ] + +xfrm_user_policy() clears the socket dst cache with __sk_dst_reset(), +i.e. the non-atomic __sk_dst_set(sk, NULL): it reads sk_dst_cache with +rcu_dereference_protected(), stores NULL and dst_release()s the old dst. +That is only safe if no other thread modifies sk_dst_cache concurrently. + +For a connected UDP socket that does not hold: the transmit fast path +(udp_sendmsg -> sk_dst_check -> sk_dst_reset) resets the cache locklessly +with an atomic xchg(). A per-socket policy change racing a send can make +both sides observe the same old dst and each dst_release() it, dropping +the socket's single reference twice and freeing the xfrm_dst bundle while +it is still referenced: + + BUG: KASAN: slab-use-after-free in dst_release + Write of size 4 at addr ffff88801897b6c0 by task exploit/155 + Call Trace: + ... + dst_release (... ./include/linux/rcuref.h:109) + xfrm_user_policy (./include/net/sock.h:2239 ./include/net/sock.h:2256 net/xfrm/xfrm_state.c:3053) + do_ip_setsockopt (net/ipv4/ip_sockglue.c:1347) + ip_setsockopt (net/ipv4/ip_sockglue.c:1417) + do_sock_setsockopt (net/socket.c:2368) + __sys_setsockopt (net/socket.c:2393) + __x64_sys_setsockopt (net/socket.c:2396) + do_syscall_64 (arch/x86/entry/syscall_64.c:94) + entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:121) + +Reachable by an unprivileged user via a user+network namespace. + +Use the atomic sk_dst_reset() so the cache is cleared and released with a +single xchg(): whichever side wins releases the dst once, the other sees +NULL and does nothing. Behaviour is otherwise unchanged. + +Fixes: 2b06cdf3e688 ("xfrm: Clear sk_dst_cache when applying per-socket policy.") +Fixes: be8f8284cd89 ("net: xfrm: allow clearing socket xfrm policies.") +Reported-by: AutonomousCodeSecurity@microsoft.com +Signed-off-by: Xiang Mei (Microsoft) +Signed-off-by: Steffen Klassert +Signed-off-by: Sasha Levin +--- + net/xfrm/xfrm_state.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c +index ec9ecf72c76ba1..511a7402ada41b 100644 +--- a/net/xfrm/xfrm_state.c ++++ b/net/xfrm/xfrm_state.c +@@ -2973,7 +2973,7 @@ int xfrm_user_policy(struct sock *sk, int optname, sockptr_t optval, int optlen) + if (sockptr_is_null(optval) && !optlen) { + xfrm_sk_policy_insert(sk, XFRM_POLICY_IN, NULL); + xfrm_sk_policy_insert(sk, XFRM_POLICY_OUT, NULL); +- __sk_dst_reset(sk); ++ sk_dst_reset(sk); + return 0; + } + +@@ -3013,7 +3013,7 @@ int xfrm_user_policy(struct sock *sk, int optname, sockptr_t optval, int optlen) + if (err >= 0) { + xfrm_sk_policy_insert(sk, err, pol); + xfrm_pol_put(pol); +- __sk_dst_reset(sk); ++ sk_dst_reset(sk); + err = 0; + } + +-- +2.53.0 + diff --git a/queue-7.1/xfrm-fix-stale-skb-prev-after-async-crypto-steals-a-.patch b/queue-7.1/xfrm-fix-stale-skb-prev-after-async-crypto-steals-a-.patch new file mode 100644 index 0000000000..0247f682f7 --- /dev/null +++ b/queue-7.1/xfrm-fix-stale-skb-prev-after-async-crypto-steals-a-.patch @@ -0,0 +1,53 @@ +From 84f63b4cbda3548a984e5e3d24beffbb536ed929 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 21 Jun 2026 12:03:27 +0200 +Subject: xfrm: fix stale skb->prev after async crypto steals a GSO segment + +From: Petr Wozniak + +[ Upstream commit 3f4c3919baf0944ad96580467c302bc6c7758b00 ] + +skb_gso_segment() leaves the segment list head with ->prev pointing at +the last segment, an invariant validate_xmit_skb_list() relies on when +it sets its tail pointer (tail = skb->prev). + +When validate_xmit_xfrm() walks a GSO list and some segments are stolen +by async crypto (->xmit() returns -EINPROGRESS), those segments are +unlinked from the list but the head ->prev is never updated. If the +last segment is the one stolen, the returned head still has ->prev +pointing at it, even though it is now owned by the crypto engine and may +be freed. validate_xmit_skb_list() later does tail->next = skb, writing +through that stale pointer -- a use-after-free. + +Repoint skb->prev at the last retained segment before returning. + +Fixes: f53c723902d1 ("net: Add asynchronous callbacks for xfrm on layer 2.") +Signed-off-by: Petr Wozniak +Signed-off-by: Steffen Klassert +Signed-off-by: Sasha Levin +--- + net/xfrm/xfrm_device.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/net/xfrm/xfrm_device.c b/net/xfrm/xfrm_device.c +index 8b526e3676389a..4719aba331cd66 100644 +--- a/net/xfrm/xfrm_device.c ++++ b/net/xfrm/xfrm_device.c +@@ -224,6 +224,14 @@ struct sk_buff *validate_xmit_xfrm(struct sk_buff *skb, netdev_features_t featur + pskb = skb2; + } + ++ /* skb_gso_segment() set skb->prev to the last segment, but async ++ * crypto may have stolen it above without updating ->prev. Repoint ++ * it at the last retained segment so validate_xmit_skb_list() does ++ * not chain onto a segment now owned by the crypto engine. ++ */ ++ if (skb) ++ skb->prev = pskb; ++ + return skb ? skb : ERR_PTR(-EINPROGRESS); + } + EXPORT_SYMBOL_GPL(validate_xmit_xfrm); +-- +2.53.0 + diff --git a/queue-7.1/xfrm-iptfs-propagate-skbfl_shared_frag-in-iptfs_skb_.patch b/queue-7.1/xfrm-iptfs-propagate-skbfl_shared_frag-in-iptfs_skb_.patch new file mode 100644 index 0000000000..3f6d4d9b1d --- /dev/null +++ b/queue-7.1/xfrm-iptfs-propagate-skbfl_shared_frag-in-iptfs_skb_.patch @@ -0,0 +1,51 @@ +From 4a4cfad61c7440a30aa8ade648f3b27e96a3a2da Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 1 Jul 2026 11:31:52 +0800 +Subject: xfrm: iptfs: propagate SKBFL_SHARED_FRAG in iptfs_skb_add_frags() + +From: Chen YanJun + +[ Upstream commit 430ea57d6daf765e88f90046afbfd1e071cb7200 ] + +When iptfs_skb_add_frags() copies frag references from the source +frag walk into a new SKB, it increments the page reference count via +__skb_frag_ref() but does not propagate SKBFL_SHARED_FRAG to the +destination SKB's skb_shinfo->flags. + +If the source SKB carries shared frags (e.g. from a page-pool backed +receive path), the new inner SKB will appear to ESP as having privately +owned frags. A subsequent esp_input() call for a nested transport-mode +SA then takes the no-COW fast path and decrypts in place, writing over +pages that are still referenced by the outer IPTFS SKB. This causes +kernel-visible memory corruption and can trigger a panic. + +All other frag-transfer helpers in the kernel (skb_try_coalesce, +skb_gro_receive, __pskb_copy_fclone, skb_shift, skb_segment) correctly +propagate SKBFL_SHARED_FRAG; align iptfs_skb_add_frags() with this +convention by setting the flag inside the loop immediately after +__skb_frag_ref() and nr_frags++, so every exit path that attaches a frag +unconditionally propagates SKBFL_SHARED_FRAG. + +Fixes: 5f2b6a909574 ("xfrm: iptfs: add skb-fragment sharing code") +Signed-off-by: Chen YanJun +Signed-off-by: Steffen Klassert +Signed-off-by: Sasha Levin +--- + net/xfrm/xfrm_iptfs.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/net/xfrm/xfrm_iptfs.c b/net/xfrm/xfrm_iptfs.c +index ad810d1f97c067..597aedeac26eba 100644 +--- a/net/xfrm/xfrm_iptfs.c ++++ b/net/xfrm/xfrm_iptfs.c +@@ -480,6 +480,7 @@ static int iptfs_skb_add_frags(struct sk_buff *skb, + } + __skb_frag_ref(tofrag); + shinfo->nr_frags++; ++ shinfo->flags |= SKBFL_SHARED_FRAG; + + /* see if we are done */ + fraglen = tofrag->len; +-- +2.53.0 + diff --git a/queue-7.1/xfrm-policy-preallocate-inexact-bins-before-xfrm_has.patch b/queue-7.1/xfrm-policy-preallocate-inexact-bins-before-xfrm_has.patch new file mode 100644 index 0000000000..d3a3b5e7d0 --- /dev/null +++ b/queue-7.1/xfrm-policy-preallocate-inexact-bins-before-xfrm_has.patch @@ -0,0 +1,75 @@ +From 6f67b13665946bc1ff6570953d2451392ce12659 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 3 Jul 2026 05:19:32 +0000 +Subject: xfrm: policy: preallocate inexact bins before xfrm_hash_rebuild + reinsert + +From: Xiang Mei (Microsoft) + +[ Upstream commit f38f8cce2f7e79775b3db7e8a5eacda04ac908e4 ] + +xfrm_hash_rebuild()'s first loop preallocates the bins/chains the reinsert +loop needs, so the reinsert (after hlist_del_rcu()) cannot allocate or +fail. But its guard is inverted: it skips policies with prefixlen < +threshold and preallocates for the rest. + +prefixlen < threshold is exactly when policy_hash_bysel() returns NULL and +the reinsert takes the allocating xfrm_policy_inexact_insert() path. So the +loop preallocates for the exact policies (which never allocate) and skips +the inexact ones, whose bin/node is then allocated GFP_ATOMIC during +reinsert. On failure the error path only WARN_ONCE()s and continues, +leaving a poisoned bydst node; the next rebuild's hlist_del_rcu() +dereferences LIST_POISON2 and takes a GPF. Reachable under memory pressure, +deterministic via failslab. + +Invert the guard so preallocation covers exactly the reinserted policies; +the reinsert then allocates nothing and cannot fail. + +Crash: + Oops: general protection fault, probably for non-canonical address + 0xfbd59c0000000024: 0000 [#1] SMP KASAN NOPTI + KASAN: maybe wild-memory-access in range [0xdead...] + ... + Workqueue: events xfrm_hash_rebuild + RIP: 0010:xfrm_hash_rebuild+0x5b3/0x1190 + RAX: dead000000000122 (LIST_POISON2 + offset) + ... + Call Trace: + hlist_del_rcu (include/linux/rculist.h:599) + xfrm_hash_rebuild (net/xfrm/xfrm_policy.c:1365) + process_one_work (kernel/workqueue.c:3322) + worker_thread (kernel/workqueue.c:3486) + kthread (kernel/kthread.c:436) + ret_from_fork (arch/x86/kernel/process.c:158) + ret_from_fork_asm (arch/x86/entry/entry_64.S:245) + ... + Kernel panic - not syncing: Fatal exception in interrupt + +Fixes: 24969facd704 ("xfrm: policy: store inexact policies in an rhashtable") +Reported-by: AutonomousCodeSecurity@microsoft.com +Signed-off-by: Xiang Mei (Microsoft) +Reviewed-by: Florian Westphal +Signed-off-by: Steffen Klassert +Signed-off-by: Sasha Levin +--- + net/xfrm/xfrm_policy.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c +index 639934f300167e..bed4b5a3fcce14 100644 +--- a/net/xfrm/xfrm_policy.c ++++ b/net/xfrm/xfrm_policy.c +@@ -1329,8 +1329,8 @@ static void xfrm_hash_rebuild(struct work_struct *work) + } + } + +- if (policy->selector.prefixlen_d < dbits || +- policy->selector.prefixlen_s < sbits) ++ if (policy->selector.prefixlen_d >= dbits && ++ policy->selector.prefixlen_s >= sbits) + continue; + + bin = xfrm_policy_inexact_alloc_bin(policy, dir); +-- +2.53.0 + diff --git a/queue-7.1/xfrm-propagate-einprogress-from-validate_xmit_xfrm.patch b/queue-7.1/xfrm-propagate-einprogress-from-validate_xmit_xfrm.patch new file mode 100644 index 0000000000..b8149fa2e3 --- /dev/null +++ b/queue-7.1/xfrm-propagate-einprogress-from-validate_xmit_xfrm.patch @@ -0,0 +1,98 @@ +From 1d33af02420e8a4a593cc62bcd93c3fb486a5233 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 21 Jun 2026 12:03:26 +0200 +Subject: xfrm: propagate -EINPROGRESS from validate_xmit_xfrm() + +From: Petr Wozniak + +[ Upstream commit 6860b467f569f732b11cbc588ae7e195e90e7e23 ] + +validate_xmit_xfrm() returns NULL both when a packet is dropped and +when it is stolen by async crypto (-EINPROGRESS from ->xmit()). +Callers cannot distinguish the two cases. + +f53c723902d1 ("net: Add asynchronous callbacks for xfrm on layer 2.") +changed the semantics of a NULL return from "dropped" to "stolen or +dropped", but __dev_queue_xmit() was not updated. On virtual/bridge +interfaces (noqueue qdisc) __dev_queue_xmit() initialises rc=-ENOMEM +and jumps to out: when skb is NULL, returning -ENOMEM to the caller +even though the packet will be delivered correctly via xfrm_dev_resume(). + +Return ERR_PTR(-EINPROGRESS) from validate_xmit_xfrm() for the async +case so callers can tell it apart from a real drop. Update +__dev_queue_xmit() to handle ERR_PTR(-EINPROGRESS) from +validate_xmit_skb() correctly. Update validate_xmit_skb_list() to +use IS_ERR_OR_NULL() so that ERR_PTR(-EINPROGRESS) is not mistakenly +added to the transmitted list. + +Fixes: f53c723902d1 ("net: Add asynchronous callbacks for xfrm on layer 2.") +Suggested-by: Sabrina Dubroca +Signed-off-by: Petr Wozniak +Signed-off-by: Steffen Klassert +Signed-off-by: Sasha Levin +--- + net/core/dev.c | 10 ++++++++-- + net/xfrm/xfrm_device.c | 4 ++-- + 2 files changed, 10 insertions(+), 4 deletions(-) + +diff --git a/net/core/dev.c b/net/core/dev.c +index f81ce83fb3250d..31741169cb0ba6 100644 +--- a/net/core/dev.c ++++ b/net/core/dev.c +@@ -4016,6 +4016,9 @@ static struct sk_buff *validate_xmit_unreadable_skb(struct sk_buff *skb, + return NULL; + } + ++/* Returns the skb on success, NULL if dropped, or ERR_PTR(-EINPROGRESS) ++ * if stolen by async xfrm crypto (delivered via xfrm_dev_resume()). ++ */ + static struct sk_buff *validate_xmit_skb(struct sk_buff *skb, struct net_device *dev, bool *again) + { + netdev_features_t features; +@@ -4087,7 +4090,7 @@ struct sk_buff *validate_xmit_skb_list(struct sk_buff *skb, struct net_device *d + skb->prev = skb; + + skb = validate_xmit_skb(skb, dev, again); +- if (!skb) ++ if (IS_ERR_OR_NULL(skb)) + continue; + + if (!head) +@@ -4858,8 +4861,11 @@ int __dev_queue_xmit(struct sk_buff *skb, struct net_device *sb_dev) + goto recursion_alert; + + skb = validate_xmit_skb(skb, dev, &again); +- if (!skb) ++ if (IS_ERR_OR_NULL(skb)) { ++ if (PTR_ERR(skb) == -EINPROGRESS) ++ rc = NET_XMIT_SUCCESS; + goto out; ++ } + + HARD_TX_LOCK(dev, txq, cpu); + +diff --git a/net/xfrm/xfrm_device.c b/net/xfrm/xfrm_device.c +index 550457e4c4f01d..8b526e3676389a 100644 +--- a/net/xfrm/xfrm_device.c ++++ b/net/xfrm/xfrm_device.c +@@ -182,7 +182,7 @@ struct sk_buff *validate_xmit_xfrm(struct sk_buff *skb, netdev_features_t featur + err = x->type_offload->xmit(x, skb, esp_features); + if (err) { + if (err == -EINPROGRESS) +- return NULL; ++ return ERR_PTR(-EINPROGRESS); + + XFRM_INC_STATS(xs_net(x), LINUX_MIB_XFRMOUTSTATEPROTOERROR); + kfree_skb(skb); +@@ -224,7 +224,7 @@ struct sk_buff *validate_xmit_xfrm(struct sk_buff *skb, netdev_features_t featur + pskb = skb2; + } + +- return skb; ++ return skb ? skb : ERR_PTR(-EINPROGRESS); + } + EXPORT_SYMBOL_GPL(validate_xmit_xfrm); + +-- +2.53.0 + diff --git a/queue-7.1/xfrm-reject-optional-iptfs-templates-in-outbound-pol.patch b/queue-7.1/xfrm-reject-optional-iptfs-templates-in-outbound-pol.patch new file mode 100644 index 0000000000..7ca5558dd0 --- /dev/null +++ b/queue-7.1/xfrm-reject-optional-iptfs-templates-in-outbound-pol.patch @@ -0,0 +1,173 @@ +From 703c32b81c93c9098705c5561e5d58d11ee80fcf Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 27 Jun 2026 10:23:43 +0200 +Subject: xfrm: reject optional IPTFS templates in outbound policies + +From: Antony Antony + +[ Upstream commit ea528f18231ec0f33317be57f8866913b19aba6e ] + +syzbot reported a stack-out-of-bounds read in xfrm_state_find() +which flows from xfrm_tmpl_resolve_one(). + +Commit 3d776e31c841 ("xfrm: Reject optional tunnel/BEET mode +templates in outbound policies") disallowed optional tunnel and +BEET in outbound policies to prevent this. Later when IPTFS +added, it was not covered by that fix and can still trigger +the out-of-bounds read; + +Extend the check to disallow optional IPTFS in outbound policies +as well. IPTFS should be identical to tunnel mode. +IN and FWD policies are not affected: xfrm_tmpl_resolve_one() +is only reachable via the outbound path. + +Reproducer, before: + +ip link add dummy0 type dummy +ip link set dummy0 up +ip addr add 10.1.1.1/24 dev dummy0 +ip xfrm policy add src 10.1.1.1/32 dst 10.1.1.2/32 dir out tmpl + src fc00::dead:1 dst fc00::dead:2 proto esp reqid 1 mode iptfs + level use tmpl src fc00::dead:1 dst fc00::dead:2 proto esp reqid + 2 mode transport +ping -W 1 -c 1 10.1.1.2 +PING 10.1.1.2 (10.1.1.2) 56(84) bytes of data. + +[ 64.168420] ================================================================== +[ 64.169977] BUG: KASAN: stack-out-of-bounds in __xfrm6_addr_hash+0x11e/0x170 +[ 64.169977] Read of size 4 at addr ffff88800e1ffd20 by task ping/2844 + +[ 64.169977] CPU: 2 UID: 0 PID: 2844 Comm: ping Not tainted 7.1.0-rc7-00180-geb23b588430a #98 PREEMPT(full) +[ 64.169977] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.16.3-debian-1.16.3-2 04/01/2014 +[ 64.169977] Call Trace: +[ 64.169977] +[ 64.169977] dump_stack_lvl+0x47/0x70 +[ 64.169977] ? __xfrm6_addr_hash+0x11e/0x170 +[ 64.169977] print_report+0x152/0x4b0 +[ 64.169977] ? ksys_mmap_pgoff+0x6d/0xa0 +[ 64.169977] ? entry_SYSCALL_64_after_hwframe+0x76/0x7e +[ 64.169977] ? rcu_read_unlock_sched+0xa/0x20 +[ 64.169977] ? __virt_addr_valid+0x21b/0x230 +[ 64.169977] ? __xfrm6_addr_hash+0x11e/0x170 +[ 64.169977] kasan_report+0xa8/0xd0 +[ 64.169977] ? __xfrm6_addr_hash+0x11e/0x170 +[ 64.169977] __xfrm6_addr_hash+0x11e/0x170 +[ 64.169977] __xfrm_dst_hash+0x24/0xc0 +[ 64.169977] xfrm_state_find+0xa2d/0x2f90 +[ 64.169977] ? __pfx_xfrm_state_find+0x10/0x10 +[ 64.169977] ? __pfx_ftrace_graph_ret_addr+0x10/0x10 +[ 64.169977] ? __pfx_ftrace_graph_ret_addr+0x10/0x10 +[ 64.169977] xfrm_tmpl_resolve_one+0x210/0x570 +[ 64.169977] ? __pfx_xfrm_tmpl_resolve_one+0x10/0x10 +[ 64.169977] ? __pfx_stack_trace_consume_entry+0x10/0x10 +[ 64.169977] ? kernel_text_address+0x5b/0x80 +[ 64.169977] ? __kernel_text_address+0xe/0x30 +[ 64.169977] ? unwind_get_return_address+0x5e/0x90 +[ 64.169977] ? arch_stack_walk+0x8c/0xe0 +[ 64.169977] xfrm_tmpl_resolve+0x130/0x200 +[ 64.169977] ? __pfx_xfrm_tmpl_resolve+0x10/0x10 +[ 64.169977] ? __pfx_xfrm_policy_inexact_lookup_rcu+0x10/0x10 +[ 64.169977] ? __refcount_add_not_zero.constprop.0+0xb2/0x110 +[ 64.169977] ? __pfx___refcount_add_not_zero.constprop.0+0x10/0x10 +[ 64.169977] xfrm_resolve_and_create_bundle+0xd5/0x310 +[ 64.169977] ? __pfx_xfrm_resolve_and_create_bundle+0x10/0x10 +[ 64.169977] ? __pfx_xfrm_policy_lookup_bytype+0x10/0x10 +[ 64.169977] ? __pfx_xfrm_policy_lookup_bytype+0x10/0x10 +[ 64.169977] xfrm_lookup_with_ifid+0x3d8/0xb80 +[ 64.169977] ? __pfx_xfrm_lookup_with_ifid+0x10/0x10 +[ 64.169977] ? ip_route_output_key_hash+0xc6/0x110 +[ 64.169977] ? kasan_save_track+0x10/0x30 +[ 64.169977] xfrm_lookup_route+0x18/0xe0 +[ 64.169977] ip4_datagram_release_cb+0x4c9/0x530 +[ 64.169977] ? __pfx_ip4_datagram_release_cb+0x10/0x10 +[ 64.169977] ? do_raw_spin_lock+0x71/0xc0 +[ 64.169977] ? __pfx_do_raw_spin_lock+0x10/0x10 +[ 64.169977] release_sock+0xb0/0x170 +[ 64.169977] udp_connect+0x43/0x50 +[ 64.169977] __sys_connect+0xa6/0x100 +[ 64.169977] ? alloc_fd+0x2e9/0x300 +[ 64.169977] ? __pfx___sys_connect+0x10/0x10 +[ 64.169977] ? preempt_latency_start+0x1f/0x70 +[ 64.169977] ? fd_install+0x7e/0x150 +[ 64.169977] ? rcu_read_unlock_sched+0xa/0x20 +[ 64.169977] ? __sys_socket+0xdf/0x130 +[ 64.169977] ? __pfx___sys_socket+0x10/0x10 +[ 64.169977] ? vma_refcount_put+0x43/0xa0 +[ 64.169977] __x64_sys_connect+0x7e/0x90 +[ 64.169977] do_syscall_64+0x11b/0x2b0 +[ 64.169977] entry_SYSCALL_64_after_hwframe+0x76/0x7e +[ 64.169977] RIP: 0033:0x7f4851ecb570 +[ 64.169977] Code: 00 f7 d8 64 89 01 48 83 c8 ff c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 44 00 00 80 3d f9 ca 0d 00 00 74 17 b8 2a 00 00 00 0f 05 <48> 3d 00 f0 ff ff 77 58 c3 0f 1f 80 00 00 00 00 48 83 ec 18 89 54 +[ 64.169977] RSP: 002b:00007ffc830e3498 EFLAGS: 00000202 ORIG_RAX: 000000000000002a +[ 64.169977] RAX: ffffffffffffffda RBX: 00007ffc830e34d0 RCX: 00007f4851ecb570 +[ 64.169977] RDX: 0000000000000010 RSI: 00007ffc830e34d0 RDI: 0000000000000005 +[ 64.169977] RBP: 0000000000000000 R08: 0000000000000003 R09: 0000000000000000 +[ 64.169977] R10: 0000000000000006 R11: 0000000000000202 R12: 0000000000000005 +[ 64.169977] R13: 0000000000000000 R14: 00005619a863f340 R15: 0000000000000000 +[ 64.169977] + +[ 64.169977] The buggy address belongs to stack of task ping/2844 +[ 64.169977] and is located at offset 88 in frame: +[ 64.169977] ip4_datagram_release_cb+0x0/0x530 + +[ 64.169977] This frame has 1 object: +[ 64.169977] [32, 88) 'fl4' + +[ 64.169977] The buggy address belongs to the physical page: +[ 64.169977] page: refcount:0 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0xe1ff +[ 64.169977] flags: 0x4000000000000000(zone=1) +[ 64.169977] raw: 4000000000000000 0000000000000000 ffffea0000387fc8 0000000000000000 +[ 64.169977] raw: 0000000000000000 0000000000000000 00000000ffffffff 0000000000000000 +[ 64.169977] page dumped because: kasan: bad access detected + +[ 64.169977] Memory state around the buggy address: +[ 64.169977] ffff88800e1ffc00: f2 f2 00 00 f3 f3 00 00 00 00 00 00 00 00 00 00 +[ 64.169977] ffff88800e1ffc80: 00 00 00 00 00 00 00 00 00 f1 f1 f1 f1 00 00 00 +[ 64.169977] >ffff88800e1ffd00: 00 00 00 00 f3 f3 f3 f3 f3 00 00 00 00 00 00 00 +[ 64.169977] ^ +[ 64.169977] ffff88800e1ffd80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 f1 f1 +[ 64.169977] ffff88800e1ffe00: f1 f1 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +[ 64.169977] ================================================================== +[ 64.245153] Disabling lock debugging due to kernel taint + +After the fix: + +ip xfrm policy add src 10.1.1.1/32 dst 10.1.1.2/32 dir out tmpl \ + src fc00::dead:1 dst fc00::dead:2 proto esp reqid 1 mode iptfs \ + level use tmpl src fc00::dead:1 dst fc00::dead:2 proto esp reqid 2 \ + mode transport + +Error: Mode in optional template not allowed in outbound policy. + +Fixes: d1716d5a44c3 ("xfrm: add generic iptfs defines and functionality") +Reported-by: syzbot+0ac4d84afe1066a1f3e9@syzkaller.appspotmail.com +Closes: https://lore.kernel.org/all/6a3ceb94.43b4ff68.30a095.0004.GAE@google.com/T/ +Signed-off-by: Antony Antony +Signed-off-by: Steffen Klassert +Signed-off-by: Sasha Levin +--- + net/xfrm/xfrm_user.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c +index 61eb5de33b87ee..b36741c4ea3de9 100644 +--- a/net/xfrm/xfrm_user.c ++++ b/net/xfrm/xfrm_user.c +@@ -2077,13 +2077,12 @@ static int validate_tmpl(int nr, struct xfrm_user_tmpl *ut, u16 family, + switch (ut[i].mode) { + case XFRM_MODE_TUNNEL: + case XFRM_MODE_BEET: ++ case XFRM_MODE_IPTFS: + if (ut[i].optional && dir == XFRM_POLICY_OUT) { + NL_SET_ERR_MSG(extack, "Mode in optional template not allowed in outbound policy"); + return -EINVAL; + } + break; +- case XFRM_MODE_IPTFS: +- break; + default: + if (ut[i].family != prev_family) { + NL_SET_ERR_MSG(extack, "Mode in template doesn't support a family change"); +-- +2.53.0 + diff --git a/queue-7.1/xfrm6-clear-dst.dev-on-error-to-avoid-double-netdev_.patch b/queue-7.1/xfrm6-clear-dst.dev-on-error-to-avoid-double-netdev_.patch new file mode 100644 index 0000000000..de3175b367 --- /dev/null +++ b/queue-7.1/xfrm6-clear-dst.dev-on-error-to-avoid-double-netdev_.patch @@ -0,0 +1,60 @@ +From 34689c1f84155c2b6012fda750473926334364ab Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 2 Jul 2026 01:05:16 +0000 +Subject: xfrm6: clear dst.dev on error to avoid double netdev_put in + xfrm6_fill_dst() + +From: Xiang Mei (Microsoft) + +[ Upstream commit 136992de9bb91871084ae52d172610541c76e4d2 ] + +On the error path where in6_dev_get(dev) returns NULL, xfrm6_fill_dst() +releases the device reference with netdev_put() but leaves +xdst->u.dst.dev set. dst_destroy() later calls netdev_put(dst->dev) +again, so the same net_device reference is released twice, underflowing +its refcount (ref_tracker WARNING + "unregister_netdevice: waiting for + to become free"). + +Clear xdst->u.dst.dev after the netdev_put(), the same way the XFRM +device-offload paths xfrm_dev_state_add() and xfrm_dev_policy_add() in +net/xfrm/xfrm_device.c NULL ->dev when releasing the reference on error. + + ref_tracker: reference already released. + ref_tracker: allocated in: + xfrm6_fill_dst (net/ipv6/xfrm6_policy.c:86) + ... + udpv6_sendmsg (net/ipv6/udp.c:1696) + ... + ref_tracker: freed in: + xfrm6_fill_dst (net/ipv6/xfrm6_policy.c:90) + ... + WARNING: lib/ref_tracker.c:322 at ref_tracker_free+0x58b/0x780 + dst_destroy (net/core/dst.c:115) + rcu_core + handle_softirqs + ... + +Fixes: 84c4a9dfbf43 ("xfrm6: release dev before returning error") +Reported-by: AutonomousCodeSecurity@microsoft.com +Signed-off-by: Xiang Mei (Microsoft) +Signed-off-by: Steffen Klassert +Signed-off-by: Sasha Levin +--- + net/ipv6/xfrm6_policy.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c +index 125ea9a5b8a082..3b749475f6ed65 100644 +--- a/net/ipv6/xfrm6_policy.c ++++ b/net/ipv6/xfrm6_policy.c +@@ -88,6 +88,7 @@ static int xfrm6_fill_dst(struct xfrm_dst *xdst, struct net_device *dev, + xdst->u.rt6.rt6i_idev = in6_dev_get(dev); + if (!xdst->u.rt6.rt6i_idev) { + netdev_put(dev, &xdst->u.dst.dev_tracker); ++ xdst->u.dst.dev = NULL; + return -ENODEV; + } + +-- +2.53.0 +