[PATCH net 1/1] ipv4: Fix fib_rebalance() divide-by-zero race

Zihan Xi <[email protected]>
Newsgroups gmane.linux.network,gmane.linux.kernel,gmane.linux.kernel.stable
Message-ID <2080e22819c552b0d186563eda255a44c68404f7.1786812660.git.zihanx@nebusec.ai>
fib_rebalance() reads ignore_routes_with_linkdown while summing active
nexthop weights and then reads it again while calculating each upper
bound. Sysctl writes are not serialized by RTNL. If all nexthops are
link-down, a concurrent 1-to-0 change can leave total at zero and make
the second pass divide by zero.

Route insertion and link-state updates call fib_rebalance() under RTNL,
and netlink devconf changes are already protected by RTNL. Make the
sysctl handler take the per-net RTNL lock before changing
ignore_routes_with_linkdown. This gives both passes a stable policy view
without adding work to route lookup or rebalance paths.

Fixes: 0e884c78ee19 ("ipv4: L3 hash-based multipath")
Cc: [email protected]
Reported-by: Vega <[email protected]>
Assisted-by: Codex:gpt-5.4
Signed-off-by: Zihan Xi <[email protected]>
---
 net/ipv4/devinet.c | 22 ++++++++++++++++++++--
 1 file changed, 20 insertions(+), 2 deletions(-)

diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index a35b72662..71d961013 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -2604,6 +2604,23 @@ static int devinet_conf_proc(const struct ctl_table *ctl, int write,
 	return ret;
 }
 
+static int devinet_conf_proc_rtnl(const struct ctl_table *ctl, int write,
+				  void *buffer, size_t *lenp, loff_t *ppos)
+{
+	struct net *net = ctl->extra2;
+	int ret;
+
+	if (write && !rtnl_net_trylock(net))
+		return restart_syscall();
+
+	ret = devinet_conf_proc(ctl, write, buffer, lenp, ppos);
+
+	if (write)
+		rtnl_net_unlock(net);
+
+	return ret;
+}
+
 static int devinet_sysctl_forward(const struct ctl_table *ctl, int write,
 				  void *buffer, size_t *lenp, loff_t *ppos)
 {
@@ -2709,8 +2726,9 @@ static struct devinet_sysctl_table {
 					"igmpv2_unsolicited_report_interval"),
 		DEVINET_SYSCTL_RW_ENTRY(IGMPV3_UNSOLICITED_REPORT_INTERVAL,
 					"igmpv3_unsolicited_report_interval"),
-		DEVINET_SYSCTL_RW_ENTRY(IGNORE_ROUTES_WITH_LINKDOWN,
-					"ignore_routes_with_linkdown"),
+		DEVINET_SYSCTL_COMPLEX_ENTRY(IGNORE_ROUTES_WITH_LINKDOWN,
+					     "ignore_routes_with_linkdown",
+					     devinet_conf_proc_rtnl),
 		DEVINET_SYSCTL_RW_ENTRY(DROP_GRATUITOUS_ARP,
 					"drop_gratuitous_arp"),
 		DEVINET_SYSCTL_RW_ENTRY(NOXFRM, "disable_xfrm"),
-- 
2.43.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.