From nobody Thu Apr 9 15:46:02 2026 Received: from mail-yw1-f178.google.com (mail-yw1-f178.google.com [209.85.128.178]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 89C2534A79A for ; Fri, 6 Mar 2026 23:39:21 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.178 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772840364; cv=none; b=X9WmyMmS38bwaD9x0DYjqNoADTGv2tgKjOi/QD4EizhD3jsrGcYKVPlUV3Fd5TVcPoJnyvzwRCmTk5/MTQtbEeJpsOOrIQ97OeNrMtxFfh0cfjQxZgfHmUv1SB4QxT9IywDV3JuKgRASUEMzolr/mkHb/ImM6ZhpNl0oNf4FrY8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772840364; c=relaxed/simple; bh=apPiXEb0O6w+YA4l9CCmEorK71PzvfzP4YtEPO9dM5Q=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version:Content-Type; b=Fb41Qx5Js9/YgEjc7craNbcQH2LC/n6OLyWzAqyW3/88dRVZ4uHlr6ppvyxI8GpyeZqcuQ84QUQjjAFSgphLLoZZs1+bZSl9XWXEY7yNnOez97vsYuPcbz+zyHN6ko16l78r3AhSP5IeyJrOyBOHVXysYF1747eaYAMGdhsjP2Y= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=ML9zOEsS; arc=none smtp.client-ip=209.85.128.178 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="ML9zOEsS" Received: by mail-yw1-f178.google.com with SMTP id 00721157ae682-79800183233so136325877b3.1 for ; Fri, 06 Mar 2026 15:39:21 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1772840361; x=1773445161; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to; bh=d9wovly74FgcJKa8Ed9Xsx768BrjeHrTIyaL2Oh1KxY=; b=ML9zOEsS+nSiY8b2DQrkVlYbYNrtRG7NSi3TqmkXwH8l/xyNyaNgXIThfhzJGzvR+6 lV1gCmc2iDzFXOW1qUpq9JTKSb0R59lNQ1ljocqhl9NetHwlT91Af26xD/zhT/TswUR2 u7eArB2SuRaaxB80KpduoM60PT5LNUnKf8CfSHX2v8DK3FnQ7DmNt6lsdu1gbh6y1uX5 gvatvieBr+sSQSJQP+rKxcdVSF+tpdJM8J5mN0eacsXfEPK5QMa5Io/anqztvo0pX3C3 GsXM/KyU723T2syXAaPrQqPrG8KrErnAw7iwUeMWot4uAShi6arINXiQUpBG2SGouMjo UNqg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1772840361; x=1773445161; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=d9wovly74FgcJKa8Ed9Xsx768BrjeHrTIyaL2Oh1KxY=; b=P+9teEHM1slc78tXa2EJeOXii+yoHmXkdqvPanPfKL/rqiegdsQi/SdSelDyNstsIw zzAGNBvTyY97nkhDxunCddEw2MVAVqf37JQgzyz5XCe294AP46PJUDeRDzScy7IYVIHA KvPfznrg43RKnqVnYrmdvCPvDT+4tTaXCZT6mkZg5ALygDiWEyNKLl3fMbWcidGcA7vs w4VIWg3L6Tbdw4UGk7KAoYlXVAAZXWkDxrH52uyfiDnYPcCfy6Pa2RbG1LDBNkNJmx1u AfFdcqUjRhUjtxBW08jF+PeMmam8duGovDPX7v4YKJOxAHK7Yup1G53yhlnCrFNHC9+K yE0A== X-Forwarded-Encrypted: i=1; AJvYcCVZu7GXyCHOivODsGVyqTbKUYMObk8pryDCfzsEsqUkjCC3j0OrmmReJ3OjPkw1CTzqE2zYhapXQDt2iyE=@vger.kernel.org X-Gm-Message-State: AOJu0YyuDsnUSkQhfpqVEacx4NyAitv3qX+1FZpjliiIJfgKWRLAqHNg f/FUUC5NZDQfJgvo9eRiK8eGT8Rmj6LqVAhw6S8QEr/dU43J0lsnb9ot X-Gm-Gg: ATEYQzyuAE1zsamnlMuiEXG/JdIrjYLbm91W8P7wqaE8656Ref8JOrD20wyjEUKFcGS dAGf9U9F8+LP6mugCENElSfqcRkY3rXfKeDXsKAgFvbMFvKRBmQCo1Nb5aBc5Abgc6fBEk7N5Xt NsFu/KTaxB6RGVZl+U7nYz6E2OsBMBAG5r/rbffidFyBnsGoc8e1FrlmPe5HMscYQ6gk7NGsT61 jfWLTwC/Cu+/teAsGuF+iR2Fk1xBPCjp3xe6G/up+DaEluEV3pYK68SSrXt+VEXhSRflUP4oPjQ 0TPfMIfef38AZVbC3WDFaWzw+YGv5mJc3C3zkaKWr3eAKh/YVh2ZrEIHB0dzpT6Bwnp4x1OTGjF oB8iA5WQ/VR6pqHOYfekv9PFPGm9Jkmg888sDIzvqz7rVEdih+CAQ3OX4VHhxvT3kzZvfRZQWzg lbhiFrsFQuk1MhiQ8oMi4e4y/ThsoVhgkEJKOCrmRS9Fxq1wxpmZpgD3gTFkTFDek3Z+U= X-Received: by 2002:a05:690c:660d:b0:798:63ab:757f with SMTP id 00721157ae682-798dd6d3d80mr35940637b3.9.1772840360031; Fri, 06 Mar 2026 15:39:20 -0800 (PST) Received: from desktop-linux.python-stargazer.ts.net ([50.168.180.218]) by smtp.gmail.com with ESMTPSA id 00721157ae682-798dee4883bsm14013957b3.31.2026.03.06.15.39.19 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 06 Mar 2026 15:39:19 -0800 (PST) From: Mehul Rao To: dsahern@kernel.org, davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com Cc: horms@kernel.org, petrm@nvidia.com, idosch@nvidia.com, netdev@vger.kernel.org, stable@vger.kernel.org, linux-kernel@vger.kernel.org, Mehul Rao Subject: [PATCH net] net: nexthop: fix percpu use-after-free in remove_nh_grp_entry Date: Fri, 6 Mar 2026 18:38:20 -0500 Message-ID: <20260306233821.196789-1-mehulrao@gmail.com> X-Mailer: git-send-email 2.53.0 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable When removing a nexthop from a group, remove_nh_grp_entry() publishes the new group via rcu_assign_pointer() then immediately frees the removed entry's percpu stats with free_percpu(). However, the synchronize_net() grace period in the caller remove_nexthop_from_groups() runs after the free. RCU readers that entered before the publish still see the old group and can dereference the freed stats via nh_grp_entry_stats_inc() -> get_cpu_ptr(nhge->stats), causing a use-after-free on percpu memory. Fix by deferring the free_percpu() until after synchronize_net() in the caller. Removed entries are chained via nh_list onto a local deferred free list. After the grace period completes and all RCU readers have finished, the percpu stats are safely freed. Fixes: f4676ea74b85 ("net: nexthop: Add nexthop group entry stats") Cc: stable@vger.kernel.org Signed-off-by: Mehul Rao Reviewed-by: Eric Dumazet Reviewed-by: Ido Schimmel --- net/ipv4/nexthop.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/net/ipv4/nexthop.c b/net/ipv4/nexthop.c index 1aa2b05ee8de..c942f1282236 100644 --- a/net/ipv4/nexthop.c +++ b/net/ipv4/nexthop.c @@ -2002,7 +2002,8 @@ static void nh_hthr_group_rebalance(struct nh_group *= nhg) } =20 static void remove_nh_grp_entry(struct net *net, struct nh_grp_entry *nhge, - struct nl_info *nlinfo) + struct nl_info *nlinfo, + struct list_head *deferred_free) { struct nh_grp_entry *nhges, *new_nhges; struct nexthop *nhp =3D nhge->nh_parent; @@ -2062,8 +2063,8 @@ static void remove_nh_grp_entry(struct net *net, stru= ct nh_grp_entry *nhge, rcu_assign_pointer(nhp->nh_grp, newg); =20 list_del(&nhge->nh_list); - free_percpu(nhge->stats); nexthop_put(nhge->nh); + list_add(&nhge->nh_list, deferred_free); =20 /* Removal of a NH from a resilient group is notified through * bucket notifications. @@ -2083,6 +2084,7 @@ static void remove_nexthop_from_groups(struct net *ne= t, struct nexthop *nh, struct nl_info *nlinfo) { struct nh_grp_entry *nhge, *tmp; + LIST_HEAD(deferred_free); =20 /* If there is nothing to do, let's avoid the costly call to * synchronize_net() @@ -2091,10 +2093,16 @@ static void remove_nexthop_from_groups(struct net *= net, struct nexthop *nh, return; =20 list_for_each_entry_safe(nhge, tmp, &nh->grp_list, nh_list) - remove_nh_grp_entry(net, nhge, nlinfo); + remove_nh_grp_entry(net, nhge, nlinfo, &deferred_free); =20 /* make sure all see the newly published array before releasing rtnl */ synchronize_net(); + + /* Now safe to free percpu stats =E2=80=94 all RCU readers have finished = */ + list_for_each_entry_safe(nhge, tmp, &deferred_free, nh_list) { + list_del(&nhge->nh_list); + free_percpu(nhge->stats); + } } =20 static void remove_nexthop_group(struct nexthop *nh, struct nl_info *nlinf= o) --=20 2.53.0