--- /dev/null
+From 084d23f818321390509e9738a0b08bbf46df6425 Mon Sep 17 00:00:00 2001
+From: Florian Westphal <fw@strlen.de>
+Date: Sat, 4 Jul 2026 12:05:15 +0200
+Subject: netfilter: ebtables: module names must be null-terminated
+
+From: Florian Westphal <fw@strlen.de>
+
+commit 084d23f818321390509e9738a0b08bbf46df6425 upstream.
+
+We need to explicitly check the length, else we may pass non-null
+terminated string to request_module().
+
+Cc: stable@vger.kernel.org
+Fixes: bcf493428840 ("netfilter: ebtables: Fix extension lookup with identical name")
+Signed-off-by: Florian Westphal <fw@strlen.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/bridge/netfilter/ebtables.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/net/bridge/netfilter/ebtables.c
++++ b/net/bridge/netfilter/ebtables.c
+@@ -403,6 +403,9 @@ ebt_check_match(struct ebt_entry_match *
+ left - sizeof(struct ebt_entry_match) < m->match_size)
+ return -EINVAL;
+
++ if (strnlen(m->u.name, XT_EXTENSION_MAXNAMELEN) == XT_EXTENSION_MAXNAMELEN)
++ return -EINVAL;
++
+ match = xt_find_match(NFPROTO_BRIDGE, m->u.name, m->u.revision);
+ if (IS_ERR(match) || match->family != NFPROTO_BRIDGE) {
+ if (!IS_ERR(match))
--- /dev/null
+From a622d2e9608c9dff47fc2e5759ac7aa3a836b45d Mon Sep 17 00:00:00 2001
+From: Xiang Mei <xmei5@asu.edu>
+Date: Sun, 5 Jul 2026 14:58:00 -0700
+Subject: netfilter: ebtables: terminate table name before find_table_lock()
+
+From: Xiang Mei <xmei5@asu.edu>
+
+commit a622d2e9608c9dff47fc2e5759ac7aa3a836b45d upstream.
+
+update_counters() and compat_update_counters() forward a user-supplied
+32-byte table name to find_table_lock() without NUL-terminating it. On a
+lookup miss, find_inlist_lock() calls try_then_request_module(..., "%s%s",
+"ebtable_", name), and vsnprintf() reads past the name field and the
+stack object until it hits a zero byte.
+
+ BUG: KASAN: stack-out-of-bounds in string (lib/vsprintf.c:648 lib/vsprintf.c:730)
+ Read of size 1 at addr ffff8880119dfb20 by task exploit/147
+ Call Trace:
+ ...
+ string (lib/vsprintf.c:648 lib/vsprintf.c:730)
+ vsnprintf (lib/vsprintf.c:2945)
+ __request_module (kernel/module/kmod.c:150)
+ do_update_counters.isra.0 (net/bridge/netfilter/ebtables.c:371 net/bridge/netfilter/ebtables.c:380)
+ update_counters (net/bridge/netfilter/ebtables.c:1440)
+ do_ebt_set_ctl (net/bridge/netfilter/ebtables.c:2573)
+ nf_setsockopt (net/netfilter/nf_sockopt.c:101)
+ ip_setsockopt (net/ipv4/ip_sockglue.c:1424)
+ raw_setsockopt (net/ipv4/raw.c:847)
+ __sys_setsockopt (net/socket.c:2393)
+ ...
+
+compat_do_replace() shares the same unterminated name via
+compat_copy_ebt_replace_from_user(); terminate it there too so all
+find_table_lock() callers behave alike. The other callers already
+terminate the name after the copy.
+
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Fixes: 81e675c227ec ("netfilter: ebtables: add CONFIG_COMPAT support")
+Cc: stable@vger.kernel.org
+Reported-by: Weiming Shi <bestswngs@gmail.com>
+Assisted-by: Claude:claude-opus-4-8
+Signed-off-by: Xiang Mei <xmei5@asu.edu>
+Signed-off-by: Florian Westphal <fw@strlen.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/bridge/netfilter/ebtables.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+--- a/net/bridge/netfilter/ebtables.c
++++ b/net/bridge/netfilter/ebtables.c
+@@ -1436,6 +1436,8 @@ static int update_counters(struct net *n
+ if (copy_from_sockptr(&hlp, arg, sizeof(hlp)))
+ return -EFAULT;
+
++ hlp.name[sizeof(hlp.name) - 1] = '\0';
++
+ if (len != sizeof(hlp) + hlp.num_counters * sizeof(struct ebt_counter))
+ return -EINVAL;
+
+@@ -2275,6 +2277,8 @@ static int compat_copy_ebt_replace_from_
+
+ memcpy(repl, &tmp, offsetof(struct ebt_replace, hook_entry));
+
++ repl->name[sizeof(repl->name) - 1] = '\0';
++
+ /* starting with hook_entry, 32 vs. 64 bit structures are different */
+ for (i = 0; i < NF_BR_NUMHOOKS; i++)
+ repl->hook_entry[i] = compat_ptr(tmp.hook_entry[i]);
+@@ -2397,6 +2401,8 @@ static int compat_update_counters(struct
+ if (copy_from_sockptr(&hlp, arg, sizeof(hlp)))
+ return -EFAULT;
+
++ hlp.name[sizeof(hlp.name) - 1] = '\0';
++
+ /* try real handler in case userland supplied needed padding */
+ if (len != sizeof(hlp) + hlp.num_counters * sizeof(struct ebt_counter))
+ return update_counters(net, arg, len);
--- /dev/null
+From cbfe53599eebffd188938ab6774cc41794f6f9d5 Mon Sep 17 00:00:00 2001
+From: Florian Westphal <fw@strlen.de>
+Date: Sat, 4 Jul 2026 10:23:31 +0200
+Subject: netfilter: ebtables: zero chainstack array
+
+From: Florian Westphal <fw@strlen.de>
+
+commit cbfe53599eebffd188938ab6774cc41794f6f9d5 upstream.
+
+sashiko reports:
+ looking at ebtables table
+ translation, could a sparse cpu_possible_mask lead to an uninitialized pointer
+ free?
+
+ If cpu_possible_mask is sparse (for example, CPU 0 and CPU 2 are possible,
+ but CPU 1 is not), the allocation loop skips CPU 1. If vmalloc_node() fails at
+ CPU 2, the cleanup loop will blindly decrement and call vfree() on
+ newinfo->chainstack[1].
+
+Not a real-world bug, such allocation isn't expected to fail
+in the first place.
+
+Cc: stable@vger.kernel.org
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Signed-off-by: Florian Westphal <fw@strlen.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/bridge/netfilter/ebtables.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+--- a/net/bridge/netfilter/ebtables.c
++++ b/net/bridge/netfilter/ebtables.c
+@@ -921,8 +921,7 @@ static int translate_table(struct net *n
+ * if an error occurs
+ */
+ newinfo->chainstack =
+- vmalloc_array(nr_cpu_ids,
+- sizeof(*(newinfo->chainstack)));
++ vcalloc(nr_cpu_ids, sizeof(*(newinfo->chainstack)));
+ if (!newinfo->chainstack)
+ return -ENOMEM;
+ for_each_possible_cpu(i) {
--- /dev/null
+From 53b3e60edb674b442b2b3bbdba484667b0f47a5d Mon Sep 17 00:00:00 2001
+From: Adrian Bente <adibente@gmail.com>
+Date: Thu, 28 May 2026 10:08:51 +0300
+Subject: netfilter: flowtable: fix offloaded ct timeout never being extended
+
+From: Adrian Bente <adibente@gmail.com>
+
+commit 53b3e60edb674b442b2b3bbdba484667b0f47a5d upstream.
+
+OpenWrt has recently migrated many platforms to kernel 6.18. On the
+MediaTek platform, which supports hardware network offloading, WiFi
+connections accelerated via the WED path were observed to drop after
+roughly 300 seconds.
+
+After several debugging sessions, assisted by the Claude LLM, the
+problem was narrowed down as follows:
+
+nf_flow_table_extend_ct_timeout() extends ct->timeout for offloaded
+flows using:
+
+ cmpxchg(&ct->timeout, expires, new_timeout);
+
+'expires' comes from nf_ct_expires(ct) and is a relative value, while
+ct->timeout holds an absolute timestamp. The two are never equal, so
+the cmpxchg always fails and the timeout is never extended.
+
+This goes unnoticed for most flows, but a long-lived hardware (WED)
+offloaded flow on MediaTek MT7986 eventually has ct->timeout decay to
+zero, the conntrack entry is reaped and the connection breaks.
+
+Open-code the relative value from a single READ_ONCE(ct->timeout)
+snapshot and compare against that same absolute snapshot in the
+cmpxchg, so the timeout extension actually takes effect while the
+datapath remains authoritative if it updates ct->timeout concurrently.
+
+Fixes: 03428ca5cee9 ("netfilter: conntrack: rework offload nf_conn timeout extension logic")
+Cc: stable@vger.kernel.org
+Suggested-by: Florian Westphal <fw@strlen.de>
+Signed-off-by: Adrian Bente <adibente@gmail.com>
+Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/netfilter/nf_flow_table_core.c | 13 +++++++++----
+ 1 file changed, 9 insertions(+), 4 deletions(-)
+
+--- a/net/netfilter/nf_flow_table_core.c
++++ b/net/netfilter/nf_flow_table_core.c
+@@ -505,8 +505,13 @@ static u32 nf_flow_table_tcp_timeout(con
+ */
+ static void nf_flow_table_extend_ct_timeout(struct nf_conn *ct)
+ {
+- static const u32 min_timeout = 5 * 60 * HZ;
+- u32 expires = nf_ct_expires(ct);
++ static const s32 min_timeout = 5 * 60 * HZ;
++ u32 ct_timeout = READ_ONCE(ct->timeout);
++ s32 expires;
++
++ expires = ct_timeout - nfct_time_stamp;
++ if (expires <= 0) /* already expired */
++ return;
+
+ /* normal case: large enough timeout, nothing to do. */
+ if (likely(expires >= min_timeout))
+@@ -524,7 +529,7 @@ static void nf_flow_table_extend_ct_time
+ if (nf_ct_is_confirmed(ct) &&
+ test_bit(IPS_OFFLOAD_BIT, &ct->status)) {
+ u8 l4proto = nf_ct_protonum(ct);
+- u32 new_timeout = true;
++ u32 new_timeout = 1;
+
+ switch (l4proto) {
+ case IPPROTO_UDP:
+@@ -549,7 +554,7 @@ static void nf_flow_table_extend_ct_time
+ */
+ if (new_timeout) {
+ new_timeout += nfct_time_stamp;
+- cmpxchg(&ct->timeout, expires, new_timeout);
++ cmpxchg(&ct->timeout, ct_timeout, new_timeout);
+ }
+ }
+
--- /dev/null
+From 6c5dcab95f4cd42a1648739ec9300fbb4b1a021f Mon Sep 17 00:00:00 2001
+From: Pablo Neira Ayuso <pablo@netfilter.org>
+Date: Tue, 30 Jun 2026 11:40:55 +0200
+Subject: netfilter: flowtable: IPIP tunnel hardware offload is not yet support
+
+From: Pablo Neira Ayuso <pablo@netfilter.org>
+
+commit 6c5dcab95f4cd42a1648739ec9300fbb4b1a021f upstream.
+
+No driver supports for IPIP tunnels yet, give up early on setting up the
+hardware offload for this scenario.
+
+This patch adds a stub that can be enhanced to add more configuration
+that are currently not supported. As of now, the offload work is
+enqueued to the worker, then ignored if the hardware offload
+configuration is not supported.
+
+Check the NF_FLOW_HW flag to know if this entry was already tried once
+to be offloaded so this is not retried on refresh when unsupported. Move
+NF_FLOW_HW flag check to nf_flow_offload_add(). If this NF_FLOW_HW flag
+is unset the _del and _stats variants are never called.
+
+This can be updated later on to skip hardware offload work to be queued
+in case hardware offload does not support it.
+
+Fixes: d98103575dcd ("netfilter: flowtable: Add IP6IP6 rx sw acceleration")
+Fixes: ab427db17885 ("netfilter: flowtable: Add IPIP rx sw acceleration")
+Cc: stable@vger.kernel.org
+Reported-by: Yuan Tan <yuantan098@gmail.com>
+Reported-by: Xin Liu <bird@lzu.edu.cn>
+Reported-by: Zhengyang Chen <chzhengyang2023@lzu.edu.cn>
+Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
+Acked-by: Lorenzo Bianconi <lorenzo@kernel.org>
+Signed-off-by: Florian Westphal <fw@strlen.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ include/net/netfilter/nf_flow_table.h | 2 ++
+ net/netfilter/nf_flow_table_core.c | 7 +++----
+ net/netfilter/nf_flow_table_offload.c | 22 ++++++++++++++++++++--
+ 3 files changed, 25 insertions(+), 6 deletions(-)
+
+--- a/include/net/netfilter/nf_flow_table.h
++++ b/include/net/netfilter/nf_flow_table.h
+@@ -357,6 +357,8 @@ static inline int nf_flow_register_bpf(v
+
+ void nf_flow_offload_add(struct nf_flowtable *flowtable,
+ struct flow_offload *flow);
++void nf_flow_offload_refresh(struct nf_flowtable *flowtable,
++ struct flow_offload *flow);
+ void nf_flow_offload_del(struct nf_flowtable *flowtable,
+ struct flow_offload *flow);
+ void nf_flow_offload_stats(struct nf_flowtable *flowtable,
+--- a/net/netfilter/nf_flow_table_core.c
++++ b/net/netfilter/nf_flow_table_core.c
+@@ -345,10 +345,8 @@ int flow_offload_add(struct nf_flowtable
+
+ nf_ct_refresh(flow->ct, NF_CT_DAY);
+
+- if (nf_flowtable_hw_offload(flow_table)) {
+- __set_bit(NF_FLOW_HW, &flow->flags);
++ if (nf_flowtable_hw_offload(flow_table))
+ nf_flow_offload_add(flow_table, flow);
+- }
+
+ return 0;
+ }
+@@ -369,7 +367,8 @@ void flow_offload_refresh(struct nf_flow
+ test_bit(NF_FLOW_CLOSING, &flow->flags))
+ return;
+
+- nf_flow_offload_add(flow_table, flow);
++ if (test_bit(NF_FLOW_HW, &flow->flags))
++ nf_flow_offload_refresh(flow_table, flow);
+ }
+ EXPORT_SYMBOL_GPL(flow_offload_refresh);
+
+--- a/net/netfilter/nf_flow_table_offload.c
++++ b/net/netfilter/nf_flow_table_offload.c
+@@ -1101,9 +1101,17 @@ nf_flow_offload_work_alloc(struct nf_flo
+ return offload;
+ }
+
++static bool nf_flow_offload_unsupported(struct flow_offload *flow)
++{
++ if (flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.tun_num ||
++ flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.tun_num)
++ return true;
+
+-void nf_flow_offload_add(struct nf_flowtable *flowtable,
+- struct flow_offload *flow)
++ return false;
++}
++
++void nf_flow_offload_refresh(struct nf_flowtable *flowtable,
++ struct flow_offload *flow)
+ {
+ struct flow_offload_work *offload;
+
+@@ -1114,6 +1122,16 @@ void nf_flow_offload_add(struct nf_flowt
+ flow_offload_queue_work(offload);
+ }
+
++void nf_flow_offload_add(struct nf_flowtable *flowtable,
++ struct flow_offload *flow)
++{
++ if (nf_flow_offload_unsupported(flow))
++ return;
++
++ set_bit(NF_FLOW_HW, &flow->flags);
++ nf_flow_offload_refresh(flowtable, flow);
++}
++
+ void nf_flow_offload_del(struct nf_flowtable *flowtable,
+ struct flow_offload *flow)
+ {
--- /dev/null
+From da5b58478a9c1b85608c9e40a3b8432d071b409e Mon Sep 17 00:00:00 2001
+From: Florian Westphal <fw@strlen.de>
+Date: Sun, 5 Jul 2026 15:29:13 +0200
+Subject: netfilter: handle unreadable frags
+
+From: Florian Westphal <fw@strlen.de>
+
+commit da5b58478a9c1b85608c9e40a3b8432d071b409e upstream.
+
+sashiko reports:
+ When an skb with unreadable fragments (such as from devmem TCP, where
+ skb_frags_readable(skb) returns false) is processed by the u32 module,
+ skb_copy_bits() will safely return a negative error code [..]
+
+xt_u32: bail out with hotdrop in this case.
+gather_frags: return -1, just as if we had no fragment header.
+nfnetlink_queue: restrict to the linear part.
+nfnetlink_log: restrict to the linear part.
+
+v2:
+ - skb_zerocopy helpers don't copy readable flag, i.e. nfnetlink_queue
+ is broken too
+ xt_u32 shouldn't return true if hotdrop was set.
+
+Fixes: 65249feb6b3d ("net: add support for skbs with unreadable frags")
+Cc: stable@vger.kernel.org
+Acked-by: Mina Almasry <almasrymina@google.com>
+Signed-off-by: Florian Westphal <fw@strlen.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ipv6/netfilter/nf_conntrack_reasm.c | 2 +-
+ net/netfilter/nfnetlink_log.c | 26 +++++++++++++++++---------
+ net/netfilter/nfnetlink_queue.c | 16 ++++++++++++----
+ net/netfilter/xt_u32.c | 16 +++++++++++-----
+ 4 files changed, 41 insertions(+), 19 deletions(-)
+
+--- a/net/ipv6/netfilter/nf_conntrack_reasm.c
++++ b/net/ipv6/netfilter/nf_conntrack_reasm.c
+@@ -418,7 +418,7 @@ find_prev_fhdr(struct sk_buff *skb, u8 *
+ return -1;
+ }
+ if (skb_copy_bits(skb, start, &hdr, sizeof(hdr)))
+- BUG();
++ return -1;
+ if (nexthdr == NEXTHDR_AUTH)
+ hdrlen = ipv6_authlen(&hdr);
+ else
+--- a/net/netfilter/nfnetlink_log.c
++++ b/net/netfilter/nfnetlink_log.c
+@@ -676,7 +676,7 @@ __build_packet_message(struct nfnl_log_n
+ goto nla_put_failure;
+
+ if (skb_copy_bits(skb, 0, nla_data(nla), data_len))
+- BUG();
++ goto nla_put_failure;
+ }
+
+ nlh->nlmsg_len = inst->skb->tail - old_tail;
+@@ -698,6 +698,21 @@ static const struct nf_loginfo default_l
+ },
+ };
+
++static unsigned int nfulnl_get_copy_len(const struct nf_loginfo *li,
++ const struct sk_buff *skb,
++ unsigned int copy_len)
++{
++ unsigned int len = skb->len;
++
++ if ((li->u.ulog.flags & NF_LOG_F_COPY_LEN) &&
++ li->u.ulog.copy_len < copy_len)
++ copy_len = li->u.ulog.copy_len;
++ if (!skb_frags_readable(skb))
++ len = skb_headlen(skb);
++
++ return min(len, copy_len);
++}
++
+ /* log handler for internal netfilter logging api */
+ static void
+ nfulnl_log_packet(struct net *net,
+@@ -790,14 +805,7 @@ nfulnl_log_packet(struct net *net,
+ break;
+
+ case NFULNL_COPY_PACKET:
+- data_len = inst->copy_range;
+- if ((li->u.ulog.flags & NF_LOG_F_COPY_LEN) &&
+- (li->u.ulog.copy_len < data_len))
+- data_len = li->u.ulog.copy_len;
+-
+- if (data_len > skb->len)
+- data_len = skb->len;
+-
++ data_len = nfulnl_get_copy_len(li, skb, inst->copy_range);
+ size += nla_total_size(data_len);
+ break;
+
+--- a/net/netfilter/nfnetlink_queue.c
++++ b/net/netfilter/nfnetlink_queue.c
+@@ -690,6 +690,17 @@ static int nfqnl_put_master_ifindex(stru
+ }
+ #endif
+
++static unsigned int nfqnl_get_data_len(const struct sk_buff *entskb,
++ unsigned int copy_range)
++{
++ unsigned int data_len = entskb->len;
++
++ if (!skb_frags_readable(entskb))
++ data_len = skb_headlen(entskb);
++
++ return min(data_len, copy_range);
++}
++
+ static struct sk_buff *
+ nfqnl_build_packet_message(struct net *net, struct nfqnl_instance *queue,
+ struct nf_queue_entry *entry,
+@@ -755,10 +766,7 @@ nfqnl_build_packet_message(struct net *n
+ nf_queue_checksum_help(entskb))
+ return NULL;
+
+- data_len = READ_ONCE(queue->copy_range);
+- if (data_len > entskb->len)
+- data_len = entskb->len;
+-
++ data_len = nfqnl_get_data_len(entskb, READ_ONCE(queue->copy_range));
+ hlen = skb_zerocopy_headlen(entskb);
+ hlen = min_t(unsigned int, hlen, data_len);
+ size += sizeof(struct nlattr) + hlen;
+--- a/net/netfilter/xt_u32.c
++++ b/net/netfilter/xt_u32.c
+@@ -14,8 +14,8 @@
+ #include <linux/netfilter/x_tables.h>
+ #include <linux/netfilter/xt_u32.h>
+
+-static bool u32_match_it(const struct xt_u32 *data,
+- const struct sk_buff *skb)
++static int u32_match_it(const struct xt_u32 *data,
++ const struct sk_buff *skb)
+ {
+ const struct xt_u32_test *ct;
+ unsigned int testind;
+@@ -40,7 +40,8 @@ static bool u32_match_it(const struct xt
+ return false;
+
+ if (skb_copy_bits(skb, pos, &n, sizeof(n)) < 0)
+- BUG();
++ return -1;
++
+ val = ntohl(n);
+ nnums = ct->nnums;
+
+@@ -68,7 +69,7 @@ static bool u32_match_it(const struct xt
+
+ if (skb_copy_bits(skb, at + pos, &n,
+ sizeof(n)) < 0)
+- BUG();
++ return -1;
+ val = ntohl(n);
+ break;
+ }
+@@ -90,9 +91,14 @@ static bool u32_match_it(const struct xt
+ static bool u32_mt(const struct sk_buff *skb, struct xt_action_param *par)
+ {
+ const struct xt_u32 *data = par->matchinfo;
+- bool ret;
++ int ret;
+
+ ret = u32_match_it(data, skb);
++ if (ret < 0) {
++ par->hotdrop = true;
++ return false;
++ }
++
+ return ret ^ data->invert;
+ }
+
mm-swap_cgroup-fix-null-deref-in-lookup_swap_cgroup_id-on-swapless-host.patch
mm-swap-add-cond_resched-in-swap_reclaim_full_clusters-to-prevent-softlockup.patch
netfilter-ctnetlink-use-nf_ct_exp_net-in-expectation-dump.patch
+netfilter-handle-unreadable-frags.patch
+netfilter-ebtables-zero-chainstack-array.patch
+netfilter-ebtables-module-names-must-be-null-terminated.patch
+netfilter-ebtables-terminate-table-name-before-find_table_lock.patch
+netfilter-flowtable-fix-offloaded-ct-timeout-never-being-extended.patch
+netfilter-flowtable-ipip-tunnel-hardware-offload-is-not-yet-support.patch