[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <1559253021-16772-6-git-send-email-tom@quantonium.net>
Date: Thu, 30 May 2019 14:50:20 -0700
From: Tom Herbert <tom@...bertland.com>
To: davem@...emloft.net, netdev@...r.kernel.org, dlebrun@...gle.com
Cc: Tom Herbert <tom@...ntonium.net>
Subject: [PATCH net-next 5/6] ah6: Be explicit about which routing types are processed.
The current code assumes that all routing headers can be processed
as type 0 when rearranging the routing header for AH verification.
Change this to be explicit. Type 0 and type 2 are supported and are
processed the same way with regards to AH.
Also check if rearranging routing header fails. Update reference
in comment to more current RFC.
Signed-off-by: Tom Herbert <tom@...ntonium.net>
---
net/ipv6/ah6.c | 37 +++++++++++++++++++++++++++++--------
1 file changed, 29 insertions(+), 8 deletions(-)
diff --git a/net/ipv6/ah6.c b/net/ipv6/ah6.c
index 1e80157..032491c 100644
--- a/net/ipv6/ah6.c
+++ b/net/ipv6/ah6.c
@@ -145,7 +145,7 @@ static bool zero_out_mutable_opts(struct ipv6_opt_hdr *opthdr)
/**
* ipv6_rearrange_destopt - rearrange IPv6 destination options header
* @iph: IPv6 header
- * @destopt: destionation options header
+ * @destopt: destination options header
*/
static void ipv6_rearrange_destopt(struct ipv6hdr *iph, struct ipv6_opt_hdr *destopt)
{
@@ -204,15 +204,16 @@ static void ipv6_rearrange_destopt(struct ipv6hdr *iph, struct ipv6_opt_hdr *des
#endif
/**
- * ipv6_rearrange_rthdr - rearrange IPv6 routing header
+ * ipv6_rearrange_type0_rthdr - rearrange type 0 IPv6 routing header
* @iph: IPv6 header
* @rthdr: routing header
*
* Rearrange the destination address in @iph and the addresses in @rthdr
* so that they appear in the order they will at the final destination.
- * See Appendix A2 of RFC 2402 for details.
+ * See Appendix A2 of RFC 4302 for details.
*/
-static void ipv6_rearrange_rthdr(struct ipv6hdr *iph, struct ipv6_rt_hdr *rthdr)
+static bool ipv6_rearrange_type0_rthdr(struct ipv6hdr *iph,
+ struct ipv6_rt_hdr *rthdr)
{
int segments, segments_left;
struct in6_addr *addrs;
@@ -220,15 +221,13 @@ static void ipv6_rearrange_rthdr(struct ipv6hdr *iph, struct ipv6_rt_hdr *rthdr)
segments_left = rthdr->segments_left;
if (segments_left == 0)
- return;
+ return true;
rthdr->segments_left = 0;
/* The value of rthdr->hdrlen has been verified either by the system
* call if it is locally generated, or by ipv6_rthdr_rcv() for incoming
* packets. So we can assume that it is even and that segments is
* greater than or equal to segments_left.
- *
- * For the same reason we can assume that this option is of type 0.
*/
segments = rthdr->hdrlen >> 1;
@@ -240,6 +239,24 @@ static void ipv6_rearrange_rthdr(struct ipv6hdr *iph, struct ipv6_rt_hdr *rthdr)
addrs[0] = iph->daddr;
iph->daddr = final_addr;
+
+ return true;
+}
+
+static bool ipv6_rearrange_rthdr(struct ipv6hdr *iph, struct ipv6_rt_hdr *rthdr)
+{
+ switch (rthdr->type) {
+ case IPV6_SRCRT_TYPE_2:
+ /* Simplified format of type 0 so same processing */
+ /* fallthrough */
+ case IPV6_SRCRT_TYPE_0: /* Deprecated */
+ return ipv6_rearrange_type0_rthdr(iph, rthdr);
+ default:
+ /* Bad or unidentified routing header, we don't know how
+ * to fix this header for security purposes. Return failure.
+ */
+ return false;
+ }
}
static int ipv6_clear_mutable_options(struct ipv6hdr *iph, int len, int dir)
@@ -271,7 +288,11 @@ static int ipv6_clear_mutable_options(struct ipv6hdr *iph, int len, int dir)
break;
case NEXTHDR_ROUTING:
- ipv6_rearrange_rthdr(iph, exthdr.rth);
+ if (!ipv6_rearrange_rthdr(iph, exthdr.rth)) {
+ net_dbg_ratelimited("bad routing header\n");
+ return -EINVAL;
+ }
+
break;
default:
--
2.7.4
Powered by blists - more mailing lists