From: Zhixing Chen <running910@gmail.com>
To: Florian Westphal <fw@strlen.de>, Pablo Neira Ayuso <pablo@netfilter.org>
Cc: Phil Sutter <phil@nwl.cc>,
"David S . Miller" <davem@davemloft.net>,
Eric Dumazet <edumazet@google.com>,
Jakub Kicinski <kuba@kernel.org>, Paolo Abeni <pabeni@redhat.com>,
Simon Horman <horms@kernel.org>,
netfilter-devel@vger.kernel.org, coreteam@netfilter.org,
netdev@vger.kernel.org, Zhixing Chen <running910@gmail.com>
Subject: [PATCH nf] netfilter: ip6tables: set hotdrop for malformed extension header matches
Date: Thu, 9 Jul 2026 14:30:12 +0800 [thread overview]
Message-ID: <20260709063012.33160-1-running910@gmail.com> (raw)
The hbh, srh and ipv6header matches have paths that return false for
malformed IPv6 extension header packets without setting hotdrop.
For hbh, strict option parsing stops when the option type or length field
cannot be read, or when advancing to the next requested option would
exceed the available header data. Mark these packets for hotdrop instead
of treating them as a rule mismatch.
For srh, keep a missing SRH as a normal mismatch, but set hotdrop when
header lookup fails for other reasons, when the SRH fixed header is not
present, when the advertised SRH length exceeds the available skb data, or
when SID selector reads fail.
For ipv6header, set hotdrop when the next extension header is not fully
present or when the advertised extension header length exceeds the
available skb data.
Returning false treats the packet as a rule mismatch. Set hotdrop for
these malformed packets so they cannot bypass rules intended to drop
packets with these IPv6 extension headers.
Signed-off-by: Zhixing Chen <running910@gmail.com>
---
This is a follow-up to the previous IPv6 extension header hotdrop fix:
https://lore.kernel.org/netfilter-devel/20260703125709.16493-6-fw@strlen.de/
---
net/ipv6/netfilter/ip6t_hbh.c | 21 +++++++++-----
| 10 +++++--
net/ipv6/netfilter/ip6t_srh.c | 42 ++++++++++++++++++++++------
3 files changed, 54 insertions(+), 19 deletions(-)
diff --git a/net/ipv6/netfilter/ip6t_hbh.c b/net/ipv6/netfilter/ip6t_hbh.c
index 6d1a5d2026a6..a67f7d0fe93f 100644
--- a/net/ipv6/netfilter/ip6t_hbh.c
+++ b/net/ipv6/netfilter/ip6t_hbh.c
@@ -104,8 +104,10 @@ hbh_mt6(const struct sk_buff *skb, struct xt_action_param *par)
break;
tp = skb_header_pointer(skb, ptr, sizeof(_opttype),
&_opttype);
- if (tp == NULL)
- break;
+ if (!tp) {
+ par->hotdrop = true;
+ return false;
+ }
/* Type check */
if (*tp != (optinfo->opts[temp] & 0xFF00) >> 8) {
@@ -120,13 +122,17 @@ hbh_mt6(const struct sk_buff *skb, struct xt_action_param *par)
u16 spec_len;
/* length field exists ? */
- if (hdrlen < 2)
- break;
+ if (hdrlen < 2) {
+ par->hotdrop = true;
+ return false;
+ }
lp = skb_header_pointer(skb, ptr + 1,
sizeof(_optlen),
&_optlen);
- if (lp == NULL)
- break;
+ if (!lp) {
+ par->hotdrop = true;
+ return false;
+ }
spec_len = optinfo->opts[temp] & 0x00FF;
if (spec_len != 0x00FF && spec_len != *lp) {
@@ -147,7 +153,8 @@ hbh_mt6(const struct sk_buff *skb, struct xt_action_param *par)
if ((ptr > skb->len - optlen || hdrlen < optlen) &&
temp < optinfo->optsnr - 1) {
pr_debug("new pointer is too large!\n");
- break;
+ par->hotdrop = true;
+ return false;
}
ptr += optlen;
hdrlen -= optlen;
--git a/net/ipv6/netfilter/ip6t_ipv6header.c b/net/ipv6/netfilter/ip6t_ipv6header.c
index c52ff929c93b..0568eb99eb1c 100644
--- a/net/ipv6/netfilter/ip6t_ipv6header.c
+++ b/net/ipv6/netfilter/ip6t_ipv6header.c
@@ -53,8 +53,10 @@ ipv6header_mt6(const struct sk_buff *skb, struct xt_action_param *par)
break;
}
/* Is there enough space for the next ext header? */
- if (len < (int)sizeof(struct ipv6_opt_hdr))
+ if (len < (int)sizeof(struct ipv6_opt_hdr)) {
+ par->hotdrop = true;
return false;
+ }
/* ESP -> evaluate */
if (nexthdr == NEXTHDR_ESP) {
temp |= MASK_ESP;
@@ -99,8 +101,10 @@ ipv6header_mt6(const struct sk_buff *skb, struct xt_action_param *par)
nexthdr = hp->nexthdr;
len -= hdrlen;
ptr += hdrlen;
- if (ptr > skb->len)
- break;
+ if (ptr > skb->len) {
+ par->hotdrop = true;
+ return false;
+ }
}
if (nexthdr != NEXTHDR_NONE && nexthdr != NEXTHDR_ESP)
diff --git a/net/ipv6/netfilter/ip6t_srh.c b/net/ipv6/netfilter/ip6t_srh.c
index db0fd64d8986..33a659b9b0e3 100644
--- a/net/ipv6/netfilter/ip6t_srh.c
+++ b/net/ipv6/netfilter/ip6t_srh.c
@@ -27,16 +27,25 @@ static bool srh_mt6(const struct sk_buff *skb, struct xt_action_param *par)
struct ipv6_sr_hdr *srh;
struct ipv6_sr_hdr _srh;
int hdrlen, srhoff = 0;
+ int err;
- if (ipv6_find_hdr(skb, &srhoff, IPPROTO_ROUTING, NULL, NULL) < 0)
+ err = ipv6_find_hdr(skb, &srhoff, IPPROTO_ROUTING, NULL, NULL);
+ if (err < 0) {
+ if (err != -ENOENT)
+ par->hotdrop = true;
return false;
+ }
srh = skb_header_pointer(skb, srhoff, sizeof(_srh), &_srh);
- if (!srh)
+ if (!srh) {
+ par->hotdrop = true;
return false;
+ }
hdrlen = ipv6_optlen(srh);
- if (skb->len - srhoff < hdrlen)
+ if (skb->len - srhoff < hdrlen) {
+ par->hotdrop = true;
return false;
+ }
if (srh->type != IPV6_SRCRT_TYPE_4)
return false;
@@ -121,16 +130,25 @@ static bool srh1_mt6(const struct sk_buff *skb, struct xt_action_param *par)
struct in6_addr _psid, _nsid, _lsid;
struct ipv6_sr_hdr *srh;
struct ipv6_sr_hdr _srh;
+ int err;
- if (ipv6_find_hdr(skb, &srhoff, IPPROTO_ROUTING, NULL, NULL) < 0)
+ err = ipv6_find_hdr(skb, &srhoff, IPPROTO_ROUTING, NULL, NULL);
+ if (err < 0) {
+ if (err != -ENOENT)
+ par->hotdrop = true;
return false;
+ }
srh = skb_header_pointer(skb, srhoff, sizeof(_srh), &_srh);
- if (!srh)
+ if (!srh) {
+ par->hotdrop = true;
return false;
+ }
hdrlen = ipv6_optlen(srh);
- if (skb->len - srhoff < hdrlen)
+ if (skb->len - srhoff < hdrlen) {
+ par->hotdrop = true;
return false;
+ }
if (srh->type != IPV6_SRCRT_TYPE_4)
return false;
@@ -206,8 +224,10 @@ static bool srh1_mt6(const struct sk_buff *skb, struct xt_action_param *par)
psidoff = srhoff + sizeof(struct ipv6_sr_hdr) +
((srh->segments_left + 1) * sizeof(struct in6_addr));
psid = skb_header_pointer(skb, psidoff, sizeof(_psid), &_psid);
- if (!psid)
+ if (!psid) {
+ par->hotdrop = true;
return false;
+ }
if (NF_SRH_INVF(srhinfo, IP6T_SRH_INV_PSID,
ipv6_masked_addr_cmp(psid, &srhinfo->psid_msk,
&srhinfo->psid_addr)))
@@ -221,8 +241,10 @@ static bool srh1_mt6(const struct sk_buff *skb, struct xt_action_param *par)
nsidoff = srhoff + sizeof(struct ipv6_sr_hdr) +
((srh->segments_left - 1) * sizeof(struct in6_addr));
nsid = skb_header_pointer(skb, nsidoff, sizeof(_nsid), &_nsid);
- if (!nsid)
+ if (!nsid) {
+ par->hotdrop = true;
return false;
+ }
if (NF_SRH_INVF(srhinfo, IP6T_SRH_INV_NSID,
ipv6_masked_addr_cmp(nsid, &srhinfo->nsid_msk,
&srhinfo->nsid_addr)))
@@ -233,8 +255,10 @@ static bool srh1_mt6(const struct sk_buff *skb, struct xt_action_param *par)
if (srhinfo->mt_flags & IP6T_SRH_LSID) {
lsidoff = srhoff + sizeof(struct ipv6_sr_hdr);
lsid = skb_header_pointer(skb, lsidoff, sizeof(_lsid), &_lsid);
- if (!lsid)
+ if (!lsid) {
+ par->hotdrop = true;
return false;
+ }
if (NF_SRH_INVF(srhinfo, IP6T_SRH_INV_LSID,
ipv6_masked_addr_cmp(lsid, &srhinfo->lsid_msk,
&srhinfo->lsid_addr)))
--
2.34.1
next reply other threads:[~2026-07-09 6:30 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-09 6:30 Zhixing Chen [this message]
2026-07-09 11:02 ` [PATCH nf] netfilter: ip6tables: set hotdrop for malformed extension header matches Phil Sutter
2026-07-13 3:10 ` Zhixing Chen
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260709063012.33160-1-running910@gmail.com \
--to=running910@gmail.com \
--cc=coreteam@netfilter.org \
--cc=davem@davemloft.net \
--cc=edumazet@google.com \
--cc=fw@strlen.de \
--cc=horms@kernel.org \
--cc=kuba@kernel.org \
--cc=netdev@vger.kernel.org \
--cc=netfilter-devel@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=pablo@netfilter.org \
--cc=phil@nwl.cc \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox