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

From: Zihan Xi

Date: Mon Aug 17 2026 - 09:17:55 EST


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: stable@xxxxxxxxxxxxxxx
Reported-by: Vega <vega@xxxxxxxxxx>
Assisted-by: Codex:gpt-5.4
Signed-off-by: Zihan Xi <zihanx@xxxxxxxxxx>
---
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