--- /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
+@@ -402,6 +402,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
+@@ -1433,6 +1433,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;
+
+@@ -2272,6 +2274,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]);
+@@ -2394,6 +2398,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 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
+@@ -415,7 +415,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;
+ }
+