Skip to content

Commit ffa319e

Browse files
CKI Backport BotHangbin Liu
authored andcommitted
ipv6: prevent infinite loop in rt6_nlmsg_size()
JIRA: https://issues.redhat.com/browse/RHEL-115578 CVE: CVE-2025-38588 commit 54e6fe9 Author: Eric Dumazet <edumazet@google.com> Date: Fri Jul 25 14:07:23 2025 +0000 ipv6: prevent infinite loop in rt6_nlmsg_size() While testing prior patch, I was able to trigger an infinite loop in rt6_nlmsg_size() in the following place: list_for_each_entry_rcu(sibling, &f6i->fib6_siblings, fib6_siblings) { rt6_nh_nlmsg_size(sibling->fib6_nh, &nexthop_len); } This is because fib6_del_route() and fib6_add_rt2node() uses list_del_rcu(), which can confuse rcu readers, because they might no longer see the head of the list. Restart the loop if f6i->fib6_nsiblings is zero. Fixes: d9ccb18 ("ipv6: Fix soft lockups in fib6_select_path under high next hop churn") Signed-off-by: Eric Dumazet <edumazet@google.com> Link: https://patch.msgid.link/20250725140725.3626540-3-edumazet@google.com Signed-off-by: Jakub Kicinski <kuba@kernel.org> Signed-off-by: CKI Backport Bot <cki-ci-bot+cki-gitlab-backport-bot@redhat.com>
1 parent 19a07a4 commit ffa319e

File tree

2 files changed

+20
-18
lines changed

2 files changed

+20
-18
lines changed

net/ipv6/ip6_fib.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1251,7 +1251,7 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct fib6_info *rt,
12511251
&rt->fib6_siblings,
12521252
fib6_siblings)
12531253
sibling->fib6_nsiblings--;
1254-
rt->fib6_nsiblings = 0;
1254+
WRITE_ONCE(rt->fib6_nsiblings, 0);
12551255
list_del_rcu(&rt->fib6_siblings);
12561256
rt6_multipath_rebalance(next_sibling);
12571257
return err;
@@ -1969,7 +1969,7 @@ static void fib6_del_route(struct fib6_table *table, struct fib6_node *fn,
19691969
list_for_each_entry_safe(sibling, next_sibling,
19701970
&rt->fib6_siblings, fib6_siblings)
19711971
sibling->fib6_nsiblings--;
1972-
rt->fib6_nsiblings = 0;
1972+
WRITE_ONCE(rt->fib6_nsiblings, 0);
19731973
list_del_rcu(&rt->fib6_siblings);
19741974
rt6_multipath_rebalance(next_sibling);
19751975
}

net/ipv6/route.c

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5587,32 +5587,34 @@ static int rt6_nh_nlmsg_size(struct fib6_nh *nh, void *arg)
55875587

55885588
static size_t rt6_nlmsg_size(struct fib6_info *f6i)
55895589
{
5590+
struct fib6_info *sibling;
5591+
struct fib6_nh *nh;
55905592
int nexthop_len;
55915593

55925594
if (f6i->nh) {
55935595
nexthop_len = nla_total_size(4); /* RTA_NH_ID */
55945596
nexthop_for_each_fib6_nh(f6i->nh, rt6_nh_nlmsg_size,
55955597
&nexthop_len);
5596-
} else {
5597-
struct fib6_nh *nh = f6i->fib6_nh;
5598-
struct fib6_info *sibling;
5599-
5600-
nexthop_len = 0;
5601-
if (f6i->fib6_nsiblings) {
5602-
rt6_nh_nlmsg_size(nh, &nexthop_len);
5603-
5604-
rcu_read_lock();
5598+
goto common;
5599+
}
56055600

5606-
list_for_each_entry_rcu(sibling, &f6i->fib6_siblings,
5607-
fib6_siblings) {
5608-
rt6_nh_nlmsg_size(sibling->fib6_nh, &nexthop_len);
5609-
}
5601+
rcu_read_lock();
5602+
retry:
5603+
nh = f6i->fib6_nh;
5604+
nexthop_len = 0;
5605+
if (READ_ONCE(f6i->fib6_nsiblings)) {
5606+
rt6_nh_nlmsg_size(nh, &nexthop_len);
56105607

5611-
rcu_read_unlock();
5608+
list_for_each_entry_rcu(sibling, &f6i->fib6_siblings,
5609+
fib6_siblings) {
5610+
rt6_nh_nlmsg_size(sibling->fib6_nh, &nexthop_len);
5611+
if (!READ_ONCE(f6i->fib6_nsiblings))
5612+
goto retry;
56125613
}
5613-
nexthop_len += lwtunnel_get_encap_size(nh->fib_nh_lws);
56145614
}
5615-
5615+
rcu_read_unlock();
5616+
nexthop_len += lwtunnel_get_encap_size(nh->fib_nh_lws);
5617+
common:
56165618
return NLMSG_ALIGN(sizeof(struct rtmsg))
56175619
+ nla_total_size(16) /* RTA_SRC */
56185620
+ nla_total_size(16) /* RTA_DST */

0 commit comments

Comments
 (0)