From patchwork Fri Mar 8 06:50:54 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Xin Long X-Patchwork-Id: 1053384 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="NGYhozcH"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 44Fynk4fTxz9s4Y for ; Fri, 8 Mar 2019 17:51:06 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726278AbfCHGvE (ORCPT ); Fri, 8 Mar 2019 01:51:04 -0500 Received: from mail-pg1-f196.google.com ([209.85.215.196]:35674 "EHLO mail-pg1-f196.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726039AbfCHGvD (ORCPT ); Fri, 8 Mar 2019 01:51:03 -0500 Received: by mail-pg1-f196.google.com with SMTP id e17so13368113pgd.2 for ; Thu, 07 Mar 2019 22:51:03 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id; bh=0s1VzlIQ7bY2WgMhD4VcQNB0aPDEMKZe/poC5UMsO0c=; b=NGYhozcHecBkD5HQQ3V8vrlhJsQ22SU5fzizKoU6mRa8XpvzgtQT3NSaZzy5JA5UXo +1zvH+MV+JKE46Nky+cBoGvNRaGAG3IOH8bDPoHs5KZ/DjbndXmVrGH4D7kVeNOW3V71 pBGCqhgf/kQW84oC/bWqJuYQYVOyjkKG6WJ9nvKwszjyZHKqnSRaIoJTgBKZviTn9hA7 HIL87IezMyhlZAxHwPBuXBKQ+pn1FtetovVTkau1lnHuSgB1N3zarvKQK5Z89hNlCRIJ io/Q7jeGJXzlpT3QNUJl98djVRIeRR2XWdUemwGbJsSWo/iR/2YPu2azAnnVNTgtOaQu MPnw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=0s1VzlIQ7bY2WgMhD4VcQNB0aPDEMKZe/poC5UMsO0c=; b=Y2PgiEnxV/mnvQ1NHzDwganMD896uHvcAS/Mjdt4Zh2FgBMOZNABpDoxFaoMFptZQZ xJ7UZ3AZ/YEeuBvl0xvw2eUKX3VIH4RitIgRK3+9mPkd14KghB19AxAu6MLhJLb03gFD u/y30R+wYOsOhCPMW2bfe//kOlEkwEpq7+oDHGMP2eZx9i0MVxuksZzTmkkBJY7lpiL3 AE7IXxnjJhX09keEXCaZ7fTVc4G/bE/qBJ5Gh+yjVM0cqY1GgJXyTEpL+O3xhBMmFFSu h0XBwkfBhHxFzcvuJa65a49/D9ILR2BXsMLjosJOvR2K1Rk8i5HPFWci8ZrTM1xpWQn0 JdAg== X-Gm-Message-State: APjAAAW1XsC414wKX/fCJRKAju+6LJ7XkFZuKZA/l4TxuHzDyvhGGxTu akrZSFa/+X6dwUS0EhI0Sn19DzxA X-Google-Smtp-Source: APXvYqzUoE7HZhSzPcEp93/qcEwbLD4Stg8XISnk7zOxQPEFV94UN+MqlRkP+/mA+OEDDMiiBoMmlw== X-Received: by 2002:a65:6112:: with SMTP id z18mr6092669pgu.272.1552027862326; Thu, 07 Mar 2019 22:51:02 -0800 (PST) Received: from localhost ([209.132.188.80]) by smtp.gmail.com with ESMTPSA id k72sm21829115pfb.122.2019.03.07.22.51.01 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 07 Mar 2019 22:51:01 -0800 (PST) From: Xin Long To: network dev Cc: davem@davemloft.net, David Ahern , Jon Maxwell , jmaxwell@redhat.com Subject: [PATCH net] route: set the deleted fnhe fnhe_daddr to 0 in ip_del_fnhe to fix a race Date: Fri, 8 Mar 2019 14:50:54 +0800 Message-Id: <42a31507d9b1d4874bb9a8570bd9f17225aaa553.1552027854.git.lucien.xin@gmail.com> X-Mailer: git-send-email 2.1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org The race occurs in __mkroute_output() when 2 threads lookup a dst: CPU A CPU B find_exception() find_exception() [fnhe expires] ip_del_fnhe() [fnhe is deleted] rt_bind_exception() In rt_bind_exception() it will bind a deleted fnhe with the new dst, and this dst will get no chance to be freed. It causes a dev defcnt leak and consecutive dmesg warnings: unregister_netdevice: waiting for ethX to become free. Usage count = 1 Especially thinks Jon to identify the issue. This patch fixes it by setting fnhe_daddr to 0 in ip_del_fnhe() to stop binding the deleted fnhe with a new dst when checking fnhe's fnhe_daddr and daddr in rt_bind_exception(). It works as both ip_del_fnhe() and rt_bind_exception() are protected by fnhe_lock and the fhne is freed by kfree_rcu(). Fixes: deed49df7390 ("route: check and remove route cache when we get route") Signed-off-by: Jon Maxwell Signed-off-by: Xin Long Reviewed-by: David Ahern --- net/ipv4/route.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 5163b64..b0eb4fa 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -1303,6 +1303,10 @@ static void ip_del_fnhe(struct fib_nh *nh, __be32 daddr) if (fnhe->fnhe_daddr == daddr) { rcu_assign_pointer(*fnhe_p, rcu_dereference_protected( fnhe->fnhe_next, lockdep_is_held(&fnhe_lock))); + /* set fnhe_daddr to 0 to ensure it won't bind with + * new dsts in rt_bind_exception(). + */ + fnhe->fnhe_daddr = 0; fnhe_flush_routes(fnhe); kfree_rcu(fnhe, rcu); break;