]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blame - releases/2.6.22.14/netfilter-nf_conntrack_tcp-fix-connection-reopening.patch
4.9-stable patches
[thirdparty/kernel/stable-queue.git] / releases / 2.6.22.14 / netfilter-nf_conntrack_tcp-fix-connection-reopening.patch
CommitLineData
1874cb39
GKH
1From stable-bounces@linux.kernel.org Mon Nov 5 03:38:25 2007
2From: Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
3Date: Mon, 05 Nov 2007 12:37:55 +0100
4Subject: NETFILTER: nf_conntrack_tcp: fix connection reopening
5To: stable@kernel.org
6Cc: Netfilter Development Mailinglist <netfilter-devel@vger.kernel.org>, "David S. Miller" <davem@davemloft.net>, Krzysztof Piotr Oledzki <ole@ans.pl>, Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
7Message-ID: <472F0093.6040508@trash.net>
8
9From: Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
10
11Upstream commits: 17311393 + bc34b841 merged together. Merge done by
12Patrick McHardy <kaber@trash.net>
13
14[NETFILTER]: nf_conntrack_tcp: fix connection reopening
15
16With your description I could reproduce the bug and actually you were
17completely right: the code above is incorrect. Somehow I was able to
18misread RFC1122 and mixed the roles :-(:
19
20 When a connection is >>closed actively<<, it MUST linger in
21 TIME-WAIT state for a time 2xMSL (Maximum Segment Lifetime).
22 However, it MAY >>accept<< a new SYN from the remote TCP to
23 reopen the connection directly from TIME-WAIT state, if it:
24 [...]
25
26The fix is as follows: if the receiver initiated an active close, then the
27sender may reopen the connection - otherwise try to figure out if we hold
28a dead connection.
29
30Signed-off-by: Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
31Tested-by: Krzysztof Piotr Oledzki <ole@ans.pl>
32Signed-off-by: Patrick McHardy <kaber@trash.net>
33Signed-off-by: David S. Miller <davem@davemloft.net>
34Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
35
36
37---
38 net/netfilter/nf_conntrack_proto_tcp.c | 38 ++++++++++++++-------------------
39 1 file changed, 17 insertions(+), 21 deletions(-)
40
41--- a/net/netfilter/nf_conntrack_proto_tcp.c
42+++ b/net/netfilter/nf_conntrack_proto_tcp.c
43@@ -839,6 +839,22 @@ static int tcp_packet(struct nf_conn *co
44 new_state = tcp_conntracks[dir][index][old_state];
45
46 switch (new_state) {
47+ case TCP_CONNTRACK_SYN_SENT:
48+ if (old_state < TCP_CONNTRACK_TIME_WAIT)
49+ break;
50+ if ((conntrack->proto.tcp.seen[!dir].flags &
51+ IP_CT_TCP_FLAG_CLOSE_INIT)
52+ || (conntrack->proto.tcp.last_dir == dir
53+ && conntrack->proto.tcp.last_index == TCP_RST_SET)) {
54+ /* Attempt to reopen a closed/aborted connection.
55+ * Delete this connection and look up again. */
56+ write_unlock_bh(&tcp_lock);
57+ if (del_timer(&conntrack->timeout))
58+ conntrack->timeout.function((unsigned long)
59+ conntrack);
60+ return -NF_REPEAT;
61+ }
62+ /* Fall through */
63 case TCP_CONNTRACK_IGNORE:
64 /* Ignored packets:
65 *
66@@ -888,27 +904,6 @@ static int tcp_packet(struct nf_conn *co
67 nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
68 "nf_ct_tcp: invalid state ");
69 return -NF_ACCEPT;
70- case TCP_CONNTRACK_SYN_SENT:
71- if (old_state < TCP_CONNTRACK_TIME_WAIT)
72- break;
73- if ((conntrack->proto.tcp.seen[dir].flags &
74- IP_CT_TCP_FLAG_CLOSE_INIT)
75- || after(ntohl(th->seq),
76- conntrack->proto.tcp.seen[dir].td_end)) {
77- /* Attempt to reopen a closed connection.
78- * Delete this connection and look up again. */
79- write_unlock_bh(&tcp_lock);
80- if (del_timer(&conntrack->timeout))
81- conntrack->timeout.function((unsigned long)
82- conntrack);
83- return -NF_REPEAT;
84- } else {
85- write_unlock_bh(&tcp_lock);
86- if (LOG_INVALID(IPPROTO_TCP))
87- nf_log_packet(pf, 0, skb, NULL, NULL,
88- NULL, "nf_ct_tcp: invalid SYN");
89- return -NF_ACCEPT;
90- }
91 case TCP_CONNTRACK_CLOSE:
92 if (index == TCP_RST_SET
93 && ((test_bit(IPS_SEEN_REPLY_BIT, &conntrack->status)
94@@ -941,6 +936,7 @@ static int tcp_packet(struct nf_conn *co
95 in_window:
96 /* From now on we have got in-window packets */
97 conntrack->proto.tcp.last_index = index;
98+ conntrack->proto.tcp.last_dir = dir;
99
100 DEBUGP("tcp_conntracks: src=%u.%u.%u.%u:%hu dst=%u.%u.%u.%u:%hu "
101 "syn=%i ack=%i fin=%i rst=%i old=%i new=%i\n",