From patchwork Tue Apr 8 23:32:37 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Daniel Borkmann X-Patchwork-Id: 337747 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id D430B1400CB for ; Wed, 9 Apr 2014 09:32:47 +1000 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932351AbaDHXcl (ORCPT ); Tue, 8 Apr 2014 19:32:41 -0400 Received: from mx1.redhat.com ([209.132.183.28]:65168 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932313AbaDHXcj (ORCPT ); Tue, 8 Apr 2014 19:32:39 -0400 Received: from int-mx01.intmail.prod.int.phx2.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id s38NWdGa003064 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Tue, 8 Apr 2014 19:32:39 -0400 Received: from localhost (vpn1-5-170.ams2.redhat.com [10.36.5.170]) by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id s38NWbgP015500; Tue, 8 Apr 2014 19:32:38 -0400 From: Daniel Borkmann To: davem@davemloft.net Cc: netdev@vger.kernel.org, linux-sctp@vger.kernel.org, Vlad Yasevich Subject: [PATCH net v2] net: sctp: test if association is dead in sctp_wake_up_waiters Date: Wed, 9 Apr 2014 01:32:37 +0200 Message-Id: X-Scanned-By: MIMEDefang 2.67 on 10.5.11.11 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org In function sctp_wake_up_waiters(), we need to involve a test if the association is declared dead. If so, we don't have any reference to a possible sibling association anymore and need to invoke sctp_write_space() instead and normally walk the socket's associations and notify them of new wmem space. The reason for special casing is that, otherwise, we could run into the following issue: sctp_association_free() `-> list_del(&asoc->asocs) <-- poisons list pointer asoc->base.dead = true sctp_outq_free(&asoc->outqueue) `-> __sctp_outq_teardown() `-> sctp_chunk_free() `-> consume_skb() `-> sctp_wfree() `-> sctp_wake_up_waiters() <-- dereferences poisoned pointers if asoc->ep->sndbuf_policy=0 Therefore, only walk the list in an 'optimized' way if we find that the current association is still active. We could also use list_del_init() in addition when we call sctp_association_free(), but as Vlad suggests, we want to trap such bugs and thus leave it poisoned as is. Stress-testing seems fine now. Fixes: cd253f9f357d ("net: sctp: wake up all assocs if sndbuf policy is per socket") Signed-off-by: Daniel Borkmann Cc: Vlad Yasevich Acked-by: Neil Horman Acked-by: Vlad Yasevich --- v1->v2: - leave list_del() net/sctp/socket.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 5f83a6a..270d5bd 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -6604,6 +6604,12 @@ static void sctp_wake_up_waiters(struct sock *sk, if (asoc->ep->sndbuf_policy) return __sctp_write_space(asoc); + /* If association goes down and is just flushing its + * outq, then just normally notify others. + */ + if (asoc->base.dead) + return sctp_write_space(sk); + /* Accounting for the sndbuf space is per socket, so we * need to wake up others, try to be fair and in case of * other associations, let them have a go first instead