ipv6: avoid overflow of offset in ip6_find_1stfragopt
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>
This commit is contained in:
parent
1e6c22aef2
commit
6399f1fae4
|
@ -78,7 +78,7 @@ EXPORT_SYMBOL(ipv6_select_ident);
|
||||||
|
|
||||||
int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr)
|
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) -
|
unsigned int packet_len = skb_tail_pointer(skb) -
|
||||||
skb_network_header(skb);
|
skb_network_header(skb);
|
||||||
int found_rhdr = 0;
|
int found_rhdr = 0;
|
||||||
|
@ -86,6 +86,7 @@ int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr)
|
||||||
|
|
||||||
while (offset <= packet_len) {
|
while (offset <= packet_len) {
|
||||||
struct ipv6_opt_hdr *exthdr;
|
struct ipv6_opt_hdr *exthdr;
|
||||||
|
unsigned int len;
|
||||||
|
|
||||||
switch (**nexthdr) {
|
switch (**nexthdr) {
|
||||||
|
|
||||||
|
@ -111,7 +112,10 @@ int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr)
|
||||||
|
|
||||||
exthdr = (struct ipv6_opt_hdr *)(skb_network_header(skb) +
|
exthdr = (struct ipv6_opt_hdr *)(skb_network_header(skb) +
|
||||||
offset);
|
offset);
|
||||||
offset += ipv6_optlen(exthdr);
|
len = ipv6_optlen(exthdr);
|
||||||
|
if (len + offset >= IPV6_MAXPLEN)
|
||||||
|
return -EINVAL;
|
||||||
|
offset += len;
|
||||||
*nexthdr = &exthdr->nexthdr;
|
*nexthdr = &exthdr->nexthdr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue