Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1761663AbZJIXmh (ORCPT ); Fri, 9 Oct 2009 19:42:37 -0400 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1757335AbZJIXmg (ORCPT ); Fri, 9 Oct 2009 19:42:36 -0400 Received: from kroah.org ([198.145.64.141]:51457 "EHLO coco.kroah.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S934577AbZJIXmN (ORCPT ); Fri, 9 Oct 2009 19:42:13 -0400 X-Mailbox-Line: From gregkh@mini.kroah.org Fri Oct 9 16:34:40 2009 Message-Id: <20091009233440.056033028@mini.kroah.org> User-Agent: quilt/0.48-1 Date: Fri, 09 Oct 2009 16:34:42 -0700 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, Eric Dumazet , "David S. Miller" Subject: [patch 31/37] net: Fix sock_wfree() race References: <20091009233411.852013234@mini.kroah.org> Content-Disposition: inline; filename=net-fix-sock_wfree-race.patch In-Reply-To: <20091009233812.GA15982@kroah.com> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 2001 Lines: 53 2.6.31-stable review patch. If anyone has any objections, please let us know. ------------------ From: Eric Dumazet [ Upstream commit d99927f4d93f36553699573b279e0ff98ad7dea6 ] Commit 2b85a34e911bf483c27cfdd124aeb1605145dc80 (net: No more expensive sock_hold()/sock_put() on each tx) opens a window in sock_wfree() where another cpu might free the socket we are working on. A fix is to call sk->sk_write_space(sk) while still holding a reference on sk. Reported-by: Jike Song Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/core/sock.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) --- a/net/core/sock.c +++ b/net/core/sock.c @@ -1218,17 +1218,22 @@ void __init sk_init(void) void sock_wfree(struct sk_buff *skb) { struct sock *sk = skb->sk; - int res; + unsigned int len = skb->truesize; - /* In case it might be waiting for more memory. */ - res = atomic_sub_return(skb->truesize, &sk->sk_wmem_alloc); - if (!sock_flag(sk, SOCK_USE_WRITE_QUEUE)) + if (!sock_flag(sk, SOCK_USE_WRITE_QUEUE)) { + /* + * Keep a reference on sk_wmem_alloc, this will be released + * after sk_write_space() call + */ + atomic_sub(len - 1, &sk->sk_wmem_alloc); sk->sk_write_space(sk); + len = 1; + } /* - * if sk_wmem_alloc reached 0, we are last user and should - * free this sock, as sk_free() call could not do it. + * if sk_wmem_alloc reaches 0, we must finish what sk_free() + * could not do because of in-flight packets */ - if (res == 0) + if (atomic_sub_and_test(len, &sk->sk_wmem_alloc)) __sk_free(sk); } EXPORT_SYMBOL(sock_wfree); -- 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/