From mboxrd@z Thu Jan 1 00:00:00 1970 Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754545AbdBETpK (ORCPT + 2 others); Sun, 5 Feb 2017 14:45:10 -0500 Received: from wtarreau.pck.nerim.net ([62.212.114.60]:28324 "EHLO 1wt.eu" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753551AbdBET0v (ORCPT ); Sun, 5 Feb 2017 14:26:51 -0500 From: Willy Tarreau To: linux-kernel@vger.kernel.org, stable@vger.kernel.org, linux@roeck-us.net Cc: Wei Yongjun , "David S . Miller" , Mike Manning , Willy Tarreau Subject: [PATCH 3.10 222/319] ipv6: addrconf: fix dev refcont leak when DAD failed Date: Sun, 5 Feb 2017 20:20:44 +0100 Message-Id: <1486322541-8206-123-git-send-email-w@1wt.eu> X-Mailer: git-send-email 2.8.0.rc2.1.gbe9624a In-Reply-To: <1486322541-8206-1-git-send-email-w@1wt.eu> References: <1486322541-8206-1-git-send-email-w@1wt.eu> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Return-Path: From: Wei Yongjun commit 751eb6b6042a596b0080967c1a529a9fe98dac1d upstream. In general, when DAD detected IPv6 duplicate address, ifp->state will be set to INET6_IFADDR_STATE_ERRDAD and DAD is stopped by a delayed work, the call tree should be like this: ndisc_recv_ns -> addrconf_dad_failure <- missing ifp put -> addrconf_mod_dad_work -> schedule addrconf_dad_work() -> addrconf_dad_stop() <- missing ifp hold before call it addrconf_dad_failure() called with ifp refcont holding but not put. addrconf_dad_work() call addrconf_dad_stop() without extra holding refcount. This will not cause any issue normally. But the race between addrconf_dad_failure() and addrconf_dad_work() may cause ifp refcount leak and netdevice can not be unregister, dmesg show the following messages: IPv6: eth0: IPv6 duplicate address fe80::XX:XXXX:XXXX:XX detected! ... unregister_netdevice: waiting for eth0 to become free. Usage count = 1 Cc: stable@vger.kernel.org Fixes: c15b1ccadb32 ("ipv6: move DAD and addrconf_verify processing to workqueue") Signed-off-by: Wei Yongjun Signed-off-by: David S. Miller Cc: Signed-off-by: Mike Manning Signed-off-by: Willy Tarreau --- net/ipv6/addrconf.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 98dd353..0f18d858 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -1694,6 +1694,7 @@ void addrconf_dad_failure(struct inet6_ifaddr *ifp) spin_unlock_bh(&ifp->state_lock); addrconf_mod_dad_work(ifp, 0); + in6_ifa_put(ifp); } /* Join to solicited addr multicast group. */ @@ -3337,6 +3338,7 @@ static void addrconf_dad_work(struct work_struct *w) addrconf_dad_begin(ifp); goto out; } else if (action == DAD_ABORT) { + in6_ifa_hold(ifp); addrconf_dad_stop(ifp, 1); goto out; } -- 2.8.0.rc2.1.gbe9624a