From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6C72E334690; Fri, 21 Nov 2025 13:33:45 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763732025; cv=none; b=ZRTMJ7sr41WZUI8u+defELvrmM7BhUBdDSvQ8M7t3CEKPsCBIaUdheEsko7MeWTAjvqo97s15NAF82URVWUH8jz8y1uMSXsrPFSGjq6Jtx7HPYCGV4moWvNeF2Q0DknYPeDUPQRpjgn7CoYuCNgCcGEnZ62UdS3So5I/GxwVq64= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763732025; c=relaxed/simple; bh=o7+3ETAT4kIxerDAKS1I5fwA3p+omcIkqVJZ/9WcTPQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=fXjihwYm0fDho8xZ4JEOE5dS+/7crTan8U21bbaWglJix+yzIKK1z6sq5kvtWZhCf3KlMGdO6v4yI0ccqUWx02iCFghbZP5C7aRgaWlf5M37Z9tbva03Ag4ktDmix3JJegPa8o8MffZbQrHS20thPyFnqxBciBQgFtr4vFpdySI= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linuxfoundation.org header.i=@linuxfoundation.org header.b=r4rV1DDf; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linuxfoundation.org header.i=@linuxfoundation.org header.b="r4rV1DDf" Received: by smtp.kernel.org (Postfix) with ESMTPSA id E0C0EC4CEF1; Fri, 21 Nov 2025 13:33:44 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=linuxfoundation.org; s=korg; t=1763732025; bh=o7+3ETAT4kIxerDAKS1I5fwA3p+omcIkqVJZ/9WcTPQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=r4rV1DDfSy2UakSSytwWrq6iIt8ge2EYk5JYLTJuXP6IEFodBGT/9ReHZYSbJc16u 04bQ6XQE6iqgVW71rGdMNz6Fy4czmXJ0nE4omvWHC2juAhr/0yXuWANvVAb+gjEucW LI7EUntXmEm6qmurkahV3su2gzDvFUKvqY7F0+VI= From: Greg Kroah-Hartman To: stable@vger.kernel.org Cc: Greg Kroah-Hartman , patches@lists.linux.dev, Chuang Wang , Ido Schimmel , Eric Dumazet , Jakub Kicinski Subject: [PATCH 6.12 120/185] ipv4: route: Prevent rt_bind_exception() from rebinding stale fnhe Date: Fri, 21 Nov 2025 14:12:27 +0100 Message-ID: <20251121130148.205203178@linuxfoundation.org> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20251121130143.857798067@linuxfoundation.org> References: <20251121130143.857798067@linuxfoundation.org> User-Agent: quilt/0.69 X-stable: review X-Patchwork-Hint: ignore Precedence: bulk X-Mailing-List: stable@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit 6.12-stable review patch. If anyone has any objections, please let me know. ------------------ From: Chuang Wang commit ac1499fcd40fe06479e9b933347b837ccabc2a40 upstream. The sit driver's packet transmission path calls: sit_tunnel_xmit() -> update_or_create_fnhe(), which lead to fnhe_remove_oldest() being called to delete entries exceeding FNHE_RECLAIM_DEPTH+random. The race window is between fnhe_remove_oldest() selecting fnheX for deletion and the subsequent kfree_rcu(). During this time, the concurrent path's __mkroute_output() -> find_exception() can fetch the soon-to-be-deleted fnheX, and rt_bind_exception() then binds it with a new dst using a dst_hold(). When the original fnheX is freed via RCU, the dst reference remains permanently leaked. CPU 0 CPU 1 __mkroute_output() find_exception() [fnheX] update_or_create_fnhe() fnhe_remove_oldest() [fnheX] rt_bind_exception() [bind dst] RCU callback [fnheX freed, dst leak] This issue manifests as a device reference count leak and a warning in dmesg when unregistering the net device: unregister_netdevice: waiting for sitX to become free. Usage count = N Ido Schimmel provided the simple test validation method [1]. The fix clears 'oldest->fnhe_daddr' before calling fnhe_flush_routes(). Since rt_bind_exception() checks this field, setting it to zero prevents the stale fnhe from being reused and bound to a new dst just before it is freed. [1] ip netns add ns1 ip -n ns1 link set dev lo up ip -n ns1 address add 192.0.2.1/32 dev lo ip -n ns1 link add name dummy1 up type dummy ip -n ns1 route add 192.0.2.2/32 dev dummy1 ip -n ns1 link add name gretap1 up arp off type gretap \ local 192.0.2.1 remote 192.0.2.2 ip -n ns1 route add 198.51.0.0/16 dev gretap1 taskset -c 0 ip netns exec ns1 mausezahn gretap1 \ -A 198.51.100.1 -B 198.51.0.0/16 -t udp -p 1000 -c 0 -q & taskset -c 2 ip netns exec ns1 mausezahn gretap1 \ -A 198.51.100.1 -B 198.51.0.0/16 -t udp -p 1000 -c 0 -q & sleep 10 ip netns pids ns1 | xargs kill ip netns del ns1 Cc: stable@vger.kernel.org Fixes: 67d6d681e15b ("ipv4: make exception cache less predictible") Signed-off-by: Chuang Wang Reviewed-by: Ido Schimmel Reviewed-by: Eric Dumazet Link: https://patch.msgid.link/20251111064328.24440-1-nashuiliang@gmail.com Signed-off-by: Jakub Kicinski Signed-off-by: Greg Kroah-Hartman --- net/ipv4/route.c | 5 +++++ 1 file changed, 5 insertions(+) --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -605,6 +605,11 @@ static void fnhe_remove_oldest(struct fn oldest_p = fnhe_p; } } + + /* Clear oldest->fnhe_daddr to prevent this fnhe from being + * rebound with new dsts in rt_bind_exception(). + */ + oldest->fnhe_daddr = 0; fnhe_flush_routes(oldest); *oldest_p = oldest->fnhe_next; kfree_rcu(oldest, rcu);