[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <1558905306-2968-5-git-send-email-tom@quantonium.net>
Date: Sun, 26 May 2019 14:15:06 -0700
From: Tom Herbert <tom@...bertland.com>
To: davem@...emloft.net, netdev@...r.kernel.org
Cc: Tom Herbert <tom@...ntonium.net>
Subject: [PATCH net-next 4/4] ipv6: Send ICMP errors for exceeding extension header limits
Define constants and add support to send ICMPv6 Parameter Problem
errors as defined in draft-ietf-6man-icmp-limits-02.
ICMPV6_TOOBIG_OPTION is sent if a packet exceeding the padding limit
is received (more than seven consecutive bytes of padding),
ICMPV6_TOOMANY_OPTIONS is sent if a packet is received and HBH option
count exceeds ipv6.sysctl.max_hbh_opts_cnt or DO option count exceeds
ipv6.sysctl.max_dst_opts_cnt. ICMPV6_EXTHDR_TOOBIG is sent if length
of HBH EH exceeds ipv6.sysctl.max_hbh_opts_len or length of DO EH
exceeds ipv6.sysctl.max_dst_opts_len.
Additionally, when packets are dropped in the above cases bump
IPSTATS_MIB_INHDRERRORS.
Signed-off-by: Tom Herbert <tom@...ntonium.net>
---
include/uapi/linux/icmpv6.h | 6 ++++++
net/ipv6/exthdrs.c | 35 ++++++++++++++++++++++++++++++-----
2 files changed, 36 insertions(+), 5 deletions(-)
diff --git a/include/uapi/linux/icmpv6.h b/include/uapi/linux/icmpv6.h
index 2622b5a..966279b 100644
--- a/include/uapi/linux/icmpv6.h
+++ b/include/uapi/linux/icmpv6.h
@@ -124,6 +124,7 @@ struct icmp6hdr {
#define ICMPV6_PORT_UNREACH 4
#define ICMPV6_POLICY_FAIL 5
#define ICMPV6_REJECT_ROUTE 6
+#define ICMPV6_SRCRT_ERR 7
/*
* Codes for Time Exceeded
@@ -137,6 +138,11 @@ struct icmp6hdr {
#define ICMPV6_HDR_FIELD 0
#define ICMPV6_UNK_NEXTHDR 1
#define ICMPV6_UNK_OPTION 2
+#define ICMPV6_FIRST_FRAG_INCOMP 3
+#define ICMPV6_EXTHDR_TOOBIG 4
+#define ICMPV6_EXTHDR_CHAINLONG 5
+#define ICMPV6_TOOMANY_OPTIONS 6
+#define ICMPV6_TOOBIG_OPTION 7
/*
* constants for (set|get)sockopt
diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c
index f0e0f7a..fe6d9b2 100644
--- a/net/ipv6/exthdrs.c
+++ b/net/ipv6/exthdrs.c
@@ -145,8 +145,11 @@ static bool ip6_parse_tlv(const struct tlvtype_proc *procs,
case IPV6_TLV_PAD1:
optlen = 1;
padlen++;
- if (padlen > 7)
+ if (padlen > 7) {
+ icmpv6_send(skb, ICMPV6_PARAMPROB,
+ ICMPV6_TOOBIG_OPTION, off);
goto bad;
+ }
break;
case IPV6_TLV_PADN:
@@ -157,8 +160,11 @@ static bool ip6_parse_tlv(const struct tlvtype_proc *procs,
* RFC 8504, Section 5.3.
*/
padlen += optlen;
- if (padlen > 7)
+ if (padlen > 7) {
+ icmpv6_send(skb, ICMPV6_PARAMPROB,
+ ICMPV6_TOOBIG_OPTION, off);
goto bad;
+ }
/* RFC 4942 recommends receiving hosts to
* actively check PadN payload to contain
* only zeroes.
@@ -174,8 +180,11 @@ static bool ip6_parse_tlv(const struct tlvtype_proc *procs,
goto bad;
tlv_count++;
- if (tlv_count > max_count)
+ if (tlv_count > max_count) {
+ icmpv6_send(skb, ICMPV6_PARAMPROB,
+ ICMPV6_TOOMANY_OPTIONS, off);
goto bad;
+ }
for (curr = procs; curr->type >= 0; curr++) {
if (curr->type == nh[off]) {
@@ -201,6 +210,8 @@ static bool ip6_parse_tlv(const struct tlvtype_proc *procs,
if (len == 0)
return true;
bad:
+ __IP6_INC_STATS(dev_net(skb->dev), __in6_dev_get(skb->dev),
+ IPSTATS_MIB_INHDRERRORS);
kfree_skb(skb);
return false;
}
@@ -301,8 +312,15 @@ static int ipv6_destopt_rcv(struct sk_buff *skb)
}
extlen = (skb_transport_header(skb)[1] + 1) << 3;
- if (extlen > net->ipv6.sysctl.max_dst_opts_len)
+ if (extlen > net->ipv6.sysctl.max_dst_opts_len) {
+ icmpv6_send(skb, ICMPV6_PARAMPROB,
+ ICMPV6_EXTHDR_TOOBIG,
+ skb_network_header_len(skb) +
+ net->ipv6.sysctl.max_dst_opts_len);
+ __IP6_INC_STATS(dev_net(dst->dev), idev,
+ IPSTATS_MIB_INHDRERRORS);
goto fail_and_free;
+ }
opt->lastopt = opt->dst1 = skb_network_header_len(skb);
#if IS_ENABLED(CONFIG_IPV6_MIP6)
@@ -844,8 +862,15 @@ int ipv6_parse_hopopts(struct sk_buff *skb)
}
extlen = (skb_transport_header(skb)[1] + 1) << 3;
- if (extlen > net->ipv6.sysctl.max_hbh_opts_len)
+ if (extlen > net->ipv6.sysctl.max_hbh_opts_len) {
+ __IP6_INC_STATS(net, __in6_dev_get(skb->dev),
+ IPSTATS_MIB_INHDRERRORS);
+ icmpv6_send(skb, ICMPV6_PARAMPROB,
+ ICMPV6_EXTHDR_TOOBIG,
+ skb_network_header_len(skb) +
+ net->ipv6.sysctl.max_hbh_opts_len);
goto fail_and_free;
+ }
opt->flags |= IP6SKB_HOPBYHOP;
if (ip6_parse_tlv(tlvprochopopt_lst, skb,
--
2.7.4
Powered by blists - more mailing lists