From: Greg Kroah-Hartman Date: Thu, 28 May 2026 08:46:03 +0000 (+0200) Subject: 6.1-stable patches X-Git-Tag: v5.10.258~44 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=945f692d7162856c661d1055c98a18b632a7addd;p=thirdparty%2Fkernel%2Fstable-queue.git 6.1-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-fix-uaf-in-l2cap_sock_cleanup_listen-vs-l2cap_conn_del.patch bluetooth-hci_uart-fix-uafs-and-race-conditions-in-close-and-init-paths.patch bluetooth-iso-drop-iso_end-frames-received-without-prior-iso_start.patch bluetooth-mgmt-validate-add-extended-advertising-data-length.patch hwmon-pmbus-adm1266-widen-blackbox-info-buffer-to-i2c_smbus_block_max.patch net-bcmgenet-keep-rbuf-eee-pm-disabled.patch net-ifb-report-ethtool-stats-over-num_tx_queues.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-6.1/alsa-asihpi-fix-potential-oob-array-access-at-reading-cache.patch b/queue-6.1/alsa-asihpi-fix-potential-oob-array-access-at-reading-cache.patch new file mode 100644 index 0000000000..c6877a4a2b --- /dev/null +++ b/queue-6.1/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-6.1/alsa-ua101-reject-too-short-usb-descriptors.patch b/queue-6.1/alsa-ua101-reject-too-short-usb-descriptors.patch new file mode 100644 index 0000000000..25c42706ab --- /dev/null +++ b/queue-6.1/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-6.1/bluetooth-bnep-fix-uaf-read-of-dev-name.patch b/queue-6.1/bluetooth-bnep-fix-uaf-read-of-dev-name.patch new file mode 100644 index 0000000000..6a21f2441e --- /dev/null +++ b/queue-6.1/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-6.1/bluetooth-fix-uaf-in-l2cap_sock_cleanup_listen-vs-l2cap_conn_del.patch b/queue-6.1/bluetooth-fix-uaf-in-l2cap_sock_cleanup_listen-vs-l2cap_conn_del.patch new file mode 100644 index 0000000000..0de3058eb1 --- /dev/null +++ b/queue-6.1/bluetooth-fix-uaf-in-l2cap_sock_cleanup_listen-vs-l2cap_conn_del.patch @@ -0,0 +1,236 @@ +From ab1513597c6cf17cd1ad2a21e3b045421b48e022 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Safa=20Karaku=C5=9F?= +Date: Sat, 16 May 2026 21:15:04 +0300 +Subject: Bluetooth: fix UAF in l2cap_sock_cleanup_listen() vs l2cap_conn_del() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Safa Karakuş + +commit ab1513597c6cf17cd1ad2a21e3b045421b48e022 upstream. + +bt_accept_dequeue() unlinks a not-yet-accepted child from the parent +accept queue and release_sock()s it before returning, so the returned +sk has no caller reference and is unlocked. + +l2cap_sock_cleanup_listen() walks these children on listening-socket +close. A concurrent HCI disconnect drives hci_rx_work -> +l2cap_conn_del() which runs l2cap_chan_del() + l2cap_sock_kill() and +frees the child sk and its l2cap_chan; cleanup_listen() then uses both: + + BUG: KASAN: slab-use-after-free in l2cap_sock_kill + l2cap_sock_kill / l2cap_sock_cleanup_listen / __x64_sys_close + Freed by: l2cap_conn_del -> l2cap_sock_close_cb -> l2cap_sock_kill + +This is distinct from the two fixes already in this area: commit +e83f5e24da741 ("Bluetooth: serialize accept_q access") serialises the +accept_q list/poll and takes temporary refs inside bt_accept_dequeue(), +and CVE-2025-39860 serialises the userspace close()/accept() race by +calling cleanup_listen() under lock_sock() in l2cap_sock_release(). +Neither covers l2cap_conn_del() running from hci_rx_work, so this UAF +still reproduces on current bluetooth/master. + +Take the reference at the source: bt_accept_dequeue() does sock_hold() +while sk is still locked, before release_sock(); callers sock_put(). +cleanup_listen() pins the chan with l2cap_chan_hold_unless_zero() under +a brief child sk lock (serialising vs l2cap_sock_teardown_cb()), drops +it before l2cap_chan_lock(), and skips a duplicate l2cap_sock_kill() on +SOCK_DEAD. conn->lock is not taken here: cleanup_listen() runs under +the parent sk lock and that would invert +conn->lock -> chan->lock -> sk_lock (lockdep). + +KASAN/SMP: an unprivileged listen/close vs HCI-disconnect race produced +12 use-after-free reports per run before this change; 0, and no lockdep +report, over 1600+ raced iterations after it on bluetooth/master. + +Fixes: 15f02b910562 ("Bluetooth: L2CAP: Add initial code for Enhanced Credit Based Mode") +Cc: stable@vger.kernel.org +Reported-by: Siwei Zhang +Reviewed-by: Siwei Zhang +Signed-off-by: Safa Karakuş +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Greg Kroah-Hartman +--- + net/bluetooth/af_bluetooth.c | 10 ++++++++ + net/bluetooth/iso.c | 9 ++++++- + net/bluetooth/l2cap_sock.c | 51 +++++++++++++++++++++++++++++++++++++------ + net/bluetooth/rfcomm/sock.c | 9 ++++++- + net/bluetooth/sco.c | 9 ++++++- + 5 files changed, 78 insertions(+), 10 deletions(-) + +--- a/net/bluetooth/af_bluetooth.c ++++ b/net/bluetooth/af_bluetooth.c +@@ -282,6 +282,16 @@ restart: + if (newsock) + sock_graft(sk, newsock); + ++ /* Hand the caller a reference taken while sk is ++ * still locked. bt_accept_unlink() just dropped ++ * the accept-queue reference; without this hold a ++ * concurrent teardown (e.g. l2cap_conn_del() -> ++ * l2cap_sock_kill()) could free sk between ++ * release_sock() and the caller using it. Every ++ * caller drops this with sock_put() when done. ++ */ ++ sock_hold(sk); ++ + release_sock(sk); + return sk; + } +--- a/net/bluetooth/iso.c ++++ b/net/bluetooth/iso.c +@@ -564,6 +564,8 @@ static void iso_sock_cleanup_listen(stru + while ((sk = bt_accept_dequeue(parent, NULL))) { + iso_sock_close(sk); + iso_sock_kill(sk); ++ /* Drop the reference handed back by bt_accept_dequeue(). */ ++ sock_put(sk); + } + + parent->sk_state = BT_CLOSED; +@@ -990,8 +992,13 @@ static int iso_sock_accept(struct socket + } + + ch = bt_accept_dequeue(sk, newsock); +- if (ch) ++ if (ch) { ++ /* Drop the bridging ref from bt_accept_dequeue(); ++ * the grafted socket keeps ch alive from here. ++ */ ++ sock_put(ch); + break; ++ } + + if (!timeo) { + err = -EAGAIN; +--- a/net/bluetooth/l2cap_sock.c ++++ b/net/bluetooth/l2cap_sock.c +@@ -367,8 +367,13 @@ static int l2cap_sock_accept(struct sock + } + + nsk = bt_accept_dequeue(sk, newsock); +- if (nsk) ++ if (nsk) { ++ /* Drop the bridging ref from bt_accept_dequeue(); ++ * the grafted socket keeps nsk alive from here. ++ */ ++ sock_put(nsk); + break; ++ } + + if (!timeo) { + err = -EAGAIN; +@@ -1477,22 +1482,54 @@ static void l2cap_sock_cleanup_listen(st + BT_DBG("parent %p state %s", parent, + state_to_string(parent->sk_state)); + +- /* Close not yet accepted channels */ ++ /* Close not yet accepted channels. ++ * ++ * bt_accept_dequeue() now returns sk with an extra reference held ++ * (taken while sk was still locked) so a concurrent l2cap_conn_del() ++ * -> l2cap_sock_kill() cannot free sk under us. ++ * ++ * cleanup_listen() runs under the parent sk lock, so unlike ++ * l2cap_sock_shutdown() we must NOT take conn->lock here: that would ++ * establish sk_lock -> conn->lock and invert the established ++ * conn->lock -> chan->lock -> sk_lock order (lockdep deadlock). ++ * ++ * Instead, briefly take the child sk lock to fetch and pin its chan. ++ * l2cap_conn_del() reaches the chan free only via ++ * l2cap_chan_del() -> l2cap_sock_teardown_cb(), which itself takes ++ * the child sk lock; holding it across l2cap_chan_hold_unless_zero() ++ * therefore guarantees the chan cannot be freed while we read and ++ * pin it (hold_unless_zero() additionally skips a chan already past ++ * its last reference). We then drop the sk lock before taking ++ * chan->lock, so sk and chan locks are never held together. ++ */ + while ((sk = bt_accept_dequeue(parent, NULL))) { +- struct l2cap_chan *chan = l2cap_pi(sk)->chan; ++ struct l2cap_chan *chan; ++ ++ lock_sock_nested(sk, L2CAP_NESTING_NORMAL); ++ chan = l2cap_chan_hold_unless_zero(l2cap_pi(sk)->chan); ++ release_sock(sk); ++ if (!chan) { ++ /* l2cap_conn_del() already tearing this child down */ ++ sock_put(sk); ++ continue; ++ } + + BT_DBG("child chan %p state %s", chan, + state_to_string(chan->state)); + +- l2cap_chan_hold(chan); + l2cap_chan_lock(chan); +- + __clear_chan_timer(chan); + l2cap_chan_close(chan, ECONNRESET); +- l2cap_sock_kill(sk); +- ++ /* l2cap_conn_del() may already have killed this socket ++ * (it sets SOCK_DEAD); skip the duplicate to avoid a ++ * double sock_put()/l2cap_chan_put(). ++ */ ++ if (!sock_flag(sk, SOCK_DEAD)) ++ l2cap_sock_kill(sk); + l2cap_chan_unlock(chan); ++ + l2cap_chan_put(chan); ++ sock_put(sk); + } + } + +--- a/net/bluetooth/rfcomm/sock.c ++++ b/net/bluetooth/rfcomm/sock.c +@@ -180,6 +180,8 @@ static void rfcomm_sock_cleanup_listen(s + while ((sk = bt_accept_dequeue(parent, NULL))) { + rfcomm_sock_close(sk); + rfcomm_sock_kill(sk); ++ /* Drop the reference handed back by bt_accept_dequeue(). */ ++ sock_put(sk); + } + + parent->sk_state = BT_CLOSED; +@@ -496,8 +498,13 @@ static int rfcomm_sock_accept(struct soc + } + + nsk = bt_accept_dequeue(sk, newsock); +- if (nsk) ++ if (nsk) { ++ /* Drop the bridging ref from bt_accept_dequeue(); ++ * the grafted socket keeps nsk alive from here. ++ */ ++ sock_put(nsk); + break; ++ } + + if (!timeo) { + err = -EAGAIN; +--- a/net/bluetooth/sco.c ++++ b/net/bluetooth/sco.c +@@ -433,6 +433,8 @@ static void sco_sock_cleanup_listen(stru + while ((sk = bt_accept_dequeue(parent, NULL))) { + sco_sock_close(sk); + sco_sock_kill(sk); ++ /* Drop the reference handed back by bt_accept_dequeue(). */ ++ sock_put(sk); + } + + parent->sk_state = BT_CLOSED; +@@ -716,8 +718,13 @@ static int sco_sock_accept(struct socket + } + + ch = bt_accept_dequeue(sk, newsock); +- if (ch) ++ if (ch) { ++ /* Drop the bridging ref from bt_accept_dequeue(); ++ * the grafted socket keeps ch alive from here. ++ */ ++ sock_put(ch); + break; ++ } + + if (!timeo) { + err = -EAGAIN; diff --git a/queue-6.1/bluetooth-hci_uart-fix-uafs-and-race-conditions-in-close-and-init-paths.patch b/queue-6.1/bluetooth-hci_uart-fix-uafs-and-race-conditions-in-close-and-init-paths.patch new file mode 100644 index 0000000000..7127be84a8 --- /dev/null +++ b/queue-6.1/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; +@@ -528,6 +540,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); + +@@ -537,24 +550,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); + +@@ -622,11 +649,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); + } + +@@ -697,6 +725,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-6.1/bluetooth-iso-drop-iso_end-frames-received-without-prior-iso_start.patch b/queue-6.1/bluetooth-iso-drop-iso_end-frames-received-without-prior-iso_start.patch new file mode 100644 index 0000000000..22ba904cb4 --- /dev/null +++ b/queue-6.1/bluetooth-iso-drop-iso_end-frames-received-without-prior-iso_start.patch @@ -0,0 +1,47 @@ +From 84c24fb151fc1179355296d7ff29129ac7c42129 Mon Sep 17 00:00:00 2001 +From: David Carlier +Date: Fri, 15 May 2026 07:25:25 +0100 +Subject: Bluetooth: ISO: drop ISO_END frames received without prior ISO_START + +From: David Carlier + +commit 84c24fb151fc1179355296d7ff29129ac7c42129 upstream. + +ISO data PDUs carry a packet-boundary flag indicating START, CONT, END +or SINGLE. The ISO_CONT branch of iso_recv() guards against a missing +ISO_START by checking conn->rx_len before touching conn->rx_skb, but +ISO_END does not. + +If a peer sends an ISO_END as the first packet on a fresh ISO +connection, conn->rx_skb is still NULL and conn->rx_len is zero, so +skb_put(conn->rx_skb, ...) dereferences NULL and oopses. For BIS, +where receivers sync to a broadcaster without pairing, any broadcaster +on the air can trigger this. + +Mirror the ISO_CONT check at the top of ISO_END so a stray end fragment +is logged and dropped instead of crashing the host. + +Fixes: ccf74f2390d6 ("Bluetooth: Add BTPROTO_ISO socket type") +Cc: stable@vger.kernel.org +Assisted-by: Claude:claude-opus-4-7 +Signed-off-by: David Carlier +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Greg Kroah-Hartman +--- + net/bluetooth/iso.c | 5 +++++ + 1 file changed, 5 insertions(+) + +--- a/net/bluetooth/iso.c ++++ b/net/bluetooth/iso.c +@@ -1771,6 +1771,11 @@ void iso_recv(struct hci_conn *hcon, str + break; + + case ISO_END: ++ if (!conn->rx_len) { ++ BT_ERR("Unexpected end frame (len %d)", skb->len); ++ goto drop; ++ } ++ + skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len), + skb->len); + conn->rx_len -= skb->len; diff --git a/queue-6.1/bluetooth-mgmt-validate-add-extended-advertising-data-length.patch b/queue-6.1/bluetooth-mgmt-validate-add-extended-advertising-data-length.patch new file mode 100644 index 0000000000..225898ecc7 --- /dev/null +++ b/queue-6.1/bluetooth-mgmt-validate-add-extended-advertising-data-length.patch @@ -0,0 +1,54 @@ +From d3f7d17960ed50df3a6709c5158caff989c8c905 Mon Sep 17 00:00:00 2001 +From: Michael Bommarito +Date: Fri, 15 May 2026 10:38:19 -0400 +Subject: Bluetooth: MGMT: validate Add Extended Advertising Data length + +From: Michael Bommarito + +commit d3f7d17960ed50df3a6709c5158caff989c8c905 upstream. + +MGMT_OP_ADD_EXT_ADV_DATA is registered as a variable-length command, +with MGMT_ADD_EXT_ADV_DATA_SIZE as the fixed header size. The handler +then uses cp->adv_data_len and cp->scan_rsp_len to validate and copy +cp->data, but it never checks that those bytes are part of the mgmt +command payload. + +A short command can therefore make add_ext_adv_data() pass an +out-of-bounds pointer into tlv_data_is_valid(). If the bytes beyond +the command buffer are addressable, they can also be copied into the +advertising instance as scan response data, where the caller can read +them back via MGMT_OP_GET_ADV_INSTANCE. The trigger requires +CAP_NET_ADMIN in the initial user namespace; KASAN reports an 8-byte +slab-out-of-bounds read. + +Reject commands whose length does not match the fixed header plus both +advertising data lengths before parsing cp->data. + +Fixes: 12410572833a ("Bluetooth: Break add adv into two mgmt commands") +Cc: stable@vger.kernel.org +Assisted-by: Claude:claude-opus-4-7 +Signed-off-by: Michael Bommarito +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Greg Kroah-Hartman +--- + net/bluetooth/mgmt.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +--- a/net/bluetooth/mgmt.c ++++ b/net/bluetooth/mgmt.c +@@ -9075,9 +9075,15 @@ static int add_ext_adv_data(struct sock + struct adv_info *adv_instance; + int err = 0; + struct mgmt_pending_cmd *cmd; ++ u16 expected_len; + + BT_DBG("%s", hdev->name); + ++ expected_len = struct_size(cp, data, cp->adv_data_len + cp->scan_rsp_len); ++ if (expected_len != data_len) ++ return mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_EXT_ADV_DATA, ++ MGMT_STATUS_INVALID_PARAMS); ++ + hci_dev_lock(hdev); + + adv_instance = hci_find_adv_instance(hdev, cp->instance); diff --git a/queue-6.1/hwmon-pmbus-adm1266-widen-blackbox-info-buffer-to-i2c_smbus_block_max.patch b/queue-6.1/hwmon-pmbus-adm1266-widen-blackbox-info-buffer-to-i2c_smbus_block_max.patch new file mode 100644 index 0000000000..4fd12e8541 --- /dev/null +++ b/queue-6.1/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-6.1/net-bcmgenet-keep-rbuf-eee-pm-disabled.patch b/queue-6.1/net-bcmgenet-keep-rbuf-eee-pm-disabled.patch new file mode 100644 index 0000000000..772fcc096e --- /dev/null +++ b/queue-6.1/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 +@@ -1344,13 +1344,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-6.1/net-ifb-report-ethtool-stats-over-num_tx_queues.patch b/queue-6.1/net-ifb-report-ethtool-stats-over-num_tx_queues.patch new file mode 100644 index 0000000000..9770fe349b --- /dev/null +++ b/queue-6.1/net-ifb-report-ethtool-stats-over-num_tx_queues.patch @@ -0,0 +1,101 @@ +From 5db89c99566fc4728cc92e941d8e1975711e24b5 Mon Sep 17 00:00:00 2001 +From: Michael Bommarito +Date: Wed, 13 May 2026 21:37:39 -0400 +Subject: net: ifb: report ethtool stats over num_tx_queues + +From: Michael Bommarito + +commit 5db89c99566fc4728cc92e941d8e1975711e24b5 upstream. + +ifb_dev_init() allocates dp->tx_private to dev->num_tx_queues +entries via kzalloc_objs(*txp, dev->num_tx_queues). Both IFB +per-queue RX and TX stats live in those entries: ifb_xmit() updates +txp->rx_stats using the skb queue mapping, ifb_ri_tasklet() updates +txp->tx_stats, and ifb_stats64() aggregates both over +dev->num_tx_queues. + +The ethtool stats callbacks instead size and walk the per-queue +stats with dev->real_num_rx_queues and dev->real_num_tx_queues. With +an asymmetric device where the RX queue count exceeds the TX queue +count, for example: + + ip link add name ifb10 numtxqueues 1 numrxqueues 8 type ifb + ethtool -S ifb10 + +ifb_get_ethtool_stats() indexes past the tx_private allocation and +copies adjacent slab data through ETHTOOL_GSTATS. + +Use dev->num_tx_queues consistently for the stats strings, the +stats count, and the stats data walks. This reports one RX stats +group and one TX stats group for each backing ifb_q_private entry, +which is the queue set IFB can actually populate. + +Reproduced under UML+KASAN at v7.1-rc2: + + BUG: KASAN: slab-out-of-bounds in ifb_fill_stats_data+0x3c/0xae + Read of size 8 at addr 0000000062dbd228 by task ethtool/36 + ifb_fill_stats_data+0x3c/0xae + ifb_get_ethtool_stats+0xc0/0x129 + __dev_ethtool+0x1ca5/0x363c + dev_ethtool+0x123/0x1b3 + dev_ioctl+0x56c/0x744 + sock_do_ioctl+0x15f/0x1b2 + sock_ioctl+0x4d5/0x50a + sys_ioctl+0xd8b/0xde9 + +With the patch applied, the same UML+KASAN repro is silent and +ethtool -S ifb10 reports only the stats backed by the single +allocated tx_private entry. + +Fixes: a21ee5b2fcb8 ("net: ifb: support ethtools stats") +Cc: stable@vger.kernel.org +Signed-off-by: Michael Bommarito +Link: https://patch.msgid.link/20260514013739.3549624-1-michael.bommarito@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/ifb.c | 11 +++++------ + 1 file changed, 5 insertions(+), 6 deletions(-) + +--- a/drivers/net/ifb.c ++++ b/drivers/net/ifb.c +@@ -211,12 +211,12 @@ static void ifb_get_strings(struct net_d + + switch (stringset) { + case ETH_SS_STATS: +- for (i = 0; i < dev->real_num_rx_queues; i++) ++ for (i = 0; i < dev->num_tx_queues; i++) + for (j = 0; j < IFB_Q_STATS_LEN; j++) + ethtool_sprintf(&p, "rx_queue_%u_%.18s", + i, ifb_q_stats_desc[j].desc); + +- for (i = 0; i < dev->real_num_tx_queues; i++) ++ for (i = 0; i < dev->num_tx_queues; i++) + for (j = 0; j < IFB_Q_STATS_LEN; j++) + ethtool_sprintf(&p, "tx_queue_%u_%.18s", + i, ifb_q_stats_desc[j].desc); +@@ -229,8 +229,7 @@ static int ifb_get_sset_count(struct net + { + switch (sset) { + case ETH_SS_STATS: +- return IFB_Q_STATS_LEN * (dev->real_num_rx_queues + +- dev->real_num_tx_queues); ++ return IFB_Q_STATS_LEN * dev->num_tx_queues * 2; + default: + return -EOPNOTSUPP; + } +@@ -262,12 +261,12 @@ static void ifb_get_ethtool_stats(struct + struct ifb_q_private *txp; + int i; + +- for (i = 0; i < dev->real_num_rx_queues; i++) { ++ for (i = 0; i < dev->num_tx_queues; i++) { + txp = dp->tx_private + i; + ifb_fill_stats_data(&data, &txp->rx_stats); + } + +- for (i = 0; i < dev->real_num_tx_queues; i++) { ++ for (i = 0; i < dev->num_tx_queues; i++) { + txp = dp->tx_private + i; + ifb_fill_stats_data(&data, &txp->tx_stats); + } diff --git a/queue-6.1/net-wwan-iosm-fix-potential-memory-leaks-in-ipc_imem_init.patch b/queue-6.1/net-wwan-iosm-fix-potential-memory-leaks-in-ipc_imem_init.patch new file mode 100644 index 0000000000..6e3f698a55 --- /dev/null +++ b/queue-6.1/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 +@@ -1423,6 +1423,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-6.1/netfilter-ip6t_hbh-reject-oversized-option-lists.patch b/queue-6.1/netfilter-ip6t_hbh-reject-oversized-option-lists.patch new file mode 100644 index 0000000000..89f34c5f05 --- /dev/null +++ b/queue-6.1/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-6.1/netfilter-ipset-stop-hash-range-iteration-at-end.patch b/queue-6.1/netfilter-ipset-stop-hash-range-iteration-at-end.patch new file mode 100644 index 0000000000..2a9436be64 --- /dev/null +++ b/queue-6.1/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-6.1/netfilter-nf_queue-hold-bridge-skb-dev-while-queued.patch b/queue-6.1/netfilter-nf_queue-hold-bridge-skb-dev-while-queued.patch new file mode 100644 index 0000000000..e5aaa367cf --- /dev/null +++ b/queue-6.1/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) +@@ -101,6 +102,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); + +@@ -201,11 +203,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 +@@ -951,6 +951,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-6.1/phonet-pep-disable-bh-around-forwarded-sk_receive_skb.patch b/queue-6.1/phonet-pep-disable-bh-around-forwarded-sk_receive_skb.patch new file mode 100644 index 0000000000..ebcd6077a1 --- /dev/null +++ b/queue-6.1/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-6.1/series b/queue-6.1/series index e394830c4e..298a527650 100644 --- a/queue-6.1/series +++ b/queue-6.1/series @@ -837,3 +837,19 @@ revert-x86-vdso-fix-output-operand-size-of-rdpid.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-fix-uaf-in-l2cap_sock_cleanup_listen-vs-l2cap_conn_del.patch +bluetooth-iso-drop-iso_end-frames-received-without-prior-iso_start.patch +bluetooth-bnep-fix-uaf-read-of-dev-name.patch +bluetooth-hci_uart-fix-uafs-and-race-conditions-in-close-and-init-paths.patch +bluetooth-mgmt-validate-add-extended-advertising-data-length.patch +phonet-pep-disable-bh-around-forwarded-sk_receive_skb.patch +net-bcmgenet-keep-rbuf-eee-pm-disabled.patch +net-ifb-report-ethtool-stats-over-num_tx_queues.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-6.1/sysfs-don-t-remove-existing-directory-on-update-failure.patch b/queue-6.1/sysfs-don-t-remove-existing-directory-on-update-failure.patch new file mode 100644 index 0000000000..a77335e6a1 --- /dev/null +++ b/queue-6.1/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 +@@ -147,7 +147,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);