From: Greg Kroah-Hartman Date: Thu, 28 May 2026 08:40:57 +0000 (+0200) Subject: 5.15-stable patches X-Git-Tag: v5.10.258~45 X-Git-Url: http://git.ipfire.org/gitweb/index.cgi?a=commitdiff_plain;h=c67d85f4cf85df4f722e50af464d054178c9ea39;p=thirdparty%2Fkernel%2Fstable-queue.git 5.15-stable patches added patches: alsa-asihpi-fix-potential-oob-array-access-at-reading-cache.patch alsa-ua101-reject-too-short-usb-descriptors.patch bluetooth-bnep-fix-uaf-read-of-dev-name.patch bluetooth-hci_uart-fix-uafs-and-race-conditions-in-close-and-init-paths.patch hwmon-pmbus-adm1266-widen-blackbox-info-buffer-to-i2c_smbus_block_max.patch net-bcmgenet-keep-rbuf-eee-pm-disabled.patch net-wwan-iosm-fix-potential-memory-leaks-in-ipc_imem_init.patch netfilter-ip6t_hbh-reject-oversized-option-lists.patch netfilter-ipset-stop-hash-range-iteration-at-end.patch netfilter-nf_queue-hold-bridge-skb-dev-while-queued.patch phonet-pep-disable-bh-around-forwarded-sk_receive_skb.patch sysfs-don-t-remove-existing-directory-on-update-failure.patch --- diff --git a/queue-5.15/alsa-asihpi-fix-potential-oob-array-access-at-reading-cache.patch b/queue-5.15/alsa-asihpi-fix-potential-oob-array-access-at-reading-cache.patch new file mode 100644 index 0000000000..c6877a4a2b --- /dev/null +++ b/queue-5.15/alsa-asihpi-fix-potential-oob-array-access-at-reading-cache.patch @@ -0,0 +1,37 @@ +From 7b7d6572145c1dab2dd9bfb550b188e5f0ff3c3f Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Fri, 15 May 2026 10:55:58 +0200 +Subject: ALSA: asihpi: Fix potential OOB array access at reading cache + +From: Takashi Iwai + +commit 7b7d6572145c1dab2dd9bfb550b188e5f0ff3c3f upstream. + +find_control() to retrieve a cached info accesses the array with the +given index blindly, which may lead to an OOB array access. +Add a sanity check for avoiding it. + +Link: https://sashiko.dev/#/patchset/20260511230121.28606-1-rosenp%40gmail.com +Cc: +Link: https://patch.msgid.link/20260515085606.242284-1-tiwai@suse.de +Signed-off-by: Takashi Iwai +Signed-off-by: Greg Kroah-Hartman +--- + sound/pci/asihpi/hpicmn.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +--- a/sound/pci/asihpi/hpicmn.c ++++ b/sound/pci/asihpi/hpicmn.c +@@ -276,6 +276,12 @@ static short find_control(u16 control_in + return 0; + } + ++ if (control_index >= p_cache->control_count) { ++ HPI_DEBUG_LOG(VERBOSE, "control_index out of bounce %d\n", ++ control_index); ++ return 0; ++ } ++ + *pI = p_cache->p_info[control_index]; + if (!*pI) { + HPI_DEBUG_LOG(VERBOSE, "Uncached Control %d\n", diff --git a/queue-5.15/alsa-ua101-reject-too-short-usb-descriptors.patch b/queue-5.15/alsa-ua101-reject-too-short-usb-descriptors.patch new file mode 100644 index 0000000000..25c42706ab --- /dev/null +++ b/queue-5.15/alsa-ua101-reject-too-short-usb-descriptors.patch @@ -0,0 +1,45 @@ +From b59d5c51bb328a60749b4dd5fe7e649bfb4089b4 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?C=C3=A1ssio=20Gabriel?= +Date: Tue, 19 May 2026 00:32:15 -0300 +Subject: ALSA: ua101: Reject too-short USB descriptors +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Cássio Gabriel + +commit b59d5c51bb328a60749b4dd5fe7e649bfb4089b4 upstream. + +find_format_descriptor() walks the class-specific interface extras by +advancing with bLength. It rejects descriptors that extend past the +remaining buffer, but it does not reject descriptor lengths smaller than +a USB descriptor header. + +Reject too-short descriptors before using bLength to advance the local +scan. This keeps the UA-101 parser robust against malformed descriptor +data and matches the usual USB descriptor walking rules. + +Fixes: 63978ab3e3e9 ("sound: add Edirol UA-101 support") +Cc: stable@vger.kernel.org +Signed-off-by: Cássio Gabriel +Link: https://patch.msgid.link/20260519-alsa-ua101-desc-len-v1-1-4307d1a5e054@gmail.com +Signed-off-by: Takashi Iwai +Signed-off-by: Greg Kroah-Hartman +--- + sound/usb/misc/ua101.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +--- a/sound/usb/misc/ua101.c ++++ b/sound/usb/misc/ua101.c +@@ -914,8 +914,9 @@ find_format_descriptor(struct usb_interf + struct uac_format_type_i_discrete_descriptor *desc; + + desc = (struct uac_format_type_i_discrete_descriptor *)extra; +- if (desc->bLength > extralen) { +- dev_err(&interface->dev, "descriptor overflow\n"); ++ if (desc->bLength < sizeof(struct usb_descriptor_header) || ++ desc->bLength > extralen) { ++ dev_err(&interface->dev, "invalid descriptor length\n"); + return NULL; + } + if (desc->bLength == UAC_FORMAT_TYPE_I_DISCRETE_DESC_SIZE(1) && diff --git a/queue-5.15/bluetooth-bnep-fix-uaf-read-of-dev-name.patch b/queue-5.15/bluetooth-bnep-fix-uaf-read-of-dev-name.patch new file mode 100644 index 0000000000..6a21f2441e --- /dev/null +++ b/queue-5.15/bluetooth-bnep-fix-uaf-read-of-dev-name.patch @@ -0,0 +1,40 @@ +From 59e932ded949fa6f0340bf7c6d7818f962fa4fd2 Mon Sep 17 00:00:00 2001 +From: Jann Horn +Date: Tue, 12 May 2026 22:15:39 +0200 +Subject: Bluetooth: bnep: Fix UAF read of dev->name + +From: Jann Horn + +commit 59e932ded949fa6f0340bf7c6d7818f962fa4fd2 upstream. + +bnep_add_connection() needs to keep holding the bnep_session_sem while +reading dev->name (just like bnep_get_connlist() does); otherwise the +bnep_session() thread can concurrently free the net_device, which can for +example be triggered by a concurrent bnep_del_connection(). + +(This UAF is fairly uninteresting from a security perspective; +calling bnep_add_connection() requires passing a capable(CAP_NET_ADMIN) +check. It also requires completely tearing down a netdev during a fairly +tight race window.) + +Cc: stable@vger.kernel.org +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Signed-off-by: Jann Horn +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Greg Kroah-Hartman +--- + net/bluetooth/bnep/core.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/net/bluetooth/bnep/core.c ++++ b/net/bluetooth/bnep/core.c +@@ -638,8 +638,8 @@ int bnep_add_connection(struct bnep_conn + goto failed; + } + +- up_write(&bnep_session_sem); + strcpy(req->device, dev->name); ++ up_write(&bnep_session_sem); + return 0; + + failed: diff --git a/queue-5.15/bluetooth-hci_uart-fix-uafs-and-race-conditions-in-close-and-init-paths.patch b/queue-5.15/bluetooth-hci_uart-fix-uafs-and-race-conditions-in-close-and-init-paths.patch new file mode 100644 index 0000000000..73b4b783e8 --- /dev/null +++ b/queue-5.15/bluetooth-hci_uart-fix-uafs-and-race-conditions-in-close-and-init-paths.patch @@ -0,0 +1,173 @@ +From c1bb9336ae6b54a5f6a353c4bd4ed9a4307e429b Mon Sep 17 00:00:00 2001 +From: Mingyu Wang <25181214217@stu.xidian.edu.cn> +Date: Mon, 18 May 2026 10:49:49 +0800 +Subject: Bluetooth: hci_uart: fix UAFs and race conditions in close and init paths + +From: Mingyu Wang <25181214217@stu.xidian.edu.cn> + +commit c1bb9336ae6b54a5f6a353c4bd4ed9a4307e429b upstream. + +Vulnerabilities leading to Use-After-Free (UAF) and Null Pointer +Dereference (NPD) conditions were observed in the lifecycle management +of hci_uart. + +The primary issue arises because the workqueues (init_ready and +write_work) are only flushed/cancelled if the HCI_UART_PROTO_READY +flag is set during TTY close. If a hangup occurs before setup completes, +hci_uart_tty_close() skips the teardown of these workqueues and +proceeds to free the `hu` struct. When the scheduled work executes +later, it blindly dereferences the freed `hu` struct. + +Furthermore, several data races and UAFs were identified in the teardown +sequence: +1. Calling hci_uart_flush() from hci_uart_close() without effectively + disabling write_work causes a race condition where both can concurrently + double-free hu->tx_skb. This happens because protocol timers can + concurrently invoke hci_uart_tx_wakeup() and requeue write_work. +2. Calling hci_free_dev(hdev) before hu->proto->close(hu) causes a UAF + when vendor specific protocol close callbacks dereference hu->hdev. +3. In the initialization error paths, failing to take the proto_lock + write lock before clearing PROTO_READY leads to races with active + readers. Additionally, hci_uart_tty_receive() accesses hu->hdev + outside the read lock, leading to UAFs if the initialization error + path frees hdev concurrently. + +Fix these synchronization and lifecycle issues by: +1. Re-ordering hci_uart_tty_close() to clear HCI_UART_PROTO_READY first, + followed immediately by a cancel_work_sync(&hu->write_work). Clearing + the flag locks out concurrent protocol timers from successfully invoking + hci_uart_tx_wakeup(), effectively rendering the cancellation permanent + and preventing the tx_skb double-free. +2. Note: Clearing PROTO_READY early causes hci_uart_close() to skip + hu->proto->flush(). This is perfectly safe in the tty_close path + because hu->proto->close() executes shortly after, which intrinsically + purges all protocol SKB queues and tears down the state. +3. Relocating hu->proto->close(hu) strictly prior to hci_free_dev(hdev) + across all close and error paths to prevent vendor-level UAFs. +4. Moving the hdev->stat.byte_rx increment in hci_uart_tty_receive() + inside the proto_lock read-side critical section to safely synchronize + with device unregistration. +5. Adding cancel_work_sync(&hu->write_work) to hci_uart_close() to safely + flush the workqueue before hci_uart_flush() is invoked via the HCI core. +6. Utilizing cancel_work_sync() instead of disable_work_sync() across + all paths to prevent permanently breaking user-space retry capabilities. + +Fixes: 3b799254cf6f ("Bluetooth: hci_uart: Cancel init work before unregistering") +Cc: stable@vger.kernel.org +Signed-off-by: Mingyu Wang <25181214217@stu.xidian.edu.cn> +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Greg Kroah-Hartman +--- + drivers/bluetooth/hci_ldisc.c | 48 +++++++++++++++++++++++++++++++++++------- + 1 file changed, 40 insertions(+), 8 deletions(-) + +--- a/drivers/bluetooth/hci_ldisc.c ++++ b/drivers/bluetooth/hci_ldisc.c +@@ -194,7 +194,15 @@ void hci_uart_init_work(struct work_stru + err = hci_register_dev(hu->hdev); + if (err < 0) { + BT_ERR("Can't register HCI device"); ++ ++ percpu_down_write(&hu->proto_lock); + clear_bit(HCI_UART_PROTO_READY, &hu->flags); ++ percpu_up_write(&hu->proto_lock); ++ ++ /* Safely cancel work after clearing flags */ ++ cancel_work_sync(&hu->write_work); ++ ++ /* Close protocol before freeing hdev */ + hu->proto->close(hu); + hdev = hu->hdev; + hu->hdev = NULL; +@@ -263,8 +271,12 @@ static int hci_uart_open(struct hci_dev + /* Close device */ + static int hci_uart_close(struct hci_dev *hdev) + { ++ struct hci_uart *hu = hci_get_drvdata(hdev); ++ + BT_DBG("hdev %p", hdev); + ++ cancel_work_sync(&hu->write_work); ++ + hci_uart_flush(hdev); + hdev->flush = NULL; + return 0; +@@ -525,6 +537,7 @@ static void hci_uart_tty_close(struct tt + { + struct hci_uart *hu = tty->disc_data; + struct hci_dev *hdev; ++ bool proto_ready; + + BT_DBG("tty %p", tty); + +@@ -534,24 +547,38 @@ static void hci_uart_tty_close(struct tt + if (!hu) + return; + +- hdev = hu->hdev; +- if (hdev) +- hci_uart_close(hdev); ++ /* Wait for init_ready to finish to prevent registration races */ ++ cancel_work_sync(&hu->init_ready); + +- if (test_bit(HCI_UART_PROTO_READY, &hu->flags)) { ++ proto_ready = test_bit(HCI_UART_PROTO_READY, &hu->flags); ++ if (proto_ready) { + percpu_down_write(&hu->proto_lock); + clear_bit(HCI_UART_PROTO_READY, &hu->flags); + percpu_up_write(&hu->proto_lock); ++ } + +- cancel_work_sync(&hu->init_ready); +- cancel_work_sync(&hu->write_work); ++ /* ++ * Unconditionally cancel write_work AFTER clearing PROTO_READY. ++ * This ensures that concurrent protocol timers cannot requeue ++ * write_work via hci_uart_tx_wakeup(), permanently preventing ++ * double-free races and UAFs. ++ */ ++ cancel_work_sync(&hu->write_work); ++ ++ hdev = hu->hdev; ++ if (hdev) ++ hci_uart_close(hdev); /* proto->flush is safely skipped */ + ++ if (proto_ready) { + if (hdev) { + if (test_bit(HCI_UART_REGISTERED, &hu->flags)) + hci_unregister_dev(hdev); +- hci_free_dev(hdev); + } ++ /* Close protocol before freeing hdev (intrinsically purges queues) */ + hu->proto->close(hu); ++ ++ if (hdev) ++ hci_free_dev(hdev); + } + clear_bit(HCI_UART_PROTO_SET, &hu->flags); + +@@ -619,11 +646,12 @@ static void hci_uart_tty_receive(struct + * tty caller + */ + hu->proto->recv(hu, data, count); +- percpu_up_read(&hu->proto_lock); + + if (hu->hdev) + hu->hdev->stat.byte_rx += count; + ++ percpu_up_read(&hu->proto_lock); ++ + tty_unthrottle(tty); + } + +@@ -694,6 +722,10 @@ static int hci_uart_register_dev(struct + percpu_down_write(&hu->proto_lock); + clear_bit(HCI_UART_PROTO_INIT, &hu->flags); + percpu_up_write(&hu->proto_lock); ++ /* Cancel work after clearing flags */ ++ cancel_work_sync(&hu->write_work); ++ ++ /* Close protocol before freeing hdev */ + hu->proto->close(hu); + hu->hdev = NULL; + hci_free_dev(hdev); diff --git a/queue-5.15/hwmon-pmbus-adm1266-widen-blackbox-info-buffer-to-i2c_smbus_block_max.patch b/queue-5.15/hwmon-pmbus-adm1266-widen-blackbox-info-buffer-to-i2c_smbus_block_max.patch new file mode 100644 index 0000000000..4fd12e8541 --- /dev/null +++ b/queue-5.15/hwmon-pmbus-adm1266-widen-blackbox-info-buffer-to-i2c_smbus_block_max.patch @@ -0,0 +1,51 @@ +From eee213daa1e1b402eb631bcd1b8c5aa340a6b081 Mon Sep 17 00:00:00 2001 +From: Abdurrahman Hussain +Date: Fri, 15 May 2026 15:11:48 -0700 +Subject: hwmon: (pmbus/adm1266) widen blackbox-info buffer to I2C_SMBUS_BLOCK_MAX + +From: Abdurrahman Hussain + +commit eee213daa1e1b402eb631bcd1b8c5aa340a6b081 upstream. + +adm1266_nvmem_read_blackbox() declares a 5-byte stack buffer and +passes it to i2c_smbus_read_block_data() to retrieve the 4-byte +BLACKBOX_INFO response. i2c_smbus_read_block_data() does not honour +caller buffer sizes -- it memcpy()s data.block[0] bytes from the +SMBus transaction (where data.block[0] is the length byte returned by +the slave device, up to I2C_SMBUS_BLOCK_MAX = 32): + + memcpy(values, &data.block[1], data.block[0]); + +If the device returns any block length above 5, the call overflows +the caller's 5-byte stack buffer before the post-call + + if (ret != 4) + return -EIO; + +check has a chance to reject the response. + +Widen the local buffer to I2C_SMBUS_BLOCK_MAX so the helper has room +for any well-formed SMBus block response, matching the convention used +by the other i2c_smbus_read_block_data() callers in this driver. + +Fixes: 15609d189302 ("hwmon: (pmbus/adm1266) read blackbox") +Cc: stable@vger.kernel.org +Signed-off-by: Abdurrahman Hussain +Link: https://lore.kernel.org/r/20260515-adm1266-fixes-v1-2-1c1ea1349cfe@nexthop.ai +Signed-off-by: Guenter Roeck +Signed-off-by: Greg Kroah-Hartman +--- + drivers/hwmon/pmbus/adm1266.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/hwmon/pmbus/adm1266.c ++++ b/drivers/hwmon/pmbus/adm1266.c +@@ -351,7 +351,7 @@ static int adm1266_nvmem_read_blackbox(s + { + int record_count; + char index; +- u8 buf[5]; ++ u8 buf[I2C_SMBUS_BLOCK_MAX]; + int ret; + + ret = i2c_smbus_read_block_data(data->client, ADM1266_BLACKBOX_INFO, buf); diff --git a/queue-5.15/net-bcmgenet-keep-rbuf-eee-pm-disabled.patch b/queue-5.15/net-bcmgenet-keep-rbuf-eee-pm-disabled.patch new file mode 100644 index 0000000000..f8e440c661 --- /dev/null +++ b/queue-5.15/net-bcmgenet-keep-rbuf-eee-pm-disabled.patch @@ -0,0 +1,62 @@ +From 9a1730245e416d11ad5c0f2c100061d61cc43f60 Mon Sep 17 00:00:00 2001 +From: Nicolai Buchwitz +Date: Wed, 20 May 2026 20:43:20 +0200 +Subject: net: bcmgenet: keep RBUF EEE/PM disabled + +From: Nicolai Buchwitz + +commit 9a1730245e416d11ad5c0f2c100061d61cc43f60 upstream. + +Setting RBUF_EEE_EN | RBUF_PM_EN in RBUF_ENERGY_CTRL breaks the RX +path on GENET hardware once MAC EEE becomes active. RX traffic stops +flowing while the link stays up and the usual descriptor/RX error +counters remain quiet. In that state the MAC still accepts frames +(rbuf_ovflow_cnt keeps climbing) but RBUF no longer forwards them to +DMA, so rx_packets is no longer incremented at the netdev level. On +some boards the corruption ends up as a paging fault in +skb_release_data via bcmgenet_rx_poll on an LPI exit. + +Reproduced on Pi 4B (BCM2711 + BCM54213PE) and confirmed by Florian +Fainelli on an internal Broadcom 4908-family board with the same crash +signature. RBUF_PM_EN is not publicly documented. + +This shows up more often now that phy_support_eee() enables EEE by +default, but it also affects older kernels as soon as TX LPI is +turned on via ethtool, so it is not specific to recent changes. + +Always clear RBUF_EEE_EN | RBUF_PM_EN in bcmgenet_eee_enable_set so +the bits stay off across resets. UMAC and TBUF setup is left alone so +TX-side EEE keeps working. + +Link: https://github.com/raspberrypi/linux/issues/7304 +Fixes: 6ef398ea60d9 ("net: bcmgenet: add EEE support") +Cc: stable@vger.kernel.org +Signed-off-by: Nicolai Buchwitz +Reviewed-by: Florian Fainelli +Link: https://patch.msgid.link/20260520184320.652053-1-nb@tipi-net.de +Signed-off-by: Jakub Kicinski +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/ethernet/broadcom/genet/bcmgenet.c | 9 ++++----- + 1 file changed, 4 insertions(+), 5 deletions(-) + +--- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c ++++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c +@@ -1275,13 +1275,12 @@ void bcmgenet_eee_enable_set(struct net_ + reg &= ~(TBUF_EEE_EN | TBUF_PM_EN); + bcmgenet_writel(reg, priv->base + off); + +- /* Do the same for thing for RBUF */ ++ /* RBUF EEE/PM can break the RX path on GENET. Keep it disabled. */ + reg = bcmgenet_rbuf_readl(priv, RBUF_ENERGY_CTRL); +- if (enable) +- reg |= RBUF_EEE_EN | RBUF_PM_EN; +- else ++ if (reg & (RBUF_EEE_EN | RBUF_PM_EN)) { + reg &= ~(RBUF_EEE_EN | RBUF_PM_EN); +- bcmgenet_rbuf_writel(priv, reg, RBUF_ENERGY_CTRL); ++ bcmgenet_rbuf_writel(priv, reg, RBUF_ENERGY_CTRL); ++ } + + if (!enable && priv->clk_eee_enabled) { + clk_disable_unprepare(priv->clk_eee); diff --git a/queue-5.15/net-wwan-iosm-fix-potential-memory-leaks-in-ipc_imem_init.patch b/queue-5.15/net-wwan-iosm-fix-potential-memory-leaks-in-ipc_imem_init.patch new file mode 100644 index 0000000000..210312383b --- /dev/null +++ b/queue-5.15/net-wwan-iosm-fix-potential-memory-leaks-in-ipc_imem_init.patch @@ -0,0 +1,34 @@ +From c5d93b2c40355e999715262a824965aac025a427 Mon Sep 17 00:00:00 2001 +From: Abdun Nihaal +Date: Tue, 19 May 2026 11:57:39 +0530 +Subject: net: wwan: iosm: fix potential memory leaks in ipc_imem_init() + +From: Abdun Nihaal + +commit c5d93b2c40355e999715262a824965aac025a427 upstream. + +The memory allocated in ipc_protocol_init() is not freed on the error +paths that follow in ipc_imem_init(). Fix that by calling the +corresponding release function ipc_protocol_deinit() in the error path. + +Fixes: 3670970dd8c6 ("net: iosm: shared memory IPC interface") +Cc: stable@vger.kernel.org +Signed-off-by: Abdun Nihaal +Link: https://patch.msgid.link/20260519062815.55545-1-nihaal@cse.iitm.ac.in +Signed-off-by: Jakub Kicinski +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/wwan/iosm/iosm_ipc_imem.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/net/wwan/iosm/iosm_ipc_imem.c ++++ b/drivers/net/wwan/iosm/iosm_ipc_imem.c +@@ -1338,6 +1338,8 @@ imem_config_fail: + protocol_init_fail: + cancel_work_sync(&ipc_imem->run_state_worker); + ipc_task_deinit(ipc_imem->ipc_task); ++ if (ipc_imem->ipc_protocol) ++ ipc_protocol_deinit(ipc_imem->ipc_protocol); + ipc_task_init_fail: + kfree(ipc_imem->ipc_task); + ipc_task_fail: diff --git a/queue-5.15/netfilter-ip6t_hbh-reject-oversized-option-lists.patch b/queue-5.15/netfilter-ip6t_hbh-reject-oversized-option-lists.patch new file mode 100644 index 0000000000..89f34c5f05 --- /dev/null +++ b/queue-5.15/netfilter-ip6t_hbh-reject-oversized-option-lists.patch @@ -0,0 +1,51 @@ +From 4322dcde6b4173c2d8e8e6118ed290794263bcc8 Mon Sep 17 00:00:00 2001 +From: Zhengchuan Liang +Date: Wed, 13 May 2026 15:57:17 +0800 +Subject: netfilter: ip6t_hbh: reject oversized option lists + +From: Zhengchuan Liang + +commit 4322dcde6b4173c2d8e8e6118ed290794263bcc8 upstream. + +struct ip6t_opts stores at most IP6T_OPTS_OPTSNR option descriptors, +but hbh_mt6_check() does not reject larger optsnr values supplied from +userspace. + +Validate optsnr in the rule setup path so only match data that fits the +fixed-size opts array can be installed. This follows the existing xtables +pattern of rejecting invalid user-provided counts in checkentry() and +keeps the packet matching path unchanged. + +`struct ip6t_opts` has a fixed `opts[IP6T_OPTS_OPTSNR]` array, +where `IP6T_OPTS_OPTSNR` is 16, then off-by-one array access is possible: + +[ 137.924693][ T8692] UBSAN: array-index-out-of-bounds in ../net/ipv6/netfilter/ip6t_hbh.c:110:29 +[ 137.926167][ T8692] index 16 is out of range for type '__u16 [16]' + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Cc: stable@kernel.org +Reported-by: Yuan Tan +Reported-by: Yifan Wu +Reported-by: Juefei Pu +Reported-by: Xin Liu +Signed-off-by: Zhengchuan Liang +Signed-off-by: Ren Wei +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: Greg Kroah-Hartman +--- + net/ipv6/netfilter/ip6t_hbh.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/net/ipv6/netfilter/ip6t_hbh.c ++++ b/net/ipv6/netfilter/ip6t_hbh.c +@@ -168,6 +168,10 @@ static int hbh_mt6_check(const struct xt + pr_debug("unknown flags %X\n", optsinfo->invflags); + return -EINVAL; + } ++ if (optsinfo->optsnr > IP6T_OPTS_OPTSNR) { ++ pr_debug("too many supported opts specified\n"); ++ return -EINVAL; ++ } + + if (optsinfo->flags & IP6T_OPTS_NSTRICT) { + pr_debug("Not strict - not implemented"); diff --git a/queue-5.15/netfilter-ipset-stop-hash-range-iteration-at-end.patch b/queue-5.15/netfilter-ipset-stop-hash-range-iteration-at-end.patch new file mode 100644 index 0000000000..2a9436be64 --- /dev/null +++ b/queue-5.15/netfilter-ipset-stop-hash-range-iteration-at-end.patch @@ -0,0 +1,130 @@ +From 0d3a282ab5f165fc207ff49ea5b6ad8f54616bd6 Mon Sep 17 00:00:00 2001 +From: Nan Li +Date: Tue, 12 May 2026 16:50:01 +0800 +Subject: netfilter: ipset: stop hash:* range iteration at end + +From: Nan Li + +commit 0d3a282ab5f165fc207ff49ea5b6ad8f54616bd6 upstream. + +The following hash set variants: + +hash:ip,mark +hash:ip,port +hash:ip,port,ip +hash:ip,port,net + +iterate IPv4 ranges with a 32-bit iterator. + +The iterator must stop once the last address in the requested range has +been processed. Advancing it once more can move the traversal state past +the end of the request, so a later retry may continue from an unintended +position. + +Handle the iterator increment explicitly at the end of the loop and stop +once the upper bound has been processed. This keeps the existing retry +behaviour intact for valid ranges while preventing traversal from +continuing past the original boundary. + +Fixes: 48596a8ddc46 ("netfilter: ipset: Fix adding an IPv4 range containing more than 2^31 addresses") +Cc: stable@kernel.org +Reported-by: Yuan Tan +Reported-by: Yifan Wu +Reported-by: Juefei Pu +Reported-by: Xin Liu +Signed-off-by: Nan Li +Signed-off-by: Ren Wei +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: Greg Kroah-Hartman +--- + net/netfilter/ipset/ip_set_hash_ipmark.c | 6 +++++- + net/netfilter/ipset/ip_set_hash_ipport.c | 5 ++++- + net/netfilter/ipset/ip_set_hash_ipportip.c | 5 ++++- + net/netfilter/ipset/ip_set_hash_ipportnet.c | 5 ++++- + 4 files changed, 17 insertions(+), 4 deletions(-) + +--- a/net/netfilter/ipset/ip_set_hash_ipmark.c ++++ b/net/netfilter/ipset/ip_set_hash_ipmark.c +@@ -150,7 +150,7 @@ hash_ipmark4_uadt(struct ip_set *set, st + + if (retried) + ip = ntohl(h->next.ip); +- for (; ip <= ip_to; ip++, i++) { ++ for (; ip <= ip_to; i++) { + e.ip = htonl(ip); + if (i > IPSET_MAX_RANGE) { + hash_ipmark4_data_next(&h->next, &e); +@@ -162,6 +162,10 @@ hash_ipmark4_uadt(struct ip_set *set, st + return ret; + + ret = 0; ++ ++ if (ip == ip_to) ++ break; ++ ip++; + } + return ret; + } +--- a/net/netfilter/ipset/ip_set_hash_ipport.c ++++ b/net/netfilter/ipset/ip_set_hash_ipport.c +@@ -175,7 +175,7 @@ hash_ipport4_uadt(struct ip_set *set, st + + if (retried) + ip = ntohl(h->next.ip); +- for (; ip <= ip_to; ip++) { ++ for (; ip <= ip_to;) { + p = retried && ip == ntohl(h->next.ip) ? ntohs(h->next.port) + : port; + for (; p <= port_to; p++, i++) { +@@ -192,6 +192,9 @@ hash_ipport4_uadt(struct ip_set *set, st + + ret = 0; + } ++ if (ip == ip_to) ++ break; ++ ip++; + } + return ret; + } +--- a/net/netfilter/ipset/ip_set_hash_ipportip.c ++++ b/net/netfilter/ipset/ip_set_hash_ipportip.c +@@ -182,7 +182,7 @@ hash_ipportip4_uadt(struct ip_set *set, + + if (retried) + ip = ntohl(h->next.ip); +- for (; ip <= ip_to; ip++) { ++ for (; ip <= ip_to;) { + p = retried && ip == ntohl(h->next.ip) ? ntohs(h->next.port) + : port; + for (; p <= port_to; p++, i++) { +@@ -199,6 +199,9 @@ hash_ipportip4_uadt(struct ip_set *set, + + ret = 0; + } ++ if (ip == ip_to) ++ break; ++ ip++; + } + return ret; + } +--- a/net/netfilter/ipset/ip_set_hash_ipportnet.c ++++ b/net/netfilter/ipset/ip_set_hash_ipportnet.c +@@ -274,7 +274,7 @@ hash_ipportnet4_uadt(struct ip_set *set, + p = port; + ip2 = ip2_from; + } +- for (; ip <= ip_to; ip++) { ++ for (; ip <= ip_to;) { + e.ip = htonl(ip); + for (; p <= port_to; p++) { + e.port = htons(p); +@@ -298,6 +298,9 @@ hash_ipportnet4_uadt(struct ip_set *set, + ip2 = ip2_from; + } + p = port; ++ if (ip == ip_to) ++ break; ++ ip++; + } + return ret; + } diff --git a/queue-5.15/netfilter-nf_queue-hold-bridge-skb-dev-while-queued.patch b/queue-5.15/netfilter-nf_queue-hold-bridge-skb-dev-while-queued.patch new file mode 100644 index 0000000000..3834126490 --- /dev/null +++ b/queue-5.15/netfilter-nf_queue-hold-bridge-skb-dev-while-queued.patch @@ -0,0 +1,90 @@ +From e196115ec330a18de415bdb9f5071aa9f08e53ce Mon Sep 17 00:00:00 2001 +From: Haoze Xie +Date: Fri, 15 May 2026 11:19:02 +0800 +Subject: netfilter: nf_queue: hold bridge skb->dev while queued + +From: Haoze Xie + +commit e196115ec330a18de415bdb9f5071aa9f08e53ce upstream. + +br_pass_frame_up() rewrites skb->dev from the ingress port to the bridge +master before queueing bridge LOCAL_IN packets. NFQUEUE only holds +references on state.in/out and bridge physdevs, so a queued bridge +packet can retain a freed bridge master in skb->dev until reinjection. + +When the verdict is reinjected later, br_netif_receive_skb() re-enters +the receive path with skb->dev still pointing at the freed bridge master, +triggering a use-after-free. + +Store skb->dev in the queue entry, hold a reference on it for the queue +lifetime, and use the saved device when dropping queued packets during +NETDEV_DOWN handling. + +Fixes: ac2863445686 ("netfilter: bridge: add nf_afinfo to enable queuing to userspace") +Cc: stable@kernel.org +Reported-by: Yuan Tan +Reported-by: Yifan Wu +Reported-by: Juefei Pu +Reported-by: Xin Liu +Signed-off-by: Haoze Xie +Signed-off-by: Ren Wei +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: Greg Kroah-Hartman +--- + include/net/netfilter/nf_queue.h | 1 + + net/netfilter/nf_queue.c | 4 +++- + net/netfilter/nfnetlink_queue.c | 2 ++ + 3 files changed, 6 insertions(+), 1 deletion(-) + +--- a/include/net/netfilter/nf_queue.h ++++ b/include/net/netfilter/nf_queue.h +@@ -12,6 +12,7 @@ + struct nf_queue_entry { + struct list_head list; + struct sk_buff *skb; ++ struct net_device *skb_dev; + unsigned int id; + unsigned int hook_index; /* index in hook_entries->hook[] */ + #if IS_ENABLED(CONFIG_BRIDGE_NETFILTER) +--- a/net/netfilter/nf_queue.c ++++ b/net/netfilter/nf_queue.c +@@ -60,6 +60,7 @@ static void nf_queue_entry_release_refs( + struct nf_hook_state *state = &entry->state; + + /* Release those devices we held, or Alexey will kill me. */ ++ dev_put(entry->skb_dev); + dev_put(state->in); + dev_put(state->out); + if (state->sk) +@@ -103,6 +104,7 @@ bool nf_queue_entry_get_refs(struct nf_q + if (state->sk && !refcount_inc_not_zero(&state->sk->sk_refcnt)) + return false; + ++ dev_hold(entry->skb_dev); + dev_hold(state->in); + dev_hold(state->out); + +@@ -203,11 +205,11 @@ static int __nf_queue(struct sk_buff *sk + + *entry = (struct nf_queue_entry) { + .skb = skb, ++ .skb_dev = skb->dev, + .state = *state, + .hook_index = index, + .size = sizeof(*entry) + route_key_size, + }; +- + __nf_queue_entry_init_physdevs(entry); + + if (!nf_queue_entry_get_refs(entry)) { +--- a/net/netfilter/nfnetlink_queue.c ++++ b/net/netfilter/nfnetlink_queue.c +@@ -944,6 +944,8 @@ dev_cmp(struct nf_queue_entry *entry, un + if (physinif == ifindex || physoutif == ifindex) + return 1; + #endif ++ if (entry->skb_dev && entry->skb_dev->ifindex == ifindex) ++ return 1; + if (entry->state.in) + if (entry->state.in->ifindex == ifindex) + return 1; diff --git a/queue-5.15/phonet-pep-disable-bh-around-forwarded-sk_receive_skb.patch b/queue-5.15/phonet-pep-disable-bh-around-forwarded-sk_receive_skb.patch new file mode 100644 index 0000000000..ebcd6077a1 --- /dev/null +++ b/queue-5.15/phonet-pep-disable-bh-around-forwarded-sk_receive_skb.patch @@ -0,0 +1,105 @@ +From dbc81608e3a653dea6cf403f20cae35468b8ab9c Mon Sep 17 00:00:00 2001 +From: Zijing Yin +Date: Tue, 19 May 2026 10:26:33 -0700 +Subject: phonet/pep: disable BH around forwarded sk_receive_skb() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Zijing Yin + +commit dbc81608e3a653dea6cf403f20cae35468b8ab9c upstream. + +The networking receive path is usually run from softirq context, but +protocols that take the socket lock may have packets stored in the +backlog and processed later from process context. In that case +release_sock() -> __release_sock() drops the slock with spin_unlock_bh() +and then calls sk->sk_backlog_rcv() with bottom halves enabled. + +Typical sk_backlog_rcv handlers process the socket whose backlog is +being drained, so the BH state at entry is irrelevant for the slocks +they touch. pep_do_rcv() is different: when the inbound skb targets an +existing PEP pipe, it forwards the skb to a different *child* socket +via sk_receive_skb(). That helper takes the child slock with +bh_lock_sock_nested(), which is just spin_lock_nested() and assumes BH +is already off. The same child slock therefore ends up acquired with +BH on (process path) and with BH off (softirq path): + + process context softirq context + --------------- --------------- + release_sock(listener) __netif_receive_skb() + __release_sock() phonet_rcv() + spin_unlock_bh() __sk_receive_skb(listener) + [BH now ENABLED] [BH already disabled] + sk_backlog_rcv: sk_backlog_rcv: + pep_do_rcv() pep_do_rcv() + sk_receive_skb(child) sk_receive_skb(child) + bh_lock_sock_nested(child) bh_lock_sock_nested(child) + => SOFTIRQ-ON-W => IN-SOFTIRQ-W + +Lockdep flags this as inconsistent lock state, and it can become a real +self-deadlock if a softirq on the same CPU tries to receive to the same +child socket while its slock is held in the BH-enabled path: + + WARNING: inconsistent lock state + inconsistent {SOFTIRQ-ON-W} -> {IN-SOFTIRQ-W} usage. + (slock-AF_PHONET/1){+.?.}-{3:3}, at: __sk_receive_skb+0x1cf/0x900 + __sk_receive_skb net/core/sock.c:563 + sk_receive_skb include/net/sock.h:2022 [inline] + pep_do_rcv net/phonet/pep.c:675 + sk_backlog_rcv include/net/sock.h:1190 + __release_sock net/core/sock.c:3216 + release_sock net/core/sock.c:3815 + pep_sock_accept net/phonet/pep.c:879 + +Wrap the forwarded sk_receive_skb() in local_bh_disable() / +local_bh_enable() so the child slock is always acquired with BH off. +local_bh_disable() nests safely on the softirq path. + +Discovered via in-house syzkaller fuzzing; the same root cause also +on the linux-6.1.y syzbot dashboard as extid 44f0626dd6284f02663c. +Reproduced under KASAN + LOCKDEP + PROVE_LOCKING, reproducer: +https://pastebin.com/A3t8xzCR + +Fixes: 9641458d3ec4 ("Phonet: Pipe End Point for Phonet Pipes protocol") +Link: https://syzkaller.appspot.com/bug?extid=44f0626dd6284f02663c +Cc: stable@vger.kernel.org +Signed-off-by: Zijing Yin +Acked-by: Rémi Denis-Courmont +Reported-by: syzbot+9f4a135646b66c509935@syzkaller.appspotmail.com +Reviewed-by: Eric Dumazet +Link: https://patch.msgid.link/20260519172635.86304-1-yzjaurora@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Greg Kroah-Hartman +--- + net/phonet/pep.c | 19 +++++++++++++++++-- + 1 file changed, 17 insertions(+), 2 deletions(-) + +--- a/net/phonet/pep.c ++++ b/net/phonet/pep.c +@@ -671,8 +671,23 @@ static int pep_do_rcv(struct sock *sk, s + + /* Look for an existing pipe handle */ + sknode = pep_find_pipe(&pn->hlist, &dst, pipe_handle); +- if (sknode) +- return sk_receive_skb(sknode, skb, 1); ++ if (sknode) { ++ int rc; ++ ++ /* pep_do_rcv() runs from two contexts: from softirq via ++ * phonet_rcv() -> __sk_receive_skb() with BH disabled, ++ * and from process context via ++ * release_sock() -> __release_sock(), which drops ++ * the listener slock with spin_unlock_bh() before draining ++ * the backlog. The child pipe slock is taken below via ++ * bh_lock_sock_nested(), which does not itself disable BH, so ++ * disable BH here to keep both acquire contexts consistent. ++ */ ++ local_bh_disable(); ++ rc = sk_receive_skb(sknode, skb, 1); ++ local_bh_enable(); ++ return rc; ++ } + + switch (hdr->message_id) { + case PNS_PEP_CONNECT_REQ: diff --git a/queue-5.15/series b/queue-5.15/series index a95e4b8776..fae555b220 100644 --- a/queue-5.15/series +++ b/queue-5.15/series @@ -681,3 +681,15 @@ kvm-x86-acquire-srcu-in-kvm_get_mp_state-to-protect-.patch revert-s390-cio-fix-device-lifecycle-handling-in-css.patch smb-client-reject-userspace-cifs.spnego-descriptions.patch i3c-mipi-i3c-hci-correct-ring_ctrl_abort-handling-in.patch +sysfs-don-t-remove-existing-directory-on-update-failure.patch +hwmon-pmbus-adm1266-widen-blackbox-info-buffer-to-i2c_smbus_block_max.patch +alsa-ua101-reject-too-short-usb-descriptors.patch +alsa-asihpi-fix-potential-oob-array-access-at-reading-cache.patch +net-wwan-iosm-fix-potential-memory-leaks-in-ipc_imem_init.patch +bluetooth-bnep-fix-uaf-read-of-dev-name.patch +bluetooth-hci_uart-fix-uafs-and-race-conditions-in-close-and-init-paths.patch +phonet-pep-disable-bh-around-forwarded-sk_receive_skb.patch +net-bcmgenet-keep-rbuf-eee-pm-disabled.patch +netfilter-ip6t_hbh-reject-oversized-option-lists.patch +netfilter-nf_queue-hold-bridge-skb-dev-while-queued.patch +netfilter-ipset-stop-hash-range-iteration-at-end.patch diff --git a/queue-5.15/sysfs-don-t-remove-existing-directory-on-update-failure.patch b/queue-5.15/sysfs-don-t-remove-existing-directory-on-update-failure.patch new file mode 100644 index 0000000000..e7a6a41ea1 --- /dev/null +++ b/queue-5.15/sysfs-don-t-remove-existing-directory-on-update-failure.patch @@ -0,0 +1,43 @@ +From 237557b8a81ab948e8332f7c0058e758f081c0a3 Mon Sep 17 00:00:00 2001 +From: Greg Kroah-Hartman +Date: Wed, 20 May 2026 15:05:04 +0200 +Subject: sysfs: don't remove existing directory on update failure + +From: Greg Kroah-Hartman + +commit 237557b8a81ab948e8332f7c0058e758f081c0a3 upstream. + +When sysfs_update_group() is called for a named group and create_files() +fails (e.g. -ENOMEM), internal_create_group() calls kernfs_remove(kn) on +the group directory. In the update path, kn was obtained via +kernfs_find_and_get() and refers to a directory that already existed +before this call. Removing it silently destroys a sysfs group that the +caller did not create. + +Only remove the directory if we created it ourselves. On update failure +the directory remains as it is left empty by remove_files() inside +create_files(), but can be repopulated by a retry. + +Cc: Rajat Jain +Fixes: c855cf2759d2 ("sysfs: Fix internal_create_group() for named group updates") +Cc: stable +Assisted-by: gkh_clanker_t1000 +Reviewed-by: Rafael J. Wysocki (Intel) +Reviewed-by: Danilo Krummrich +Link: https://patch.msgid.link/2026052003-uniquely-hastily-c093@gregkh +Signed-off-by: Greg Kroah-Hartman +--- + fs/sysfs/group.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/fs/sysfs/group.c ++++ b/fs/sysfs/group.c +@@ -148,7 +148,7 @@ static int internal_create_group(struct + kernfs_get(kn); + error = create_files(kn, kobj, uid, gid, grp, update); + if (error) { +- if (grp->name) ++ if (grp->name && !update) + kernfs_remove(kn); + } + kernfs_put(kn);