lkml.org 
[lkml]   [2019]   [Aug]   [14]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.19 36/91] netfilter: conntrack: always store window size un-scaled
    Date
    [ Upstream commit 959b69ef57db00cb33e9c4777400ae7183ebddd3 ]

    Jakub Jankowski reported following oddity:

    After 3 way handshake completes, timeout of new connection is set to
    max_retrans (300s) instead of established (5 days).

    shortened excerpt from pcap provided:
    25.070622 IP (flags [DF], proto TCP (6), length 52)
    10.8.5.4.1025 > 10.8.1.2.80: Flags [S], seq 11, win 64240, [wscale 8]
    26.070462 IP (flags [DF], proto TCP (6), length 48)
    10.8.1.2.80 > 10.8.5.4.1025: Flags [S.], seq 82, ack 12, win 65535, [wscale 3]
    27.070449 IP (flags [DF], proto TCP (6), length 40)
    10.8.5.4.1025 > 10.8.1.2.80: Flags [.], ack 83, win 512, length 0

    Turns out the last_win is of u16 type, but we store the scaled value:
    512 << 8 (== 0x20000) becomes 0 window.

    The Fixes tag is not correct, as the bug has existed forever, but
    without that change all that this causes might cause is to mistake a
    window update (to-nonzero-from-zero) for a retransmit.

    Fixes: fbcd253d2448b8 ("netfilter: conntrack: lower timeout to RETRANS seconds if window is 0")
    Reported-by: Jakub Jankowski <shasta@toxcorp.com>
    Tested-by: Jakub Jankowski <shasta@toxcorp.com>
    Signed-off-by: Florian Westphal <fw@strlen.de>
    Acked-by: Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
    Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
    Signed-off-by: Sasha Levin <sashal@kernel.org>
    ---
    net/netfilter/nf_conntrack_proto_tcp.c | 8 +++++---
    1 file changed, 5 insertions(+), 3 deletions(-)

    diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c
    index 842f3f86fb2e7..7011ab27c4371 100644
    --- a/net/netfilter/nf_conntrack_proto_tcp.c
    +++ b/net/netfilter/nf_conntrack_proto_tcp.c
    @@ -480,6 +480,7 @@ static bool tcp_in_window(const struct nf_conn *ct,
    struct ip_ct_tcp_state *receiver = &state->seen[!dir];
    const struct nf_conntrack_tuple *tuple = &ct->tuplehash[dir].tuple;
    __u32 seq, ack, sack, end, win, swin;
    + u16 win_raw;
    s32 receiver_offset;
    bool res, in_recv_win;

    @@ -488,7 +489,8 @@ static bool tcp_in_window(const struct nf_conn *ct,
    */
    seq = ntohl(tcph->seq);
    ack = sack = ntohl(tcph->ack_seq);
    - win = ntohs(tcph->window);
    + win_raw = ntohs(tcph->window);
    + win = win_raw;
    end = segment_seq_plus_len(seq, skb->len, dataoff, tcph);

    if (receiver->flags & IP_CT_TCP_FLAG_SACK_PERM)
    @@ -663,14 +665,14 @@ static bool tcp_in_window(const struct nf_conn *ct,
    && state->last_seq == seq
    && state->last_ack == ack
    && state->last_end == end
    - && state->last_win == win)
    + && state->last_win == win_raw)
    state->retrans++;
    else {
    state->last_dir = dir;
    state->last_seq = seq;
    state->last_ack = ack;
    state->last_end = end;
    - state->last_win = win;
    + state->last_win = win_raw;
    state->retrans = 0;
    }
    }
    --
    2.20.1


    \
     
     \ /
      Last update: 2019-08-14 19:26    [W:4.095 / U:0.024 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site