Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S964971AbYBVVzz (ORCPT ); Fri, 22 Feb 2008 16:55:55 -0500 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1761827AbYBVVo2 (ORCPT ); Fri, 22 Feb 2008 16:44:28 -0500 Received: from cantor2.suse.de ([195.135.220.15]:60656 "EHLO mx2.suse.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752595AbYBVVoV (ORCPT ); Fri, 22 Feb 2008 16:44:21 -0500 Date: Fri, 22 Feb 2008 13:41:02 -0800 From: Greg KH To: linux-kernel@vger.kernel.org, stable@kernel.org Cc: Justin Forbes , Zwane Mwaikambo , "Theodore Ts'o" , Randy Dunlap , Dave Jones , Chuck Wolber , Chris Wedgwood , Michael Krufky , Chuck Ebbert , Domenico Andreoli , torvalds@linux-foundation.org, akpm@linux-foundation.org, alan@lxorguk.ukuu.org.uk, Netfilter Development Mailinglist , "David S. Miller" , Jozsef Kadlecsik , Patrick McHardy Subject: [patch 23/23] NETFILTER: nf_conntrack_tcp: conntrack reopening fix Message-ID: <20080222214102.GX8686@suse.de> References: <20080222213114.583282464@mini.kroah.org> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline; filename="netfilter-nf_conntrack_tcp-conntrack-reopening-fix.patch" In-Reply-To: <20080222213927.GA8686@suse.de> User-Agent: Mutt/1.5.16 (2007-06-09) Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 4319 Lines: 114 2.6.22-stable review patch. If anyone has any objections, please let us know. ------------------ From: Jozsef Kadlecsik [NETFILTER]: nf_conntrack_tcp: conntrack reopening fix [Upstream commits b2155e7f + d0c1fd7a] TCP connection tracking in netfilter did not handle TCP reopening properly: active close was taken into account for one side only and not for any side, which is fixed now. The patch includes more comments to explain the logic how the different cases are handled. The bug was discovered by Jeff Chua. Signed-off-by: Jozsef Kadlecsik Signed-off-by: Patrick McHardy Signed-off-by: Greg Kroah-Hartman --- net/netfilter/nf_conntrack_proto_tcp.c | 35 +++++++++++++++++++++++++-------- 1 file changed, 27 insertions(+), 8 deletions(-) --- a/net/netfilter/nf_conntrack_proto_tcp.c +++ b/net/netfilter/nf_conntrack_proto_tcp.c @@ -143,7 +143,7 @@ enum tcp_bit_set { * CLOSE_WAIT: ACK seen (after FIN) * LAST_ACK: FIN seen (after FIN) * TIME_WAIT: last ACK seen - * CLOSE: closed connection + * CLOSE: closed connection (RST) * * LISTEN state is not used. * @@ -842,8 +842,21 @@ static int tcp_packet(struct nf_conn *co case TCP_CONNTRACK_SYN_SENT: if (old_state < TCP_CONNTRACK_TIME_WAIT) break; - if ((conntrack->proto.tcp.seen[!dir].flags & - IP_CT_TCP_FLAG_CLOSE_INIT) + /* RFC 1122: "When a connection is closed actively, + * it MUST linger in TIME-WAIT state for a time 2xMSL + * (Maximum Segment Lifetime). However, it MAY accept + * a new SYN from the remote TCP to reopen the connection + * directly from TIME-WAIT state, if..." + * We ignore the conditions because we are in the + * TIME-WAIT state anyway. + * + * Handle aborted connections: we and the server + * think there is an existing connection but the client + * aborts it and starts a new one. + */ + if (((conntrack->proto.tcp.seen[dir].flags + | conntrack->proto.tcp.seen[!dir].flags) + & IP_CT_TCP_FLAG_CLOSE_INIT) || (conntrack->proto.tcp.last_dir == dir && conntrack->proto.tcp.last_index == TCP_RST_SET)) { /* Attempt to reopen a closed/aborted connection. @@ -856,18 +869,25 @@ static int tcp_packet(struct nf_conn *co } /* Fall through */ case TCP_CONNTRACK_IGNORE: - /* Ignored packets: + /* Ignored packets: + * + * Our connection entry may be out of sync, so ignore + * packets which may signal the real connection between + * the client and the server. * * a) SYN in ORIGINAL * b) SYN/ACK in REPLY * c) ACK in reply direction after initial SYN in original. + * + * If the ignored packet is invalid, the receiver will send + * a RST we'll catch below. */ if (index == TCP_SYNACK_SET && conntrack->proto.tcp.last_index == TCP_SYN_SET && conntrack->proto.tcp.last_dir != dir && ntohl(th->ack_seq) == conntrack->proto.tcp.last_end) { - /* This SYN/ACK acknowledges a SYN that we earlier + /* b) This SYN/ACK acknowledges a SYN that we earlier * ignored as invalid. This means that the client and * the server are both in sync, while the firewall is * not. We kill this session and block the SYN/ACK so @@ -892,7 +912,7 @@ static int tcp_packet(struct nf_conn *co write_unlock_bh(&tcp_lock); if (LOG_INVALID(IPPROTO_TCP)) nf_log_packet(pf, 0, skb, NULL, NULL, NULL, - "nf_ct_tcp: invalid packed ignored "); + "nf_ct_tcp: invalid packet ignored "); return NF_ACCEPT; case TCP_CONNTRACK_MAX: /* Invalid packet */ @@ -948,8 +968,7 @@ static int tcp_packet(struct nf_conn *co conntrack->proto.tcp.state = new_state; if (old_state != new_state - && (new_state == TCP_CONNTRACK_FIN_WAIT - || new_state == TCP_CONNTRACK_CLOSE)) + && new_state == TCP_CONNTRACK_FIN_WAIT) conntrack->proto.tcp.seen[dir].flags |= IP_CT_TCP_FLAG_CLOSE_INIT; timeout = conntrack->proto.tcp.retrans >= nf_ct_tcp_max_retrans && *tcp_timeouts[new_state] > nf_ct_tcp_timeout_max_retrans -- -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/