xfrm6_find_1stfragopt() may now return an error code and we must not treat it as a length.
Fixes: 2423496af35d ("ipv6: Prevent overrun when parsing v6 header options")
Signed-off-by: Ben Hutchings <[email protected]>
---
Commits 2423496af35d "ipv6: Prevent overrun when parsing v6 header
options" and 7dd7eb9513bd "ipv6: Check ip6_find_1stfragopt() return
value properly." changed ip6_find_1stfragopt() to return negative
error codes and changed some of its callers to handle this.
However, there is also xfrm6_find_1stfragopt() which is a wrapper for
ip6_find_1stfragopt() and is called indirectly by xfrm6_ro_output()
and xfrm6_transport_output(). Neither of them check for errors.
This is totally untested. I think xfrm_type::hdr_offset deserves a
comment about its semantics, but I don't understand it well enogugh to
write that.
Ben.
net/ipv6/xfrm6_mode_ro.c | 2 ++
net/ipv6/xfrm6_mode_transport.c | 2 ++
2 files changed, 4 insertions(+)
diff --git a/net/ipv6/xfrm6_mode_ro.c b/net/ipv6/xfrm6_mode_ro.c
index 0e015906f9ca..07d36573f50b 100644
--- a/net/ipv6/xfrm6_mode_ro.c
+++ b/net/ipv6/xfrm6_mode_ro.c
@@ -47,6 +47,8 @@ static int xfrm6_ro_output(struct xfrm_state *x, struct
sk_buff *skb)
iph = ipv6_hdr(skb);
hdr_len = x->type->hdr_offset(x, skb, &prevhdr);
+ if (hdr_len < 0)
+ return hdr_len;
skb_set_mac_header(skb, (prevhdr - x->props.header_len) - skb->data);
skb_set_network_header(skb, -x->props.header_len);
skb->transport_header = skb->network_header + hdr_len;
diff --git a/net/ipv6/xfrm6_mode_transport.c b/net/ipv6/xfrm6_mode_transport.c
index 7a92c0f31912..9ad07a91708e 100644
--- a/net/ipv6/xfrm6_mode_transport.c
+++ b/net/ipv6/xfrm6_mode_transport.c
@@ -30,6 +30,8 @@ static int xfrm6_transport_output(struct xfrm_state *x,
struct sk_buff *skb)
skb_set_inner_transport_header(skb, skb_transport_offset(skb));
hdr_len = x->type->hdr_offset(x, skb, &prevhdr);
+ if (hdr_len < 0)
+ return hdr_len;
skb_set_mac_header(skb, (prevhdr - x->props.header_len) - skb->data);
skb_set_network_header(skb, -x->props.header_len);
skb->transport_header = skb->network_header + hdr_len;
signature.asc
Description: Digital signature
