]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
7.1-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 29 Jul 2026 14:46:47 +0000 (16:46 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 29 Jul 2026 14:46:47 +0000 (16:46 +0200)
added patches:
gve-fix-rx-queue-stall-on-alloc-failure.patch
ice-reject-out-of-range-ptype-in-ice_parser_profile_init.patch
ice-use-read_once-to-access-cached-phc-time.patch
ila-reload-ipv6-header-after-pskb_may_pull-in-checksum-adjust.patch
mac802154-hold-an-interface-reference-across-the-scan-worker.patch
mac802154-llsec-reject-frames-shorter-than-the-authentication-tag.patch
mctp-serial-handle-zero-length-frames-to-prevent-rx-buffer-overflow.patch
openvswitch-fix-gso-userspace-truncation-underflow.patch
ovpn-fix-peer-refcount-leak-in-tcp-error-paths.patch
ovpn-hold-peer-before-scheduling-keepalive-work.patch
pppoe-reload-header-pointer-after-dev_hard_header.patch
rtase-workaround-for-tx-hang-caused-by-hardware-packet-parsing.patch
tcp-challenge-ack-for-non-exact-rst-in-syn-received.patch
tcp-initialize-standalone-tcp-ao-response-padding.patch
tipc-clear-sock-sk-on-the-failed-insert-path-in-tipc_sk_create.patch
vsock-virtio-collapse-receive-queue-under-memory-pressure.patch
vxlan-mdb-fix-source-list-corruption-on-a-failed-replace.patch
watchdog-s32g_wdt-remove-incorrect-options-in-watchdog_info-struct.patch

19 files changed:
queue-7.1/gve-fix-rx-queue-stall-on-alloc-failure.patch [new file with mode: 0644]
queue-7.1/ice-reject-out-of-range-ptype-in-ice_parser_profile_init.patch [new file with mode: 0644]
queue-7.1/ice-use-read_once-to-access-cached-phc-time.patch [new file with mode: 0644]
queue-7.1/ila-reload-ipv6-header-after-pskb_may_pull-in-checksum-adjust.patch [new file with mode: 0644]
queue-7.1/mac802154-hold-an-interface-reference-across-the-scan-worker.patch [new file with mode: 0644]
queue-7.1/mac802154-llsec-reject-frames-shorter-than-the-authentication-tag.patch [new file with mode: 0644]
queue-7.1/mctp-serial-handle-zero-length-frames-to-prevent-rx-buffer-overflow.patch [new file with mode: 0644]
queue-7.1/openvswitch-fix-gso-userspace-truncation-underflow.patch [new file with mode: 0644]
queue-7.1/ovpn-fix-peer-refcount-leak-in-tcp-error-paths.patch [new file with mode: 0644]
queue-7.1/ovpn-hold-peer-before-scheduling-keepalive-work.patch [new file with mode: 0644]
queue-7.1/pppoe-reload-header-pointer-after-dev_hard_header.patch [new file with mode: 0644]
queue-7.1/rtase-workaround-for-tx-hang-caused-by-hardware-packet-parsing.patch [new file with mode: 0644]
queue-7.1/series
queue-7.1/tcp-challenge-ack-for-non-exact-rst-in-syn-received.patch [new file with mode: 0644]
queue-7.1/tcp-initialize-standalone-tcp-ao-response-padding.patch [new file with mode: 0644]
queue-7.1/tipc-clear-sock-sk-on-the-failed-insert-path-in-tipc_sk_create.patch [new file with mode: 0644]
queue-7.1/vsock-virtio-collapse-receive-queue-under-memory-pressure.patch [new file with mode: 0644]
queue-7.1/vxlan-mdb-fix-source-list-corruption-on-a-failed-replace.patch [new file with mode: 0644]
queue-7.1/watchdog-s32g_wdt-remove-incorrect-options-in-watchdog_info-struct.patch [new file with mode: 0644]

diff --git a/queue-7.1/gve-fix-rx-queue-stall-on-alloc-failure.patch b/queue-7.1/gve-fix-rx-queue-stall-on-alloc-failure.patch
new file mode 100644 (file)
index 0000000..1dbe02a
--- /dev/null
@@ -0,0 +1,147 @@
+From b65352a1bac64442ad95e64f385b40ccb9f1b0db Mon Sep 17 00:00:00 2001
+From: Eddie Phillips <eddiephillips@google.com>
+Date: Thu, 9 Jul 2026 21:19:06 +0000
+Subject: gve: fix Rx queue stall on alloc failure
+
+From: Eddie Phillips <eddiephillips@google.com>
+
+commit b65352a1bac64442ad95e64f385b40ccb9f1b0db upstream.
+
+When the system is under extreme memory pressure, page allocations can
+fail during the Rx buffer refill loop. If the number of buffers posted
+to hardware falls below a critical low threshold and the refill loop
+exits due to allocation failures, the queue can stall:
+
+1. The device drops incoming packets because there are no descriptors.
+2. Since no packets are processed, no Rx completions are generated.
+3. Because no completions occur, NAPI is never scheduled, preventing
+   the refill loop from running again even after memory is freed.
+
+This results in a permanent queue stall.
+
+Resolve this by introducing a starvation recovery timer for each Rx queue.
+If the number of buffers posted to hardware falls below a critical low
+threshold, start a timer to periodically reschedule NAPI. Once NAPI runs
+and successfully refills the queue above the threshold, the timer is
+not rescheduled.
+
+The threshold is set to 32 because a single maximum-sized Receive Segment
+Coalescing (RSC) packet can consume up to 19 descriptors in the Rx path.
+Lower thresholds (such as 8 or 16) would be insufficient to process a
+complete maximum-sized RSC packet, risking packet drops or unexpected
+hardware behavior under memory pressure. Setting the threshold to 32
+guarantees a safe margin to handle at least one full RSC packet.
+
+Cc: stable@vger.kernel.org
+Fixes: 9b8dd5e5ea48 ("gve: DQO: Add RX path")
+Reviewed-by: Jordan Rhee <jordanrhee@google.com>
+Signed-off-by: Eddie Phillips <eddiephillips@google.com>
+Signed-off-by: Harshitha Ramamurthy <hramamurthy@google.com>
+Reviewed-by: Przemek Kitszel <przemyslaw.kitszel@intel.com>
+Link: https://patch.msgid.link/20260709211906.3322883-1-hramamurthy@google.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/ethernet/google/gve/gve.h        |    3 ++
+ drivers/net/ethernet/google/gve/gve_rx_dqo.c |   34 +++++++++++++++++++++++++++
+ 2 files changed, 37 insertions(+)
+
+--- a/drivers/net/ethernet/google/gve/gve.h
++++ b/drivers/net/ethernet/google/gve/gve.h
+@@ -13,6 +13,7 @@
+ #include <linux/netdevice.h>
+ #include <linux/net_tstamp.h>
+ #include <linux/pci.h>
++#include <linux/timer.h>
+ #include <linux/ptp_clock_kernel.h>
+ #include <linux/u64_stats_sync.h>
+ #include <net/page_pool/helpers.h>
+@@ -41,6 +42,7 @@
+ /* Interval to schedule a stats report update, 20000ms. */
+ #define GVE_STATS_REPORT_TIMER_PERIOD 20000
++#define GVE_RX_NAPI_RESCHED_MS 20 /* msecs */
+ /* Numbers of NIC tx/rx stats in stats report. */
+ #define NIC_TX_STATS_REPORT_NUM       0
+@@ -341,6 +343,7 @@ struct gve_rx_ring {
+       struct xdp_rxq_info xdp_rxq;
+       struct xsk_buff_pool *xsk_pool;
+       struct page_frag_cache page_cache; /* Page cache to allocate XDP frames */
++      struct timer_list starvation_timer; /* for queue starvation recovery */
+ };
+ /* A TX desc ring entry */
+--- a/drivers/net/ethernet/google/gve/gve_rx_dqo.c
++++ b/drivers/net/ethernet/google/gve/gve_rx_dqo.c
+@@ -18,6 +18,16 @@
+ #include <net/tcp.h>
+ #include <net/xdp_sock_drv.h>
++static void gve_rx_starvation_timer(struct timer_list *t)
++{
++      struct gve_rx_ring *rx = timer_container_of(rx, t, starvation_timer);
++      struct gve_priv *priv = rx->gve;
++      struct gve_notify_block *block;
++
++      block = &priv->ntfy_blocks[rx->ntfy_id];
++      napi_schedule(&block->napi);
++}
++
+ static void gve_rx_free_hdr_bufs(struct gve_priv *priv, struct gve_rx_ring *rx)
+ {
+       struct device *hdev = &priv->pdev->dev;
+@@ -120,6 +130,7 @@ void gve_rx_stop_ring_dqo(struct gve_pri
+       if (rx->dqo.page_pool)
+               page_pool_disable_direct_recycling(rx->dqo.page_pool);
++      timer_shutdown_sync(&rx->starvation_timer);
+       gve_remove_napi(priv, ntfy_idx);
+       gve_rx_remove_from_block(priv, idx);
+       gve_rx_reset_ring_dqo(priv, idx);
+@@ -208,8 +219,10 @@ static int gve_rx_alloc_hdr_bufs(struct
+ void gve_rx_start_ring_dqo(struct gve_priv *priv, int idx)
+ {
+       int ntfy_idx = gve_rx_idx_to_ntfy(priv, idx);
++      struct gve_rx_ring *rx = &priv->rx[idx];
+       gve_rx_add_to_block(priv, idx);
++      timer_setup(&rx->starvation_timer, gve_rx_starvation_timer, 0);
+       gve_add_napi(priv, ntfy_idx, gve_napi_poll_dqo);
+ }
+@@ -365,6 +378,7 @@ void gve_rx_post_buffers_dqo(struct gve_
+       struct gve_rx_compl_queue_dqo *complq = &rx->dqo.complq;
+       struct gve_rx_buf_queue_dqo *bufq = &rx->dqo.bufq;
+       struct gve_priv *priv = rx->gve;
++      u32 num_bufs_avail_to_hw;
+       u32 num_avail_slots;
+       u32 num_full_slots;
+       u32 num_posted = 0;
+@@ -400,6 +414,26 @@ void gve_rx_post_buffers_dqo(struct gve_
+       }
+       rx->fill_cnt += num_posted;
++
++      /* If the queue has fewer than GVE_RX_BUF_THRESH_DQO descriptors
++       * visible to the hardware, the hardware is in danger of starving
++       * and cannot trigger interrupts.
++       *
++       * We use a threshold of 32 because a single maximum-sized RSC
++       * packet can consume up to 19 descriptors in the Rx path. Lower
++       * thresholds (e.g., 8 or 16) would be unsafe as they could cause
++       * the device to drop/stall on a maximum-sized RSC packet.
++       *
++       * Start the timer to periodically reschedule NAPI and recover.
++       */
++      num_bufs_avail_to_hw =
++              ((bufq->tail & ~(GVE_RX_BUF_THRESH_DQO - 1)) -
++               bufq->head) & bufq->mask;
++
++      if (num_bufs_avail_to_hw < GVE_RX_BUF_THRESH_DQO) {
++              mod_timer(&rx->starvation_timer,
++                        jiffies + msecs_to_jiffies(GVE_RX_NAPI_RESCHED_MS));
++      }
+ }
+ static void gve_rx_skb_csum(struct sk_buff *skb,
diff --git a/queue-7.1/ice-reject-out-of-range-ptype-in-ice_parser_profile_init.patch b/queue-7.1/ice-reject-out-of-range-ptype-in-ice_parser_profile_init.patch
new file mode 100644 (file)
index 0000000..f0ee664
--- /dev/null
@@ -0,0 +1,64 @@
+From 59abb87159c53605c063f6e2ceb215b5eba43ee6 Mon Sep 17 00:00:00 2001
+From: Aleksandr Loktionov <aleksandr.loktionov@intel.com>
+Date: Fri, 17 Jul 2026 11:53:33 -0700
+Subject: ice: reject out-of-range ptype in ice_parser_profile_init
+
+From: Aleksandr Loktionov <aleksandr.loktionov@intel.com>
+
+commit 59abb87159c53605c063f6e2ceb215b5eba43ee6 upstream.
+
+set_bit(rslt->ptype, prof->ptypes) operates on a DECLARE_BITMAP of
+ICE_FLOW_PTYPE_MAX (1024) bits. Nothing prevents a malicious VF from
+providing ptype >= 1024 through VIRTCHNL, resulting in a write past
+the end of the bitmap and a kernel page fault.
+
+Reproduced with a custom kernel module injecting a crafted
+VIRTCHNL_OP_ADD_RSS_CFG on E810-C QSFP (8086:1592),
+FW 4.91 0x800214af 1.3909.0, ICE COMMS DDP 1.3.53.0,
+kernel 7.1.0-rc1.
+
+crash_parser: ice_parser_profile_init @ ffffffffc0d61b60
+crash_parser: setting ptype=0xffff (max valid=1023)
+crash_parser: calling ice_parser_profile_init -- expect OOB crash!
+BUG: kernel NULL pointer dereference, address: 0000000000000000
+Oops: Oops: 0002 [#1] SMP NOPTI
+CPU: 56 UID: 0 PID: 165011 Comm: insmod Kdump: loaded Tainted: G S U OE 7.1.0-rc1 #1
+Hardware name: Intel Corporation S2600BPB/S2600BPB
+RIP: 0010:ice_parser_profile_init+0x2d/0x1d0 [ice]
+Call Trace:
+ <TASK>
+ ? __pfx_ice_parser_profile_init+0x10/0x10 [ice]
+ crash_init+0x127/0xff0 [crash_parser]
+ do_one_initcall+0x45/0x310
+ do_init_module+0x64/0x270
+ init_module_from_file+0xcc/0xf0
+ idempotent_init_module+0x17b/0x280
+ __x64_sys_finit_module+0x6e/0xe0
+
+Bail out early with -EINVAL when ptype is out of range.
+
+Fixes: e312b3a1e209 ("ice: add API for parser profile initialization")
+Cc: stable@vger.kernel.org
+Signed-off-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com>
+Reviewed-by: Marcin Szycik <marcin.szycik@linux.intel.com>
+Tested-by: Rafal Romanowski <rafal.romanowski@intel.com>
+Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
+Link: https://patch.msgid.link/20260717185340.3595286-12-anthony.l.nguyen@intel.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/ethernet/intel/ice/ice_parser.c |    3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/drivers/net/ethernet/intel/ice/ice_parser.c
++++ b/drivers/net/ethernet/intel/ice/ice_parser.c
+@@ -2368,6 +2368,9 @@ int ice_parser_profile_init(struct ice_p
+       u16 proto_off = 0;
+       u16 off;
++      if (rslt->ptype >= ICE_FLOW_PTYPE_MAX)
++              return -EINVAL;
++
+       memset(prof, 0, sizeof(*prof));
+       set_bit(rslt->ptype, prof->ptypes);
+       if (blk == ICE_BLK_SW) {
diff --git a/queue-7.1/ice-use-read_once-to-access-cached-phc-time.patch b/queue-7.1/ice-use-read_once-to-access-cached-phc-time.patch
new file mode 100644 (file)
index 0000000..3b7f378
--- /dev/null
@@ -0,0 +1,39 @@
+From 2915681b89f817677ab9f1166d95b595bc144f5f Mon Sep 17 00:00:00 2001
+From: Sergey Temerkhanov <sergey.temerkhanov@intel.com>
+Date: Fri, 17 Jul 2026 11:53:30 -0700
+Subject: ice: use READ_ONCE() to access cached PHC time
+
+From: Sergey Temerkhanov <sergey.temerkhanov@intel.com>
+
+commit 2915681b89f817677ab9f1166d95b595bc144f5f upstream.
+
+ptp.cached_phc_time is a 64-bit value updated by a periodic work item
+on one CPU and read locklessly on another.  On 32-bit or non-atomic
+architectures this can result in a torn read.  Use READ_ONCE() to
+enforce a single atomic load.
+
+Fixes: 77a781155a65 ("ice: enable receive hardware timestamping")
+Cc: stable@vger.kernel.org
+Signed-off-by: Sergey Temerkhanov <sergey.temerkhanov@intel.com>
+Signed-off-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Tested-by: Rinitha S <sx.rinitha@intel.com> (A Contingent worker at Intel)
+Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
+Link: https://patch.msgid.link/20260717185340.3595286-9-anthony.l.nguyen@intel.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/ethernet/intel/ice/ice_ptp.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/net/ethernet/intel/ice/ice_ptp.c
++++ b/drivers/net/ethernet/intel/ice/ice_ptp.c
+@@ -350,7 +350,7 @@ static u64 ice_ptp_extend_40b_ts(struct
+               return 0;
+       }
+-      return ice_ptp_extend_32b_ts(pf->ptp.cached_phc_time,
++      return ice_ptp_extend_32b_ts(READ_ONCE(pf->ptp.cached_phc_time),
+                                    (in_tstamp >> 8) & mask);
+ }
diff --git a/queue-7.1/ila-reload-ipv6-header-after-pskb_may_pull-in-checksum-adjust.patch b/queue-7.1/ila-reload-ipv6-header-after-pskb_may_pull-in-checksum-adjust.patch
new file mode 100644 (file)
index 0000000..2a6a819
--- /dev/null
@@ -0,0 +1,83 @@
+From 92d3817649df2b0b6a008a686c8275c88d7ef594 Mon Sep 17 00:00:00 2001
+From: Michael Bommarito <michael.bommarito@gmail.com>
+Date: Tue, 14 Jul 2026 07:49:03 -0400
+Subject: ila: reload IPv6 header after pskb_may_pull in checksum adjust
+
+From: Michael Bommarito <michael.bommarito@gmail.com>
+
+commit 92d3817649df2b0b6a008a686c8275c88d7ef594 upstream.
+
+ila_csum_adjust_transport() caches ip6h = ipv6_hdr(skb) before calling
+pskb_may_pull(). On a non-linear skb whose transport header sits in a page
+fragment, pskb_may_pull() can call __pskb_pull_tail() / pskb_expand_head()
+and free the old skb head, leaving ip6h dangling; the following
+get_csum_diff(ip6h, p) then reads freed memory. ila_update_ipv6_locator()
+uses ip6h (and the iaddr derived from it) again after the csum-adjust
+call and additionally writes the new locator through that pointer.
+
+Impact: a remote IPv6 packet routed through a configured ILA
+csum-adjust-transport route or receive-side mapping triggers a
+slab-use-after-free in ila_update_ipv6_locator() (KASAN). The route or
+mapping requires CAP_NET_ADMIN to configure, but trigger packets are
+unauthenticated once it exists.
+
+Reload ip6h after each pskb_may_pull() in ila_csum_adjust_transport()
+before the csum-diff read. In ila_update_ipv6_locator() only the
+ILA_CSUM_ADJUST_TRANSPORT case pulls the skb, so reload ip6h and iaddr in
+that case alone before the destination-address write; the neutral-map
+modes never pull and keep their cached pointers.
+
+Fixes: 33f11d16142b ("ila: Create net/ipv6/ila directory")
+Cc: stable@vger.kernel.org
+Signed-off-by: Michael Bommarito <michael.bommarito@gmail.com>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Reviewed-by: Antoine Tenart <atenart@kernel.org>
+Link: https://patch.msgid.link/20260714114903.3763420-1-michael.bommarito@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ipv6/ila/ila_common.c |   12 ++++++++++++
+ 1 file changed, 12 insertions(+)
+
+--- a/net/ipv6/ila/ila_common.c
++++ b/net/ipv6/ila/ila_common.c
+@@ -85,6 +85,7 @@ static void ila_csum_adjust_transport(st
+                       struct tcphdr *th = (struct tcphdr *)
+                                       (skb_network_header(skb) + nhoff);
++                      ip6h = ipv6_hdr(skb);
+                       diff = get_csum_diff(ip6h, p);
+                       inet_proto_csum_replace_by_diff(&th->check, skb,
+                                                       diff, true, true);
+@@ -96,6 +97,7 @@ static void ila_csum_adjust_transport(st
+                                       (skb_network_header(skb) + nhoff);
+                       if (uh->check || skb->ip_summed == CHECKSUM_PARTIAL) {
++                              ip6h = ipv6_hdr(skb);
+                               diff = get_csum_diff(ip6h, p);
+                               inet_proto_csum_replace_by_diff(&uh->check, skb,
+                                                               diff, true, true);
+@@ -110,6 +112,7 @@ static void ila_csum_adjust_transport(st
+                       struct icmp6hdr *ih = (struct icmp6hdr *)
+                                       (skb_network_header(skb) + nhoff);
++                      ip6h = ipv6_hdr(skb);
+                       diff = get_csum_diff(ip6h, p);
+                       inet_proto_csum_replace_by_diff(&ih->icmp6_cksum, skb,
+                                                       diff, true, true);
+@@ -127,6 +130,15 @@ void ila_update_ipv6_locator(struct sk_b
+       switch (p->csum_mode) {
+       case ILA_CSUM_ADJUST_TRANSPORT:
+               ila_csum_adjust_transport(skb, p);
++              /*
++               * ila_csum_adjust_transport() calls pskb_may_pull(), which can
++               * reallocate the skb head and leave ip6h (and the iaddr derived
++               * from it) dangling; reload both before the write below.  The
++               * other csum modes do not pull, so their cached pointers stay
++               * valid.
++               */
++              ip6h = ipv6_hdr(skb);
++              iaddr = ila_a2i(&ip6h->daddr);
+               break;
+       case ILA_CSUM_NEUTRAL_MAP:
+               if (sir2ila) {
diff --git a/queue-7.1/mac802154-hold-an-interface-reference-across-the-scan-worker.patch b/queue-7.1/mac802154-hold-an-interface-reference-across-the-scan-worker.patch
new file mode 100644 (file)
index 0000000..498fe03
--- /dev/null
@@ -0,0 +1,78 @@
+From 234e5e898b713bc0b3a631b6f002897f43d046c8 Mon Sep 17 00:00:00 2001
+From: Ibrahim Hashimov <security@auditcode.ai>
+Date: Tue, 21 Jul 2026 23:12:28 +0200
+Subject: mac802154: hold an interface reference across the scan worker
+
+From: Ibrahim Hashimov <security@auditcode.ai>
+
+commit 234e5e898b713bc0b3a631b6f002897f43d046c8 upstream.
+
+mac802154_scan_worker() captures the scanning sub-interface under RCU
+and then keeps dereferencing sdata->dev after rcu_read_unlock() and
+outside the rtnl -- in the failure traces, in
+mac802154_transmit_beacon_req() (skb->dev = sdata->dev), and in the
+end_scan cleanup. Nothing keeps that netdev alive across the worker
+iteration.
+
+A concurrent DEL_INTERFACE or PHY removal can unregister the interface
+once the worker drops the rtnl between its two drv_set_channel()
+sections. unregister_netdevice() frees the netdev asynchronously from
+netdev_run_todo() with the rtnl already dropped, so neither holding the
+rtnl nor the per-PHY IEEE802154_IS_SCANNING flag prevents a stale worker
+iteration from dereferencing the freed netdev -- a KASAN
+slab-use-after-free, reachable by racing TRIGGER_SCAN against
+DEL_INTERFACE (both CAP_NET_ADMIN).
+
+Pin the netdev with netdev_hold() while the RCU read lock is still held,
+and release it at every worker exit.
+
+Fixes: 57588c71177f ("mac802154: Handle passive scanning")
+Cc: stable@vger.kernel.org
+Signed-off-by: Ibrahim Hashimov <security@auditcode.ai>
+Link: https://patch.msgid.link/20260721211228.34578-1-security@auditcode.ai
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/mac802154/scan.c |   11 +++++++++++
+ 1 file changed, 11 insertions(+)
+
+--- a/net/mac802154/scan.c
++++ b/net/mac802154/scan.c
+@@ -179,6 +179,7 @@ void mac802154_scan_worker(struct work_s
+       enum nl802154_scan_types scan_req_type;
+       struct ieee802154_sub_if_data *sdata;
+       unsigned int scan_duration = 0;
++      netdevice_tracker dev_tracker;
+       struct wpan_phy *wpan_phy;
+       u8 scan_req_duration;
+       u8 page, channel;
+@@ -209,6 +210,14 @@ void mac802154_scan_worker(struct work_s
+               return;
+       }
++      /*
++       * sdata->dev is dereferenced below after rcu_read_unlock() and outside
++       * the rtnl, and a concurrent DEL_INTERFACE / PHY teardown can free it
++       * asynchronously from netdev_run_todo(). Pin it with a reference taken
++       * while the RCU read lock is still held, and drop it at every exit.
++       */
++      netdev_hold(sdata->dev, &dev_tracker, GFP_ATOMIC);
++
+       wpan_phy = scan_req->wpan_phy;
+       scan_req_type = scan_req->type;
+       scan_req_duration = scan_req->duration;
+@@ -262,12 +271,14 @@ void mac802154_scan_worker(struct work_s
+               "Scan page %u channel %u for %ums\n",
+               page, channel, jiffies_to_msecs(scan_duration));
+       queue_delayed_work(local->mac_wq, &local->scan_work, scan_duration);
++      netdev_put(sdata->dev, &dev_tracker);
+       return;
+ end_scan:
+       rtnl_lock();
+       mac802154_scan_cleanup_locked(local, sdata, false);
+       rtnl_unlock();
++      netdev_put(sdata->dev, &dev_tracker);
+ }
+ int mac802154_trigger_scan_locked(struct ieee802154_sub_if_data *sdata,
diff --git a/queue-7.1/mac802154-llsec-reject-frames-shorter-than-the-authentication-tag.patch b/queue-7.1/mac802154-llsec-reject-frames-shorter-than-the-authentication-tag.patch
new file mode 100644 (file)
index 0000000..efb1183
--- /dev/null
@@ -0,0 +1,55 @@
+From fd3a3f28ed60c6af4b2a39933b151d6b27842c3b Mon Sep 17 00:00:00 2001
+From: Doruk Tan Ozturk <doruk@0sec.ai>
+Date: Thu, 16 Jul 2026 21:34:23 +0200
+Subject: mac802154: llsec: reject frames shorter than the authentication tag
+
+From: Doruk Tan Ozturk <doruk@0sec.ai>
+
+commit fd3a3f28ed60c6af4b2a39933b151d6b27842c3b upstream.
+
+llsec_do_decrypt_auth() computes the associated-data length for the
+AEAD request as
+
+       assoclen += datalen - authlen;
+
+where datalen is the number of bytes after the MAC header and authlen
+(4, 8 or 16) is the length of the authentication tag. Nothing verifies
+that the frame actually carries at least authlen payload bytes. A
+secured frame whose payload is shorter than the tag makes
+datalen - authlen negative; assoclen is then passed to
+aead_request_set_ad() as an unsigned value close to 4 GiB, so
+crypto_aead_decrypt() walks far off the end of the scatterlist that
+only spans the real frame.
+
+The frame is fully attacker-controlled and reaches this path from any
+IEEE 802.15.4 peer in radio range. Reject frames whose payload is
+shorter than the authentication tag before the subtraction.
+
+Dynamically reproduced on a KASAN kernel as a general-protection-fault
+in the AEAD scatterwalk, and the fix confirmed.
+
+Fixes: 4c14a2fb5d14 ("mac802154: add llsec decryption method")
+Cc: stable@vger.kernel.org
+Reviewed-by: Simon Horman <horms@kernel.org>
+Signed-off-by: Doruk Tan Ozturk <doruk@0sec.ai>
+Link: https://patch.msgid.link/20260716193423.32498-1-doruk@0sec.ai
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/mac802154/llsec.c |    5 +++++
+ 1 file changed, 5 insertions(+)
+
+--- a/net/mac802154/llsec.c
++++ b/net/mac802154/llsec.c
+@@ -891,6 +891,11 @@ llsec_do_decrypt_auth(struct sk_buff *sk
+       data = skb_mac_header(skb) + skb->mac_len;
+       datalen = skb_tail_pointer(skb) - data;
++      if (datalen < authlen) {
++              kfree_sensitive(req);
++              return -EBADMSG;
++      }
++
+       sg_init_one(&sg, skb_mac_header(skb), assoclen + datalen);
+       if (!(hdr->sec.level & IEEE802154_SCF_SECLEVEL_ENC)) {
diff --git a/queue-7.1/mctp-serial-handle-zero-length-frames-to-prevent-rx-buffer-overflow.patch b/queue-7.1/mctp-serial-handle-zero-length-frames-to-prevent-rx-buffer-overflow.patch
new file mode 100644 (file)
index 0000000..510ce50
--- /dev/null
@@ -0,0 +1,93 @@
+From 793b9b729f1e8de57be8c8daf1a9838be96cabed Mon Sep 17 00:00:00 2001
+From: Doruk Tan Ozturk <doruk@0sec.ai>
+Date: Wed, 15 Jul 2026 10:20:21 +0200
+Subject: mctp: serial: handle zero-length frames to prevent rx buffer overflow
+
+From: Doruk Tan Ozturk <doruk@0sec.ai>
+
+commit 793b9b729f1e8de57be8c8daf1a9838be96cabed upstream.
+
+The MCTP serial receive state machine reads a frame length byte in
+mctp_serial_push_header() case 2 and validates it upper-bound-only:
+
+       if (c > MCTP_SERIAL_FRAME_MTU) {
+               dev->rxstate = STATE_ERR;
+       } else {
+               dev->rxlen = c;
+               dev->rxpos = 0;
+               dev->rxstate = STATE_DATA;
+               ...
+       }
+
+A length of zero passes this check, so rxlen is set to 0 and the state
+machine advances to STATE_DATA. In mctp_serial_push() STATE_DATA, the
+incoming byte is stored and rxpos incremented before the terminator is
+tested:
+
+       dev->rxbuf[dev->rxpos] = c;
+       dev->rxpos++;
+       dev->rxstate = STATE_DATA;
+       if (dev->rxpos == dev->rxlen) {
+               dev->rxpos = 0;
+               dev->rxstate = STATE_TRAILER;
+       }
+
+With rxlen == 0 the "rxpos == rxlen" terminator can never fire (rxpos is
+already 1 on the first data byte), so subsequent bytes are written past
+the end of the fixed 74-byte rxbuf, which is the last member of the
+netdev private area. Every following data byte is an attacker-controlled
+1-byte out-of-bounds heap write, and the overflow continues until a
+frame (0x7e) or escape byte resets the parser -- effectively unbounded.
+
+Reaching this requires CAP_NET_ADMIN to attach the N_MCTP line
+discipline and bring the resulting mctpserialN netdev up, after which
+the bytes arrive via the tty receive path.
+
+Route a zero-length frame straight to STATE_TRAILER instead of
+STATE_DATA. The trailer/framing bytes are still consumed, and the frame
+resolves to a zero-length skb that the MCTP core rejects; the parser
+never enters STATE_DATA with rxlen == 0, so the out-of-bounds write can
+no longer occur.
+
+KASAN, on a frame of 0x7e 0x01 0x00 followed by data bytes (before this
+change):
+
+  UBSAN: array-index-out-of-bounds in drivers/net/mctp/mctp-serial.c:370
+  index 74 is out of range for type 'u8 [74]'
+  BUG: KASAN: slab-out-of-bounds in mctp_serial_tty_receive_buf
+  Write of size 1 at addr ... by task kworker/u16:0
+   mctp_serial_tty_receive_buf
+   tty_ldisc_receive_buf
+   flush_to_ldisc
+  Allocated by task 152:
+   alloc_netdev_mqs
+   mctp_serial_open
+
+v2: route zero-length frames to STATE_TRAILER instead of STATE_ERR so
+    the trailer/framing bytes are still consumed (Jeremy Kerr).
+
+Found by 0sec automated security-research tooling (https://0sec.ai).
+Fixes: a0c2ccd9b5ad ("mctp: Add MCTP-over-serial transport binding")
+Cc: stable@vger.kernel.org
+Suggested-by: Jeremy Kerr <jk@codeconstruct.com.au>
+Assisted-by: 0sec:multi-model
+Signed-off-by: Doruk Tan Ozturk <doruk@0sec.ai>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Link: https://patch.msgid.link/20260715082021.46315-1-doruk@0sec.ai
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/mctp/mctp-serial.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/net/mctp/mctp-serial.c
++++ b/drivers/net/mctp/mctp-serial.c
+@@ -318,7 +318,7 @@ static void mctp_serial_push_header(stru
+               } else {
+                       dev->rxlen = c;
+                       dev->rxpos = 0;
+-                      dev->rxstate = STATE_DATA;
++                      dev->rxstate = c > 0 ? STATE_DATA : STATE_TRAILER;
+                       dev->rxfcs = crc_ccitt_byte(dev->rxfcs, c);
+               }
+               break;
diff --git a/queue-7.1/openvswitch-fix-gso-userspace-truncation-underflow.patch b/queue-7.1/openvswitch-fix-gso-userspace-truncation-underflow.patch
new file mode 100644 (file)
index 0000000..b77402b
--- /dev/null
@@ -0,0 +1,198 @@
+From 4032f8ed10fcb84d41c508dfb04be96589f78dfe Mon Sep 17 00:00:00 2001
+From: Kyle Zeng <kylebot@openai.com>
+Date: Tue, 7 Jul 2026 15:16:35 -0700
+Subject: openvswitch: fix GSO userspace truncation underflow
+
+From: Kyle Zeng <kylebot@openai.com>
+
+commit 4032f8ed10fcb84d41c508dfb04be96589f78dfe upstream.
+
+OVS_ACTION_ATTR_TRUNC currently stores a delta from the original skb
+length in OVS_CB(skb)->cutlen. When a later userspace action segments a
+GSO skb, queue_gso_packets() reuses that delta for each smaller segment.
+A segment can then reach queue_userspace_packet() with cutlen greater
+than skb->len, underflowing the length passed to skb_zerocopy().
+
+Store the maximum preserved length instead and bound each consumer
+against the current skb length. Use U32_MAX as the no-truncation
+sentinel so the value remains valid if skb geometry changes before a
+consumer handles it.
+
+Fixes: f2a4d086ed4c ("openvswitch: Add packet truncation support.")
+Cc: stable@vger.kernel.org
+Assisted-by: Codex:gpt-5.5
+Signed-off-by: Kyle Zeng <kylebot@openai.com>
+Reviewed-by: Ilya Maximets <i.maximets@ovn.org>
+Reviewed-by: Aaron Conole <aconole@redhat.com>
+Link: https://patch.msgid.link/20260707221635.27489-1-kylebot@openai.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/openvswitch/actions.c  |   19 +++++++------------
+ net/openvswitch/datapath.c |   25 ++++++++++++++-----------
+ net/openvswitch/datapath.h |    2 +-
+ net/openvswitch/vport.c    |    2 +-
+ 4 files changed, 23 insertions(+), 25 deletions(-)
+
+--- a/net/openvswitch/actions.c
++++ b/net/openvswitch/actions.c
+@@ -837,12 +837,8 @@ static void do_output(struct datapath *d
+               u16 mru = OVS_CB(skb)->mru;
+               u32 cutlen = OVS_CB(skb)->cutlen;
+-              if (unlikely(cutlen > 0)) {
+-                      if (skb->len - cutlen > ovs_mac_header_len(key))
+-                              pskb_trim(skb, skb->len - cutlen);
+-                      else
+-                              pskb_trim(skb, ovs_mac_header_len(key));
+-              }
++              if (unlikely(cutlen < skb->len))
++                      pskb_trim(skb, max(cutlen, ovs_mac_header_len(key)));
+               if (likely(!mru ||
+                          (skb->len <= mru + vport->dev->hard_header_len))) {
+@@ -1234,7 +1230,7 @@ static void execute_psample(struct datap
+       psample_group.net = ovs_dp_get_net(dp);
+       md.in_ifindex = OVS_CB(skb)->input_vport->dev->ifindex;
+-      md.trunc_size = skb->len - OVS_CB(skb)->cutlen;
++      md.trunc_size = min(skb->len, OVS_CB(skb)->cutlen);
+       md.rate_as_probability = 1;
+       rate = OVS_CB(skb)->probability ? OVS_CB(skb)->probability : U32_MAX;
+@@ -1284,22 +1280,21 @@ static int do_execute_actions(struct dat
+                       clone = skb_clone(skb, GFP_ATOMIC);
+                       if (clone)
+                               do_output(dp, clone, port, key);
+-                      OVS_CB(skb)->cutlen = 0;
++                      OVS_CB(skb)->cutlen = U32_MAX;
+                       break;
+               }
+               case OVS_ACTION_ATTR_TRUNC: {
+                       struct ovs_action_trunc *trunc = nla_data(a);
+-                      if (skb->len > trunc->max_len)
+-                              OVS_CB(skb)->cutlen = skb->len - trunc->max_len;
++                      OVS_CB(skb)->cutlen = trunc->max_len;
+                       break;
+               }
+               case OVS_ACTION_ATTR_USERSPACE:
+                       output_userspace(dp, skb, key, a, attr,
+                                                    len, OVS_CB(skb)->cutlen);
+-                      OVS_CB(skb)->cutlen = 0;
++                      OVS_CB(skb)->cutlen = U32_MAX;
+                       if (nla_is_last(a, rem)) {
+                               consume_skb(skb);
+                               return 0;
+@@ -1453,7 +1448,7 @@ static int do_execute_actions(struct dat
+               case OVS_ACTION_ATTR_PSAMPLE:
+                       execute_psample(dp, skb, a);
+-                      OVS_CB(skb)->cutlen = 0;
++                      OVS_CB(skb)->cutlen = U32_MAX;
+                       if (nla_is_last(a, rem)) {
+                               consume_skb(skb);
+                               return 0;
+--- a/net/openvswitch/datapath.c
++++ b/net/openvswitch/datapath.c
+@@ -276,7 +276,7 @@ void ovs_dp_process_packet(struct sk_buf
+                       upcall.portid = ovs_vport_find_upcall_portid(p, skb);
+               upcall.mru = OVS_CB(skb)->mru;
+-              error = ovs_dp_upcall(dp, skb, key, &upcall, 0);
++              error = ovs_dp_upcall(dp, skb, key, &upcall, U32_MAX);
+               switch (error) {
+               case 0:
+               case -EAGAIN:
+@@ -457,7 +457,8 @@ static int queue_userspace_packet(struct
+       struct sk_buff *nskb = NULL;
+       struct sk_buff *user_skb = NULL; /* to be queued to userspace */
+       struct nlattr *nla;
+-      size_t len;
++      size_t msg_size;
++      size_t skb_len;
+       unsigned int hlen;
+       int err, dp_ifindex;
+       u64 hash;
+@@ -478,7 +479,8 @@ static int queue_userspace_packet(struct
+               skb = nskb;
+       }
+-      if (nla_attr_size(skb->len) > USHRT_MAX) {
++      skb_len = min(skb->len, cutlen);
++      if (nla_attr_size(skb_len) > USHRT_MAX) {
+               err = -EFBIG;
+               goto out;
+       }
+@@ -493,13 +495,13 @@ static int queue_userspace_packet(struct
+        * padding logic. Only perform zerocopy if padding is not required.
+        */
+       if (dp->user_features & OVS_DP_F_UNALIGNED)
+-              hlen = skb_zerocopy_headlen(skb);
++              hlen = min(skb_zerocopy_headlen(skb), cutlen);
+       else
+-              hlen = skb->len;
++              hlen = skb_len;
+-      len = upcall_msg_size(upcall_info, hlen - cutlen,
+-                            OVS_CB(skb)->acts_origlen);
+-      user_skb = genlmsg_new(len, GFP_ATOMIC);
++      msg_size = upcall_msg_size(upcall_info, hlen,
++                                 OVS_CB(skb)->acts_origlen);
++      user_skb = genlmsg_new(msg_size, GFP_ATOMIC);
+       if (!user_skb) {
+               err = -ENOMEM;
+               goto out;
+@@ -560,7 +562,7 @@ static int queue_userspace_packet(struct
+       }
+       /* Add OVS_PACKET_ATTR_LEN when packet is truncated */
+-      if (cutlen > 0 &&
++      if (skb_len < skb->len &&
+           nla_put_u32(user_skb, OVS_PACKET_ATTR_LEN, skb->len)) {
+               err = -ENOBUFS;
+               goto out;
+@@ -585,9 +587,9 @@ static int queue_userspace_packet(struct
+               err = -ENOBUFS;
+               goto out;
+       }
+-      nla->nla_len = nla_attr_size(skb->len - cutlen);
++      nla->nla_len = nla_attr_size(skb_len);
+-      err = skb_zerocopy(user_skb, skb, skb->len - cutlen, hlen);
++      err = skb_zerocopy(user_skb, skb, skb_len, hlen);
+       if (err)
+               goto out;
+@@ -644,6 +646,7 @@ static int ovs_packet_cmd_execute(struct
+               packet->ignore_df = 1;
+       }
+       OVS_CB(packet)->mru = mru;
++      OVS_CB(packet)->cutlen = U32_MAX;
+       if (a[OVS_PACKET_ATTR_HASH]) {
+               hash = nla_get_u64(a[OVS_PACKET_ATTR_HASH]);
+--- a/net/openvswitch/datapath.h
++++ b/net/openvswitch/datapath.h
+@@ -118,7 +118,7 @@ struct datapath {
+  * @mru: The maximum received fragement size; 0 if the packet is not
+  * fragmented.
+  * @acts_origlen: The netlink size of the flow actions applied to this skb.
+- * @cutlen: The number of bytes from the packet end to be removed.
++ * @cutlen: The number of bytes in the packet to preserve on output.
+  * @probability: The sampling probability that was applied to this skb; 0 means
+  * no sampling has occurred; U32_MAX means 100% probability.
+  * @upcall_pid: Netlink socket PID to use for sending this packet to userspace;
+--- a/net/openvswitch/vport.c
++++ b/net/openvswitch/vport.c
+@@ -502,7 +502,7 @@ int ovs_vport_receive(struct vport *vpor
+       OVS_CB(skb)->input_vport = vport;
+       OVS_CB(skb)->mru = 0;
+-      OVS_CB(skb)->cutlen = 0;
++      OVS_CB(skb)->cutlen = U32_MAX;
+       OVS_CB(skb)->probability = 0;
+       OVS_CB(skb)->upcall_pid = 0;
+       if (unlikely(dev_net(skb->dev) != ovs_dp_get_net(vport->dp))) {
diff --git a/queue-7.1/ovpn-fix-peer-refcount-leak-in-tcp-error-paths.patch b/queue-7.1/ovpn-fix-peer-refcount-leak-in-tcp-error-paths.patch
new file mode 100644 (file)
index 0000000..fba0d74
--- /dev/null
@@ -0,0 +1,64 @@
+From 63bbe18fc03062f483c627838a566a707b62da79 Mon Sep 17 00:00:00 2001
+From: Pavitra Jha <jhapavitra98@gmail.com>
+Date: Sat, 23 May 2026 05:02:43 -0400
+Subject: ovpn: fix peer refcount leak in TCP error paths
+
+From: Pavitra Jha <jhapavitra98@gmail.com>
+
+commit 63bbe18fc03062f483c627838a566a707b62da79 upstream.
+
+When either the TCP RX or TX error path calls ovpn_peer_hold() followed
+by schedule_work(&peer->tcp.defer_del_work), and the work item is already
+pending from the other path, schedule_work() returns false and the work
+runs only once. Since ovpn_tcp_peer_del_work() calls ovpn_peer_put()
+exactly once, the extra reference taken by the losing path is never
+dropped, leaking the peer object.
+
+The race window:
+
+  CPU0 (strparser/RX error):       CPU1 (tcp_tx_work/TX error):
+  ovpn_peer_hold()   <- refcnt+1   ovpn_peer_hold()   <- refcnt+2
+  schedule_work()    <- queued      schedule_work()    <- NO-OP
+                                    (work already pending)
+  ovpn_tcp_peer_del_work runs:
+    ovpn_peer_del()
+    ovpn_peer_put()  <- refcnt+1
+                                   <- peer never freed
+
+Fix by checking the return value of schedule_work() in both paths and
+calling ovpn_peer_put() to drop the extra reference if the work was
+already pending. ovpn_peer_hold() is kept unconditional in the TX path
+as it cannot fail at that point.
+
+Fixes: a6a5e87b3ee4 ("ovpn: avoid sleep in atomic context in TCP RX error path")
+Cc: stable@vger.kernel.org
+Signed-off-by: Pavitra Jha <jhapavitra98@gmail.com>
+Reviewed-by: Sabrina Dubroca <sd@queasysnail.net>
+Signed-off-by: Antonio Quartulli <antonio@openvpn.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/ovpn/tcp.c |    6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+--- a/drivers/net/ovpn/tcp.c
++++ b/drivers/net/ovpn/tcp.c
+@@ -151,7 +151,8 @@ err:
+       /* take reference for deferred peer deletion. should never fail */
+       if (WARN_ON(!ovpn_peer_hold(peer)))
+               goto err_nopeer;
+-      schedule_work(&peer->tcp.defer_del_work);
++      if (!schedule_work(&peer->tcp.defer_del_work))
++              ovpn_peer_put(peer);
+       ovpn_dev_dstats_rx_dropped(peer->ovpn->dev);
+ err_nopeer:
+       kfree_skb(skb);
+@@ -283,7 +284,8 @@ static void ovpn_tcp_send_sock(struct ov
+                        * stream therefore we abort the connection
+                        */
+                       ovpn_peer_hold(peer);
+-                      schedule_work(&peer->tcp.defer_del_work);
++                      if (!schedule_work(&peer->tcp.defer_del_work))
++                              ovpn_peer_put(peer);
+                       /* we bail out immediately and keep tx_in_progress set
+                        * to true. This way we prevent more TX attempts
diff --git a/queue-7.1/ovpn-hold-peer-before-scheduling-keepalive-work.patch b/queue-7.1/ovpn-hold-peer-before-scheduling-keepalive-work.patch
new file mode 100644 (file)
index 0000000..368eede
--- /dev/null
@@ -0,0 +1,47 @@
+From a4710ae2e7e322fdaefb4be8604228279cfaf48c Mon Sep 17 00:00:00 2001
+From: Shuvam Pandey <shuvampandey1@gmail.com>
+Date: Sat, 23 May 2026 20:38:27 +0545
+Subject: ovpn: hold peer before scheduling keepalive work
+
+From: Shuvam Pandey <shuvampandey1@gmail.com>
+
+commit a4710ae2e7e322fdaefb4be8604228279cfaf48c upstream.
+
+ovpn_peer_keepalive_send() passes its peer reference to
+ovpn_xmit_special(), which ultimately drops it. The keepalive scheduler
+currently queues the work first and takes the reference only after
+schedule_work() reports that the work was queued.
+
+Once schedule_work() queues the item, another CPU may run the worker
+before the caller gets to ovpn_peer_hold(). In that case the worker can
+consume a reference that was not acquired for it, corrupting the peer
+lifetime accounting.
+
+Take the peer reference before queueing the work and drop it again when
+the work was already pending.
+
+Fixes: 3ecfd9349f40 ("ovpn: implement keepalive mechanism")
+Cc: stable@vger.kernel.org
+Signed-off-by: Shuvam Pandey <shuvampandey1@gmail.com>
+Reviewed-by: Sabrina Dubroca <sd@queasysnail.net>
+Signed-off-by: Antonio Quartulli <antonio@openvpn.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/ovpn/peer.c |    6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+--- a/drivers/net/ovpn/peer.c
++++ b/drivers/net/ovpn/peer.c
+@@ -1285,8 +1285,10 @@ static time64_t ovpn_peer_keepalive_work
+               netdev_dbg(peer->ovpn->dev,
+                          "sending keepalive to peer %u\n",
+                          peer->id);
+-              if (schedule_work(&peer->keepalive_work))
+-                      ovpn_peer_hold(peer);
++              if (WARN_ON(!ovpn_peer_hold(peer)))
++                      return 0;
++              if (!schedule_work(&peer->keepalive_work))
++                      ovpn_peer_put(peer);
+       }
+       if (next_run1 < next_run2)
diff --git a/queue-7.1/pppoe-reload-header-pointer-after-dev_hard_header.patch b/queue-7.1/pppoe-reload-header-pointer-after-dev_hard_header.patch
new file mode 100644 (file)
index 0000000..fd5472d
--- /dev/null
@@ -0,0 +1,44 @@
+From e9c238f6fe42fb1b4dba3a578277de32cb487937 Mon Sep 17 00:00:00 2001
+From: Asim Viladi Oglu Manizada <manizada@pm.me>
+Date: Wed, 22 Jul 2026 09:38:43 +0000
+Subject: pppoe: reload header pointer after dev_hard_header()
+
+From: Asim Viladi Oglu Manizada <manizada@pm.me>
+
+commit e9c238f6fe42fb1b4dba3a578277de32cb487937 upstream.
+
+pppoe_sendmsg() saves a pointer to the PPPoE header before calling
+dev_hard_header(). Device header callbacks are allowed to reallocate the
+skb head, invalidating pointers into it.
+
+This can happen when a send is blocked in copy_from_user() while the first
+non-Ethernet port is added to an empty team device. The team's delegated
+GRE header callback then expands the skb head. PPPoE subsequently writes
+six bytes through the stale pointer into the freed head.
+
+Reload the PPPoE header through the skb's network-header offset after
+device header creation. pskb_expand_head() updates that offset when it
+relocates the head.
+
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Cc: stable@vger.kernel.org
+Signed-off-by: Asim Viladi Oglu Manizada <manizada@pm.me>
+Reviewed-by: Vadim Fedorenko <vadim.fedorenko@linux.dev>
+Reviewed-by: Eric Dumazet <edumazet@google.com>
+Link: https://patch.msgid.link/20260722093814.3017176-1-manizada@pm.me
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/ppp/pppoe.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/net/ppp/pppoe.c
++++ b/drivers/net/ppp/pppoe.c
+@@ -824,6 +824,7 @@ static int pppoe_sendmsg(struct socket *
+       dev_hard_header(skb, dev, ETH_P_PPP_SES,
+                       po->pppoe_pa.remote, NULL, total_len);
++      ph = pppoe_hdr(skb);
+       memcpy(ph, &hdr, sizeof(struct pppoe_hdr));
+       ph->length = htons(total_len);
diff --git a/queue-7.1/rtase-workaround-for-tx-hang-caused-by-hardware-packet-parsing.patch b/queue-7.1/rtase-workaround-for-tx-hang-caused-by-hardware-packet-parsing.patch
new file mode 100644 (file)
index 0000000..5c960ef
--- /dev/null
@@ -0,0 +1,301 @@
+From 1c50efa1faf3a1a96e100b07ec7a2f3164d90bee Mon Sep 17 00:00:00 2001
+From: Justin Lai <justinlai0215@realtek.com>
+Date: Thu, 9 Jul 2026 18:34:56 +0800
+Subject: rtase: Workaround for TX hang caused by hardware packet parsing
+
+From: Justin Lai <justinlai0215@realtek.com>
+
+commit 1c50efa1faf3a1a96e100b07ec7a2f3164d90bee upstream.
+
+The hardware performs packet parsing before packet transmission.
+Parsing incomplete IPv4, IPv6, TCP, or UDP headers may trigger a TX
+hang because the hardware parser expects additional protocol header
+data that is not present in the packet.
+
+The hardware performs additional PTP parsing on UDP packets identified
+by destination ports 319/320 at the expected UDP destination port
+offset.
+
+If such a packet has transport data smaller than RTASE_MIN_PAD_LEN,
+the hardware parser expects additional packet data and may trigger a
+TX hang.
+
+To avoid these hardware issues, the driver applies the following
+workarounds.
+
+Drop malformed packets that may trigger this hardware issue before
+transmission.
+
+For IPv4 non-initial fragments, the hardware does not check the
+fragment offset before parsing the expected transport header location.
+As a result, these packets are still subject to transport header
+parsing even though they do not contain a transport header. If the
+transport data is shorter than the minimum transport header required
+by the hardware parser, pad the transport data to the minimum
+transport header length required by the hardware parser. Packets that
+also match the hardware PTP parsing conditions continue to follow the
+corresponding workaround.
+
+For IPv6 fragmented packets, neither of the above hardware issues
+occurs because the hardware only continues packet parsing when the
+IPv6 Base Header Next Header field directly indicates UDP. Packets
+carrying a Fragment Header do not continue through the subsequent
+packet parsing stages.
+
+For packets identified for hardware PTP parsing, pad the transport
+data so it reaches RTASE_MIN_PAD_LEN before transmission.
+
+Fixes: d6e882b89fdf ("rtase: Implement .ndo_start_xmit function")
+Cc: stable@vger.kernel.org
+Signed-off-by: Justin Lai <justinlai0215@realtek.com>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Link: https://patch.msgid.link/20260709103456.83789-1-justinlai0215@realtek.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/ethernet/realtek/rtase/rtase.h      |    8 
+ drivers/net/ethernet/realtek/rtase/rtase_main.c |  197 ++++++++++++++++++++++++
+ 2 files changed, 205 insertions(+)
+
+--- a/drivers/net/ethernet/realtek/rtase/rtase.h
++++ b/drivers/net/ethernet/realtek/rtase/rtase.h
+@@ -188,6 +188,12 @@ enum rtase_sw_flag_content {
+       RTASE_SWF_MSIX_ENABLED = BIT(2),
+ };
++enum rtase_parse_result {
++      RTASE_PARSE_OK,
++      RTASE_PARSE_SKIP,
++      RTASE_PARSE_DROP,
++};
++
+ #define RSVD_MASK 0x3FFFC000
+ struct rtase_tx_desc {
+@@ -359,4 +365,6 @@ struct rtase_private {
+ #define RTASE_MSS_MASK GENMASK(28, 18)
++#define RTASE_MIN_PAD_LEN 47
++
+ #endif /* RTASE_H */
+--- a/drivers/net/ethernet/realtek/rtase/rtase_main.c
++++ b/drivers/net/ethernet/realtek/rtase/rtase_main.c
+@@ -61,6 +61,7 @@
+ #include <linux/pci.h>
+ #include <linux/pm_runtime.h>
+ #include <linux/prefetch.h>
++#include <linux/ptp_classify.h>
+ #include <linux/rtnetlink.h>
+ #include <linux/tcp.h>
+ #include <asm/irq.h>
+@@ -1249,6 +1250,199 @@ static u32 rtase_tx_csum(struct sk_buff
+       return csum_cmd;
+ }
++static enum rtase_parse_result rtase_get_l3_proto(struct sk_buff *skb,
++                                                __be16 *proto,
++                                                u32 *network_offset)
++{
++      struct vlan_hdr *vh, _vh;
++      struct ethhdr *eh, _eh;
++      u32 offset = ETH_HLEN;
++
++      eh = skb_header_pointer(skb, 0, sizeof(_eh), &_eh);
++      if (!eh)
++              return RTASE_PARSE_DROP;
++
++      *proto = eh->h_proto;
++
++      while (eth_type_vlan(*proto)) {
++              vh = skb_header_pointer(skb, offset, sizeof(_vh), &_vh);
++              if (!vh)
++                      return RTASE_PARSE_DROP;
++
++              *proto = vh->h_vlan_encapsulated_proto;
++              offset += VLAN_HLEN;
++      }
++
++      *network_offset = offset;
++
++      return RTASE_PARSE_OK;
++}
++
++static bool rtase_pad_to_transport_len(struct sk_buff *skb,
++                                     u32 transport_offset,
++                                     u32 pad_to_len)
++{
++      u32 trans_data_len;
++      u32 pad_len;
++
++      trans_data_len = skb->len - transport_offset;
++      if (trans_data_len >= pad_to_len)
++              return true;
++
++      if (skb_is_nonlinear(skb)) {
++              if (skb_linearize(skb))
++                      return false;
++      }
++
++      pad_len = pad_to_len - trans_data_len;
++      if (__skb_put_padto(skb, skb->len + pad_len, false))
++              return false;
++
++      return true;
++}
++
++static enum rtase_parse_result rtase_get_transport_offset(struct sk_buff *skb,
++                                                        u32 *transport_offset,
++                                                        u8 *transport_proto,
++                                                        u32 *pad_to_len)
++{
++      enum rtase_parse_result ret;
++      struct ipv6hdr *i6h, _i6h;
++      struct iphdr *ih, _ih;
++      bool non_first_frag;
++      __be16 proto;
++      u32 offset;
++      u32 no;
++
++      ret = rtase_get_l3_proto(skb, &proto, &no);
++      if (ret != RTASE_PARSE_OK)
++              return ret;
++
++      switch (proto) {
++      case htons(ETH_P_IP):
++              ih = skb_header_pointer(skb, no, sizeof(_ih), &_ih);
++              if (!ih)
++                      return RTASE_PARSE_DROP;
++
++              if (ih->ihl < 5)
++                      return RTASE_PARSE_DROP;
++
++              offset = no + ih->ihl * 4;
++              if (offset > skb->len)
++                      return RTASE_PARSE_DROP;
++
++              non_first_frag = ntohs(ih->frag_off) & IP_OFFSET;
++
++              if (ih->protocol == IPPROTO_TCP) {
++                      if (skb->len - offset < sizeof(struct tcphdr)) {
++                              if (non_first_frag) {
++                                      *transport_offset = offset;
++                                      *transport_proto = IPPROTO_TCP;
++                                      *pad_to_len = sizeof(struct tcphdr);
++
++                                      return RTASE_PARSE_OK;
++                              }
++
++                              return RTASE_PARSE_DROP;
++                      }
++
++                      return RTASE_PARSE_SKIP;
++              }
++
++              if (ih->protocol != IPPROTO_UDP)
++                      return RTASE_PARSE_SKIP;
++
++              *transport_offset = offset;
++              *transport_proto = IPPROTO_UDP;
++
++              if (skb->len - offset < sizeof(struct udphdr)) {
++                      if (non_first_frag) {
++                              *pad_to_len = sizeof(struct udphdr);
++
++                              return RTASE_PARSE_OK;
++                      }
++
++                      return RTASE_PARSE_DROP;
++              }
++
++              return RTASE_PARSE_OK;
++
++      case htons(ETH_P_IPV6):
++              i6h = skb_header_pointer(skb, no, sizeof(_i6h), &_i6h);
++              if (!i6h)
++                      return RTASE_PARSE_DROP;
++
++              offset = no + sizeof(*i6h);
++
++              if (i6h->nexthdr == IPPROTO_TCP) {
++                      if (skb->len - offset < sizeof(struct tcphdr))
++                              return RTASE_PARSE_DROP;
++
++                      return RTASE_PARSE_SKIP;
++              }
++
++              if (i6h->nexthdr != IPPROTO_UDP)
++                      return RTASE_PARSE_SKIP;
++
++              if (skb->len - offset < sizeof(struct udphdr))
++                      return RTASE_PARSE_DROP;
++
++              *transport_offset = offset;
++              *transport_proto = IPPROTO_UDP;
++
++              return RTASE_PARSE_OK;
++
++      default:
++              return RTASE_PARSE_SKIP;
++      }
++}
++
++static bool rtase_skb_pad(struct sk_buff *skb)
++{
++      enum rtase_parse_result ret;
++      u32 transport_offset;
++      __be16 *dest, _dest;
++      u32 trans_data_len;
++      u32 pad_to_len = 0;
++      u8 transport_proto;
++      u16 dest_port;
++
++      ret = rtase_get_transport_offset(skb, &transport_offset,
++                                       &transport_proto, &pad_to_len);
++      if (ret == RTASE_PARSE_SKIP) {
++              return true;
++      } else if (ret == RTASE_PARSE_DROP) {
++              netdev_dbg(skb->dev, "drop malformed packet\n");
++              return false;
++      }
++
++      if (pad_to_len &&
++          !rtase_pad_to_transport_len(skb, transport_offset, pad_to_len))
++              return false;
++
++      if (transport_proto != IPPROTO_UDP)
++              return true;
++
++      trans_data_len = skb->len - transport_offset;
++      if (trans_data_len < offsetof(struct udphdr, len) ||
++          trans_data_len >= RTASE_MIN_PAD_LEN)
++              return true;
++
++      dest = skb_header_pointer(skb,
++                                transport_offset +
++                                offsetof(struct udphdr, dest),
++                                sizeof(_dest), &_dest);
++      if (!dest)
++              return true;
++
++      dest_port = ntohs(*dest);
++      if (dest_port != PTP_EV_PORT && dest_port != PTP_GEN_PORT)
++              return true;
++
++      return rtase_pad_to_transport_len(skb, transport_offset,
++                                        RTASE_MIN_PAD_LEN);
++}
++
+ static int rtase_xmit_frags(struct rtase_ring *ring, struct sk_buff *skb,
+                           u32 opts1, u32 opts2)
+ {
+@@ -1362,6 +1556,9 @@ static netdev_tx_t rtase_start_xmit(stru
+               opts2 |= rtase_tx_csum(skb, dev);
+       }
++      if (!rtase_skb_pad(skb))
++              goto err_dma_0;
++
+       frags = rtase_xmit_frags(ring, skb, opts1, opts2);
+       if (unlikely(frags < 0))
+               goto err_dma_0;
index 04d98dd14c6864ca2eeb3d0fc7de8a496aafecdf..e5459cf89b924f1a1a214d3742c076d8449c56a1 100644 (file)
@@ -675,4 +675,22 @@ rbd-reset-positive-result-codes-to-zero-in-object-map-update-path.patch
 smb-client-handle-status_stopped_on_symlink-responses-without-a-symlink-target.patch
 ksmbd-defer-destroy_previous_session-until-after-ntlm-authentication.patch
 ksmbd-validate-minimum-pdu-size-for-transform-requests.patch
+gve-fix-rx-queue-stall-on-alloc-failure.patch
+ice-reject-out-of-range-ptype-in-ice_parser_profile_init.patch
+ice-use-read_once-to-access-cached-phc-time.patch
+ila-reload-ipv6-header-after-pskb_may_pull-in-checksum-adjust.patch
+mac802154-hold-an-interface-reference-across-the-scan-worker.patch
+mac802154-llsec-reject-frames-shorter-than-the-authentication-tag.patch
+mctp-serial-handle-zero-length-frames-to-prevent-rx-buffer-overflow.patch
+openvswitch-fix-gso-userspace-truncation-underflow.patch
+ovpn-fix-peer-refcount-leak-in-tcp-error-paths.patch
+ovpn-hold-peer-before-scheduling-keepalive-work.patch
+pppoe-reload-header-pointer-after-dev_hard_header.patch
+rtase-workaround-for-tx-hang-caused-by-hardware-packet-parsing.patch
+tcp-initialize-standalone-tcp-ao-response-padding.patch
+tcp-challenge-ack-for-non-exact-rst-in-syn-received.patch
+tipc-clear-sock-sk-on-the-failed-insert-path-in-tipc_sk_create.patch
+vsock-virtio-collapse-receive-queue-under-memory-pressure.patch
+vxlan-mdb-fix-source-list-corruption-on-a-failed-replace.patch
+watchdog-s32g_wdt-remove-incorrect-options-in-watchdog_info-struct.patch
 mm-slab-prevent-unbounded-recursion-in-free-path-with-new-kmalloc-type.patch
diff --git a/queue-7.1/tcp-challenge-ack-for-non-exact-rst-in-syn-received.patch b/queue-7.1/tcp-challenge-ack-for-non-exact-rst-in-syn-received.patch
new file mode 100644 (file)
index 0000000..0d7bef7
--- /dev/null
@@ -0,0 +1,165 @@
+From a28c4fcbf774e23b4779cae468e3497a5ad1f4a1 Mon Sep 17 00:00:00 2001
+From: Yuxiang Yang <yangyx22@mails.tsinghua.edu.cn>
+Date: Fri, 17 Jul 2026 08:14:42 +0000
+Subject: tcp: challenge ACK for non-exact RST in SYN-RECEIVED
+
+From: Yuxiang Yang <yangyx22@mails.tsinghua.edu.cn>
+
+commit a28c4fcbf774e23b4779cae468e3497a5ad1f4a1 upstream.
+
+The SYN-RECEIVED request-socket path in tcp_check_req() accepts an
+in-window RST without requiring SEG.SEQ to exactly match RCV.NXT.  A
+non-exact RST therefore removes the request instead of eliciting a
+challenge ACK.
+
+RFC 9293 section 3.10.7.4 applies the RFC 5961 reset check in
+SYN-RECEIVED: an exact RST resets the connection, while a non-exact
+in-window RST must trigger a challenge ACK and be dropped.
+
+Apply that check before the ACK-field validation, following the RFC
+sequence-number, RST, then ACK processing order.  Factor the per-netns
+challenge ACK quota out of tcp_send_challenge_ack() so request sockets
+can share it.  Use the request socket's send_ack() callback and its own
+out-of-window ACK timestamp to send and rate-limit the response.
+
+Reported-by: Yuxiang Yang <yangyx22@mails.tsinghua.edu.cn>
+Reported-by: Yizhou Zhao <zhaoyz24@mails.tsinghua.edu.cn>
+Reported-by: Ao Wang <wangao@seu.edu.cn>
+Reported-by: Xuewei Feng <fengxw06@126.com>
+Reported-by: Qi Li <qli01@tsinghua.edu.cn>
+Reported-by: Ke Xu <xuke@tsinghua.edu.cn>
+Fixes: 282f23c6ee34 ("tcp: implement RFC 5961 3.2")
+Cc: stable@vger.kernel.org
+Signed-off-by: Yuxiang Yang <yangyx22@mails.tsinghua.edu.cn>
+Reviewed-by: Eric Dumazet <edumazet@google.com>
+Link: https://patch.msgid.link/20260717081443.809393-2-yangyx22@mails.tsinghua.edu.cn
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ include/net/tcp.h        |    2 +
+ net/ipv4/tcp_input.c     |   56 ++++++++++++++++++++++++++++++++++++-----------
+ net/ipv4/tcp_minisocks.c |   12 +++++++++-
+ 3 files changed, 56 insertions(+), 14 deletions(-)
+
+--- a/include/net/tcp.h
++++ b/include/net/tcp.h
+@@ -1965,6 +1965,8 @@ static inline void tcp_fast_path_check(s
+ bool tcp_oow_rate_limited(struct net *net, const struct sk_buff *skb,
+                         int mib_idx, u32 *last_oow_ack_time);
++void tcp_reqsk_send_challenge_ack(struct sock *sk, struct sk_buff *skb,
++                                struct request_sock *req);
+ static inline void tcp_mib_init(struct net *net)
+ {
+--- a/net/ipv4/tcp_input.c
++++ b/net/ipv4/tcp_input.c
+@@ -4038,24 +4038,17 @@ static void tcp_send_ack_reflect_ect(str
+       __tcp_send_ack(sk, tp->rcv_nxt, flags);
+ }
+-/* RFC 5961 7 [ACK Throttling] */
+-static void tcp_send_challenge_ack(struct sock *sk, bool accecn_reflector)
++/* Consume one slot from the per-netns RFC 5961 challenge ACK quota.
++ * Returns true if a challenge ACK may be sent.
++ */
++static bool tcp_challenge_ack_allowed(struct net *net)
+ {
+-      struct tcp_sock *tp = tcp_sk(sk);
+-      struct net *net = sock_net(sk);
+       u32 count, now, ack_limit;
+-      /* First check our per-socket dupack rate limit. */
+-      if (__tcp_oow_rate_limited(net,
+-                                 LINUX_MIB_TCPACKSKIPPEDCHALLENGE,
+-                                 &tp->last_oow_ack_time))
+-              return;
+-
+       ack_limit = READ_ONCE(net->ipv4.sysctl_tcp_challenge_ack_limit);
+       if (ack_limit == INT_MAX)
+-              goto send_ack;
++              return true;
+-      /* Then check host-wide RFC 5961 rate limit. */
+       now = jiffies / HZ;
+       if (now != READ_ONCE(net->ipv4.tcp_challenge_timestamp)) {
+               u32 half = (ack_limit + 1) >> 1;
+@@ -4067,12 +4060,49 @@ static void tcp_send_challenge_ack(struc
+       count = READ_ONCE(net->ipv4.tcp_challenge_count);
+       if (count > 0) {
+               WRITE_ONCE(net->ipv4.tcp_challenge_count, count - 1);
+-send_ack:
++              return true;
++      }
++      return false;
++}
++
++/* RFC 5961 7 [ACK Throttling] */
++static void tcp_send_challenge_ack(struct sock *sk, bool accecn_reflector)
++{
++      struct tcp_sock *tp = tcp_sk(sk);
++      struct net *net = sock_net(sk);
++
++      /* First check our per-socket dupack rate limit. */
++      if (__tcp_oow_rate_limited(net,
++                                 LINUX_MIB_TCPACKSKIPPEDCHALLENGE,
++                                 &tp->last_oow_ack_time))
++              return;
++
++      /* Then check the per-netns RFC 5961 rate limit. */
++      if (tcp_challenge_ack_allowed(net)) {
+               NET_INC_STATS(net, LINUX_MIB_TCPCHALLENGEACK);
+               tcp_send_ack_reflect_ect(sk, accecn_reflector);
+       }
+ }
++/* Send a challenge ACK from a SYN-RECEIVED request socket. Uses
++ * __tcp_oow_rate_limited() directly so that an RST carrying payload
++ * cannot bypass the per-request rate limit.
++ */
++void tcp_reqsk_send_challenge_ack(struct sock *sk, struct sk_buff *skb,
++                                struct request_sock *req)
++{
++      struct net *net = sock_net(sk);
++
++      if (__tcp_oow_rate_limited(net, LINUX_MIB_TCPACKSKIPPEDCHALLENGE,
++                                 &tcp_rsk(req)->last_oow_ack_time))
++              return;
++
++      if (tcp_challenge_ack_allowed(net)) {
++              NET_INC_STATS(net, LINUX_MIB_TCPCHALLENGEACK);
++              req->rsk_ops->send_ack(sk, skb, req);
++      }
++}
++
+ static void tcp_store_ts_recent(struct tcp_sock *tp)
+ {
+       tp->rx_opt.ts_recent = tp->rx_opt.rcv_tsval;
+--- a/net/ipv4/tcp_minisocks.c
++++ b/net/ipv4/tcp_minisocks.c
+@@ -835,7 +835,7 @@ struct sock *tcp_check_req(struct sock *
+        * elsewhere and is checked directly against the child socket rather
+        * than req because user data may have been sent out.
+        */
+-      if ((flg & TCP_FLAG_ACK) && !fastopen &&
++      if ((flg & TCP_FLAG_ACK) && !(flg & TCP_FLAG_RST) && !fastopen &&
+           (TCP_SKB_CB(skb)->ack_seq !=
+            tcp_rsk(req)->snt_isn + 1))
+               return sk;
+@@ -874,6 +874,16 @@ struct sock *tcp_check_req(struct sock *
+               flg &= ~TCP_FLAG_SYN;
+       }
++      /* RFC 5961 section 3.2, as clarified by RFC 9293 section
++       * 3.10.7.4, requires a challenge ACK for a non-exact
++       * in-window RST in SYN-RECEIVED.
++       */
++      if ((flg & TCP_FLAG_RST) &&
++          TCP_SKB_CB(skb)->seq != tcp_rsk(req)->rcv_nxt) {
++              tcp_reqsk_send_challenge_ack(sk, skb, req);
++              return NULL;
++      }
++
+       /* RFC793: "second check the RST bit" and
+        *         "fourth, check the SYN bit"
+        */
diff --git a/queue-7.1/tcp-initialize-standalone-tcp-ao-response-padding.patch b/queue-7.1/tcp-initialize-standalone-tcp-ao-response-padding.patch
new file mode 100644 (file)
index 0000000..2a4d955
--- /dev/null
@@ -0,0 +1,67 @@
+From e1a9d3cc11829c5414a75eb39c704f461936eb24 Mon Sep 17 00:00:00 2001
+From: Yizhou Zhao <zhaoyz24@mails.tsinghua.edu.cn>
+Date: Mon, 13 Jul 2026 18:56:30 +0800
+Subject: tcp: initialize standalone TCP-AO response padding
+
+From: Yizhou Zhao <zhaoyz24@mails.tsinghua.edu.cn>
+
+commit e1a9d3cc11829c5414a75eb39c704f461936eb24 upstream.
+
+tcp_v4_send_ack() and tcp_v6_send_response() construct standalone TCP
+responses with TCP-AO options.  The option length carries the actual MAC
+length, but the TCP header length includes the option rounded up to a
+four-byte boundary.
+
+tcp_ao_hash_hdr() writes the MAC only.  Thus, when the MAC length is not
+four-byte aligned, the one to three bytes after the MAC are left
+uninitialized and may be transmitted.  For the normal TCP-AO hashing
+mode, those bytes also have to be initialized before computing the MAC.
+
+Initialize only the alignment padding in the TCP-AO branches, before
+hashing the header.  Use TCPOPT_NOP, as in the normal TCP-AO output path.
+This avoids adding work to non-AO TCP responses while preserving a valid
+authenticated header.
+
+Fixes: decde2586b34 ("net/tcp: Add TCP-AO sign to twsk")
+Fixes: da7dfaa6d6f7 ("net/tcp: Consistently align TCP-AO option in the header")
+Cc: stable@vger.kernel.org
+Reported-by: Yizhou Zhao <zhaoyz24@mails.tsinghua.edu.cn>
+Reported-by: Yuxiang Yang <yangyx22@mails.tsinghua.edu.cn>
+Reported-by: Ao Wang <wangao@seu.edu.cn>
+Reported-by: Xuewei Feng <fengxw06@126.com>
+Reported-by: Qi Li <qli01@tsinghua.edu.cn>
+Reported-by: Ke Xu <xuke@tsinghua.edu.cn>
+Suggested-by: Eric Dumazet <edumazet@google.com>
+Signed-off-by: Yizhou Zhao <zhaoyz24@mails.tsinghua.edu.cn>
+Reviewed-by: Eric Dumazet <edumazet@google.com>
+Link: https://patch.msgid.link/20260713105631.8616-1-zhaoyz24@mails.tsinghua.edu.cn
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ipv4/tcp_ipv4.c |    3 +++
+ net/ipv6/tcp_ipv6.c |    2 ++
+ 2 files changed, 5 insertions(+)
+
+--- a/net/ipv4/tcp_ipv4.c
++++ b/net/ipv4/tcp_ipv4.c
+@@ -971,6 +971,9 @@ static void tcp_v4_send_ack(const struct
+                                         key->rcv_next);
+               arg.iov[0].iov_len += tcp_ao_len_aligned(key->ao_key);
+               rep.th.doff = arg.iov[0].iov_len / 4;
++              memset((u8 *)&rep.opt[offset] + tcp_ao_maclen(key->ao_key),
++                     TCPOPT_NOP, tcp_ao_len_aligned(key->ao_key) -
++                                  tcp_ao_len(key->ao_key));
+               tcp_ao_hash_hdr(AF_INET, (char *)&rep.opt[offset],
+                               key->ao_key, key->traffic_key,
+--- a/net/ipv6/tcp_ipv6.c
++++ b/net/ipv6/tcp_ipv6.c
+@@ -915,6 +915,8 @@ static void tcp_v6_send_response(const s
+                               (tcp_ao_len(key->ao_key) << 16) |
+                               (key->ao_key->sndid << 8) |
+                               (key->rcv_next));
++              memset((u8 *)topt + tcp_ao_maclen(key->ao_key), TCPOPT_NOP,
++                     tcp_ao_len_aligned(key->ao_key) - tcp_ao_len(key->ao_key));
+               tcp_ao_hash_hdr(AF_INET6, (char *)topt, key->ao_key,
+                               key->traffic_key,
diff --git a/queue-7.1/tipc-clear-sock-sk-on-the-failed-insert-path-in-tipc_sk_create.patch b/queue-7.1/tipc-clear-sock-sk-on-the-failed-insert-path-in-tipc_sk_create.patch
new file mode 100644 (file)
index 0000000..3fa7bca
--- /dev/null
@@ -0,0 +1,82 @@
+From ba0533fc163f905fe817cfabdf8ed4058da44800 Mon Sep 17 00:00:00 2001
+From: Daehyeon Ko <4ncienth@gmail.com>
+Date: Tue, 14 Jul 2026 22:19:39 +0900
+Subject: tipc: clear sock->sk on the failed-insert path in tipc_sk_create()
+
+From: Daehyeon Ko <4ncienth@gmail.com>
+
+commit ba0533fc163f905fe817cfabdf8ed4058da44800 upstream.
+
+When tipc_sk_create() fails to insert the new socket (tipc_sk_insert()
+returns non-zero), its error path frees the sk with sk_free() but leaves
+sock->sk pointing at the freed object:
+
+       if (tipc_sk_insert(tsk)) {
+               sk_free(sk);
+               pr_warn("Socket create failed; port number exhausted\n");
+               return -EINVAL;
+       }
+
+This is harmless for plain socket(): the syscall layer clears sock->ops
+before releasing, so tipc_release() is never called. It is not harmless
+on the accept() path. tipc_accept() creates the pre-allocated child
+socket with tipc_sk_create(net, new_sock, 0, kern); on failure it leaves
+new_sock->sk dangling and new_sock->ops non-NULL, and do_accept() then
+fput()s the new file, so __sock_release() -> tipc_release() runs
+lock_sock(new_sock->sk) on the freed sk -- a use-after-free write of the
+sk_lock spinlock.
+
+tipc_release() already guards this exact "failed accept() releases a
+pre-allocated child" case with "if (sk == NULL) return 0;", but the
+guard is bypassed because tipc_sk_create() left sock->sk non-NULL
+(dangling) rather than NULL.
+
+Clear sock->sk on the failed-insert path so the existing tipc_release()
+NULL check fires and the use-after-free is avoided.
+
+The tipc_sk_insert() failure is reached when the per-netns socket
+rhashtable hits its max_size (tsk_rht_params.max_size = 1048576, ~2M
+elements) -- i.e. once a netns holds ~2M TIPC sockets every insert
+returns -E2BIG.
+
+  BUG: KASAN: slab-use-after-free in lock_sock_nested (net/core/sock.c:3839)
+  Write of size 8 at addr ffff8880047cdc38 by task init/1
+   lock_sock_nested (net/core/sock.c:3839)
+   tipc_release (net/tipc/socket.c:638)
+   __sock_release (net/socket.c:710)
+   sock_close (net/socket.c:1501)
+   __fput (fs/file_table.c:512)
+  Allocated by task 1:
+   sk_alloc (net/core/sock.c:2308)
+   tipc_sk_create (net/tipc/socket.c:487)
+   tipc_accept (net/tipc/socket.c:2744)
+   do_accept (net/socket.c:2034)
+  Freed by task 1:
+   __sk_destruct (net/core/sock.c:2391)
+   tipc_sk_create (net/tipc/socket.c:504)
+   tipc_accept (net/tipc/socket.c:2744)
+   do_accept (net/socket.c:2034)
+
+Fixes: 00aff3590fc0 ("net: tipc: fix possible refcount leak in tipc_sk_create()")
+Cc: stable@vger.kernel.org
+Reviewed-by: Tung Nguyen <tung.quang.nguyen@est.tech>
+Reviewed-by: Breno Leitao <leitao@debian.org>
+Signed-off-by: Daehyeon Ko <4ncienth@gmail.com>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Link: https://patch.msgid.link/20260714131939.1255974-1-4ncienth@gmail.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/tipc/socket.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/net/tipc/socket.c
++++ b/net/tipc/socket.c
+@@ -501,6 +501,7 @@ static int tipc_sk_create(struct net *ne
+       tipc_set_sk_state(sk, TIPC_OPEN);
+       if (tipc_sk_insert(tsk)) {
+               sk_free(sk);
++              sock->sk = NULL;
+               pr_warn("Socket create failed; port number exhausted\n");
+               return -EINVAL;
+       }
diff --git a/queue-7.1/vsock-virtio-collapse-receive-queue-under-memory-pressure.patch b/queue-7.1/vsock-virtio-collapse-receive-queue-under-memory-pressure.patch
new file mode 100644 (file)
index 0000000..240dbb5
--- /dev/null
@@ -0,0 +1,250 @@
+From 2a12c05aef213ff304ecc9e2f351de20731946b8 Mon Sep 17 00:00:00 2001
+From: Stefano Garzarella <sgarzare@redhat.com>
+Date: Wed, 8 Jul 2026 12:29:03 +0200
+Subject: vsock/virtio: collapse receive queue under memory pressure
+
+From: Stefano Garzarella <sgarzare@redhat.com>
+
+commit 2a12c05aef213ff304ecc9e2f351de20731946b8 upstream.
+
+When many small packets accumulate in the receive queue, the skb overhead
+can exceed buf_alloc even while the payload is within bounds. This causes
+virtio_transport_inc_rx_pkt() to reject packets, leading to connection
+resets during large transfers under backpressure.
+
+The issue was reported by Brien, who has a reproducer, but it is also
+easily reproducible with iperf-vsock [1] using a small packet size:
+
+  iperf3 --vsock -c $CID -l 129
+
+which fails immediately without this patch but with commit 059b7dbd20a6
+("vsock/virtio: fix potential unbounded skb queue").
+
+Inspired by TCP's tcp_collapse() which solves a similar problem, add
+virtio_transport_collapse_rx_queue() that walks the receive queue and
+re-copies data into compact linear skbs to reduce the overhead.
+
+The collapse is triggered proactively from when the number of skb queued
+is close to exceeding the overhead budget.
+
+A pre-scan counts the eligible bytes to size each allocation precisely,
+avoiding waste for isolated small packets. Partially consumed skbs are
+kept as-is to preserve buf_used/fwd_cnt accounting, EOM-marked skbs to
+maintain SEQPACKET message boundaries, and skbs already larger than the
+collapse target because they already have a good data-to-overhead ratio.
+
+Walking a large queue may take a significant amount of time and cache
+misses, causing traffic burstiness. To limit this, the collapse stops
+once enough room is freed for this packet and the next one, but may
+opportunistically free more to fill each collapsed skb to capacity.
+
+[1] https://github.com/stefano-garzarella/iperf-vsock
+
+Fixes: 059b7dbd20a6 ("vsock/virtio: fix potential unbounded skb queue")
+Cc: stable@vger.kernel.org
+Reported-by: Brien Oberstein <brienpub@gmail.com>
+Closes: https://lore.kernel.org/netdev/618701dd023e$063de350$12b9a9f0$@gmail.com/
+Tested-by: Brien Oberstein <brienpub@gmail.com>
+Signed-off-by: Stefano Garzarella <sgarzare@redhat.com>
+Acked-by: Michael S. Tsirkin <mst@redhat.com>
+Reviewed-by: Bobby Eshleman <bobbyeshleman@meta.com>
+Link: https://patch.msgid.link/20260708102904.50732-2-sgarzare@redhat.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/vmw_vsock/virtio_transport_common.c |  165 +++++++++++++++++++++++++++++++-
+ 1 file changed, 164 insertions(+), 1 deletion(-)
+
+--- a/net/vmw_vsock/virtio_transport_common.c
++++ b/net/vmw_vsock/virtio_transport_common.c
+@@ -26,6 +26,13 @@
+ /* Threshold for detecting small packets to copy */
+ #define GOOD_COPY_LEN  128
++/* Max payload that can be collapsed into a single linear skb, using the same
++ * allocation threshold as virtio_vsock_alloc_skb() to avoid adding pressure
++ * on the page allocator.
++ */
++#define MAX_COLLAPSE_LEN \
++      SKB_MAX_ORDER(VIRTIO_VSOCK_SKB_HEADROOM, PAGE_ALLOC_COSTLY_ORDER)
++
+ static void virtio_transport_cancel_close_work(struct vsock_sock *vsk,
+                                              bool cancel_timeout);
+ static s64 virtio_transport_has_space(struct virtio_vsock_sock *vvs);
+@@ -420,6 +427,145 @@ static int virtio_transport_send_pkt_inf
+       return ret;
+ }
++static bool virtio_transport_can_collapse(struct sk_buff *skb)
++{
++      /* skbs that are partially consumed, mark a SEQPACKET message boundary,
++       * or are already large enough should not be collapsed: they either
++       * need special accounting, carry protocol state, or already have a
++       * good data-to-overhead ratio.
++       */
++      if (VIRTIO_VSOCK_SKB_CB(skb)->offset)
++              return false;
++      if (le32_to_cpu(virtio_vsock_hdr(skb)->flags) & VIRTIO_VSOCK_SEQ_EOM)
++              return false;
++      if (skb->len >= MAX_COLLAPSE_LEN)
++              return false;
++      return true;
++}
++
++/* Iterate through the packets in the queue starting from the current skb to
++ * count the number of bytes we can collapse.
++ */
++static unsigned int
++virtio_transport_collapse_size(struct sk_buff *skb, struct sk_buff_head *queue)
++{
++      unsigned int target = skb->len - VIRTIO_VSOCK_SKB_CB(skb)->offset;
++
++      while ((skb = skb_peek_next(skb, queue)) &&
++             virtio_transport_can_collapse(skb)) {
++              unsigned int len = skb->len - VIRTIO_VSOCK_SKB_CB(skb)->offset;
++
++              if (len > MAX_COLLAPSE_LEN - target)
++                      return target;
++
++              target += len;
++      }
++
++      return target;
++}
++
++/* Called under lock_sock to compact the receive queue by merging small skbs.
++ * @min_to_free: minimum number of skbs to eliminate from the queue. May free
++ *               more to fill each collapsed skb to capacity.
++ */
++static void
++virtio_transport_collapse_rx_queue(struct virtio_vsock_sock *vvs,
++                                 u32 min_to_free)
++{
++      struct sk_buff *skb, *next_skb, *new_skb = NULL;
++      struct sk_buff_head new_queue;
++      u32 saved = 0;
++
++      __skb_queue_head_init(&new_queue);
++
++      skb_queue_walk_safe(&vvs->rx_queue, skb, next_skb) {
++              struct virtio_vsock_hdr *hdr = virtio_vsock_hdr(skb);
++              u32 src_off = VIRTIO_VSOCK_SKB_CB(skb)->offset;
++              u32 src_len = skb->len - src_off;
++              bool keep;
++
++              keep = !virtio_transport_can_collapse(skb);
++              if (keep) {
++                      /* Finalize pending collapsed skb to preserve packet
++                       * ordering.
++                       */
++                      if (new_skb) {
++                              __skb_queue_tail(&new_queue, new_skb);
++                              new_skb = NULL;
++                              saved--;
++                      }
++                      goto next;
++              }
++
++              /* Finalize if this packet won't fit in the remaining tailroom,
++               * so we can allocate a right-sized new_skb.
++               */
++              if (new_skb && src_len > skb_tailroom(new_skb)) {
++                      __skb_queue_tail(&new_queue, new_skb);
++                      new_skb = NULL;
++                      saved--;
++              }
++
++              if (!new_skb) {
++                      unsigned int alloc_size;
++
++                      /* Check after finalizing to opportunistically fill
++                       * each collapsed skb to capacity, merging more skbs
++                       * than strictly required.
++                       */
++                      if (saved >= min_to_free)
++                              break;
++
++                      alloc_size = virtio_transport_collapse_size(skb, &vvs->rx_queue);
++
++                      /* Only this skb's data is eligible, nothing to merge
++                       * with. Keep as-is.
++                       */
++                      if (alloc_size <= src_len) {
++                              keep = true;
++                              goto next;
++                      }
++
++                      new_skb = virtio_vsock_alloc_linear_skb(alloc_size +
++                                      VIRTIO_VSOCK_SKB_HEADROOM, GFP_KERNEL);
++                      if (!new_skb)
++                              break;
++
++                      memcpy(virtio_vsock_hdr(new_skb), hdr,
++                             sizeof(struct virtio_vsock_hdr));
++                      virtio_vsock_hdr(new_skb)->len = 0;
++              }
++
++              /* Cannot fail since src_off/src_len are within bounds, but if
++               * it does, discard new_skb to avoid queuing corrupted data.
++               */
++              if (WARN_ON_ONCE(skb_copy_bits(skb, src_off,
++                                             skb_put(new_skb, src_len),
++                                             src_len))) {
++                      kfree_skb(new_skb);
++                      new_skb = NULL;
++                      break;
++              }
++
++              le32_add_cpu(&virtio_vsock_hdr(new_skb)->len, src_len);
++              virtio_vsock_hdr(new_skb)->flags |= hdr->flags;
++
++next:
++              __skb_unlink(skb, &vvs->rx_queue);
++              if (keep) {
++                      __skb_queue_tail(&new_queue, skb);
++              } else {
++                      consume_skb(skb);
++                      saved++;
++              }
++      }
++
++      if (new_skb)
++              __skb_queue_tail(&new_queue, new_skb);
++
++      skb_queue_splice(&new_queue, &vvs->rx_queue);
++}
++
+ static bool virtio_transport_inc_rx_pkt(struct virtio_vsock_sock *vvs,
+                                       u32 len)
+ {
+@@ -1354,12 +1500,29 @@ virtio_transport_recv_enqueue(struct vso
+ {
+       struct virtio_vsock_sock *vvs = vsk->trans;
+       bool can_enqueue, free_pkt = false;
++      u32 len, queue_max, queue_len;
+       struct virtio_vsock_hdr *hdr;
+-      u32 len;
+       hdr = virtio_vsock_hdr(skb);
+       len = le32_to_cpu(hdr->len);
++      /* virtio_transport_inc_rx_pkt() rejects packets when the per-skb
++       * overhead (skb_queue_len * SKB_TRUESIZE(0)) exceeds buf_alloc.
++       * Proactively collapse the queue before that happens.
++       * No rx_lock needed: lock_sock is held by caller, preventing
++       * concurrent enqueue or dequeue.
++       */
++      queue_max = vvs->buf_alloc / SKB_TRUESIZE(0);
++      queue_len = skb_queue_len(&vvs->rx_queue);
++      if (queue_len >= queue_max) {
++              /* Walking a large queue may take a significant amount of time
++               * and cache misses, causing traffic burstiness. Limit the
++               * collapse to freeing room for this packet and the next one.
++               * It may free more to fill each collapsed skb to capacity.
++               */
++              virtio_transport_collapse_rx_queue(vvs, queue_len + 2 - queue_max);
++      }
++
+       spin_lock_bh(&vvs->rx_lock);
+       can_enqueue = virtio_transport_inc_rx_pkt(vvs, len);
diff --git a/queue-7.1/vxlan-mdb-fix-source-list-corruption-on-a-failed-replace.patch b/queue-7.1/vxlan-mdb-fix-source-list-corruption-on-a-failed-replace.patch
new file mode 100644 (file)
index 0000000..f35476f
--- /dev/null
@@ -0,0 +1,131 @@
+From dcd9b465965422b9654f6026e8a2fa8984f74c3c Mon Sep 17 00:00:00 2001
+From: James Raphael Tiovalen <jamestiotio@gmail.com>
+Date: Tue, 21 Jul 2026 00:04:24 +0800
+Subject: vxlan: mdb: Fix source list corruption on a failed replace
+
+From: James Raphael Tiovalen <jamestiotio@gmail.com>
+
+commit dcd9b465965422b9654f6026e8a2fa8984f74c3c upstream.
+
+When replacing the source list of an MDB remote entry, all existing
+sources are first marked for deletion and vxlan_mdb_remote_srcs_add()
+is then called to add the new source list. Sources present in the new
+list have their deletion mark cleared, and any sources left marked
+afterwards are removed.
+
+If vxlan_mdb_remote_srcs_add() fails partway through, its error path
+deletes all entries on the remote's source list. That rollback is only
+correct for its other caller, vxlan_mdb_remote_add(), where the remote
+was just allocated and the list contains solely entries added during
+the call. On the replace path the list also holds pre-existing sources,
+so a failed replace tears them down together with their (S, G)
+forwarding entries instead of leaving the entry unchanged.
+
+This is reachable from an existing (*, G) remote. An EXCLUDE filter
+that loses sources starts forwarding traffic that should be blocked,
+while an INCLUDE filter that loses sources drops traffic that should be
+forwarded.
+
+Mark entries created during the current pass with a new
+VXLAN_SGRP_F_NEW flag. On failure, delete only those entries and clear
+the deletion mark on the pre-existing ones, so a failed replace leaves
+the source list untouched. Retain the flag until the whole operation
+succeeds and then clear it. Also stop vxlan_mdb_remote_src_add() from
+deleting a pre-existing entry it only looked up when adding that
+entry's forwarding entry fails.
+
+Fixes: a3a48de5eade ("vxlan: mdb: Add MDB control path support")
+Cc: stable@vger.kernel.org
+Signed-off-by: James Raphael Tiovalen <jamestiotio@gmail.com>
+Reviewed-by: Ido Schimmel <idosch@nvidia.com>
+Reviewed-by: Antoine Tenart <atenart@kernel.org>
+Reviewed-by: Nikolay Aleksandrov <razor@blackwall.org>
+Link: https://patch.msgid.link/20260720160428.249356-1-jamestiotio@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/vxlan/vxlan_mdb.c |   30 ++++++++++++++++++------------
+ 1 file changed, 18 insertions(+), 12 deletions(-)
+
+--- a/drivers/net/vxlan/vxlan_mdb.c
++++ b/drivers/net/vxlan/vxlan_mdb.c
+@@ -42,6 +42,7 @@ struct vxlan_mdb_remote {
+ };
+ #define VXLAN_SGRP_F_DELETE   BIT(0)
++#define VXLAN_SGRP_F_NEW      BIT(1)
+ struct vxlan_mdb_src_entry {
+       struct hlist_node node;
+@@ -844,6 +845,7 @@ vxlan_mdb_remote_src_add(const struct vx
+               ent = vxlan_mdb_remote_src_entry_add(remote, &src->addr);
+               if (!ent)
+                       return -ENOMEM;
++              ent->flags |= VXLAN_SGRP_F_NEW;
+       } else if (!(cfg->nlflags & NLM_F_REPLACE)) {
+               NL_SET_ERR_MSG_MOD(extack, "Source entry already exists");
+               return -EEXIST;
+@@ -853,15 +855,16 @@ vxlan_mdb_remote_src_add(const struct vx
+       if (err)
+               goto err_src_del;
+-      /* Clear flags in case source entry was marked for deletion as part of
+-       * replace flow.
++      /* Clear the deletion mark so the entry survives the replace sweep.
++       * The new mark is retained until the whole operation succeeds.
+        */
+-      ent->flags = 0;
++      ent->flags &= ~VXLAN_SGRP_F_DELETE;
+       return 0;
+ err_src_del:
+-      vxlan_mdb_remote_src_entry_del(ent);
++      if (ent->flags & VXLAN_SGRP_F_NEW)
++              vxlan_mdb_remote_src_entry_del(ent);
+       return err;
+ }
+@@ -889,11 +892,19 @@ static int vxlan_mdb_remote_srcs_add(con
+                       goto err_src_del;
+       }
++      hlist_for_each_entry(ent, &remote->src_list, node)
++              ent->flags &= ~VXLAN_SGRP_F_NEW;
++
+       return 0;
+ err_src_del:
+-      hlist_for_each_entry_safe(ent, tmp, &remote->src_list, node)
+-              vxlan_mdb_remote_src_del(cfg->vxlan, &cfg->group, remote, ent);
++      hlist_for_each_entry_safe(ent, tmp, &remote->src_list, node) {
++              if (ent->flags & VXLAN_SGRP_F_NEW)
++                      vxlan_mdb_remote_src_del(cfg->vxlan, &cfg->group, remote,
++                                               ent);
++              else
++                      ent->flags &= ~VXLAN_SGRP_F_DELETE;
++      }
+       return err;
+ }
+@@ -1069,7 +1080,7 @@ vxlan_mdb_remote_srcs_replace(const stru
+       err = vxlan_mdb_remote_srcs_add(cfg, remote, extack);
+       if (err)
+-              goto err_clear_delete;
++              return err;
+       hlist_for_each_entry_safe(ent, tmp, &remote->src_list, node) {
+               if (ent->flags & VXLAN_SGRP_F_DELETE)
+@@ -1078,11 +1089,6 @@ vxlan_mdb_remote_srcs_replace(const stru
+       }
+       return 0;
+-
+-err_clear_delete:
+-      hlist_for_each_entry(ent, &remote->src_list, node)
+-              ent->flags &= ~VXLAN_SGRP_F_DELETE;
+-      return err;
+ }
+ static int vxlan_mdb_remote_replace(const struct vxlan_mdb_config *cfg,
diff --git a/queue-7.1/watchdog-s32g_wdt-remove-incorrect-options-in-watchdog_info-struct.patch b/queue-7.1/watchdog-s32g_wdt-remove-incorrect-options-in-watchdog_info-struct.patch
new file mode 100644 (file)
index 0000000..793ffca
--- /dev/null
@@ -0,0 +1,40 @@
+From 2b37415618bfc6a83d4aceb00fd8d6491096f2ed Mon Sep 17 00:00:00 2001
+From: Ethan Nelson-Moore <enelsonmoore@gmail.com>
+Date: Mon, 4 May 2026 19:44:09 -0700
+Subject: watchdog: s32g_wdt: remove incorrect options in watchdog_info struct
+
+From: Ethan Nelson-Moore <enelsonmoore@gmail.com>
+
+commit 2b37415618bfc6a83d4aceb00fd8d6491096f2ed upstream.
+
+The s32g_wdt driver uses two incorrect constants in the options field
+of its watchdog_info struct. This bit mask should contain WDIOF_*
+constants, but the driver uses two WDIOC_* ioctl constants (in addition
+to correct WDIOF_* constants). This causes many incorrect bits to be
+set in the bit mask. The functionality indicated by these ioctl
+constants is supported by all drivers using the watchdog framework, so
+this patch simply removes them.
+
+Fixes: bd3f54ec559b ("watchdog: Add the Watchdog Timer for the NXP S32 platform")
+Cc: stable@vger.kernel.org # 6.18+
+Signed-off-by: Ethan Nelson-Moore <enelsonmoore@gmail.com>
+Acked-by: Daniel Lezcano <daniel.lezcano@oss.qualcomm.com>
+Link: https://lore.kernel.org/r/20260505024409.60301-1-enelsonmoore@gmail.com
+Signed-off-by: Guenter Roeck <linux@roeck-us.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/watchdog/s32g_wdt.c |    3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+--- a/drivers/watchdog/s32g_wdt.c
++++ b/drivers/watchdog/s32g_wdt.c
+@@ -56,8 +56,7 @@ MODULE_PARM_DESC(early_enable,
+ static const struct watchdog_info s32g_wdt_info = {
+       .identity = "s32g watchdog",
+-      .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE |
+-      WDIOC_GETTIMEOUT | WDIOC_GETTIMELEFT,
++      .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE,
+ };
+ static struct s32g_wdt_device *wdd_to_s32g_wdt(struct watchdog_device *wdd)