Commit 0280f429 authored by David S. Miller's avatar David S. Miller

Merge branch 'tcp-options-oob-fixes'

Maxim Mikityanskiy says:

====================
Fix out of bounds when parsing TCP options

This series fixes out-of-bounds access in various places in the kernel
where parsing of TCP options takes place. Fortunately, many more
occurrences don't have this bug.

v2 changes:

synproxy: Added an early return when length < 0 to avoid calling
skb_header_pointer with negative length.

sch_cake: Added doff validation to avoid parsing garbage.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents d1b5bee4 ba91c49d
...@@ -356,6 +356,8 @@ void mptcp_get_options(const struct sk_buff *skb, ...@@ -356,6 +356,8 @@ void mptcp_get_options(const struct sk_buff *skb,
length--; length--;
continue; continue;
default: default:
if (length < 2)
return;
opsize = *ptr++; opsize = *ptr++;
if (opsize < 2) /* "silly options" */ if (opsize < 2) /* "silly options" */
return; return;
......
...@@ -31,6 +31,9 @@ synproxy_parse_options(const struct sk_buff *skb, unsigned int doff, ...@@ -31,6 +31,9 @@ synproxy_parse_options(const struct sk_buff *skb, unsigned int doff,
int length = (th->doff * 4) - sizeof(*th); int length = (th->doff * 4) - sizeof(*th);
u8 buf[40], *ptr; u8 buf[40], *ptr;
if (unlikely(length < 0))
return false;
ptr = skb_header_pointer(skb, doff + sizeof(*th), length, buf); ptr = skb_header_pointer(skb, doff + sizeof(*th), length, buf);
if (ptr == NULL) if (ptr == NULL)
return false; return false;
...@@ -47,6 +50,8 @@ synproxy_parse_options(const struct sk_buff *skb, unsigned int doff, ...@@ -47,6 +50,8 @@ synproxy_parse_options(const struct sk_buff *skb, unsigned int doff,
length--; length--;
continue; continue;
default: default:
if (length < 2)
return true;
opsize = *ptr++; opsize = *ptr++;
if (opsize < 2) if (opsize < 2)
return true; return true;
......
...@@ -943,7 +943,7 @@ static struct tcphdr *cake_get_tcphdr(const struct sk_buff *skb, ...@@ -943,7 +943,7 @@ static struct tcphdr *cake_get_tcphdr(const struct sk_buff *skb,
} }
tcph = skb_header_pointer(skb, offset, sizeof(_tcph), &_tcph); tcph = skb_header_pointer(skb, offset, sizeof(_tcph), &_tcph);
if (!tcph) if (!tcph || tcph->doff < 5)
return NULL; return NULL;
return skb_header_pointer(skb, offset, return skb_header_pointer(skb, offset,
...@@ -967,6 +967,8 @@ static const void *cake_get_tcpopt(const struct tcphdr *tcph, ...@@ -967,6 +967,8 @@ static const void *cake_get_tcpopt(const struct tcphdr *tcph,
length--; length--;
continue; continue;
} }
if (length < 2)
break;
opsize = *ptr++; opsize = *ptr++;
if (opsize < 2 || opsize > length) if (opsize < 2 || opsize > length)
break; break;
...@@ -1104,6 +1106,8 @@ static bool cake_tcph_may_drop(const struct tcphdr *tcph, ...@@ -1104,6 +1106,8 @@ static bool cake_tcph_may_drop(const struct tcphdr *tcph,
length--; length--;
continue; continue;
} }
if (length < 2)
break;
opsize = *ptr++; opsize = *ptr++;
if (opsize < 2 || opsize > length) if (opsize < 2 || opsize > length)
break; break;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment