[PATCH net] ipv6: avoid divide by zero in rt6_multipath_rebalance
From: Cen Zhang (Microsoft)
Date: Sun Aug 16 2026 - 21:33:08 EST
rt6_multipath_rebalance() calculates the total eligible nexthop weight
in one pass and programs upper bounds in a second pass. Since
RTM_NEWROUTE is RTNL-free, a concurrent
ignore_routes_with_linkdown update can make the first pass return zero
while the second sees an eligible nexthop, causing
rt6_upper_bound_set() to divide by zero.
UBSAN: division-overflow in net/ipv6/route.c:4845:17
Oops: divide error: 0000 [#1] SMP KASAN NOPTI
rt6_upper_bound_set() net/ipv6/route.c:4845
rt6_multipath_rebalance()
fib6_add_rt2node()
ip6_route_multipath_add()
inet6_rtm_newroute()
Skip upper-bound calculation when the first pass reports a zero total.
This respects the lock-free performance considerations here and solves
insecure scenarios.
Fixes: bd11ff421d36 ("ipv6: Get rid of RTNL for SIOCDELRT and RTM_DELROUTE.")
Reported-by: AutonomousCodeSecurity@xxxxxxxxxxxxx
Reported-by: Xiang Mei (Microsoft) <xmei5@xxxxxxx>
Reported-by: Cen Zhang (Microsoft) <blbllhy@xxxxxxxxx>
Signed-off-by: Cen Zhang (Microsoft) <blbllhy@xxxxxxxxx>
---
net/ipv6/route.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 5968ce5ad150..68924cff9205 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -4840,7 +4840,7 @@ static void rt6_upper_bound_set(struct fib6_info *rt, int *weight, int total)
{
int upper_bound = -1;
- if (!rt6_is_dead(rt)) {
+ if (total && !rt6_is_dead(rt)) {
*weight += rt->fib6_nh->fib_nh_weight;
upper_bound = DIV_ROUND_CLOSEST_ULL((u64) (*weight) << 31,
total) - 1;
--
2.52.0