diff mbox

KASAN, xt_TCPMSS finally found nasty use-after-free bug? 4.10.8

Message ID 1491153972.10124.14.camel@edumazet-glaptop3.roam.corp.google.com
State Awaiting Upstream, archived
Delegated to: David Miller
Headers show

Commit Message

Eric Dumazet April 2, 2017, 5:26 p.m. UTC
On Sun, 2017-04-02 at 10:14 -0700, Eric Dumazet wrote:

> Could that be that netfilter does not abort earlier if TCP header is
> completely wrong ?
> 

Yes, I wonder if this patch would be better, unless we replicate the
th->doff sanity check in all netfilter modules dissecting TCP frames.

Comments

Denys Fedoryshchenko April 3, 2017, 8:10 a.m. UTC | #1
On 2017-04-02 20:26, Eric Dumazet wrote:
> On Sun, 2017-04-02 at 10:14 -0700, Eric Dumazet wrote:
> 
>> Could that be that netfilter does not abort earlier if TCP header is
>> completely wrong ?
>> 
> 
> Yes, I wonder if this patch would be better, unless we replicate the
> th->doff sanity check in all netfilter modules dissecting TCP frames.
> 
> diff --git a/net/netfilter/xt_tcpudp.c b/net/netfilter/xt_tcpudp.c
> index
> ade024c90f4f129a7c384e9e1cbfdb8ffe73065f..8cb4eadd5ba1c20e74bc27ee52a0bc36a5b26725
> 100644
> --- a/net/netfilter/xt_tcpudp.c
> +++ b/net/netfilter/xt_tcpudp.c
> @@ -103,11 +103,11 @@ static bool tcp_mt(const struct sk_buff *skb,
> struct xt_action_param *par)
>  	if (!NF_INVF(tcpinfo, XT_TCP_INV_FLAGS,
>  		     (((unsigned char *)th)[13] & tcpinfo->flg_mask) == 
> tcpinfo->flg_cmp))
>  		return false;
> +	if (th->doff * 4 < sizeof(_tcph)) {
> +		par->hotdrop = true;
> +		return false;
> +	}
>  	if (tcpinfo->option) {
> -		if (th->doff * 4 < sizeof(_tcph)) {
> -			par->hotdrop = true;
> -			return false;
> -		}
>  		if (!tcp_find_option(tcpinfo->option, skb, par->thoff,
>  				     th->doff*4 - sizeof(_tcph),
>  				     tcpinfo->invflags & XT_TCP_INV_OPTION,
I modified patch a little as:
if (th->doff * 4 < sizeof(_tcph)) {
  par->hotdrop = true;
  WARN_ON_ONCE(!tcpinfo->option);
  return false;
}

And it did triggered WARN once at morning, and didn't hit KASAN. I will 
run for a while more, to see if it is ok, and then if stable, will try 
to enable SFQ again.
Eric Dumazet April 3, 2017, 12:09 p.m. UTC | #2
On Mon, 2017-04-03 at 11:10 +0300, Denys Fedoryshchenko wrote:

> I modified patch a little as:
> if (th->doff * 4 < sizeof(_tcph)) {
>   par->hotdrop = true;
>   WARN_ON_ONCE(!tcpinfo->option);
>   return false;
> }
> 
> And it did triggered WARN once at morning, and didn't hit KASAN. I will 
> run for a while more, to see if it is ok, and then if stable, will try 
> to enable SFQ again.

Excellent news !
We will post an official fix today, thanks a lot for this detective work
Denys.
Denys Fedoryshchenko April 3, 2017, 12:14 p.m. UTC | #3
On 2017-04-03 15:09, Eric Dumazet wrote:
> On Mon, 2017-04-03 at 11:10 +0300, Denys Fedoryshchenko wrote:
> 
>> I modified patch a little as:
>> if (th->doff * 4 < sizeof(_tcph)) {
>>   par->hotdrop = true;
>>   WARN_ON_ONCE(!tcpinfo->option);
>>   return false;
>> }
>> 
>> And it did triggered WARN once at morning, and didn't hit KASAN. I 
>> will
>> run for a while more, to see if it is ok, and then if stable, will try
>> to enable SFQ again.
> 
> Excellent news !
> We will post an official fix today, thanks a lot for this detective 
> work
> Denys.
I am not sure it is finally fixed, maybe we need test more?
I'm doing extensive tests today with identical configuration (i had to 
run fifo, because customer cannot afford anymore outages). I've dded sfq 
now different way, and identical config i will run after 3 hours approx.
Eric Dumazet April 3, 2017, 12:24 p.m. UTC | #4
On Mon, 2017-04-03 at 15:14 +0300, Denys Fedoryshchenko wrote:
> On 2017-04-03 15:09, Eric Dumazet wrote:
> > On Mon, 2017-04-03 at 11:10 +0300, Denys Fedoryshchenko wrote:
> > 
> >> I modified patch a little as:
> >> if (th->doff * 4 < sizeof(_tcph)) {
> >>   par->hotdrop = true;
> >>   WARN_ON_ONCE(!tcpinfo->option);
> >>   return false;
> >> }
> >> 
> >> And it did triggered WARN once at morning, and didn't hit KASAN. I 
> >> will
> >> run for a while more, to see if it is ok, and then if stable, will try
> >> to enable SFQ again.
> > 
> > Excellent news !
> > We will post an official fix today, thanks a lot for this detective 
> > work
> > Denys.
> I am not sure it is finally fixed, maybe we need test more?
> I'm doing extensive tests today with identical configuration (i had to 
> run fifo, because customer cannot afford anymore outages). I've dded sfq 
> now different way, and identical config i will run after 3 hours approx.

I did not say this bug fix would be the last one.

But this check is definitely needed, otherwise xt_TCPMSS can iterate
whole memory, and either crash or scramble two bytes in memory, that do
not belong to the frame at all.

If tcp_hdrlen is 0 (can happen if tcph->doff is 0)

Then :

for (i = sizeof(struct tcphdr); i <= tcp_hdrlen - TCPOLEN_MSS; i +=
optlen(opt, i)) {

Can look at 4 GB of memory, until it finds a 0x02, 0x04  sequence.

It can also loop forever in some cases, depending on memory content.
diff mbox

Patch

diff --git a/net/netfilter/xt_tcpudp.c b/net/netfilter/xt_tcpudp.c
index ade024c90f4f129a7c384e9e1cbfdb8ffe73065f..8cb4eadd5ba1c20e74bc27ee52a0bc36a5b26725 100644
--- a/net/netfilter/xt_tcpudp.c
+++ b/net/netfilter/xt_tcpudp.c
@@ -103,11 +103,11 @@  static bool tcp_mt(const struct sk_buff *skb, struct xt_action_param *par)
 	if (!NF_INVF(tcpinfo, XT_TCP_INV_FLAGS,
 		     (((unsigned char *)th)[13] & tcpinfo->flg_mask) == tcpinfo->flg_cmp))
 		return false;
+	if (th->doff * 4 < sizeof(_tcph)) {
+		par->hotdrop = true;
+		return false;
+	}
 	if (tcpinfo->option) {
-		if (th->doff * 4 < sizeof(_tcph)) {
-			par->hotdrop = true;
-			return false;
-		}
 		if (!tcp_find_option(tcpinfo->option, skb, par->thoff,
 				     th->doff*4 - sizeof(_tcph),
 				     tcpinfo->invflags & XT_TCP_INV_OPTION,