From patchwork Thu May 19 19:55:13 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacek Luczak X-Patchwork-Id: 96451 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 8DCDCB718A for ; Fri, 20 May 2011 05:55:36 +1000 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S934528Ab1ESTzb (ORCPT ); Thu, 19 May 2011 15:55:31 -0400 Received: from mail-ww0-f44.google.com ([74.125.82.44]:49450 "EHLO mail-ww0-f44.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S934358Ab1ESTza (ORCPT ); Thu, 19 May 2011 15:55:30 -0400 Received: by wwa36 with SMTP id 36so3266587wwa.1 for ; Thu, 19 May 2011 12:55:29 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:message-id:date:from:user-agent:mime-version:to :cc:subject:content-type:content-transfer-encoding; bh=QNc80AAcASVEmPdaQKhTyK5G4amU8d085PnHLKNUi4U=; b=FcHRutYskoY0rBQdccB68I2GZodjcqa4TTcqbT0zD++P/t3duTUryvPoqJaB27L+9B muSA5JnhRQa9B9ZalQKpmM/K/Yd1qJk77L2Fg4OeRbFczuhobw6s5/eoDflE+2a+UiJ1 d1sJHUB/0UnXiXx/5+IPhlF94HEmt8JEmjYAc= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=message-id:date:from:user-agent:mime-version:to:cc:subject :content-type:content-transfer-encoding; b=tdDqGXlhx8Fkxd1wHglab4M77u0grfqZMjbfzHVUDUVU5aGF0IQe4Y7wx2h9CeBaOc 2LRXBCl0SnfdfWET4oo6Vcsimh5nziV1zxyXHwAKMTzqXOKur++RpoMq8d8SOv97NI8a kTd5xxnKoxVaCD3TBBV8EuKGaDui87/LZ18kA= Received: by 10.227.199.21 with SMTP id eq21mr3450107wbb.101.1305834929189; Thu, 19 May 2011 12:55:29 -0700 (PDT) Received: from [172.16.10.101] (dynamic-62-87-147-252.ssp.dialog.net.pl [62.87.147.252]) by mx.google.com with ESMTPS id bo14sm1831269wbb.11.2011.05.19.12.55.26 (version=TLSv1/SSLv3 cipher=OTHER); Thu, 19 May 2011 12:55:28 -0700 (PDT) Message-ID: <4DD575A1.4080405@gmail.com> Date: Thu, 19 May 2011 21:55:13 +0200 From: Jacek Luczak User-Agent: Mozilla/5.0 (X11; U; Linux i686; pl; rv:1.9.2.17) Gecko/20110414 Lightning/1.0b2 Thunderbird/3.1.10 MIME-Version: 1.0 To: David Miller CC: vladislav.yasevich@hp.com, eric.dumazet@gmail.com, netdev@vger.kernel.org Subject: [PATCH FINAL] SCTP: fix race between sctp_bind_addr_free() and sctp_bind_addr_conflict() Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org During the sctp_close() call, we do not use rcu primitives to destroy the address list attached to the endpoint. At the same time, we do the removal of addresses from this list before attempting to remove the socket from the port hash As a result, it is possible for another process to find the socket in the port hash that is in the process of being closed. It then proceeds to traverse the address list to find the conflict, only to have that address list suddenly disappear without rcu() critical section. Fix issue by closing address list removal inside RCU critical section. Race can result in a kernel crash with general protection fault or kernel NULL pointer dereference: kernel: general protection fault: 0000 [#1] SMP kernel: RIP: 0010:[] [] sctp_bind_addr_conflict+0x64/0x82 [sctp] kernel: Call Trace: kernel: [] ? sctp_get_port_local+0x17b/0x2a3 [sctp] kernel: [] ? sctp_bind_addr_match+0x33/0x68 [sctp] kernel: [] ? sctp_do_bind+0xd3/0x141 [sctp] kernel: [] ? sctp_bindx_add+0x4d/0x8e [sctp] kernel: [] ? sctp_setsockopt_bindx+0x112/0x4a4 [sctp] kernel: [] ? generic_file_aio_write+0x7f/0x9b kernel: [] ? sctp_setsockopt+0x14f/0xfee [sctp] kernel: [] ? do_sync_write+0xab/0xeb kernel: [] ? fsnotify+0x239/0x282 kernel: [] ? alloc_file+0x18/0xb1 kernel: [] ? compat_sys_setsockopt+0x1a5/0x1d9 kernel: [] ? compat_sys_socketcall+0x143/0x1a4 kernel: [] ? sysenter_dispatch+0x7/0x32 Signed-off-by: Jacek Luczak Acked-by: Vlad Yasevich CC: Eric Dumazet Reviewed-by: Eric Dumazet --- net/sctp/bind_addr.c | 10 ++++------ 1 files changed, 4 insertions(+), 6 deletions(-) -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html diff --git a/net/sctp/bind_addr.c b/net/sctp/bind_addr.c index faf71d1..6150ac5 100644 --- a/net/sctp/bind_addr.c +++ b/net/sctp/bind_addr.c @@ -140,14 +140,12 @@ void sctp_bind_addr_init(struct sctp_bind_addr *bp, __u16 port) /* Dispose of the address list. */ static void sctp_bind_addr_clean(struct sctp_bind_addr *bp) { - struct sctp_sockaddr_entry *addr; - struct list_head *pos, *temp; + struct sctp_sockaddr_entry *addr, *temp; /* Empty the bind address list. */ - list_for_each_safe(pos, temp, &bp->address_list) { - addr = list_entry(pos, struct sctp_sockaddr_entry, list); - list_del(pos); - kfree(addr); + list_for_each_entry_safe(addr, temp, &bp->address_list, list) { + list_del_rcu(&addr->list); + call_rcu(&addr->rcu, sctp_local_addr_free); SCTP_DBG_OBJCNT_DEC(addr); } }