From patchwork Mon Dec 16 22:37:52 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiri Kosina X-Patchwork-Id: 301908 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 32A652C009A for ; Tue, 17 Dec 2013 09:38:22 +1100 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751714Ab3LPWh5 (ORCPT ); Mon, 16 Dec 2013 17:37:57 -0500 Received: from cantor2.suse.de ([195.135.220.15]:40436 "EHLO mx2.suse.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750972Ab3LPWh4 (ORCPT ); Mon, 16 Dec 2013 17:37:56 -0500 Received: from relay1.suse.de (charybdis-ext.suse.de [195.135.220.254]) by mx2.suse.de (Postfix) with ESMTP id 2094FABC7; Mon, 16 Dec 2013 22:37:55 +0000 (UTC) Date: Mon, 16 Dec 2013 23:37:52 +0100 (CET) From: Jiri Kosina To: Eric Dumazet , Shawn Bohrer , "David S. Miller" cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH] [RFC] udp: ipv4: fix potential deadlock on sk_dst_lock Message-ID: User-Agent: Alpine 2.00 (LNX 1167 2008-08-23) MIME-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Commit 975022310 ("udp: ipv4: must add synchronization in udp_sk_rx_dst_set()) caused sk_dst_lock to be obtained in udp4 receive path, which is happening in softirq context. inet_bind() is taking sk_dst_lock (through sk_dst_reset()) without turning IRQs off, which results in the lockdep splat below. Fix that by disabling IRQs while taking the lock in sk_dst_reset(). inconsistent {SOFTIRQ-ON-W} -> {IN-SOFTIRQ-W} usage. openvpn/10482 [HC0[0]:SC1[1]:HE1:SE0] takes: (&(&sk->sk_dst_lock)->rlock){+.?...}, at: [] __udp4_lib_rcv+0x77e/0x7b0 {SOFTIRQ-ON-W} state was registered at: [] mark_irqflags+0x144/0x190 [] __lock_acquire+0x4ec/0x5f0 [] lock_acquire+0xf1/0x120 [] _raw_spin_lock+0x34/0x50 [] inet_bind+0x1bd/0x240 [] SyS_bind+0xb0/0xd0 [] system_call_fastpath+0x16/0x1b irq event stamp: 162866 hardirqs last enabled at (162866): [] local_bh_enable+0x66/0xc0 hardirqs last disabled at (162865): [] local_bh_enable+0x29/0xc0 softirqs last enabled at (162822): [] skb_free_datagram_locked+0xaa/0xd0 softirqs last disabled at (162853): [] do_softirq_own_stack+0x1c/0x30 other info that might help us debug this: Possible unsafe locking scenario: CPU0 ---- lock(&(&sk->sk_dst_lock)->rlock); lock(&(&sk->sk_dst_lock)->rlock); *** DEADLOCK *** 2 locks held by openvpn/10482: #0: (rcu_read_lock){.+.+..}, at: [] __netif_receive_skb_core+0xb7/0x6d0 #1: (rcu_read_lock){.+.+..}, at: [] ip_local_deliver_finish+0x40/0x170 stack backtrace: CPU: 0 PID: 10482 Comm: openvpn Not tainted 3.13.0-rc4-00001-gc01a871 #1 Hardware name: LENOVO 7470BN2/7470BN2, BIOS 6DET38WW (2.02 ) 12/19/2008 ffffffff81f015d8 ffff88007c203a98 ffffffff8158ff8b ffff88007c203af8 ffffffff8109a287 0000000000000001 0000000000000001 ffff880000000000 0000000000000001 ffffffff817ddf8f 0000000000000006 0000000000000004 Call Trace: [] dump_stack+0x72/0x87 [] print_usage_bug+0x197/0x1a0 [] ? print_irq_inversion_bug+0x240/0x240 [] mark_lock_irq+0xf5/0x220 [] mark_lock+0x11c/0x1c0 [] mark_irqflags+0xf6/0x190 [] __lock_acquire+0x4ec/0x5f0 [] lock_acquire+0xf1/0x120 [] ? __udp4_lib_rcv+0x77e/0x7b0 [] _raw_spin_lock+0x34/0x50 [] ? __udp4_lib_rcv+0x77e/0x7b0 [] __udp4_lib_rcv+0x77e/0x7b0 [] udp_rcv+0x15/0x20 [] ip_local_deliver_finish+0xa3/0x170 [] ? ip_local_deliver_finish+0x40/0x170 [] ip_local_deliver+0x80/0x90 [] ip_rcv_finish+0x19a/0x510 [] ? ip_local_deliver+0x90/0x90 [] NF_HOOK+0x2f/0x70 [] ? sock_wfree+0x67/0x70 [] ip_rcv+0x2bd/0x370 [] __netif_receive_skb_core+0x5a8/0x6d0 [] ? __netif_receive_skb_core+0xb7/0x6d0 [] ? process_backlog+0x16e/0x1a0 [] __netif_receive_skb+0x2b/0x80 [] process_backlog+0xb8/0x1a0 [] net_rx_action+0xbc/0x1c0 [] __do_softirq+0x128/0x2b0 [] do_softirq_own_stack+0x1c/0x30 [] do_softirq+0x65/0x70 [] netif_rx_ni+0x3d/0x40 [] tun_get_user+0x25d/0x710 [tun] [] tun_chr_aio_write+0x81/0xb0 [tun] [] do_sync_write+0x60/0x90 [] ? rw_verify_area+0x54/0xf0 [] vfs_write+0xc7/0x1e0 [] ? sysret_check+0x1b/0x56 [] SyS_write+0x5d/0xa0 [] system_call_fastpath+0x16/0x1b Signed-off-by: Jiri Kosina --- include/net/sock.h | 6 ++++-- 1 files changed, 4 insertions(+), 2 deletions(-) diff --git a/include/net/sock.h b/include/net/sock.h index 2ef3c3e..ce13255 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -1790,9 +1790,11 @@ __sk_dst_reset(struct sock *sk) static inline void sk_dst_reset(struct sock *sk) { - spin_lock(&sk->sk_dst_lock); + unsigned long flags; + + spin_lock_irqsave(&sk->sk_dst_lock, flags); __sk_dst_reset(sk); - spin_unlock(&sk->sk_dst_lock); + spin_unlock_irqrestore(&sk->sk_dst_lock, flags); } struct dst_entry *__sk_dst_check(struct sock *sk, u32 cookie);