Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4a0851b8 authored by JP Abgrall's avatar JP Abgrall Committed by John Stultz
Browse files

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: default avatarJP Abgrall <jpa@google.com>
parent 564578ba
Loading
Loading
Loading
Loading
+8 −5
Original line number Original line Diff line number Diff line
@@ -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;
			}
			}