From: netdev-bot+sashiko@kernel.org
To: xiaolinkui@126.com
Cc: dsahern@kernel.org, idosch@nvidia.com, davem@davemloft.net,
edumazet@google.com, kuba@kernel.org, pabeni@redhat.com,
horms@kernel.org, netdev@vger.kernel.org,
linux-kernel@vger.kernel.org, xiaolinkui@kylinos.cn
Subject: Re: [PATCH net v2] ipv4: fib: fix data-race and stale genid check around nh->nh_saddr
Date: Thu, 17 Sep 2026 07:18:12 +0000 [thread overview]
Message-ID: <178962949299.22033.4111144579519364166@kernel.org> (raw)
In-Reply-To: <20260915071503.465875-1-xiaolinkui@126.com>
Thank you for your contribution! Sashiko AI review found 1 potential
issue(s) to consider:
Critical: 0 · High: 1 · Medium: 0 · Low: 0
- [High] In fib_select_multipath() (net/ipv4/fib_semantics.c), the newly
added `READ_ONCE(nexthop_nh->nh_saddr_genid) == genid` test treats a…
--
ipv4: fib: fix data-race and stale genid check around nh->nh_saddr
This adds READ_ONCE() to the two lockless reads of nh->nh_saddr and
nh->nh_saddr_genid in fib_select_multipath(), and additionally requires the
cached nh_saddr_genid to equal a snapshot of net->ipv4.dev_addr_genid before
the source-address match can add its scoring bonus. The stated intent is to
mirror fib_result_prefsrc().
> diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c
> index 7a362f2e2c2bd..e2bfc11aea09c 100644
> --- a/net/ipv4/fib_semantics.c
> +++ b/net/ipv4/fib_semantics.c
> @@ -2192,6 +2193,7 @@ void fib_select_multipath(struct fib_result *res, int hash,
>
> use_neigh = READ_ONCE(net->ipv4.sysctl_fib_multipath_use_neigh);
> saddr = fl4 ? fl4->saddr : 0;
> + genid = saddr ? atomic_read(&net->ipv4.dev_addr_genid) : 0;
>
> change_nexthops(fi) {
> int nh_upper_bound, nh_score = 0;
> @@ -2204,7 +2206,9 @@ void fib_select_multipath(struct fib_result *res, int hash,
> (use_neigh && !fib_good_nh(nexthop_nh)))
> continue;
>
> - if (saddr && nexthop_nh->nh_saddr == saddr)
> + if (saddr &&
> + READ_ONCE(nexthop_nh->nh_saddr_genid) == genid &&
> + READ_ONCE(nexthop_nh->nh_saddr) == saddr)
> nh_score += 2;
[Severity: High]
Does this genid check turn a cache miss into a permanent disqualification,
so that the source-address preference from 32607a332cfe stops working after
any address event in the netns?
The function the commit message says is being mirrored treats a genid
mismatch as a miss and repopulates the cache:
net/ipv4/fib_semantics.c:fib_result_prefsrc() {
...
if (READ_ONCE(nh->nh_saddr_genid) ==
atomic_read(&net->ipv4.dev_addr_genid))
return READ_ONCE(nh->nh_saddr);
}
return fib_info_update_nhc_saddr(net, nhc, res->fi->fib_scope);
}
fib_select_multipath() has no such fallback: on mismatch the nexthop simply
loses nh_score += 2, and nothing recomputes nh_saddr for it.
nh_saddr_genid is only stamped in fib_create_info() (once per fib_info at
route creation, for all nexthops), at nexthop object creation in
net/ipv4/nexthop.c, and by fib_result_prefsrc() for res->nhc alone.
Meanwhile dev_addr_genid is a per-netns counter bumped for any IPv4 address
event on any device:
net/ipv4/fib_frontend.c:fib_inetaddr_event() {
...
atomic_inc(&net->ipv4.dev_addr_genid);
rt_cache_flush(net);
The same pattern appears for NETDEV_DOWN and in fib_netdev_event(). So after
one unrelated ip addr add/del, DHCP renew or NETDEV_UP, every fib_nh in the
netns has a stale nh_saddr_genid, and the accompanying rt_cache_flush()
forces established sockets into fresh lookups that already carry
fl4->saddr != 0.
Is there anything on that path that would refresh the cache? The only lazy
refresher reachable from here is gated on the opposite condition:
net/ipv4/fib_semantics.c:fib_select_path() {
...
check_saddr:
if (!fl4->saddr) {
...
fl4->saddr = fib_result_prefsrc(net, res);
That block is skipped exactly when saddr is non-zero, which is the only case
the new check governs, and even when it does run it refreshes res->nhc only,
not the sibling nexthops walked by the scoring loop. The other caller,
ip_mkroute_input() in net/ipv4/route.c, passes fl4 == NULL, so saddr is 0
there and the check has no effect on forwarding.
With that in place, for every output lookup that already has a source
address (socket bound before connect(), UDP or raw sendmsg with a fixed
source, and the post-flush re-lookups), does the +2 bonus become
unreachable, making nh_score == 3 impossible and reducing selection to plain
hash ECMP? That would let a flow sourced from veth0's address egress via
veth1, which is the behaviour 32607a332cfe was written to avoid.
Would calling fib_info_update_nhc_saddr() on mismatch, or restricting this
patch to the READ_ONCE() annotations that the KCSAN report actually
justifies, be preferable here? As it stands the Fixes: tag would carry this
behavioural change into stable.
[Severity: Low]
On the commit message wording:
fib_info_update_nhc_saddr() stores a new value from another CPU as soon
as the preferred source address of the egress device changes.
Is that accurate? fib_info_update_nhc_saddr() is only called on demand
(from fib_result_prefsrc() on a genid mismatch, and at route creation), not
from the address-change notifier itself, which only bumps dev_addr_genid.
--
Sashiko AI review · https://netdev-ai.bots.linux.dev/sashiko/#/patchset/20260915071503.465875-1-xiaolinkui%40126.com
prev parent reply other threads:[~2026-09-17 7:18 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-15 7:15 [PATCH net v2] ipv4: fib: fix data-race and stale genid check around nh->nh_saddr Linkui Xiao
2026-09-15 17:53 ` Ido Schimmel
2026-09-16 2:15 ` Linkui Xiao
2026-09-17 7:18 ` netdev-bot+sashiko [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=178962949299.22033.4111144579519364166@kernel.org \
--to=netdev-bot+sashiko@kernel.org \
--cc=davem@davemloft.net \
--cc=dsahern@kernel.org \
--cc=edumazet@google.com \
--cc=horms@kernel.org \
--cc=idosch@nvidia.com \
--cc=kuba@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=xiaolinkui@126.com \
--cc=xiaolinkui@kylinos.cn \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.