From patchwork Sun Oct 16 18:50:26 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Cong Wang X-Patchwork-Id: 682730 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 3sxr5B31srz9sC3 for ; Mon, 17 Oct 2016 05:50:54 +1100 (AEDT) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b=yEiIj0vs; dkim-atps=neutral Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756906AbcJPSuv (ORCPT ); Sun, 16 Oct 2016 14:50:51 -0400 Received: from mail-io0-f174.google.com ([209.85.223.174]:35868 "EHLO mail-io0-f174.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753411AbcJPSur (ORCPT ); Sun, 16 Oct 2016 14:50:47 -0400 Received: by mail-io0-f174.google.com with SMTP id j37so168558249ioo.3 for ; Sun, 16 Oct 2016 11:50:47 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:in-reply-to:references:from:date:message-id:subject:to :cc; bh=pvLZ8wgb3yur7xpGGbezfHcSobljNU+3T9HfLgqDCVk=; b=yEiIj0vsBAfM/37bYjYqHkrbGaDEVOBUYw6pBfhmcL+8Q34vXPPVVrI8y0Bjbm6iJJ IbeQEAt7SCdcc+hiIw0dzfx8l1ReOONU+QwVkXuQIEY2EXfSzpOxQb0oz3xP1WqU0ClS 7G/0yDWUo5r00aUNS2Q7R+zKjMOnl4oWqx+2p+LMPAyBRalJCuSBxplHDKGjBfzHHfrC 68xM7B7MckYoIzLwcZTrP5/gSkrJfOYuD1Ke2FmbLQUVAU4b+bD45gxA2aRvdVUAM3oo +FQKpgow0WnX501N3mR1J86Kjm7X/EIx5u5p7ieg+0ln0kQxXViMUZ8T5Gr5gD/p3IEI v1cA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:in-reply-to:references:from:date :message-id:subject:to:cc; bh=pvLZ8wgb3yur7xpGGbezfHcSobljNU+3T9HfLgqDCVk=; b=D8y9HNBw4rGUnUnJky9ZZKNH9p1tocoP9p3JOMOB7kiArIi4lWwXUdFQO8R7+1/3Tg P2b1qY02DXXY16EV/p3IMdRlOwwowz96IvPZMGyx7nM8xakbCBPedOSfyqJfqzxp7gkZ 46z+MgBwfufYRVkdU2QOeETKvq9oEkmOrvMP+fYt2OUqA0muxyiQa+YGopiZZl8zpOXO pgrz9SKt1L5uhsoMVx1uln+bypZQktmJICW+k9ipovqGMGDsabD1yH8L/O1sqBiU0xXw Z76kPVLpIAiLSTVnM80t76ebdOVz0NZMpQRp1+QCQHjDwQTHqB8Vq01nEhOcwfcObC3G 9u3A== X-Gm-Message-State: AA6/9RmlQnlSRiKFUESQD+WKTyvbvKPd6hLMtlX9Rclz/diI8UheY8+0kNB2lF0YZjARXGaFIE5ZRfWVUzOVLg== X-Received: by 10.107.15.27 with SMTP id x27mr19427362ioi.218.1476643847105; Sun, 16 Oct 2016 11:50:47 -0700 (PDT) MIME-Version: 1.0 Received: by 10.107.130.215 with HTTP; Sun, 16 Oct 2016 11:50:26 -0700 (PDT) In-Reply-To: References: From: Cong Wang Date: Sun, 16 Oct 2016 11:50:26 -0700 Message-ID: Subject: Re: net/ipv6: potential deadlock in do_ipv6_setsockopt To: Baozeng Ding Cc: Linux Kernel Network Developers Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org On Sun, Oct 16, 2016 at 6:34 AM, Baozeng Ding wrote: > Possible unsafe locking scenario: > > CPU0 CPU1 > ---- ---- > lock([ 165.136033] sk_lock-AF_INET6 > ); > lock([ 165.136033] rtnl_mutex > ); > lock([ 165.136033] sk_lock-AF_INET6 > ); > lock([ 165.136033] rtnl_mutex > ); > > *** DEADLOCK *** This is caused by the conditional rtnl locking in do_ipv6_setsockopt(). It looks like we miss the case of IPV6_ADDRFORM. Please try the attached patch. Tested-by: Baozeng Ding Tested-by: Baozeng Ding diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index 46ad699..b8c8d20 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c @@ -414,7 +414,9 @@ int inet6_release(struct socket *sock) return -EINVAL; /* Free mc lists */ + rtnl_lock(); ipv6_sock_mc_close(sk); + rtnl_unlock(); /* Free ac lists */ ipv6_sock_ac_close(sk); diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c index 5330262..1e4bcce 100644 --- a/net/ipv6/ipv6_sockglue.c +++ b/net/ipv6/ipv6_sockglue.c @@ -120,6 +120,7 @@ struct ipv6_txoptions *ipv6_update_options(struct sock *sk, static bool setsockopt_needs_rtnl(int optname) { switch (optname) { + case IPV6_ADDRFORM: case IPV6_ADD_MEMBERSHIP: case IPV6_DROP_MEMBERSHIP: case IPV6_JOIN_ANYCAST: diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c index 75c1fc5..41badfd 100644 --- a/net/ipv6/mcast.c +++ b/net/ipv6/mcast.c @@ -282,10 +282,11 @@ void ipv6_sock_mc_close(struct sock *sk) struct ipv6_mc_socklist *mc_lst; struct net *net = sock_net(sk); + ASSERT_RTNL(); + if (!rcu_access_pointer(np->ipv6_mc_list)) return; - rtnl_lock(); while ((mc_lst = rtnl_dereference(np->ipv6_mc_list)) != NULL) { struct net_device *dev; @@ -305,7 +306,6 @@ void ipv6_sock_mc_close(struct sock *sk) kfree_rcu(mc_lst, rcu); } - rtnl_unlock(); } int ip6_mc_source(int add, int omode, struct sock *sk,