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>
This commit is contained in:
parent
564578ba45
commit
4a0851b8b5
1 changed files with 8 additions and 5 deletions
|
@ -166,15 +166,15 @@ EXPORT_SYMBOL_GPL(ipv6_find_tlv);
|
||||||
* to explore inner IPv6 header, eg. ICMPv6 error messages.
|
* to explore inner IPv6 header, eg. ICMPv6 error messages.
|
||||||
*
|
*
|
||||||
* If target header is found, its offset is set in *offset and return protocol
|
* 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
|
* If the first fragment doesn't contain the final protocol header or
|
||||||
* NEXTHDR_NONE it is considered invalid.
|
* NEXTHDR_NONE it is considered invalid.
|
||||||
*
|
*
|
||||||
* Note that non-1st fragment is special case that "the protocol number
|
* 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,
|
* 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
|
* *offset is meaningless. If fragoff is not NULL, the fragment offset is
|
||||||
* isn't NULL.
|
* stored in *fragoff; if it is NULL, return -EINVAL.
|
||||||
*
|
*
|
||||||
* if flags is not NULL and it's a fragment, then the frag flag
|
* 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
|
* 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 &&
|
if (target < 0 &&
|
||||||
((!ipv6_ext_hdr(hp->nexthdr)) ||
|
((!ipv6_ext_hdr(hp->nexthdr)) ||
|
||||||
hp->nexthdr == NEXTHDR_NONE)) {
|
hp->nexthdr == NEXTHDR_NONE)) {
|
||||||
if (fragoff)
|
if (fragoff) {
|
||||||
*fragoff = _frag_off;
|
*fragoff = _frag_off;
|
||||||
return hp->nexthdr;
|
return hp->nexthdr;
|
||||||
|
} else {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue