Skip to content

Commit

Permalink
ipv6: avoid overflow of offset in ip6_find_1stfragopt
Browse files Browse the repository at this point in the history
In some cases, offset can overflow and can cause an infinite loop in
ip6_find_1stfragopt(). Make it unsigned int to prevent the overflow, and
cap it at IPV6_MAXPLEN, since packets larger than that should be invalid.

This problem has been here since before the beginning of git history.

Signed-off-by: Sabrina Dubroca <sd@queasysnail.net>
Acked-by: Hannes Frederic Sowa <hannes@stressinduktion.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
qsn authored and davem330 committed Jul 20, 2017
1 parent 1e6c22a commit 6399f1f
Showing 1 changed file with 6 additions and 2 deletions.
8 changes: 6 additions & 2 deletions net/ipv6/output_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -78,14 +78,15 @@ EXPORT_SYMBOL(ipv6_select_ident);

int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr)
{
u16 offset = sizeof(struct ipv6hdr);
unsigned int offset = sizeof(struct ipv6hdr);
unsigned int packet_len = skb_tail_pointer(skb) -
skb_network_header(skb);
int found_rhdr = 0;
*nexthdr = &ipv6_hdr(skb)->nexthdr;

while (offset <= packet_len) {
struct ipv6_opt_hdr *exthdr;
unsigned int len;

switch (**nexthdr) {

Expand All @@ -111,7 +112,10 @@ int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr)

exthdr = (struct ipv6_opt_hdr *)(skb_network_header(skb) +
offset);
offset += ipv6_optlen(exthdr);
len = ipv6_optlen(exthdr);
if (len + offset >= IPV6_MAXPLEN)
return -EINVAL;
offset += len;
*nexthdr = &exthdr->nexthdr;
}

Expand Down

0 comments on commit 6399f1f

Please sign in to comment.