Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755660Ab0LHAhA (ORCPT ); Tue, 7 Dec 2010 19:37:00 -0500 Received: from kroah.org ([198.145.64.141]:54881 "EHLO coco.kroah.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754813Ab0LHAeu (ORCPT ); Tue, 7 Dec 2010 19:34:50 -0500 X-Mailbox-Line: From gregkh@clark.site Tue Dec 7 16:06:43 2010 Message-Id: <20101208000643.076689896@clark.site> User-Agent: quilt/0.48-11.2 Date: Tue, 07 Dec 2010 16:04:34 -0800 From: Greg KH To: linux-kernel@vger.kernel.org, stable@kernel.org Cc: stable-review@kernel.org, torvalds@linux-foundation.org, akpm@linux-foundation.org, alan@lxorguk.ukuu.org.uk, Tom Marshall , Eric Dumazet , "David S. Miller" Subject: [35/44] tcp: Fix race in tcp_poll In-Reply-To: <20101208003205.GA4286@kroah.com> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 1815 Lines: 64 2.6.27-stable review patch. If anyone has any objections, please let us know. ------------------ From: Tom Marshall [ Upstream commit a4d258036ed9b2a1811c3670c6099203a0f284a0 ] If a RST comes in immediately after checking sk->sk_err, tcp_poll will return POLLIN but not POLLOUT. Fix this by checking sk->sk_err at the end of tcp_poll. Additionally, ensure the correct order of operations on SMP machines with memory barriers. Signed-off-by: Tom Marshall Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv4/tcp.c | 7 +++++-- net/ipv4/tcp_input.c | 2 ++ 2 files changed, 7 insertions(+), 2 deletions(-) --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -347,8 +347,6 @@ unsigned int tcp_poll(struct file *file, */ mask = 0; - if (sk->sk_err) - mask = POLLERR; /* * POLLHUP is certainly not done right. But poll() doesn't @@ -413,6 +411,11 @@ unsigned int tcp_poll(struct file *file, if (tp->urg_data & TCP_URG_VALID) mask |= POLLPRI; } + /* This barrier is coupled with smp_wmb() in tcp_reset() */ + smp_rmb(); + if (sk->sk_err) + mask |= POLLERR; + return mask; } --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -3617,6 +3617,8 @@ static void tcp_reset(struct sock *sk) default: sk->sk_err = ECONNRESET; } + /* This barrier is coupled with smp_rmb() in tcp_poll() */ + smp_wmb(); if (!sock_flag(sk, SOCK_DEAD)) sk->sk_error_report(sk); -- 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/