summaryrefslogtreecommitdiff
path: root/net
AgeCommit message (Collapse)AuthorFilesLines
2026-08-25tls: device: fix out-of-bounds write in tls_append_frag()Jiayuan Chen1-1/+2
Found with syzkaller and a local syzbot instance running on top of a netdevsim TLS offload emulation; tls_device.c is otherwise only reachable on a machine with a NIC that implements the offload. tls_push_data() only checks whether the open record still has room for another frag at the bottom of its loop, and the MSG_MORE early break skips that check. The record survives to the next syscall with the frag count it already had, and tls_append_frag() does not check either, so with TLS_TX_ZEROCOPY_RO every splice(SPLICE_F_MORE) of a byte or two adds a non-coalescing pipe page and num_frags walks off the end of tls_record_info.frags[MAX_SKB_FRAGS]. Once the record is pushed, tls_push_record() runs the same index over sg_tx_data[MAX_SKB_FRAGS] and the sg_set_page() writes land on the destruct_work that follows it, which the workqueue then calls. The byte limit is fine because copy drops to 0 and the loop falls through to the same check; the frag count has no such feedback. Push the record rather than keep a full one open, which is what a plain TCP socket does - tcp_sendmsg_locked() uses tcp_mark_push() and new_segment in both the copy and the MSG_SPLICE_PAGES paths, and tls_sw already sets full_record when the sk_msg ring fills up, MSG_MORE or not. BUG: KASAN: slab-out-of-bounds in tls_append_frag ( net/tls/tls_device.c:269) Write of size 8 at addr ffff8881104d1530 by task tls_oob/450 CPU: 2 UID: 0 PID: 450 Comm: tls_oob Not tainted 7.2.0-rc7+ #329 PREEMPT Call Trace: <TASK> dump_stack_lvl (lib/dump_stack.c:94 lib/dump_stack.c:120) print_report (mm/kasan/report.c:378 mm/kasan/report.c:482) kasan_report (mm/kasan/report.c:595) tls_append_frag (net/tls/tls_device.c:269) tls_push_data (net/tls/tls_device.c:518) tls_device_sendmsg (net/tls/tls_device.c:583) inet_sendmsg (net/ipv4/af_inet.c:865) sock_sendmsg (net/socket.c:775 net/socket.c:790 net/socket.c:813) splice_to_socket (fs/splice.c:884) do_splice (fs/splice.c:936 fs/splice.c:1349) __do_splice (fs/splice.c:1431) __x64_sys_splice (fs/splice.c:1634 fs/splice.c:1616) do_syscall_64 (arch/x86/entry/syscall_64.c:63 arch/x86/entry/syscall_64.c:94) entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:121) </TASK> and, once the record is pushed: UBSAN: array-index-out-of-bounds in net/tls/tls_device.c:300:24 index 18 is out of range for type 'skb_frag_t [17]' UBSAN: array-index-out-of-bounds in net/tls/tls_device.c:301:41 index 18 is out of range for type 'scatterlist [17]' UBSAN: array-index-out-of-bounds in net/tls/tls_device.c:302:39 index 18 is out of range for type 'scatterlist [17]' UBSAN: array-index-out-of-bounds in net/tls/tls_device.c:307:38 index 26 is out of range for type 'scatterlist [17]' kernel tried to execute NX-protected page - exploit attempt? (uid: 0) BUG: unable to handle page fault for address: ffffea000411a680 #PF: supervisor instruction fetch in kernel mode #PF: error_code(0x0011) - permissions violation Oops: Oops: 0011 [#1] SMP KASAN PTI Workqueue: ktls_device_destruct 0xffffea000411a680 RIP: 0010:0xffffea000411a680 Call Trace: <TASK> worker_thread (kernel/workqueue.c:3405 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) </TASK> Fixes: e8f69799810c ("net/tls: Add generic NIC offload infrastructure") Cc: stable@vger.kernel.org Signed-off-by: Jiayuan Chen <jiayuan.chen@linux.dev> Link: https://patch.msgid.link/20260823084758.20936-1-jiayuan.chen@linux.dev Signed-off-by: Paolo Abeni <pabeni@redhat.com>
2026-08-25net: skbuff: don't touch shared zerocopy state in skb_tx_error()Norbert Szetei1-1/+4
skb_tx_error() completes the zerocopy uarg and clears SKBFL_ALL_ZEROCOPY, and skb_zcopy_downgrade_managed() clears SKBFL_MANAGED_FRAG_REFS. Both live in skb_shinfo(), which every clone shares, while the caller only owns the reference it is about to drop. Through a clone it tells the producer its pages are free and drops SKBFL_SHARED_FRAG for an skb that is still in flight. Open vSwitch reaches this with a non-last OVS_ACTION_ATTR_RECIRC: clone_execute() sends a skb_clone() into ovs_dp_process_packet() while do_execute_actions() keeps forwarding the original, and skb_clone() does not privatise the frags here -- skb_orphan_frags() returns early on SKBFL_DONT_ORPHAN. A flow miss on the clone then strips the marker from the packet still being forwarded, and a later local ESP delivery decrypts in place over frags it does not own privately. Skip it for a cloned skb. Nothing is lost: skb_release_data() clears the zerocopy state once the last reference to the shared data goes. Fixes: 25121173f7b1 ("skb: api to report errors for zero copy skbs") Cc: stable@vger.kernel.org Suggested-by: Ilya Maximets <i.maximets@ovn.org> Signed-off-by: Norbert Szetei <norbert@doyensec.com> Reviewed-by: Ilya Maximets <i.maximets@ovn.org> Tested-by: Jongmin Jang <payload.jang@gmail.com> Reviewed-by: Willem de Bruijn <willemb@google.com> Link: https://patch.msgid.link/CFAB292A-674B-4C14-BB2C-BB8830AD5659@doyensec.com Signed-off-by: Paolo Abeni <pabeni@redhat.com>
2026-08-25net: skbuff: don't skb_tx_error() the source skb in skb_zerocopy()Norbert Szetei1-1/+0
skb_zerocopy() copies frags from @from into @to. On an skb_orphan_frags() failure it calls skb_tx_error(@from), a destructive operation on the source skb the copy helper does not own. That completes @from's zerocopy uarg and clears SKBFL_ALL_ZEROCOPY, including the SKBFL_SHARED_FRAG page-ownership marker. Both callers already report the failure on their own drop path. nfnetlink_queue does it at nla_put_failure, and Open vSwitch does it in the flow-miss drop arm of ovs_dp_process_packet(), so nothing is lost by dropping it here. On Open vSwitch's OVS_ACTION_ATTR_USERSPACE path the skb is not freed on this error: do_execute_actions() ignores output_userspace()'s return value and, unless the upcall was the last action, keeps forwarding the same skb through the flow's remaining actions. The uarg is completed while that skb is still in flight, telling the producer its buffers are free, and SKBFL_SHARED_FRAG is cleared on an skb the rest of the stack still handles. That flag is what makes esp_input() call skb_cow_data() instead of decrypting in place, so a later local ESP delivery can decrypt over frags the skb does not own privately. Leave error reporting to the callers. Fixes: 36d5fe6a0007 ("core, nfqueue, openvswitch: Orphan frags in skb_zerocopy and handle errors") Cc: stable@vger.kernel.org Suggested-by: Ilya Maximets <i.maximets@ovn.org> Signed-off-by: Norbert Szetei <norbert@doyensec.com> Reviewed-by: Ilya Maximets <i.maximets@ovn.org> Reviewed-by: Willem de Bruijn <willemb@google.com> Link: https://patch.msgid.link/6E3A780D-FB87-421F-9964-B1D457D7D106@doyensec.com Signed-off-by: Paolo Abeni <pabeni@redhat.com>
2026-08-25openvswitch: only skb_tx_error() a packet we are about to dropNorbert Szetei1-2/+1
queue_userspace_packet() borrows the packet skb -- it only copies it into a private netlink message (user_skb) and does not own it; on return do_execute_actions() keeps forwarding it through the flow's remaining actions. Its error path nevertheless calls skb_tx_error(skb), which via skb_zcopy_clear() does skb_shinfo(skb)->flags &= ~SKBFL_ALL_ZEROCOPY, stripping SKBFL_SHARED_FRAG from that live skb (skb_tx_error()'s kerneldoc says "skb must be freed afterwards"). For a MSG_ZEROCOPY skb carrying page-cache frags, SKBFL_SHARED_FRAG is what makes esp_input() skb_cow_data() before in-place AEAD; once it is stripped a later local ESP-in-UDP delivery decrypts in place over pages the sender does not own -- an unprivileged page-cache write (the "Fragnesia" primitive). do_execute_actions() ignores output_userspace()'s return value, so any action after a failed USERSPACE upcall inherits the stripped skb. Move the skb_tx_error() to the flow-miss drop path - the "default" branch of ovs_dp_process_packet()'s switch(error), before kfree_skb(). The call has been here since commit 36d5fe6a0007 ("core, nfqueue, openvswitch: Orphan frags in skb_zerocopy and handle errors") but was harmless until esp_input() began relying on SKBFL_SHARED_FRAG to gate in-place decrypt; only then did stripping it on a still-forwarded skb become a page-cache write primitive. Fixes: 36d5fe6a0007 ("core, nfqueue, openvswitch: Orphan frags in skb_zerocopy and handle errors") Fixes: f4c50a4034e6 ("xfrm: esp: avoid in-place decrypt on shared skb frags") Cc: stable@vger.kernel.org Assisted-by: Claude:claude-opus-5 Signed-off-by: Norbert Szetei <norbert@doyensec.com> Reviewed-by: Ilya Maximets <i.maximets@ovn.org> Tested-by: Jongmin Jang <payload.jang@gmail.com> Link: https://patch.msgid.link/55A52703-7548-4A55-A9CE-2A37145BDCAD@doyensec.com Signed-off-by: Paolo Abeni <pabeni@redhat.com>
2026-08-24Merge tag 'for-net-2026-08-24' of ↵Jakub Kicinski9-40/+131
git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth Luiz Augusto von Dentz says: ==================== bluetooth pull request for net: Core: - hci_core: use skb_get() instead of skb_clone() for req_skb - hci_conn: re-enable advertising only for peripheral role - hci_event: clear HCI_LE_ADV only on a created connection - hci_sync: Clear HCI_CMD_PENDING when dropping the last request - hci_sync: add conditional locking annotations - hci_sync: do not leak an hci_conn when a second LE connect is rejected - eir: Fix OOB read in eir_get_service_data() - mgmt: fix 'hdev->discovery.uuids' NULL dereference - L2CAP: access chan->conn safely in get/setsockopt - L2CAP: reject accept queue add unless BT_LISTEN - L2CAP: fix race l2cap_sock_cleanup_listen() vs. put_chan - RFCOMM: serialize security confirmation handling - RFCOMM: serialize session teardown - RFCOMM: Validate MTU in rfcomm_apply_pn() to prevent infinite loop - ISO: fix use-after-free of listener socket in iso_conn_ready Drivers: - btnxpuart: Validate the FW dump header length - btnxpuart: Check remote M.2 connector availability before pwrseq - btmtksdio: Take exclusive ownership of the SKB before TX - btmtksdio: Fix out-of-bounds DMA read in the TX path - hci_uart: Fix false success return in hci_uart_setup() - hci_bcm: fix usage_count leak when autosuspend_delay is negative - hci_h5: fix usage_count leak when autosuspend_delay is negative - hci_intel: fix usage_count leak when autosuspend_delay is negative - btmtk: Do not report success when subsys reset fails - btmtk: Do not discard the subsystem reset timeout - btusb: limit RTL8761B BROKEN_EXT_SCAN quirk to 0bda:a728 - hci_bcm4377: Ignore reserved PHY in ext adv reports on BCM4378 * tag 'for-net-2026-08-24' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth: (27 commits) Bluetooth: RFCOMM: serialize session teardown Bluetooth: do not leak an hci_conn when a second LE connect is rejected Bluetooth: RFCOMM: serialize security confirmation handling Bluetooth: btusb: limit RTL8761B BROKEN_EXT_SCAN quirk to 0bda:a728 Bluetooth: hci_uart: Fix false success return in hci_uart_setup() Bluetooth: RFCOMM: Validate MTU in rfcomm_apply_pn() to prevent infinite loop Bluetooth: ISO: fix use-after-free of listener socket in iso_conn_ready Bluetooth: hci_core: use skb_get() instead of skb_clone() for req_skb Bluetooth: hci_event: clear HCI_LE_ADV only on a created connection Bluetooth: hci_conn: re-enable advertising only for peripheral role Bluetooth: hci_bcm4377: Ignore reserved PHY in ext adv reports on BCM4378 Bluetooth: eir: Fix OOB read in eir_get_service_data() Bluetooth: btnxpuart: Validate the FW dump header length Bluetooth: hci_sync: add conditional locking annotations Bluetooth: btnxpuart: Check remote M.2 connector availability before pwrseq Bluetooth: btmtksdio: Fix out-of-bounds DMA read in the TX path Bluetooth: btmtksdio: Take exclusive ownership of the SKB before TX Bluetooth: btmtk: Do not discard the subsystem reset timeout Bluetooth: btmtk: Do not report success when subsys reset fails Bluetooth: L2CAP: fix race l2cap_sock_cleanup_listen() vs. put_chan ... ==================== Link: https://patch.msgid.link/20260824180639.3570348-1-luiz.dentz@gmail.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2026-08-24net/iucv: filter frames in afiucv_hs_rcv() by ingress deviceAlexandra Winter1-0/+2
afiucv_hs_rcv() selects a socket from iucv_sk_list by matching four 8-byte name fields in the transport header alone. No check is made against the net_device the frame arrived on. This can cause a frame arriving on any netdev to be delivered to an AF_IUCV socket. Three problems follow. First, a frame arriving over HiperSockets can be delivered to a socket bound to the classic z/VM IUCV transport, which has iucv->hs_dev == NULL. iucv_sock_bind() takes the classic path whenever the requested userid matches iucv_userid, even on a guest that also has a HiperSockets device carrying the same identifier. The child socket created by afiucv_hs_callback_syn() for such a match inherits hs_dev = NULL and transport = AF_IUCV_TRANS_HIPER, so the first send() on it returns -ENODEV. The socket delivered to accept() is unusable. Second, a frame arriving on one netdev can be delivered to a socket bound to a different IQD device. Which can lead to - Accept-queue exhaustion (DoS) - Attacker-controlled peer identity in the child socket - Data injection into existing sockets - Fabric noise on the IQD fabric, where bogus replies are sent - killing established connections Third, all AF_IUCV sockets live in init_net, as iucv_sock_alloc() calls sk_alloc(&init_net, ...). But even frames arriving on netdev devices in a namespace can be delivered to an IUCV socket. So a process in an unprivileged user and network namespace holding only the CAP_NET_RAW capability valid within that namespace can send a raw ETH_P_AF_IUCV frame on its own lo device and have it matched against init_net sockets. Fix all three by skipping any socket whose hs_dev does not match the ingress device. A classic z/VM IUCV socket has hs_dev == NULL; the ingress dev is never NULL, so classic sockets are skipped automatically. An unbound HIPER socket also has hs_dev == NULL and is skipped. A bound HIPER socket is only reachable from the exact IQD device it was bound to. Because hs_dev is always a device in init_net (iucv_sock_bind() scans for_each_netdev_rcu(&init_net, ...) exclusively), a frame whose ingress device belongs to another namespace never matches any socket. Note that AF_IUCV over HiperSockets provides no per-connection authentication: no sequence numbers, no TLS, no nonce. The four name fields identifying a connection are exchanged in plaintext on the shared HiperSockets segment (VCHID). Any host on the same HiperSockets segment could spoof any frame type against an existing connection. That is a protocol-level property unchanged by this patch. The fix reduces the attack surface to peers present on the same HiperSockets segment. Fixes: 3881ac441f64 ("af_iucv: add HiperSockets transport") Cc: stable@vger.kernel.org Co-developed-by: Bryam Vargas <hexlabsecurity@proton.me> Signed-off-by: Alexandra Winter <wintera@linux.ibm.com> Link: https://patch.msgid.link/20260821125501.3718748-1-wintera@linux.ibm.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2026-08-24net/rds: use wq_has_sleeper() in rds_cong_map_updated()Allison Henderson1-2/+2
rds_cong_map_updated() runs after a peer's congestion map has been rewritten (by rds_tcp_cong_recv() and rds_ib_cong_recv(), or the clear-all in the loopback and IB send-completion paths). It bumps rds_cong_generation and then checks waitqueue_active() on map->m_waitq and on rds_poll_waitq to decide whether anyone needs waking. atomic_inc() carries no ordering and waitqueue_active() is a plain load, so nothing orders the map and generation stores before the wait queue reads. The waiters do the mirror image: rds_cong_wait() adds itself to m_waitq and then tests the port bit, and rds_poll() registers on rds_poll_waitq and then reads the generation. That is the store-buffering pattern described above waitqueue_active() in include/linux/wait.h - the updater can observe an empty wait queue while the waiter still observes the port as congested, and no wake-up is issued. rds_cong_wait() is an interruptible sleep with no timeout, so a sender blocked on a congested port stays blocked until the next congestion update from that peer arrives or a signal is delivered. A poll() waiter misses the map-updated notification the same way. Use wq_has_sleeper(), which is waitqueue_active() preceded by the required full barrier, as rds_tcp_state_change() already does for the same pattern. Fixes: 922cb17a5c81 ("RDS: Congestion-handling code") Signed-off-by: Allison Henderson <achender@kernel.org> Reviewed-by: Simon Horman <horms@kernel.org> Link: https://patch.msgid.link/20260822052647.88318-1-achender@kernel.org Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2026-08-24net/sched: act_ife: Only operate on Ethernet framesVictor Nogueira2-11/+35
act_ife encapsulates/decapsulates the original Ethernet header and uses skb->dev->hard_header_len as the length of that header. That is only correct for Ethernet devices: on a device where hard_header_len does not match the L2 header that was actually pulled (PPP reports PPP_HDRLEN while nothing is stripped on ingress), the ingress skb_push()/skb_pull() use the wrong length and can hit skb_under_panic when headroom is tight. IFE is Ethernet-only by design - it builds an outer ethhdr, rewrites h_source/h_dest/h_proto, and calls eth_type_trans() on decode - so instead of trying to make the offsets work for arbitrary link types, simply drop packets that do not carry an Ethernet header. Checking skb->dev->type alone is not enough. We have to cater for a corner case where mirred can redirect an skb from a non-Ethernet device to an Ethernet one, and skb->dev then says nothing about the framing the skb actually has: an skb redirected from ppp0 reaches the target's ingress hook with mac_len 0 and no Ethernet header at all. So at ingress also require mac_len to be ETH_HLEN. On egress mac_len is not maintained, so the device type is all we have; a bogus redirect there yields a malformed frame rather than an out-of-bounds push, and it would be malformed with or without IFE. That corner case is not theoretical - redirecting from ppp0 into a veth that has an ife encode action on its ingress hook panics without this patch: skbuff: skb_under_panic: len:98 put:14 head:ffff88800e410000 data:ffff88800e40fff5 tail:0x57 end:0x640 dev:veth3 kernel BUG at net/core/skbuff.c:214! Call Trace: skb_push (net/core/skbuff.c:224 net/core/skbuff.c:2657) tcf_ife_act (net/sched/act_ife.c:829 net/sched/act_ife.c:874) tc_run (net/core/dev.c:4463) netif_receive_skb (net/core/dev.c:6463 net/core/dev.c:6522) tcf_mirred_to_dev (net/sched/act_mirred.c:248 net/sched/act_mirred.c:328) tcf_mirred_act (net/sched/act_mirred.c:489) tc_run (net/core/dev.c:4463) process_backlog (net/core/dev.c:6728) With Ethernet framing guaranteed, use ETH_HLEN instead of hard_header_len. Fixes: 295a6e06d21e ("net/sched: act_ife: Change to use ife module") Reported-by: vega@nebusec.ai Acked-by: Jamal Hadi Salim <jhs@mojatatu.com> Signed-off-by: Victor Nogueira <victor@mojatatu.com> Link: https://patch.msgid.link/20260821164031.32824-1-victor@mojatatu.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2026-08-24net/smc: fix use-after-free in smc_rx_pipe_buf_release()Hidayath Khan1-6/+5
smc_rx_splice() hands RMB pages to a pipe and takes a socket reference per entry so the smc_sock stays alive until the reader finishes. The connection does not: a concurrent close runs smc_conn_free(), which releases the receive buffer back to the link group pool. smc_rx_pipe_buf_release() tests sk_state before taking the socket lock. The state can change between the test and the lock, and smc_rx_update_cons() then dereferences conn->rmb_desc and walks conn->lgr, which smc_conn_free() has already released. On the is_reg_err path smcr_buf_unuse() frees the descriptor outright, so this is a use-after-free. Take the socket lock first and test conn->freed instead. smc_conn_free() sets that flag before releasing anything, and every caller holds the socket lock. The two paths exclude each other: either the pipe release runs first with everything valid, or it sees the flag and skips the update. Fixes: 9014db202cb7 ("smc: add support for splice()") Cc: stable@vger.kernel.org Reviewed-by: Mahanta Jambigi <mjambigi@linux.ibm.com> Signed-off-by: Hidayath Khan <hidayath@linux.ibm.com> Reviewed-by: Simon Horman <horms@kernel.org> Link: https://patch.msgid.link/20260820074642.966856-3-hidayath@linux.ibm.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2026-08-24net/smc: stop killed, freed and out_of_sync sharing a byteHidayath Khan1-3/+3
The three connection state flags are single-bit bitfields, so they occupy one byte of struct smc_connection and every store to one is a read-modify-write of the other two: u8 killed : 1; u8 freed : 1; u8 out_of_sync : 1; They are not written under a common lock. smc_cdc_msg_validate() sets out_of_sync from the receive tasklet, while smc_conn_kill() sets killed from process context under lock_sock(), and the receive path does not defer to the backlog when the socket is owned -- smc_cdc_msg_recv() takes only bh_lock_sock(). Give each flag its own byte so a store no longer touches its neighbours. All readers test them as booleans and are unchanged. struct smc_connection grows by two bytes. Fixes: b286a0651e44 ("net/smc: handle incoming CDC validation message") Cc: stable@vger.kernel.org Reviewed-by: Mahanta Jambigi <mjambigi@linux.ibm.com> Signed-off-by: Hidayath Khan <hidayath@linux.ibm.com> Reviewed-by: Simon Horman <horms@kernel.org> Link: https://patch.msgid.link/20260820074642.966856-2-hidayath@linux.ibm.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2026-08-24net/smc: fix socket refcount leak in smc_switch_conns()Hidayath Khan1-7/+7
smc_switch_conns() takes a reference on the SMC socket before dropping lgr->conns_lock, so the connection stays alive while the CDC slot is fetched: sock_hold(&smc->sk); read_unlock_bh(&lgr->conns_lock); /* pre-fetch buffer outside of send_lock, might sleep */ rc = smc_cdc_get_free_slot(conn, to_lnk, &wr_buf, NULL, &pend); if (rc) goto err_out; The err_out label only drops the wr_tx link reference, so this early exit returns without the matching sock_put(). The second error exit is not affected, because sock_put() has already run by then. A leaked sk_refcnt means the smc_sock is never destroyed. Its send and receive buffers stay allocated, and for a user socket the reference held on the network namespace is never released, so the netns can no longer be torn down. smc_cdc_get_free_slot() fails when the target link goes down or when the connection has been killed while the switch is in progress. Both are reachable during the link failover this function implements, so the leak is triggered by the same hardware events that make smc_switch_conns() run in the first place. Restructure so there is a single sock_put() covering both outcomes, instead of adding a second one to the error path. Fixes: 95f7f3e7dc6b ("net/smc: improved fix wait on already cleared link") Cc: stable@vger.kernel.org Reviewed-by: Mahanta Jambigi <mjambigi@linux.ibm.com> Reviewed-by: Breno Leitao <leitao@debian.org> Signed-off-by: Hidayath Khan <hidayath@linux.ibm.com> Link: https://patch.msgid.link/20260820144729.1019399-1-hidayath@linux.ibm.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2026-08-24net: l2tp: do not propagate multicast notification errorsZihan Xi1-8/+8
The tunnel create, tunnel modify, session create, and session modify netlink handlers send multicast notifications through helpers that can fail while allocating or encoding a message, or while multicasting it. For tunnel and session create/modify, a notification is sent after the live operation has completed. Returning a best-effort notification error as the command result can therefore report failure for an operation that already committed and can cause callers to retry and accumulate live objects. Keep sending notifications for listener visibility, but do not propagate their best-effort status as the command result. This also keeps the tunnel modify command consistent with the other notification-only paths. Fixes: 33f72e6f0c67 ("l2tp : multicast notification to the registered listeners") Cc: stable@vger.kernel.org Reported-by: Vega <vega@nebusec.ai> Signed-off-by: Zihan Xi <zihanx@nebusec.ai> Reviewed-by: Simon Horman <horms@kernel.org> Link: https://patch.msgid.link/54f48e812ca0424c47ffdb9a8182180921f7e6b2.1787247008.git.zihanx@nebusec.ai Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2026-08-24openvswitch: Fix CT limit teardown use-after-freeYuqi Xu4-46/+98
Packet processing uses CT limit state under RCU, while netns teardown frees that state under ovs_mutex. The CT limit pointer was neither removed from readers nor protected by a grace period, allowing packet processing to dereference the freed state. An unprivileged user can trigger this bug from a user and network namespace, causing a slab-use-after-free in ovs_ct_execute() when the netns is torn down. Publish the CT limit pointer through RCU, remove it before teardown, and wait for readers before freeing its contents. Keep ovs_mutex around individual CT limit updates, and use the RCU read-side lock while GET traverses the RCU-protected limit lists. Netns teardown detaches the RCU-protected CT limit state in the pernet .pre_exit callback while holding ovs_mutex. The pernet core guarantees an RCU grace period between the .pre_exit and .exit callbacks, so the .exit callback completes the teardown without adding any extra synchronization. The netlink command handlers do not need NULL checks because the userspace netlink socket holds an active reference to its network namespace while a request is processed. The per-netns exit path therefore cannot run concurrently with SET, DEL, or GET for that socket's namespace. Fixes: 11efd5cb04a1 ("openvswitch: Support conntrack zone limit") Cc: stable@vger.kernel.org Reported-by: Vega <vega@nebusec.ai> Link: https://lore.kernel.org/all/cover.1784711445.git.xuyuqiabc@gmail.com Co-developed-by: Nan Li <tonanli66@gmail.com> Signed-off-by: Nan Li <tonanli66@gmail.com> Signed-off-by: Yuqi Xu <xuyuqiabc@gmail.com> Reviewed-by: Ren Wei <enjou1224z@gmail.com> Reviewed-by: Ilya Maximets <i.maximets@ovn.org> Link: https://patch.msgid.link/288fbd5459d92b9dd0dcc6faf625f04819161ff3.1787280296.git.xuyuqiabc@gmail.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2026-08-24xsk: honor XDP_TX_METADATA in zero-copy pathStanislav Fomichev1-2/+5
The zero-copy path reads TX metadata whenever the UMEM has metadata space, even if the descriptor does not set XDP_TX_METADATA. Pass descriptor options through the metadata helpers and ignore metadata unless the option is set. This does not fix the existing per-WQE metadata handling for mlx5 MPWQEs. Only the descriptor that starts a session passes through xsk_tx_metadata_request() and configures offload state shared by the batch. Metadata on descriptors joining an open session is therefore not validated and does not configure its requested offloads. In addition, a non-NULL metadata pointer from such a descriptor is treated as a timestamp completion request even when XDP_TXMD_FLAGS_TIMESTAMP is not set, so its metadata union can be overwritten with an unrequested timestamp. Fixing mixed metadata states within one MPWQE requires a separate change. Fixes: 48eb03dd2630 ("xsk: Add TX timestamp and TX checksum offload support") Reviewed-by: Alexander Lobakin <aleksander.lobakin@intel.com> Signed-off-by: Stanislav Fomichev <sdf@fomichev.me> Reviewed-by: Maciej Fijalkowski <maciej.fijalkowski@intel.com> Reviewed-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com> Link: https://patch.msgid.link/20260819160535.1472459-3-sdf@fomichev.me Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2026-08-24Bluetooth: RFCOMM: serialize session teardownChengfeng Ye1-0/+2
rfcomm_kill_listener() walks session_list and deletes every session without holding rfcomm_mutex, unlike the normal session processing and connect error paths. Under normal operation, an open RFCOMM socket pins rfcomm.ko, so rfcomm_kill_listener() does not run concurrently with rfcomm_dlc_open(). However, forced module unload via delete_module(O_TRUNC) can stop krfcommd while a failed connect is still unwinding. connect task forced unload / krfcommd ------------ ------------------------ rfcomm_lock() rfcomm_session_add() delete_module("rfcomm", O_TRUNC) rfcomm_kill_listener() fetch session from session_list kernel_connect() fails rfcomm_session_del() remove and free session rfcomm_session_del(session) The final call then reads the freed session and may corrupt the list. KASAN reported with mdelay() to enlarge critical window: BUG: KASAN: slab-use-after-free in rfcomm_run+0x3802/0x3f00 [rfcomm] Read of size 8 at addr ffff888111058d40 by task krfcommd/79 Tainted: [R]=FORCED_RMMOD Allocated by task 86: rfcomm_session_add+0xa1/0x300 [rfcomm] rfcomm_dlc_open+0x8b2/0xf30 [rfcomm] rfcomm_sock_connect+0x34c/0x530 [rfcomm] Freed by task 86: kfree+0x121/0x3c0 rfcomm_dlc_open+0xab7/0xf30 [rfcomm] rfcomm_sock_connect+0x34c/0x530 [rfcomm] Hold rfcomm_mutex across the teardown traversal so every reachable session_list walk uses the same serialization. Reviewed-by: Ali Ahmet Memis <ali@iusegentoo.com> Tested-by: Ali Ahmet Memis <ali@iusegentoo.com> Reviewed-by: Pauli Virtanen <pav@iki.fi> Signed-off-by: Chengfeng Ye <nicoyip.dev@gmail.com> Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
2026-08-24Bluetooth: do not leak an hci_conn when a second LE connect is rejectedRadek Podgorny1-2/+7
create_le_conn_complete() decides whether the failed connection is still pending by comparing it against hci_lookup_le_connect(), which returns the first LE connection in BT_CONNECT. That is the same connection only while at most one is pending. Two can be pending. Connections created on the passive scan path sit in BT_CONNECT with HCI_CONN_SCANNING set and are invisible to hci_lookup_le_connect() until hci_le_create_conn_sync() clears the flag when their command is issued, so the -EBUSY guard in hci_connect_le() does not prevent a second connection from being queued while the first is still on the scan path. Whenever two connections are in BT_CONNECT at once, the lookup may return one connection while create_le_conn_complete() is reporting the failure of the other; the early exit then drops the error and hci_conn_failed() never runs on the connection that failed. The controller also rejects a second HCI_OP_LE_CREATE_CONN issued while another connection creation is still outstanding, per Core Spec Vol 4, Part E. The spec calls for Command Disallowed there; the bcm43438 observed here answers with an LMP/LL error code instead, which bt_to_errno() maps to the -EPROTO (-71) in the log below. The leaked connection stays in BT_CONNECT forever, and because hci_connect_le() refuses to dial while hci_lookup_le_connect() finds anything, every subsequent attempt to reach any peer fails with -EBUSY and no command reaches the controller at all. Seen on a bcm43438 with two BLE peers polled on the same interval (state 5 is BT_CONNECT; both handles are UNSET ones, allocated from the ida above HCI_CONN_HANDLE_MAX): Bluetooth: hci1: Opcode 0x2013 failed: -71 # hcitool con < LE 14:9C:EF:03:68:81 handle 3840 state 5 lm CENTRAL < LE C4:D3:6A:8C:B5:38 handle 3841 state 5 lm CENTRAL A btmon capture across the next ten minutes of connect attempts contains no HCI_OP_LE_CREATE_CONN at all; outgoing LE connections do not recover until the adapter is reset. With this change the same scenario fails the rejected connection cleanly and further connects to both peers go through. Ask about the connection itself instead of about the device. Fixes: c9f73a2178c1 ("Bluetooth: hci_conn: Fix hci_connect_le_sync") Signed-off-by: Radek Podgorny <radek@podgorny.cz> Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
2026-08-24Bluetooth: RFCOMM: serialize security confirmation handlingChengfeng Ye1-1/+7
rfcomm_security_cfm() looks up a session on session_list and then walks its DLC list without holding rfcomm_mutex. Since RFCOMM session teardown uses rfcomm_mutex, krfcommd can close and free the same session and DLCs concurrently: hci_rx_work krfcommd ----------- --------- rfcomm_session_get() rfcomm_lock() rfcomm_session_close() rfcomm_dlc_unlink() rfcomm_session_del() kfree(s) rfcomm_unlock() walk s->dlcs The callback can then read a freed session list head and touch freed DLCs while updating their flags or timers. Serialize the session lookup and DLC traversal in rfcomm_security_cfm() with rfcomm_mutex. This matches the existing RFCOMM session lifetime rules and prevents concurrent rfcomm_session_del() / rfcomm_dlc_unlink() from tearing the objects down while the callback is using them. KASAN reported: BUG: KASAN: slab-use-after-free in rfcomm_security_cfm+0x41c/0x440 Read of size 8 at addr ffff888111fb3960 by task kworker/u17:1/89 Workqueue: hci0 hci_rx_work Call Trace: rfcomm_security_cfm+0x41c/0x440 hci_encrypt_cfm+0x139/0x590 hci_encrypt_change_evt+0x37b/0xc40 hci_event_packet+0x71b/0xb20 hci_rx_work+0x293/0x730 Allocated by task 69: rfcomm_session_add+0x9e/0x2f0 rfcomm_run+0x44b/0x41e0 Freed by task 69: kfree+0x131/0x3c0 rfcomm_session_del+0x188/0x220 rfcomm_run+0x1985/0x41e0 Fixes: 08c30aca9e698faddebd34f81e1196295f9dc063 ("Bluetooth: Remove RFCOMM session refcnt") Cc: stable@vger.kernel.org Signed-off-by: Chengfeng Ye <nicoyip.dev@gmail.com> Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
2026-08-24Bluetooth: RFCOMM: Validate MTU in rfcomm_apply_pn() to prevent infinite loopHyunwoo Kim1-0/+4
rfcomm_apply_pn() accepts the MTU value from a remote PN (Parameter Negotiation) frame without checking for zero. When the remote peer sends an MTU of zero, d->mtu is set to 0. This causes the sendmsg path to enter an infinite loop when fragmenting data, as each fragment has size == min_t(size_t, len, 0) == 0, so the remaining length never decreases. The infinite allocation of zero-length skbs exhausts all system memory. Fix by clamping d->mtu to RFCOMM_DEFAULT_MTU when the negotiated value is zero, consistent with the initial value assigned in rfcomm_dlc_alloc(). Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") Signed-off-by: Hyunwoo Kim <imv4bel@gmail.com> Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
2026-08-24Bluetooth: ISO: fix use-after-free of listener socket in iso_conn_readyHang Nan1-0/+8
iso_conn_ready() looks up the BIS listener socket with iso_get_sock(), which takes a reference, and then, without re-checking its state, creates a child socket from it: parent = iso_get_sock(hdev, ...); if (!parent) return; lock_sock(parent); sk = iso_sock_alloc(sock_net(parent), NULL, BTPROTO_ISO, ...); ... iso_chan_add(conn, sk, parent); ... release_sock(parent); sock_put(parent); If the listener socket is closed concurrently, between iso_get_sock() and lock_sock(), the reference taken by iso_get_sock() may be the last one: the close path drops the link-list reference, and once iso_conn_ready() drops its own reference at the end of the function the socket is freed. The child socket, however, is already linked to the freed parent, and a later disconnect of the child runs iso_chan_del() -> bt_accept_unlink(), which dereferences the dangling parent pointer into the freed accept queue (a use-after-free). The same dangling pointer is also dereferenced through parent->***() in iso_chan_del(). Fix it the same way the connected (non-BIS) path was fixed in commit 0d255e63fcf3 ("Bluetooth: ISO: hold sk properly in iso_conn_ready"): after taking the socket lock, re-check that the parent is still a listening, alive socket, and bail out otherwise. Fixes: ccf74f2390d60 ("Bluetooth: Add BTPROTO_ISO socket type") Cc: stable@vger.kernel.org Signed-off-by: Hang Nan <2122295973@qq.com> Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
2026-08-24Bluetooth: hci_core: use skb_get() instead of skb_clone() for req_skbXin Chen1-1/+1
BT enable fails intermittently with -ETIMEDOUT (-110). The kernel log shows the HCI Read Local Version command was sent and the firmware replied with status 0x00 (logged by hci_req_cmd_complete() BT_DBG), but the waiter in __hci_cmd_sync_sk() never woke up and timed out after 10 s: bluetooth hci0: Opcode 0xfc00 // __hci_cmd_sync_sk bluetooth hci0: opcode 0xfc00 plen 1 // hci_cmd_sync_add bluetooth hci0: skb len 4 // hci_cmd_sync_alloc bluetooth hci0: length 1 // hci_req_sync_run Bluetooth: hci0 cmd_cnt 1 cmd queued 1 // hci_cmd_work Bluetooth: hci0 type 1 len 4 // hci_send_frame Bluetooth: opcode 0xfc00 status 0x00 // hci_req_cmd_complete <-- req_skb NULL: req_complete_skb not set, hci_cmd_sync_complete() never called, req_status stays HCI_REQ_PEND --> <-- 10 s later: wait_event_interruptible_timeout expires --> bluetooth hci0: end: err -110 // __hci_cmd_sync_sk The root cause is that hci_send_cmd_sync() clones the sent command into hdev->req_skb so that hci_req_cmd_complete() can locate the registered completion callback. Under memory pressure this skb_clone() fails, leaving hdev->req_skb NULL. The firmware reply is received and processed, but hci_req_cmd_complete() finds NULL req_skb, so hci_cmd_sync_complete() is never called, req_status stays HCI_REQ_PEND, and the waiter times out with -ETIMEDOUT. req_skb is only used to read bt_cb(skb)->hci callbacks and opcode -- it is never modified. Replace skb_clone() with skb_get(), which simply increments the reference count of hdev->sent_cmd without allocating new memory and therefore cannot fail. This issue was first observed as a use-after-free in ttyport_close() when ttyport_open() failed, which was investigated in an earlier patch series [1]. That investigation led to the discovery of the true root cause described above. [1] https://lore.kernel.org/all/20250430111617.1151390-1-quic_cxin@quicinc.com/ Fixes: 2615fd9a7c25 ("Bluetooth: hci_sync: Fix overwriting request callback") Cc: stable@vger.kernel.org Signed-off-by: Xin Chen <xin.chen2@oss.qualcomm.com> Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
2026-08-24Bluetooth: hci_event: clear HCI_LE_ADV only on a created connectionValentin Kindschi1-3/+4
le_conn_complete_evt() clears HCI_LE_ADV before looking at the event status, on the premise stated in its comment that all controllers stop advertising when a connection is created. That premise only holds when a connection was actually created. On a non-zero status none was, and the controller is still advertising: after the host issues LE Create Connection Cancel the event arrives with Unknown Connection Identifier (0x02), and a connection timeout behaves the same way. Clearing the flag there leaves the host believing advertising is off while the controller has it on. It is also wrong for extended advertising, where several sets can be advertising at once. hci_cc_le_set_ext_adv_enable() is careful about this - on disabling one set it walks hdev->adv_instances and only clears HCI_LE_ADV once no instance is still enabled. The unconditional clear here discards that bookkeeping, so one set connecting drops the flag while the others keep advertising. The direction of the error matters. A flag left set is self-correcting: hci_disable_advertising_sync() sends LE Set Advertising Enable(0) and the command complete puts the state back. A flag left clear is not, because that same function returns early without sending anything while the flag is clear: - LE Set Advertising Parameters is then sent to a controller that is still advertising, and is correctly rejected with Command Disallowed (0x0c); - hci_enable_advertising_sync() returns at that point, before the LE Set Advertising Enable that would set HCI_LE_ADV again. On a controller without LE Extended Advertising that is reachable from here: hci_schedule_adv_instance_sync() re-arms adv_instance_expire every HCI_DEFAULT_ADV_DURATION (2 s) and its "already advertising" shortcut tests HCI_LE_ADV, which can no longer become true, so the parameter write is retried for as long as advertising is configured: Bluetooth: hci0: Opcode 0x2006 failed: -16 Only clear the flag when a connection was established. Note this is not on its own sufficient to stop that retry loop - the redundant enable queued by hci_le_conn_failed() clears HCI_LE_ADV itself and recreates the same mismatch, which patch 1 addresses. This patch fixes the event handler reporting a state the controller is not in. Verified on the affected device (BCM43455, legacy advertising only) with this patch and patch 1 applied. A 221 s btmon capture with an out-of-range peer at -90 dBm contains two outgoing connection attempts that the host cancelled, each producing exactly the event this patch changes: < LE Set Advertising Parameters 0x2006 Success < LE Set Advertising Enable 0x200a Success < LE Create Connection Cancel 0x200e Success > LE Connection Complete Unknown Connection Identifier (0x02), central Nothing follows either one; the next command is an unrelated scan restart 70 ms later. Over the whole capture: 7 LE Set Advertising Parameters sent, all Success; 10 LE Set Advertising Enable, all Success; no Command Disallowed of any opcode, and no 2 s cadence anywhere. Two central connections to other peers completed normally afterwards, with feature exchange and a connection parameter update, so advertising was still live across the cancelled attempts. The extended advertising case above is a code argument, not a measurement: this controller has no LE Extended Advertising, so that path is not exercised by the capture. Fixes: fbd96c151cdc ("Bluetooth: Fix clearing HCI_LE_ADV for LE connections") Cc: stable@vger.kernel.org Assisted-by: Claude:claude-opus-5 btmon Signed-off-by: Valentin Kindschi <valentin.kindschi@fiveco.ch> Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
2026-08-24Bluetooth: hci_conn: re-enable advertising only for peripheral roleValentin Kindschi1-1/+2
hci_le_conn_failed() unconditionally calls hci_enable_advertising(), although its own comment states advertising should be re-enabled only when the failed attempt was made as a peripheral. hci_le_conn_failed() is reached from hci_conn_failed() for every failed LE connection, including outgoing central connections. For a central attempt this enable is redundant: hci_le_create_conn_sync() already restores advertising via hci_resume_advertising_sync() in its done: block. Because hci_enable_advertising() only queues the work on cmd_sync_work, it runs *after* that resume has already succeeded and set HCI_LE_ADV. The resulting HCI sequence, captured on a BCM43455 (no LE Extended Advertising, so legacy advertising is used): LE Create Connection Status Success ... 13.8 s, peer never answers ... LE Set Advertising Parameters (0x2006) Success <- done: resume, LE Set Advertising Enable (0x200a) Success HCI_LE_ADV set LE Create Connection Cancel (0x200e) Success LE Connection Complete Unknown Conn Id LE Set Advertising Parameters (0x2006) Command Disallowed (0x0c) The last command is the queued enable from hci_le_conn_failed() running as a second hci_enable_advertising_sync() pass. It clears HCI_LE_ADV (hci_sync.c, "Clear the HCI_LE_ADV bit temporarily"), then sends LE Set Advertising Parameters while the controller is still advertising, which the controller correctly rejects with Command Disallowed. The disable-first call at the top of hci_enable_advertising_sync() cannot prevent this: hci_disable_advertising_sync() returns early without sending anything when HCI_LE_ADV is clear, so it is a no-op exactly when the flag is wrong. hci_enable_advertising_sync() then returns without sending LE Set Advertising Enable, so HCI_LE_ADV is never set again. The legacy software rotation loop re-arms hci_schedule_adv_instance_sync() every HCI_DEFAULT_ADV_DURATION (2 s), and its "already advertising" shortcut tests HCI_LE_ADV, which can no longer become true. The command is therefore retried every 2 s indefinitely: Bluetooth: hci0: Opcode 0x2006 failed: -16 Observed on a gateway as 5326 occurrences over 3 hours, ending only when bluetoothd was restarted. Connection attempts that succeed do not call hci_le_conn_failed() and never trigger this. Add the role test the comment already describes. Both other hci_enable_advertising() call sites reached from a failed/closed LE connection (hci_cs_disconnect() and hci_disconn_complete_evt()) already guard on conn->role == HCI_ROLE_SLAVE; this one was missed. Reproducing needs legacy advertising (ext_adv_capable() false, so the software rotation loop is used), simultaneous peripheral advertising and outgoing central connects, and a central connect that times out rather than failing fast. The Fixes tag points at the commit that introduced the advertising restart into this path for the directed-advertising (peripheral) case; the role test that the later commit 0b1db38ca26b ("Bluetooth: Fix check for direct advertising") added to the sibling paths was never applied here. Fixes: 3c857757ef6e ("Bluetooth: Add directed advertising support through connect()") Cc: stable@vger.kernel.org Assisted-by: Claude:claude-opus-5 btmon Signed-off-by: Valentin Kindschi <valentin.kindschi@fiveco.ch> Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
2026-08-24Bluetooth: eir: Fix OOB read in eir_get_service_data()HyeongJun An1-1/+2
eir_get_service_data() walks the advertising data for a Service Data field with a matching UUID. On a mismatch it advances: eir += dlen; eir_len -= dlen; eir_get_data() reports dlen as the field's data length, but the field spans dlen + 2 bytes once its length and type bytes count, and more when non-Service-Data fields were skipped to reach it. The pointer lands correctly on the next field. eir_len does not, and the shortfall compounds across fields until eir_get_data() reads the length and type bytes of a "field" past the end of the buffer. For an ISO broadcast sink that buffer is hcon->le_per_adv_data[], filled from the periodic advertising reports of a remote broadcaster. A PA payload packed with mismatching Service Data fields walks off the array into the rest of struct hci_conn. A drifted field that matches the BAA UUID puts those bytes in iso_pi(sk)->base, where user space reads them back with getsockopt(BT_ISO_BASE). Recompute eir_len from the end of the buffer each iteration. Fixes: 8f9ae5b3ae80 ("Bluetooth: eir: Add helpers for managing service data") Cc: stable@vger.kernel.org Assisted-by: Claude:claude-opus-5 Signed-off-by: HyeongJun An <sammiee5311@gmail.com> Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
2026-08-24Bluetooth: hci_sync: add conditional locking annotationsPauli Virtanen1-0/+5
Add context analysis annotations to functions doing conditional locking, to suppress analysis warnings. Fixes: cdc36db204ff ("Bluetooth: hci_sync: Fix advertising data UAFs") Tested-by: Nathan Chancellor <nathan@kernel.org> # build Signed-off-by: Pauli Virtanen <pav@iki.fi> Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
2026-08-24Bluetooth: L2CAP: fix race l2cap_sock_cleanup_listen() vs. put_chanPauli Virtanen1-10/+13
For L2CAP sockets without owning sk->sk_socket, reading l2cap_pi(sk)->chan may race against concurrent l2cap_sock_kill() -> l2cap_sock_put_chan(). This excludes simultaneous proto_ops callbacks, but access in l2cap_sock_cleanup_listen() has unsafe lockless read. [Task 1] [Task 2 (hdev->workqueue)] l2cap_sock_release(parent) l2cap_disconn_cfm l2cap_sock_cleanup_listen l2cap_conn_del bt_accept_dequeue l2cap_chan_del lock_sock(sk) l2cap_sock_teardown_cb bt_accept_unlink bt_sk(sk)->parent = NULL release_sock(sk) ----------------> lock_sock(sk) parent = /* NULL */ lock_sock(sk) <--------------------- release_sock(sk) sock_set_flag(sk, SOCK_ZAPPED) l2cap_sock_close_cb l2cap_sock_kill(sk) l2cap_sock_put_chan chan = READ l2cap_pi(sk)->chan l2cap_pi(sk)->chan = NULL l2cap_chan_hold_unless_zero l2cap_put_chan(chan) kref_get_unless_zero(&chan->ref) Task 1 may observe NULL which causes null-ptr-deref. Fix the race by taking lock_sock() in l2cap_sock_kill() to synchronize with l2cap_sock_cleanup_listen(). hold_unless_zero() is not needed here, l2cap_pi(sk)->chan owns reference if it is non-NULL. Clarify code comments vs. locking. Fixes: 6fef032af009 ("Bluetooth: L2CAP: Fix use-after-free in l2cap_sock_new_connection_cb()") Reported-by: syzbot+e6382a2f53f5fc7453ac@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=e6382a2f53f5fc7453ac Signed-off-by: Pauli Virtanen <pav@iki.fi> Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
2026-08-24Bluetooth: mgmt: fix 'hdev->discovery.uuids' NULL dereferencePavel Shpakovskiy1-5/+13
'uuid_count' member of struct 'discovery_state' is assigned and read without any locks, so there is a chance of situation when uuid_count != 0, but uuids is NULL and there will be NULL pointer dereference. Possible race: 'hci_update_passive_scan_sync' 'hci_discovery_filter_clear' hdev->discovery.uuid_count = 0; <----------------------preempted-----------------------------> 'start_service_discovery' // Set uuid_count to value != 0 hdev->discovery.uuid_count = uuid_count; hdev->discovery.uuids = kmemdup(...); <----------------------preempted-----------------------------> spin_lock(&hdev->discovery.lock); kfree(hdev->discovery.uuids); hdev->discovery.uuids = NULL; spin_unlock(&hdev->discovery.lock); Now uuids == NULL and uuid_count != 0. So 'mgmt_device_found' -> 'is_filter_match' -> 'eir_has_uuids' receives non consistent discovery state, where NULL dereference of uuids happens. To fix it let's add discovery.lock around every read/write of uuid_count, uuids pair of struct members. It is also important to assign uuid_count value only after success kmemdup() allocation in start_service_discovery(), otherwise uuids is NULL, because kmemdup failed, but uuid_count is already assigned to non zero value. The following panic happens: [ ] ------------[ cut here ]------------ [ ] Unable to handle kernel NULL pointer dereference at virtual address 0000000000000000 [ ] Internal error: Oops: 0000000096000006 [#1] PREEMPT SMP [ ] CPU: 0 PID: 15056 Comm: kworker/u9:2 [ ] Workqueue: hci0 hci_rx_work [ ] pstate: 10400009 (nzcV daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--) [ ] pc : eir_has_uuids+0x2d8/0x590 [ ] lr : is_filter_match+0x258/0x320 ... [ ] Call trace: [ ] eir_has_uuids+0x2d8/0x590 [ ] is_filter_match+0x258/0x320 [ ] mgmt_device_found+0x5b0/0xafc [ ] process_adv_report.part.0+0x8c8/0xf14 [ ] hci_le_adv_report_evt+0x338/0x3f0 [ ] hci_le_meta_evt+0x1f0/0x4c8 [ ] hci_event_packet+0x440/0xc9c [ ] hci_rx_work+0x44c/0xaf8 [ ] process_one_work+0x54c/0x103c [ ] worker_thread+0x6c4/0x10c4 [ ] kthread+0x274/0x2ec [ ] ret_from_fork+0x10/0x20 [ ] Code: 14000004 91004021 eb14003f 54000180 (f9400024) [ ] ---[ end trace 0000000000000000 ]--- Fixes: 2935e556850e ("Bluetooth: hci_sync: fix double free in 'hci_discovery_filter_clear()'") Signed-off-by: Pavel Shpakovskiy <pashpakovskii@salutedevices.com> Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
2026-08-24Bluetooth: L2CAP: reject accept queue add unless BT_LISTENPauli Virtanen1-0/+13
New sk should not be added to parent socket accept queue after last l2cap_sock_cleanup_listen() has run in l2cap_sock_teardown_cb() and state set to BT_CLOSED, as that can result to UAF on dereferencing the dangling parent reference. l2cap_sock_new_connection_cb() may race with parent l2cap_chan teardown, due to chan->state accessed without consistent locking: [Task 1] [Task 2] l2cap_sock_release(parent) l2cap_connect l2cap_sock_shutdown pchan = l2cap_global_chan_by_psm l2cap_chan_lock(pchan) l2cap_chan_close l2cap_sock_teardown_cb pchan->state = BT_CLOSED l2cap_chan_unlock(pchan) ------> l2cap_chan_lock(pchan) l2cap_new_connection l2cap_sock_new_connection_cb l2cap_chan_lock(pchan) <-------- l2cap_chan_unlock(pchan) l2cap_sock_kill(parent) /* bt_sk(sk)->parent dangling */ Fix by adding check for sk_state == BT_LISTEN after acquiring sk lock in l2cap_sock_new_connection_cb(). Add lock_sock() around sk_state writes where missing, to avoid data races. Although the data races on pchan->state should be fixed too, this defensive sk_state check probably makes sense in any case. Fixes: 2ff1a41a912d ("Bluetooth: L2CAP: Fix null-ptr-deref in l2cap_sock_state_change_cb()") Reported-by: syzbot+9265e754091c2d27ea29@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=9265e754091c2d27ea29 Signed-off-by: Pauli Virtanen <pav@iki.fi> Reported-by: syzbot+9265e754091c2d27ea29@syzkaller.appspotmail.com Tested-by: syzbot+9265e754091c2d27ea29@syzkaller.appspotmail.com Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
2026-08-24Bluetooth: L2CAP: access chan->conn safely in get/setsockoptPauli Virtanen1-16/+48
Since commit b66774b48dd9 ("Bluetooth: L2CAP: Fix UAF in channel timeout by holding conn ref") l2cap_chan::conn has held reference and remains non-NULL also after the corresponding hci_conn is deleted. In this state accessing various fields eg. hci_conn::hdev is invalid, which leads to KASAN crash in l2cap_sock_setsockopt() access of conn->hcon->hdev. Check l2cap_chan::conn.hcon corresponds to an alive hci_conn before trying to use it in l2cap_sock.c. Hold l2cap_chan_lock() in getsockopt/setsockopt to ensure it stays alive, and to avoid data races in l2cap_chan fields. Fixes: b66774b48dd9 ("Bluetooth: L2CAP: Fix UAF in channel timeout by holding conn ref") Reported-by: syzbot+b106284c2a0b7bc80cf9@syzkaller.appspotmail.com Link: https://syzkaller.appspot.com/bug?extid=b106284c2a0b7bc80cf9 Signed-off-by: Pauli Virtanen <pav@iki.fi> Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
2026-08-24Bluetooth: hci_sync: Clear HCI_CMD_PENDING when dropping the last requestIbrahim Abdelkader1-0/+2
A synchronous HCI command that never receives a response leaves HCI_CMD_PENDING set: hci_req_cmd_complete() is the only place that clears it, and it only runs when a response matching the last command sent arrives. hci_send_cmd_sync() populates hdev->req_skb only when the flag transitions from clear to set, while hci_dev_open_sync() and hci_dev_close_sync() drop req_skb without clearing the flag. After a timeout followed by either, the two disagree: the flag claims a request is outstanding while req_skb is NULL. Subsequent synchronous commands are then sent with no req_skb, so hci_event_packet() has nothing to match an arriving event against, and the caller times out even though the controller answered. Commands answered by Command Complete recover on their own, since hci_req_cmd_complete() clears the flag as a side effect. Drivers using __hci_cmd_sync_ev() with a custom event do not, because a vendor event never reaches that path. On a WCN3988 (hci_qca over UART) this makes a controller firmware hang unrecoverable: the driver injects a hardware error and re-runs qca_setup(), qca_read_soc_version() waits for HCI_EV_VENDOR, the reply arrives within 4 ms and is discarded, and every retry fails the same way. The adapter is left down until the driver is unbound and rebound, or power is removed. Clear the flag wherever the last request is dropped, restoring the invariant that req_skb is non-NULL exactly when HCI_CMD_PENDING is set. Verified on hardware by forcing a command timeout: without this change setup fails on every attempt, with it setup succeeds on the first. Fixes: 2615fd9a7c25 ("Bluetooth: hci_sync: Fix overwriting request callback") Cc: stable@vger.kernel.org Signed-off-by: Ibrahim Abdelkader <iabdelka@qti.qualcomm.com> Signed-off-by: Hans de Goede <johannes.goede@oss.qualcomm.com> Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
2026-08-24hv_sock: Remove check for old Hyper-V hostsMichael Kelley1-3/+0
With the overall removal of Linux support for running on Hyper-V hosts earlier than WS2016 and Windows 10, the check for such versions during hv_sock initialization is no longer necessary. Remove the check. Signed-off-by: Michael Kelley <mhklinux@outlook.com> Signed-off-by: Wei Liu <wei.liu@kernel.org>
2026-08-22net/sched: sch_cake: fix autorate reconfiguration throttlingGiuseppe Piscitelli1-0/+1
CAKE's autorate-ingress path intends to limit shaper reconfiguration to once per 250 ms, but last_reconfig_time is only checked and never updated. Since the field stays zero, every qualifying capacity-estimate window can call cake_reconfigure(), causing avoidable rate churn and scheduler work under bursty traffic. Store the current timestamp when autorate actually reconfigures the qdisc so the guard enforces the intended interval. Fixes: 7298de9cd725 ("sch_cake: Add ingress mode") Signed-off-by: Giuseppe Piscitelli <ooonea@gmail.com> Acked-by: Toke Høiland-Jørgensen <toke@toke.dk> Link: https://patch.msgid.link/20260820154503.892214-1-ooonea@gmail.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2026-08-22net_sched: sch_fq: fix pacing delay underflow with pacing offloadEric Dumazet1-2/+6
When pacing offload is enabled (q->offload_horizon > 0), FQ can dequeue packets early (now < f->time_next_packet). In this case, the drift calculation (now - f->time_next_packet) underflows to a large unsigned value. min(len/2, now - f->time_next_packet) then evaluates to len/2, incorrectly halving the pacing delay for the next packet. Fix this by only applying drift compensation if now > f->time_next_packet. This bug was triggered when flow_max_rate was set on the qdisc or for non EDT packets (packets with a zero skb->tstamp). Fixes: f26080d47007 ("net_sched: sch_fq: add the ability to offload pacing") Reported-by: Willem de Bruijn <willemb@google.com> Closes: https://lore.kernel.org/netdev/CANn89iK6O7ujR9zCJzd04MNLQoDi3mA+HWsR-hgQWYzLS3gZfw@mail.gmail.com/ Signed-off-by: Eric Dumazet <edumazet@google.com> Signed-off-by: Willem de Bruijn <willemb@google.com> Link: https://patch.msgid.link/20260820120706.1995449-1-willemdebruijn.kernel@gmail.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2026-08-22net: page_pool: Remove zone/policy GFP flags when allocating XArray entriesRong Zhang1-0/+7
Net drivers request GFP flags according to both the current context and the device constraints, but the XArray entry itself is by no mean used by the device. Passing though device constraints to XArray allocation is a bug and will be warned and fixed up by slab, e.g.: Unexpected gfp: 0x4 (GFP_DMA32). Fixing up to gfp: 0x82820 (GFP_ATOMIC|__GFP_NOWARN|__GFP_NOMEMALLOC). Fix your code! CPU: 2 UID: 0 PID: 1071629 Comm: kworker/u80:1 Not tainted 7.2.0-rc7+ #1 PREEMPT(lazy) Hardware name: LENOVO 21Q4/LNVNB161216, BIOS PXCN27WW 10/20/2025 Workqueue: mt76 mt792x_pm_wake_work [mt792x_lib] Call Trace: <TASK> dump_stack_lvl+0x6e/0x90 kmalloc_fix_flags+0x4d/0x6a refill_objects+0x10a/0x330 __pcs_replace_empty_main+0x292/0x5c0 kmem_cache_alloc_lru_noprof+0x4c2/0x680 ? __xas_nomem+0x3a/0x120 __xas_nomem+0x3a/0x120 __xa_alloc+0xd4/0x190 page_pool_dma_map+0xef/0x400 __page_pool_alloc_netmems_slow+0xed/0x480 ? lock_release+0x280/0x490 page_pool_alloc_frag_netmem+0xe0/0x3a0 page_pool_alloc_frag+0xe/0x20 mt76_dma_rx_fill_buf+0x1f6/0x580 [mt76] mt76_dma_rx_reset+0x1cf/0x230 [mt76] mt792x_wpdma_reset+0x183/0x1b0 [mt792x_lib] mt792x_wpdma_reinit_cond+0x5e/0xa0 [mt792x_lib] mt792xe_mcu_drv_pmctrl+0x28/0x60 [mt792x_lib] mt792x_mcu_drv_pmctrl+0x3e/0x90 [mt792x_lib] mt792x_pm_wake_work+0x2d/0x1d0 [mt792x_lib] ? process_one_work+0x20e/0x600 process_one_work+0x230/0x600 ? process_one_work+0x256/0x600 worker_thread+0x1ec/0x3c0 ? rescuer_thread+0x610/0x610 kthread+0xf2/0x130 ? kthread_affine_node+0x140/0x140 ret_from_fork+0x2a5/0x380 ? kthread_affine_node+0x140/0x140 ret_from_fork_asm+0x11/0x20 </TASK> Currently mt76 and stmmac may allocate page pool pages with GFP_DMA32. Fix it by removing zone/policy GFP flags when allocating XArray entries. This is inspired by commit 96d578088085 ("iommu/dma: Use the gfp parameter in __iommu_dma_alloc_noncontiguous()"). Fixes: ee62ce7a1d90 ("page_pool: Track DMA-mapped pages and unmap them when destroying the pool") Signed-off-by: Rong Zhang <i@rong.moe> Reviewed-by: Toke Høiland-Jørgensen <toke@redhat.com> Link: https://patch.msgid.link/20260821-page-pool-xa-drop-dma32-v1-1-6eab295c3478@rong.moe Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2026-08-22net/smc: carry oversized SMC-Rv2 LLC messages in the queue entryYehyeong Lee2-39/+90
smc_llc_rmt_delete_rkey() and smc_llc_save_add_link_rkeys() read the part of a v2 message that does not fit into the 44-byte union smc_llc_msg, and both bound themselves by the size of the buffer it landed in, not by what arrived. On a link with a shared v2 receive buffer a 44-byte DELETE_RKEY_V2 declaring 255 rkeys reaches rkey[9..254] in whatever an earlier message left in lgr->wr_rx_buf_v2, and passes each of them to smc_rtoken_delete(). One of those 255 matched a registered rtoken and deleted it. An ADD_LINK on such a link installs up to 255 rtokens from the same bytes. Copy the tail into the queue entry, so its length is the length of the message that arrived, and declare the rkeys that fit inline as a member of the union instead of reaching them through a cast. The same DELETE_RKEY_V2 now processes the 9 rkeys it carries. The copy is limited to the longest tail the two functions can read, so the peer does not pick the size of the entry. The bound the previous patch placed on links without a shared v2 receive buffer is no longer needed. Fixes: 27ef6a9981fe ("net/smc: support SMC-R V2 for rdma devices with max_recv_sge equals to 1") Cc: stable@vger.kernel.org Suggested-by: D. Wythe <alibuda@linux.alibaba.com> Reviewed-by: Sidraya Jayagond <sidraya@linux.ibm.com> Signed-off-by: Yehyeong Lee <yhlee@isslab.korea.ac.kr> Link: https://patch.msgid.link/20260819023306.644849-4-yhlee@isslab.korea.ac.kr Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2026-08-22net/smc: bound the peer rkey counts in SMC-Rv2 LLC messagesYehyeong Lee1-0/+16
On a link whose device has max_recv_sge == 1 there is no shared v2 receive buffer, and smc_llc_save_add_link_rkeys() takes the v2 extension from 44 bytes past the start of the queue entry's inline message: ext = (struct smc_llc_msg_add_link_v2_ext *)(llc_msg + SMC_WR_TX_SIZE); The entry is a 72-byte allocation and the extension starts at offset 68, so ext->num_rkeys at offset 94 is already past it. This happens on every SMC-Rv2 link addition, whatever the peer sends: [ 2.490065] BUG: KASAN: slab-out-of-bounds in smc_llc_save_add_link_rkeys+0x333/0x350 [ 2.490431] Read of size 2 at addr ffff8880056406de by task smctest/106 [ 2.490709] [ 2.490792] CPU: 0 UID: 0 PID: 106 Comm: smctest Not tainted 7.2.0-rc5-p1-g77a5d9d9c99f #32 PREEMPT(lazy) [ 2.490795] Hardware name: QEMU Ubuntu 24.04 PC v2 (i440FX + PIIX, arch_caps fix, 1996), BIOS 1.16.3-debian-1.16.3-2 04/01/2014 [ 2.490798] Call Trace: [ 2.490803] <TASK> [ 2.490805] dump_stack_lvl+0x53/0x70 [ 2.490810] print_report+0xd0/0x630 [ 2.490828] ? __pfx__raw_spin_lock_irqsave+0x10/0x10 [ 2.490832] ? smc_llc_save_add_link_rkeys+0x333/0x350 [ 2.490834] kasan_report+0xce/0x100 [ 2.490836] ? smc_llc_save_add_link_rkeys+0x333/0x350 [ 2.490837] smc_llc_save_add_link_rkeys+0x333/0x350 [ 2.490839] ? smcr_buf_map_lgr+0x1bf/0x2b0 [ 2.490844] smc_llc_cli_add_link+0xca7/0x1e80 [ 2.490848] ? smc_llc_wait+0x355/0x810 [ 2.490850] ? __pfx_smc_llc_wait+0x10/0x10 [ 2.490851] ? __pfx_smc_llc_cli_add_link+0x10/0x10 [ 2.490853] ? __pfx_autoremove_wake_function+0x10/0x10 [ 2.490863] __smc_connect+0x3f5c/0x4980 [ 2.490873] ? __pfx_kernel_connect+0x10/0x10 [ 2.490888] ? __pfx___smc_connect+0x10/0x10 [ 2.490891] ? release_sock+0x148/0x1d0 [ 2.490894] smc_connect+0x42c/0x580 [ 2.490896] __sys_connect+0xfc/0x130 [ 2.490898] ? __pfx___sys_connect+0x10/0x10 [ 2.490900] ? handle_mm_fault+0x1a1/0x430 [ 2.490908] __x64_sys_connect+0x6d/0xb0 [ 2.490909] ? fpregs_assert_state_consistent+0x56/0xe0 [ 2.490917] do_syscall_64+0xf9/0x540 [ 2.490921] entry_SYSCALL_64_after_hwframe+0x77/0x7f [ 2.490924] RIP: 0033:0x421bb4 [ 2.490927] Code: ff f7 d8 64 89 01 48 83 c8 ff c3 66 2e 0f 1f 84 00 00 00 00 00 90 f3 0f 1e fa 80 3d ad 34 09 00 00 74 13 b8 2a 00 00 00 0f 05 <48> 3d 00 f0 ff ff 77 4c c3 0f 1f 00 55 48 89 e5 48 83 ec 10 89 55 [ 2.490929] RSP: 002b:00007ffd473b01a8 EFLAGS: 00000202 ORIG_RAX: 000000000000002a [ 2.490935] RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 0000000000421bb4 [ 2.490936] RDX: 0000000000000010 RSI: 00007ffd473b01d0 RDI: 0000000000000003 [ 2.490937] RBP: 0000000000003930 R08: 0000000000000004 R09: 0000000000000000 [ 2.490938] R10: 00007ffd473b0f98 R11: 0000000000000202 R12: 0000000000000006 [ 2.490939] R13: 00007ffd473b0f87 R14: 0000000000000003 R15: 00007ffd473b0f90 [ 2.490940] </TASK> [ 2.490941] [ 2.499545] Allocated by task 44: [ 2.499693] kasan_save_stack+0x33/0x60 [ 2.499860] kasan_save_track+0x14/0x30 [ 2.500026] __kasan_kmalloc+0x8f/0xa0 [ 2.500190] __kmalloc_cache_noprof+0x158/0x370 [ 2.500393] smc_llc_enqueue+0x72/0x560 [ 2.500559] smc_wr_rx_tasklet_fn+0x474/0xa80 [ 2.500747] tasklet_action_common+0x20f/0x8a0 [ 2.500945] handle_softirqs+0x18e/0x590 [ 2.501115] do_softirq+0x3b/0x60 [ 2.501266] __local_bh_enable_ip+0x61/0x70 [ 2.501446] __alloc_skb+0x732/0x890 [ 2.501604] rxe_init_packet+0x16b/0x4f0 [ 2.501783] prepare_ack_packet+0xb8/0x830 [ 2.501962] rxe_receiver+0x495/0x96e0 [ 2.502125] do_work+0x144/0x470 [ 2.502269] process_one_work+0x633/0x1030 [ 2.502450] worker_thread+0x45b/0xd10 [ 2.502617] kthread+0x2c6/0x3b0 [ 2.502762] ret_from_fork+0x36e/0x5a0 [ 2.502925] ret_from_fork_asm+0x1a/0x30 [ 2.503103] [ 2.503177] The buggy address belongs to the object at ffff888005640680 [ 2.503177] which belongs to the cache kmalloc-96 of size 96 [ 2.503692] The buggy address is located 22 bytes to the right of [ 2.503692] allocated 72-byte region [ffff888005640680, ffff8880056406c8) [ 2.504227] [ 2.504300] The buggy address belongs to the physical page: [ 2.504535] page: refcount:0 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x5640 [ 2.504865] flags: 0x100000000000000(node=0|zone=1) [ 2.505076] page_type: f5(slab) [ 2.505221] raw: 0100000000000000 ffff888001041280 dead000000000122 0000000000000000 [ 2.505544] raw: 0000000000000000 0000000000200020 00000000f5000000 0000000000000000 [ 2.505867] page dumped because: kasan: bad access detected [ 2.506102] [ 2.506176] Memory state around the buggy address: [ 2.506380] ffff888005640580: 00 00 00 00 00 00 00 00 00 fc fc fc fc fc fc fc [ 2.506683] ffff888005640600: 00 00 00 00 00 00 00 00 00 fc fc fc fc fc fc fc [ 2.506987] >ffff888005640680: 00 00 00 00 00 00 00 00 00 fc fc fc fc fc fc fc [ 2.507291] ^ [ 2.507548] ffff888005640700: 00 00 00 00 00 00 00 00 00 fc fc fc fc fc fc fc [ 2.507850] ffff888005640780: 00 00 00 00 00 00 00 00 00 fc fc fc fc fc fc fc Whatever that read finds then bounds the ext->rt[] loop, so a peer that declares 255 rkeys reads much further. smc_llc_rmt_delete_rkey() has the same shape for llcv2->rkey[]. Bound both loops by the buffer they read from, and skip the extension altogether when there is no shared v2 receive buffer. The extension does arrive on the link, but smc_llc_enqueue() copies only sizeof(union smc_llc_msg) into the queue entry, so what that code read past the 44 inline bytes was heap and not peer data. Fixes: 27ef6a9981fe ("net/smc: support SMC-R V2 for rdma devices with max_recv_sge equals to 1") Cc: stable@vger.kernel.org Reviewed-by: Sidraya Jayagond <sidraya@linux.ibm.com> Signed-off-by: Yehyeong Lee <yhlee@isslab.korea.ac.kr> Link: https://patch.msgid.link/20260819023306.644849-3-yhlee@isslab.korea.ac.kr Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2026-08-22net/smc: fix use-after-free of the LLC qentry in smc_llc_srv_add_link()Yehyeong Lee1-4/+5
smc_llc_srv_add_link() keeps add_llc pointing into the queue entry: add_llc = &qentry->msg.add_link; smc_llc.c:1482 ... smc_llc_save_add_link_info(link_new, add_llc); smc_llc.c:1494 smc_llc_flow_qentry_del(&lgr->llc_flow_lcl); smc_llc.c:1495 ... u8 *llc_msg = smc_link_shared_v2_rxbuf(link) ? (u8 *)lgr->wr_rx_buf_v2 : (u8 *)add_llc; smc_llc.c:1504 smc_llc_save_add_link_rkeys(link, link_new, llc_msg); smc_llc.c:1506 smc_llc_flow_qentry_del() kfree()s the entry, so on a link without a shared v2 receive buffer the pointer handed to smc_llc_save_add_link_rkeys() is already freed. Before the Fixes: commit that branch always used lgr->wr_rx_buf_v2 and add_llc was not used after the free. Reproduced on an unpatched tree over rxe, with KASAN, kasan_multi_shot and a link forced to max_recv_sge == 1: the entry is freed and read by the same call, and the freeing frame is smc_llc_srv_add_link() itself. [ 2.523161] BUG: KASAN: slab-use-after-free in smc_llc_save_add_link_rkeys+0x333/0x350 [ 2.523499] Read of size 2 at addr ffff8880052194de by task kworker/0:1/11 [ 2.523789] [ 2.523862] CPU: 0 UID: 0 PID: 11 Comm: kworker/0:1 Not tainted 7.2.0-rc5-p0-g2c9dd296545d #35 PREEMPT(lazy) [ 2.523865] Hardware name: QEMU Ubuntu 24.04 PC v2 (i440FX + PIIX, arch_caps fix, 1996), BIOS 1.16.3-debian-1.16.3-2 04/01/2014 [ 2.523866] Workqueue: smc_hs_wq smc_listen_work [ 2.523869] Call Trace: [ 2.523870] <TASK> [ 2.523871] dump_stack_lvl+0x53/0x70 [ 2.523872] print_report+0xd0/0x630 [ 2.523874] ? __pfx__raw_spin_lock_irqsave+0x10/0x10 [ 2.523876] ? smc_llc_save_add_link_rkeys+0x333/0x350 [ 2.523878] kasan_report+0xce/0x100 [ 2.523879] ? smc_llc_save_add_link_rkeys+0x333/0x350 [ 2.523881] smc_llc_save_add_link_rkeys+0x333/0x350 [ 2.523883] ? smcr_buf_reg_lgr+0x2a4/0x660 [ 2.523885] smc_llc_srv_add_link+0xaa2/0x1e50 [ 2.523888] ? _printk+0xba/0xf0 [ 2.523897] ? __pfx_smc_llc_srv_add_link+0x10/0x10 [ 2.523899] ? down_write+0xb0/0x130 [ 2.523903] ? __pfx_down_write+0x10/0x10 [ 2.523905] smc_listen_work+0x489e/0x4d00 [ 2.523907] ? kmem_cache_free+0x1c6/0x3a0 [ 2.523911] ? __pfx_smc_listen_work+0x10/0x10 [ 2.523913] ? release_sock+0x148/0x1d0 [ 2.523915] ? smc_tcp_listen_work+0xb4f/0xfc0 [ 2.523917] ? _raw_spin_lock_irq+0x80/0xe0 [ 2.523918] ? __pfx__raw_spin_lock_irq+0x10/0x10 [ 2.523920] process_one_work+0x633/0x1030 [ 2.523922] ? assign_work+0x11d/0x370 [ 2.523924] worker_thread+0x45b/0xd10 [ 2.523926] ? __pfx_worker_thread+0x10/0x10 [ 2.523928] ? __pfx_worker_thread+0x10/0x10 [ 2.523929] kthread+0x2c6/0x3b0 [ 2.523931] ? recalc_sigpending+0x15c/0x1e0 [ 2.523934] ? __pfx_kthread+0x10/0x10 [ 2.523935] ret_from_fork+0x36e/0x5a0 [ 2.523937] ? __pfx_ret_from_fork+0x10/0x10 [ 2.523938] ? __switch_to+0x572/0xdd0 [ 2.523943] ? __pfx_kthread+0x10/0x10 [ 2.523944] ret_from_fork_asm+0x1a/0x30 [ 2.523947] </TASK> [ 2.523948] [ 2.531253] Allocated by task 48: [ 2.531399] kasan_save_stack+0x33/0x60 [ 2.531570] kasan_save_track+0x14/0x30 [ 2.531737] __kasan_kmalloc+0x8f/0xa0 [ 2.531905] __kmalloc_cache_noprof+0x158/0x370 [ 2.532100] smc_llc_enqueue+0x72/0x560 [ 2.532268] smc_wr_rx_tasklet_fn+0x474/0xa80 [ 2.532491] tasklet_action_common+0x20f/0x8a0 [ 2.532714] handle_softirqs+0x18e/0x590 [ 2.532886] do_softirq+0x3b/0x60 [ 2.533036] __local_bh_enable_ip+0x61/0x70 [ 2.533221] __alloc_skb+0x732/0x890 [ 2.533384] rxe_init_packet+0x16b/0x4f0 [ 2.533567] prepare_ack_packet+0xb8/0x830 [ 2.533760] rxe_receiver+0x495/0x96e0 [ 2.533933] do_work+0x144/0x470 [ 2.534078] process_one_work+0x633/0x1030 [ 2.534257] worker_thread+0x45b/0xd10 [ 2.534424] kthread+0x2c6/0x3b0 [ 2.534569] ret_from_fork+0x36e/0x5a0 [ 2.534737] ret_from_fork_asm+0x1a/0x30 [ 2.534907] [ 2.534980] Freed by task 11: [ 2.535112] kasan_save_stack+0x33/0x60 [ 2.535279] kasan_save_track+0x14/0x30 [ 2.535444] kasan_save_free_info+0x3b/0x60 [ 2.535625] __kasan_slab_free+0x43/0x70 [ 2.535798] kfree+0x121/0x380 [ 2.535935] smc_llc_srv_add_link+0x9a8/0x1e50 [ 2.536128] smc_listen_work+0x489e/0x4d00 [ 2.536305] process_one_work+0x633/0x1030 [ 2.536482] worker_thread+0x45b/0xd10 [ 2.536652] kthread+0x2c6/0x3b0 [ 2.536794] ret_from_fork+0x36e/0x5a0 [ 2.536958] ret_from_fork_asm+0x1a/0x30 [ 2.537133] [ 2.537205] The buggy address belongs to the object at ffff888005219480 [ 2.537205] which belongs to the cache kmalloc-96 of size 96 [ 2.537719] The buggy address is located 94 bytes inside of [ 2.537719] freed 96-byte region [ffff888005219480, ffff8880052194e0) [ 2.538216] [ 2.538289] The buggy address belongs to the physical page: [ 2.538524] page: refcount:0 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x5219 [ 2.538857] flags: 0x100000000000000(node=0|zone=1) [ 2.539066] page_type: f5(slab) [ 2.539210] raw: 0100000000000000 ffff888001041280 dead000000000122 0000000000000000 [ 2.539534] raw: 0000000000000000 0000000000200020 00000000f5000000 0000000000000000 [ 2.539863] page dumped because: kasan: bad access detected [ 2.540098] [ 2.540170] Memory state around the buggy address: [ 2.540379] ffff888005219380: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc [ 2.540684] ffff888005219400: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc [ 2.540988] >ffff888005219480: fa fb fb fb fb fb fb fb fb fb fb fb fc fc fc fc [ 2.541291] ^ [ 2.541548] ffff888005219500: 00 00 00 00 00 00 00 00 00 fc fc fc fc fc fc fc [ 2.541857] ffff888005219580: 00 00 00 00 00 00 00 00 00 fc fc fc fc fc fc fc The offset is past the 72-byte queue entry because the out-of-bounds read fixed by the next patch is on the same line; what this patch removes is the free at smc_llc_srv_add_link+0x9a8 happening before the read at +0xaa2. Detach the entry instead of freeing it there, and free it at the single exit label. The reject path has to detach as well, otherwise it would be freed twice. This changes only the lifetime of the entry. The same read still runs past its end until the next two patches bound it, so a backport wants all three. Fixes: 27ef6a9981fe ("net/smc: support SMC-R V2 for rdma devices with max_recv_sge equals to 1") Cc: stable@vger.kernel.org Reviewed-by: Sidraya Jayagond <sidraya@linux.ibm.com> Signed-off-by: Yehyeong Lee <yhlee@isslab.korea.ac.kr> Reviewed-by: Breno Leitao <leitao@debian.org> Link: https://patch.msgid.link/20260819023306.644849-2-yhlee@isslab.korea.ac.kr Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2026-08-22xdp: fix zero-copy frame layoutWeiming Shi1-2/+2
xdp_convert_zc_to_xdp_frame() clones an XSK packet into an order-0 page and advertises PAGE_SIZE as its frame size. It allows the copied frame to occupy the page tail needed by skb_shared_info and records zero headroom even when metadata separates the frame header from packet data. An AF_XDP zero-copy packet redirected through cpumap can therefore make the skb overlap skb_shared_info or place it beyond the allocated page. Limit the copied layout to SKB_WITH_OVERHEAD(PAGE_SIZE) and include the metadata length in frame headroom. Redirect callers already handle a NULL conversion result. BUG: KASAN: slab-out-of-bounds in skb_gro_receive Write of size 4 at addr ffff88800cf37004 by task cpumap/1/map:1/146 Call Trace: skb_gro_receive (net/core/gro.c:174) udp_gro_receive (net/ipv4/udp_offload.c:812) inet_gro_receive (net/ipv4/af_inet.c:1539) dev_gro_receive (net/core/gro.c:515) gro_receive_skb (net/core/gro.c:633) cpu_map_kthread_run (kernel/bpf/cpumap.c:395) kthread (kernel/kthread.c:436) ret_from_fork (arch/x86/kernel/process.c:164) ret_from_fork_asm (arch/x86/entry/entry_64.S:255) Kernel panic - not syncing: KASAN: panic_on_warn set ... Fixes: b0d1beeff2a9 ("xdp: implement convert_to_xdp_frame for MEM_TYPE_ZERO_COPY") Cc: stable@vger.kernel.org Reported-by: Xiang Mei <xmei5@asu.edu> Signed-off-by: Weiming Shi <bestswngs@gmail.com> Link: https://patch.msgid.link/20260818154516.793517-1-bestswngs@gmail.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2026-08-22tcp: clamp route advmss to TCP_MIN_MSSYong Wang4-6/+6
tcp_select_initial_window() assumes that callers never pass an MSS smaller than 1, but route-derived advmss values can violate that assumption. A too-small explicit RTAX_ADVMSS is one way to get there, but it is not the only one. The same divide-by-zero can also be reached through the "default advmss" path when RTAX_ADVMSS is left at 0 and the effective advmss is later driven down by route MTU and min_adv_mss. Introduce a tcp_dst_advmss() helper that clamps route advmss to TCP_MIN_MSS before TCP consumes it, and use it in the TCP paths that derive advmss from dst metrics. This keeps the effective MSS from dropping to zero before tcp_select_initial_window() rounds the receive window. Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") Cc: stable@vger.kernel.org Reported-by: Vega <vega@nebusec.ai> Signed-off-by: Yong Wang <edragain@163.com> Signed-off-by: Ren Wei <weir@nebusec.ai> Link: https://patch.msgid.link/251eaf8277fa7c66364c9815c5da01662d269181.1787074852.git.edragain@163.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2026-08-22ipip: fix skb leak in collect_md mode when metadata_dst allocation failsAnton Danilov1-1/+1
In collect_md mode ipip_tunnel_rcv() returns 0 without freeing the skb when ip_tun_rx_dst() fails to allocate the metadata_dst. ipip_rcv() and mplsip_rcv() are registered as xfrm_tunnel handlers, so tunnel4_rcv() and tunnelmpls4_rcv() read the zero return as "the packet has been consumed" and do not free it either. The skb is leaked. The other tunnel drivers all dispose of the packet at this point: ip6_tunnel.c jumps to its drop label, ip_gre.c and ip6_gre.c return PACKET_REJECT, which makes gre_rcv() free the skb. Only ipip returns 0. Jump to the existing drop label instead. It frees the skb and still returns 0, so the packet keeps being reported as consumed, which is what we want here: the outer header has already been pulled, and neither the remaining handlers nor an ICMP unreachable have any use for it. Triggering this needs an ipip or mplsip tunnel in collect_md mode and an atomic allocation failure, which is why it has gone unnoticed. Fixes: cfc7381b3002 ("ip_tunnel: add collect_md mode to IPIP tunnel") Cc: stable@vger.kernel.org Signed-off-by: Anton Danilov <littlesmilingcloud@gmail.com> Reviewed-by: Fernando Fernandez Mancera <fmancera@suse.de> Link: https://patch.msgid.link/20260819104338.432631-2-littlesmilingcloud@gmail.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2026-08-22net/sched: account classifier filter allocations to memcgJamal Hadi Salim10-21/+25
Allocations in the tc classifier *_change() paths (filter objects, per-CPU counters, and per-filter aux data) use plain GFP_KERNEL without __GFP_ACCOUNT, allowing unprivileged users to pin kernel memory outside memcg charging. The shared tcf_exts_init_ex() action array allocation in cls_api.c was also uncharged; this patch closes it along with the per-classifier filter-object/percpu/aux allocations that remain unaccounted. Add GFP_KERNEL_ACCOUNT to: - the shared tcf_exts_init_ex() action array (cls_api.c), common to every filter of every classifier (32 pointers, 256 bytes); - the filter-object, per-CPU-counter, and per-filter aux allocations in cls_basic, cls_bpf, cls_cgroup, cls_flow, cls_flower, cls_fw, cls_matchall, cls_route and cls_u32; - the u32_init_knode() replace-path knode allocation (cls_u32.c), which allocates the same struct tc_u_knode + sel.keys on every replace of an existing knode and was missed by the create-path-only conversion. Also fix the cls_basic error path: basic_change() inserts fnew into the IDR before allocating the per-CPU counter. If alloc_percpu() fails the errout path kfree'd fnew without idr_remove, leaving a dangling pointer in the IDR. With GFP_KERNEL_ACCOUNT the percpu alloc becomes failable on demand (memcg at memory.max), making the dead path attacker-reachable and burning the handle permanently. Add the idr_remove on the percpu failure path, matching the basic_set_parms failure-path pattern. Note: vega@nebusec.ai provided a poc for basic_cls, but it was easy to extend to the other classifiers. Conditions to recreate the bug: - CONFIG_NET_SCHED, CONFIG_NET_CLS_* (the classifier being used), CONFIG_NET_CLS_ACT, CONFIG_MEMCG, CONFIG_USER_NS, CONFIG_NET_NS. - Unprivileged user in a fresh user+network namespace (unshare -Urn), or root with CAP_NET_ADMIN. - Create a large number of tc filters (e.g. tc filter add dev lo ingress ... <classifier> ...) while watching a memcg-limited cgroup: system slab grows far faster than memory.current, pinning kernel memory outside memcg charging. Fixes: 0da974f4f303 ("[NET]: Conversions from kmalloc+memset to k(z|c)alloc.") Reported-by: vega@nebusec.ai Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com> Reviewed-by: Breno Leitao <leitao@debian.org> Link: https://patch.msgid.link/20260819143733.57538-1-jhs@mojatatu.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2026-08-22Merge tag 'batadv-net-pullrequest-20260821' of https://git.open-mesh.org/batadvJakub Kicinski6-64/+100
Simon Wunderlich says: ==================== Here are a few batman-adv bugfixes: - fix stale receive device on merged fragments, by Zhiling Zou the others are written by Sven Eckelmann: - bla: fix potential CRC corruption issues (2 patches) - dat: avoid unaligned fault in IP extraction - dat: atomically update mac addresses - mcast: fix TX priority extraction for BATADV_FORW_MCAST - mcast: fix skb sharing and linearization (2 patches) - bla: fix freeing of claims on meshif deletion * tag 'batadv-net-pullrequest-20260821' of https://git.open-mesh.org/batadv: batman-adv: bla: fix freeing of claims on meshif deletion batman-adv: mcast: linearize skbuff for packet generation batman-adv: mcast: ensure unshared skb for multicast packets batman-adv: fix TX priority extraction for BATADV_FORW_MCAST batman-adv: dat: atomically update mac addresses batman-adv: dat: avoid unaligned fault in IP extraction batman-adv: bla: prevent CRC corruptions after claim flush batman-adv: bla: avoid CRC corruption due to parallel claim add batman-adv: fix stale receive device on merged fragments ==================== Link: https://patch.msgid.link/20260821094813.201800-1-sw@simonwunderlich.de Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2026-08-21Merge tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rdma/rdmaLinus Torvalds6-23/+31
Pull RDMA updates from Jason Gunthorpe: "About the normal size, still a lot of AI bug fixes and so on, but some interesting new functionality too: - Assorted locking, bounds-checking, cleanup, and error-path fixes across UCMA/CMA, bng_re, bnxt_re, cxgb4, EFA, ERDMA, HFI1, HNS, ionic, iRDMA, mlx4/mlx5, RXE, SIW, SRP/SRPT, and iSER target. - netlink report for max # of supported resources - get_zeroed_page()/etc removal - Robust udata for ionic - Allow unique RDMA device names per network namespace - Completion counters and v2 admit queue support for EFA - UC QP support for MANA - Completion timestamps for ionic - Harden uverbs data validation and resource lifetime handling, fixing several core use-after-free conditions. - bnxt_re toggle-page ownership and lifetime bug fixes - dmabuf SRQ support for mlx5" * tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rdma/rdma: (160 commits) RDMA/ucma: Allow path records to exactly fit the output buffer RDMA/uverbs: Guard legacy bundles without method_elm RDMA/efa: Add support for 128B admin v2 SQ entry RDMA/efa: Generalize the admin SQ RDMA/efa: Decouple admin command payload from admin header RDMA/rxe: Fix OOB in free_rd_atomic_resources() RDMA/cma: Fix WARNING in res_to_rt RDMA/cxgb4: Free debugfs on registration failure RDMA/cxgb4: Cancel reg_work before freeing device on remove RDMA/ucma: Lock the handler in ucma_set_ib_path() RDMA/ucma: Lock the handler in ucma_write_cm_event() RDMA/erdma: restrict the driver to little-endian systems RDMA/ionic: Embed counter driver data in rdma_counter allocation RDMA/ionic: Cap eq_count to the eth driver's interrupt vector budget RDMA/siw: Fix use-after-free in siw_accept() IB/isert: post the full-feature receive buffers after session registration IB/isert: delay the final Login Response until the session is registered RDMA/srp: fix heap information leak on a truncated SRP_CRED_REQ RDMA/erdma: Hold QP references for AE and CM processing RDMA/erdma: Hold CQ references when processing EQ events ...
2026-08-20Merge tag 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mst/vhostLinus Torvalds1-0/+13
Pull vhost,vdpa,virtio updates from Michael Tsirkin: - transport v3 support in virtio-mmio - suspend support in vduse - fixes, cleanups all over the place * tag 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost: (54 commits) vduse: Add suspend vduse: do not take rwsem at reset work flush vduse: add F_QUEUE_READY feature vduse: add VDUSE_SET_FEATURES ioctl vduse: add VDUSE_GET_FEATURES ioctl vduse: store control device pointer tools/virtio: Fix control typo in trace agent comment tools/virtio: Fix userspace typo in vringh test comment vhost: reject zero-size IOTLB INVALIDATE vdpa: Remove redundant dev_err() virtio_ring: fix infinite loop in virtnet_poll_cleantx when device is broken vdpa/mlx5: roll back MR update after VQ setup failure MAINTAINERS: remove Gabriel from LiteX and fw-cfg drivers virtio_mem: fix typo in comment vdpa/solidrun: fix typos in snet_ctrl comments virtio: fix article before virtio in dma-buf comment vhost: fix inaccurate kdoc in iotlb helpers virtio: rtc: time out alarm requests vdpa/mlx5: fix wrong MLX5_ADDR_OF struct type in alloc_inout() vdpa: octeon_ep: add missing MODULE_DEVICE_TABLE() ...
2026-08-20net: bridge: arp/nd proxy: fix reading neigh haNikolay Aleksandrov1-10/+14
Currently neigh ha address is read directly, but that can result in torn/partial reads if the neigh is being updated. Use neigh_ha_snapshot to take a stable snapshot of the address. Fixes: 057658cb33fb ("bridge: suppress arp pkts on BR_NEIGH_SUPPRESS ports") Fixes: ed842faeb2bd ("bridge: suppress nd pkts on BR_NEIGH_SUPPRESS ports") Signed-off-by: Nikolay Aleksandrov <razor@blackwall.org> Reviewed-by: Petr Machata <petrm@nvidia.com> Reviewed-by: Ido Schimmel <idosch@nvidia.com> Link: https://patch.msgid.link/20260818150756.890025-2-razor@blackwall.org Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2026-08-20net/smc: free pending qentry in smc_llc_flow_stop() before memsetMahanta Jambigi1-0/+1
smc_llc_flow_stop() resets a flow struct with a blind memset: spin_lock_bh(&lgr->llc_flow_lock); memset(flow, 0, sizeof(*flow)); flow->type = SMC_LLC_FLOW_NONE; spin_unlock_bh(&lgr->llc_flow_lock); If flow->qentry is non-NULL at this point the pointer is overwritten without the allocation being freed, leaking one kmalloc object. A late-arriving duplicate CONFIRM_LINK or ADD_LINK_CONT message can set flow->qentry after the legitimate message has been consumed by the waiter via smc_llc_flow_qentry_clr() (which NULLs the pointer but leaves flow->type non-zero) but before the flow completes and smc_llc_flow_stop() runs. In that window the duplicate is stashed into flow->qentry, and then lost when smc_llc_flow_stop() zeros the struct. Call smc_llc_flow_qentry_del() inside the lock before the memset. smc_llc_flow_qentry_del() already checks flow->qentry before freeing, so the normal case where no entry is pending is a no-op. Fixes: 555da9af827d ("net/smc: add event-based llc_flow framework") Reviewed-by: Hidayath Khan <hidayath@linux.ibm.com> Signed-off-by: Mahanta Jambigi <mjambigi@linux.ibm.com> Link: https://patch.msgid.link/20260818073943.1108383-1-mjambigi@linux.ibm.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2026-08-20net/smc: free stashed qentry before overwrite in REQ_ADD_LINK to ADD_LINK ↵Mahanta Jambigi1-0/+2
transition When smc_llc_event_handler() transitions the local LLC flow from SMC_LLC_FLOW_REQ_ADD_LINK to SMC_LLC_FLOW_ADD_LINK on arrival of an ADD_LINK request, it calls smc_llc_flow_qentry_set() unconditionally: if (lgr->llc_flow_lcl.type == SMC_LLC_FLOW_REQ_ADD_LINK) { lgr->llc_flow_lcl.type = SMC_LLC_FLOW_ADD_LINK; smc_llc_flow_qentry_set(&lgr->llc_flow_lcl, qentry); ... } A CONFIRM_LINK or ADD_LINK_CONT arriving while flow->type is SMC_LLC_FLOW_REQ_ADD_LINK is stashed into flow->qentry via the SMC_LLC_CONFIRM_LINK / SMC_LLC_ADD_LINK_CONT handler (which stores into flow->qentry for any non-NONE flow type). When the subsequent ADD_LINK arrives, the REQ_ADD_LINK branch overwrites flow->qentry with the new pointer without first freeing the stashed allocation, leaking one kmalloc object. The stashed entry has no consumer: smc_llc_wait() is only called from llc_add_link_work, which is not yet scheduled while the flow type remains REQ_ADD_LINK. No waiter is sleeping on llc_msg_waiter at this point. It is safe to unconditionally free any stashed qentry before the overwrite. Call smc_llc_flow_qentry_del() before smc_llc_flow_qentry_set() in the REQ_ADD_LINK branch. smc_llc_flow_qentry_del() already checks flow->qentry before freeing, so the normal path where no entry is stashed is a no-op. Fixes: b4ba4652b3f8 ("net/smc: extend LLC layer for SMC-Rv2") Reviewed-by: Hidayath Khan <hidayath@linux.ibm.com> Signed-off-by: Mahanta Jambigi <mjambigi@linux.ibm.com> Link: https://patch.msgid.link/20260818073107.466506-1-mjambigi@linux.ibm.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2026-08-20Merge tag 'for-7.3/block-20260819' of ↵Linus Torvalds1-2/+2
git://git.kernel.org/pub/scm/linux/kernel/git/axboe/linux Pull block updates from Jens Axboe: - NVMe updates via Keith: - Enable Clang context analysis for the nvme host driver, adding context annotations across core, fabrics, rdma, tcp and pci - nvmet reservation state exposed through a new namespace-level debugfs directory, plus ABI documentation for the host sysfs and target configfs interfaces - nvme-tcp host memory disclosure fixes on the read path: reject a read that transferred too few bytes, don't accept C2HData based on blk_rq_payload_bytes() alone, and fix the R2T case for a read command - Parallelize nvme-rdma I/O queue allocation and startup (Surabhi) - Apple nvme fixes and quirks: page aligned admin queue buffers, destroy the admin queue on removal, and various DMA/NVMMU correctness fixes - A large pile of nvmet and host fixes for out-of-bounds reads, refcount/resource leaks, and NULL derefs across auth, zns, passthru, pci-epf, rdma and configfs - Various other fixes and cleanups - MD updates via Yu Kuai: - llbitmap reshape support, the large series wiring exact bitmap mapping and reshape lifecycle through raid5 and raid10, growing the page cache in place, and remapping checkpointed bits as reshape progresses - raid5 fixes for lockless max_nr_stripes and recovery_offset accesses, a reshape deadlock with more failed devices than max degraded, and bitmap batch counter consistency - Atomic write handling for raid1/raid10, and removal of the REQ_NOWAIT support from raid1/10/456 - raid5-ppl use-after-free fix in ppl_do_flush() - A batch of smaller fixes across md core and the bitmap code - s390/dasd ESE full-track write support and the surrounding infrastructure, plus enabling CONTEXT_ANALYSIS for s390/block - RWF_DONTCACHE support for block devices, built on new task-context bio completion infrastructure, and wiring it up for the iomap and buffer dropbehind writeback paths - Async io_uring zone reset all, plus zone management command cleanups allowing REQ_NOWAIT and tightening conventional zone rejection - Block integrity refactoring: lift BIP_CHECK_FLAGS to the shared header, handle nogenerate/noverify properly in fs-integrity, and drop the blk-integrity.h include from bdev.c - Split out a new blk_plug.h header - ublk improvements: add UBLK_F_IO_DESC_SIZE, split request validation from io_desc init, reject non-power-of-2 zone sizes in SET_PARAMS, and a series of hardening fixes around map/unmap and auto buf reg - null_blk cleanups and configfs serialization fixes - nbd queue freeze removal on the setup paths, and a new pre_defined_connections module parameter for pre-created devices - blk-cgroup fixes for the race between policy activation and blkg destruction, and accounting per-cpu stats over possible CPUs across blk-stat, iolatency, iocost and kyber - Various dio fixes: leak on metadata mapping error, validate user space vectors during extraction, and set dma_alignment from the backing file for loop and zloop direct I/O - bio cleanups - Various other fixes and cleanups all over * tag 'for-7.3/block-20260819' of git://git.kernel.org/pub/scm/linux/kernel/git/axboe/linux: (241 commits) nbd: add pre_defined_connections module parameter for pre-created devices nbd: remove queue freeze for newly created nbd from netlink path nbd: factor out a nbd_genl_foreach_sock nbd: skip queue freeze when setting size at device startup nbd: remove queue freeze in nbd_add_socket nbd: clear queue limits on disconnect nbd: disallow NBD_SET_SOCK on an active device nbd: simplify find_fallback() by removing redundant logic blk-mq: add missing call to srcu_barrier() in blk_mq_free_tag_set() block: mtip32xx: synchronize ioctls with device removal ublk: avoid teardown retry loop on xarray allocation failure null_blk: fix UBSAN shift-out-of-bounds when zone_size is 0 or overflows block: don't include blk-integrity.h in bdev.c xfs: avoid double deferrals for RWF_DONTCACHE writes loop: Fix recently introduced lock inversion block: set QUEUE_FLAG_DYING unconditionally in blk_mark_disk_dead() swim3: Add missing MODULE_DESCRIPTION selftests: ublk: add SET_PARAMS validation test selftests: ublk: add helper for SET_PARAMS ublk: reject non-power-of-2 zone sizes in SET_PARAMS ...
2026-08-20sctp: drop a chunk if its transport was removedHyunwoo Kim1-2/+5
sctp_rcv() resolves the transport once per packet and leaves it in chunk->transport. The lookup reference, or the one sctp_add_backlog() takes if the socket is owned by userspace, keeps it around until the chunk has been processed. An authenticated ASCONF DEL-IP can remove it in the meantime. sctp_assoc_rm_peer() takes the transport out of the association and calls sctp_transport_free(), which tags it dead and drops the reference the association held. There is a window on both paths: the packet can sit on the socket backlog, and on the direct path the lookup completes before bh_lock_sock(). The DATA chunk in that packet puts the removed transport back into asoc->peer.last_data_from. Once the packet is done that reference goes away and the transport is freed by RCU, so the next delayed SACK carries the pointer into the SACK chunk and sctp_outq_select_transport() reads the freed transport's state. Drop the chunk in sctp_inq_push(), next to the existing rcvr->dead check. Both paths reach it with the association's socket lock held. The peer retransmits it. Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") Cc: stable@vger.kernel.org Signed-off-by: Hyunwoo Kim <imv4bel@gmail.com> Acked-by: Xin Long <lucien.xin@gmail.com> Link: https://patch.msgid.link/aoUJHQmxL0LFIMCw@v4bel Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2026-08-20net: sched: fix 32-bit backlog wrap in gred, bfifo and plug enqueueJamal Hadi Salim3-4/+4
gred_enqueue(), bfifo_enqueue() and plug_enqueue() admit a packet when the current backlog plus the packet length fits within the queue limit: sch->qstats.backlog + qdisc_pkt_len(skb) <= sch->limit (gred default VQ) gred_backlog+qdisc_pkt_len(skb) <= q->limit (gred configured VQ) sch->qstats.backlog + qdisc_pkt_len(skb) <= sch->limit (bfifo) sch->qstats.backlog + skb->len <= q->limit (plug) sch->qstats.backlog and q->backlog are u32, and qdisc_pkt_len()/skb->len are unsigned int, so all sums are computed in 32 bits and wrap at 2^32. Once the true backlog exceeds 4 GiB the wrapped sum becomes small and admission keeps succeeding, so the queue grows without bound and the kernel can be driven to OOM. Promote the sums to u64 so admission stops once the true backlog exceeds the limit. The limit is u32, so the bounded queue stays below 2^32 and the stored u32 backlog never wraps. The bug can only be reproduced as root (albeit with ridiculous setup): attach a gred (or bfifo/plug) qdisc with a limit near 4 GiB, leaving the default VQ unconfigured (for gred), and drive >4 GiB of queued traffic (e.g. via a size table / stab to inflate qdisc_pkt_len, or sustained high-rate traffic). The u32 backlog+len sum wraps at 2^32, admission keeps succeeding, and the queue grows unboundedly to OOM. Fixes: a3eb95f891d6 ("net_sched: gred: add TCA_GRED_LIMIT attribute") Reported-by: vega@nebusec.ai Tested-by: Victor Nogueira <victor@mojatatu.com> Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com> Reviewed-by: Simon Horman <horms@kernel.org> Link: https://patch.msgid.link/20260818095927.15901-1-jhs@mojatatu.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2026-08-20net: tcp: block mixing readable and unreadable fragsMina Almasry1-1/+2
Protect tcp_sendmsg_locked() from mistakenly mixing readable and unreadable page fragments in the same SKB. Check that the devmem binding matches the existing SKB's readability. If a mismatch is detected, avoid collapsing and create a new segment. Fixes: bd61848900bff ("net: devmem: Implement TX path") Suggested-by: Eric Dumazet <edumazet@google.com> Cc: Pavel Begunkov <asml.silence@gmail.com> Cc: Stanislav Fomichev <sdf@fomichev.me> Cc: Bobby Eshleman <bobbyeshleman@gmail.com> Signed-off-by: Mina Almasry <almasrymina@google.com> Link: https://patch.msgid.link/20260814191336.187243-2-almasrymina@google.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>