diff options
author | JP Abgrall <jpa@google.com> | 2011-09-29 15:36:49 -0700 |
---|---|---|
committer | John Stultz <john.stultz@linaro.org> | 2016-02-16 13:51:32 -0800 |
commit | 4a0851b8b57ec8c873e336d3ac24fb6593ab1c86 (patch) | |
tree | 725dde5fe86880ca51d01baaff207dccefe9d707 /net/ipv6 | |
parent | 564578ba4578682401bd4416fcf42555dc056434 (diff) |
netfilter: ipv6: fix crash caused by ipv6_find_hdr()
When calling:
ipv6_find_hdr(skb, &thoff, -1, NULL)
on a fragmented packet, thoff would be left with a random
value causing callers to read random memory offsets with:
skb_header_pointer(skb, thoff, ...)
Now we force ipv6_find_hdr() to return a failure in this case.
Calling:
ipv6_find_hdr(skb, &thoff, -1, &fragoff)
will set fragoff as expected, and not return a failure.
Change-Id: Ib474e8a4267dd2b300feca325811330329684a88
Signed-off-by: JP Abgrall <jpa@google.com>
Diffstat (limited to 'net/ipv6')
-rw-r--r-- | net/ipv6/exthdrs_core.c | 13 |
1 files changed, 8 insertions, 5 deletions
diff --git a/net/ipv6/exthdrs_core.c b/net/ipv6/exthdrs_core.c index 5c5d23e59da5..835ec57c233b 100644 --- a/net/ipv6/exthdrs_core.c +++ b/net/ipv6/exthdrs_core.c @@ -166,15 +166,15 @@ EXPORT_SYMBOL_GPL(ipv6_find_tlv); * to explore inner IPv6 header, eg. ICMPv6 error messages. * * If target header is found, its offset is set in *offset and return protocol - * number. Otherwise, return -1. + * number. Otherwise, return -ENOENT or -EBADMSG. * * If the first fragment doesn't contain the final protocol header or * NEXTHDR_NONE it is considered invalid. * * Note that non-1st fragment is special case that "the protocol number * of last header" is "next header" field in Fragment header. In this case, - * *offset is meaningless and fragment offset is stored in *fragoff if fragoff - * isn't NULL. + * *offset is meaningless. If fragoff is not NULL, the fragment offset is + * stored in *fragoff; if it is NULL, return -EINVAL. * * if flags is not NULL and it's a fragment, then the frag flag * IP6_FH_F_FRAG will be set. If it's an AH header, the @@ -253,9 +253,12 @@ int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset, if (target < 0 && ((!ipv6_ext_hdr(hp->nexthdr)) || hp->nexthdr == NEXTHDR_NONE)) { - if (fragoff) + if (fragoff) { *fragoff = _frag_off; - return hp->nexthdr; + return hp->nexthdr; + } else { + return -EINVAL; + } } return -ENOENT; } |