]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
6.18-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 13 Jul 2026 13:56:15 +0000 (15:56 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 13 Jul 2026 13:56:15 +0000 (15:56 +0200)
added patches:
netfilter-ebtables-module-names-must-be-null-terminated.patch
netfilter-ebtables-terminate-table-name-before-find_table_lock.patch
netfilter-ebtables-zero-chainstack-array.patch
netfilter-flowtable-fix-offloaded-ct-timeout-never-being-extended.patch
netfilter-handle-unreadable-frags.patch

queue-6.18/netfilter-ebtables-module-names-must-be-null-terminated.patch [new file with mode: 0644]
queue-6.18/netfilter-ebtables-terminate-table-name-before-find_table_lock.patch [new file with mode: 0644]
queue-6.18/netfilter-ebtables-zero-chainstack-array.patch [new file with mode: 0644]
queue-6.18/netfilter-flowtable-fix-offloaded-ct-timeout-never-being-extended.patch [new file with mode: 0644]
queue-6.18/netfilter-handle-unreadable-frags.patch [new file with mode: 0644]
queue-6.18/series

diff --git a/queue-6.18/netfilter-ebtables-module-names-must-be-null-terminated.patch b/queue-6.18/netfilter-ebtables-module-names-must-be-null-terminated.patch
new file mode 100644 (file)
index 0000000..6a39901
--- /dev/null
@@ -0,0 +1,32 @@
+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))
diff --git a/queue-6.18/netfilter-ebtables-terminate-table-name-before-find_table_lock.patch b/queue-6.18/netfilter-ebtables-terminate-table-name-before-find_table_lock.patch
new file mode 100644 (file)
index 0000000..bebdd3e
--- /dev/null
@@ -0,0 +1,77 @@
+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);
diff --git a/queue-6.18/netfilter-ebtables-zero-chainstack-array.patch b/queue-6.18/netfilter-ebtables-zero-chainstack-array.patch
new file mode 100644 (file)
index 0000000..67df12d
--- /dev/null
@@ -0,0 +1,42 @@
+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) {
diff --git a/queue-6.18/netfilter-flowtable-fix-offloaded-ct-timeout-never-being-extended.patch b/queue-6.18/netfilter-flowtable-fix-offloaded-ct-timeout-never-being-extended.patch
new file mode 100644 (file)
index 0000000..85783a5
--- /dev/null
@@ -0,0 +1,81 @@
+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
+@@ -500,8 +500,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))
+@@ -519,7 +524,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:
+@@ -544,7 +549,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);
+               }
+       }
diff --git a/queue-6.18/netfilter-handle-unreadable-frags.patch b/queue-6.18/netfilter-handle-unreadable-frags.patch
new file mode 100644 (file)
index 0000000..f5f588d
--- /dev/null
@@ -0,0 +1,176 @@
+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
+@@ -668,7 +668,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;
+@@ -690,6 +690,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,
+@@ -782,14 +797,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
+@@ -676,6 +676,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,
+@@ -741,10 +752,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;
+ }
index 4c1aa383e8bdbc828690dde523018c9d6876371a..224a02fe7f4f6416f2b42100bfdc7e65bc449faa 100644 (file)
@@ -192,3 +192,8 @@ mm-shrinker-fix-null-pointer-dereference-in-debugfs.patch
 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