From: netdev-bot+sashiko@kernel.org
To: edumazet@google.com
Cc: davem@davemloft.net, kuba@kernel.org, pabeni@redhat.com,
horms@kernel.org, andrew+netdev@lunn.ch, idosch@nvidia.com,
kuniyu@google.com, lorenzo.bianconi@oss.qualcomm.com,
iprintercanon@gmail.com, netdev@vger.kernel.org,
eric.dumazet@gmail.com
Subject: Re: [PATCH net-next 8/9] sit: convert configuration to RCU protection
Date: Tue, 08 Sep 2026 11:00:59 +0000 [thread overview]
Message-ID: <178886525919.219967.16743451973276511375@kernel.org> (raw)
In-Reply-To: <20260907075846.2913645-9-edumazet@google.com>
Thank you for your contribution! Sashiko AI review found 1 potential
issue(s) to consider:
Critical: 0 · High: 0 · Medium: 1 · Low: 0
- [Medium] SIT tunnel parameters are now read from two objects that live
in different synchronization domains, and ipip6_tunnel_update()…
--
sit: convert configuration to RCU protection
This converts tunnel->sit_parms into an RCU-protected pointer, so that
ipip6_tunnel_update() publishes a freshly allocated parameter block with
rcu_assign_pointer() and frees the old one with kfree_rcu(). The unlink /
re-link plus synchronize_net() are now skipped when neither saddr nor daddr
changed.
> diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c
> index dc37c7109af53..c9049ab87e010 100644
> --- a/net/ipv6/sit.c
> +++ b/net/ipv6/sit.c
[ ... ]
> @@ -1087,13 +1119,17 @@ static netdev_tx_t sit_tunnel_xmit__(struct sk_buff *skb,
> struct net_device *dev, u8 ipproto)
> {
> struct ip_tunnel *tunnel = netdev_priv(dev);
> - const struct iphdr *tiph = &tunnel->sit_parms->iph;
> + const struct ip_tunnel_parm_kern *parms;
> + const struct iphdr *tiph;
>
> if (iptunnel_handle_offloads(skb, SKB_GSO_IPXIP4))
> goto tx_error;
>
> skb_set_inner_ipproto(skb, ipproto);
>
> + parms = rcu_dereference(tunnel->sit_parms);
> + tiph = &parms->iph;
> +
> ip_tunnel_xmit(skb, dev, tiph, ipproto);
> return NETDEV_TX_OK;
> tx_error:
[ ... ]
> @@ -1194,21 +1235,29 @@ static int ipip6_tunnel_update(struct ip_tunnel *t,
> new_p->iph.tos = p->iph.tos;
> new_p->iph.frag_off = p->iph.frag_off;
> new_p->link = p->link;
> - ipip6_tunnel_unlink(sitn, t);
> - synchronize_net();
> - t->sit_parms = new_p;
> + move = old_p->iph.saddr != p->iph.saddr ||
> + old_p->iph.daddr != p->iph.daddr;
> +
> + if (move)
> + ipip6_tunnel_unlink(sitn, t);
> +
> t->parms.iph = new_p->iph;
> WRITE_ONCE(t->parms.link, new_p->link);
> - __dev_addr_set(t->dev, &p->iph.saddr, 4);
> - memcpy(t->dev->broadcast, &p->iph.daddr, 4);
> - ipip6_tunnel_link(sitn, t);
> + rcu_assign_pointer(t->sit_parms, new_p);
[Severity: Medium]
After this change, are the SIT transmit parameters read from two objects
that are no longer updated together?
ipip6_tunnel_update() now performs two separate stores here:
t->parms.iph = new_p->iph; /* plain struct copy */
WRITE_ONCE(t->parms.link, new_p->link);
rcu_assign_pointer(t->sit_parms, new_p); /* published */
On the transmit side, sit_tunnel_xmit__() takes the header out of the
RCU-published block:
parms = rcu_dereference(tunnel->sit_parms);
tiph = &parms->iph;
ip_tunnel_xmit(skb, dev, tiph, ipproto);
but ip_tunnel_xmit() in net/ipv4/ip_tunnel.c mixes that with the shadow
copy that is not RCU protected:
connected = (tunnel->parms.iph.daddr != 0);
...
dst = tnl_params->daddr;
...
rt = connected ? dst_cache_get_ip4(&tunnel->dst_cache,
&fl4.saddr) : NULL;
...
else if (!md && connected)
dst_cache_set_ip4(&tunnel->dst_cache, &rt->dst,
fl4.saddr);
Since sit_tunnel_xmit() runs locklessly, can it observe the two objects
from different generations, e.g. sit_parms with daddr == 0 (so dst is
derived per packet from the skb/neighbour) while tunnel->parms.iph.daddr
already holds the new address, making connected true? In that case
ip_tunnel_xmit() would consult and populate tunnel->dst_cache for a
destination-specific route on a tunnel that the header says is NBMA, so a
burst of packets could be routed via the cached entry. The reverse pairing
(old shadow daddr, new sit_parms daddr) looks possible too where the plain
tunnel->parms.iph.daddr load can be reordered against the rcu_dereference().
Independently of the ordering question, is the plain struct assignment
t->parms.iph = new_p->iph a data race? It writes roughly twenty bytes
without any annotation while the xmit path is reading ttl, tos, frag_off
and daddr from tunnel->parms, which KCSAN should flag and which can hand
the transmit path a mixture of old and new field values.
The synchronize_net() in the move case only runs after publication, so it
bounds but does not close the window for a reader that entered right at the
grace period boundary.
Would it make sense for ip_tunnel_xmit() to derive connected and link from
the same parameter block that tiph came from, so that only one object is
consulted per packet?
>
> + if (move) {
> + synchronize_net();
> + __dev_addr_set(t->dev, &p->iph.saddr, 4);
> + memcpy(t->dev->broadcast, &p->iph.daddr, 4);
> + ipip6_tunnel_link(sitn, t);
> + }
> if (old_p->link != p->link || t->fwmark != fwmark) {
> WRITE_ONCE(t->fwmark, fwmark);
> ipip6_tunnel_bind_dev(t->dev);
> }
> dst_cache_reset(&t->dst_cache);
> netdev_state_change(t->dev);
> - kfree(old_p);
> + kfree_rcu(old_p, rcu);
> return 0;
> }
[ ... ]
--
Sashiko AI review · https://netdev-ai.bots.linux.dev/sashiko/#/patchset/20260907075846.2913645-1-edumazet%40google.com
next prev parent reply other threads:[~2026-09-08 11:01 UTC|newest]
Thread overview: 28+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-07 7:58 [PATCH net-next 0/9] sit: convert configuration to RCU and lockless fill_info Eric Dumazet
2026-09-07 7:58 ` [PATCH net-next 1/9] sit: fix UAF in ipip6_tunnel_del_prl() Eric Dumazet
2026-09-07 12:28 ` Lorenzo Bianconi
2026-09-07 7:58 ` [PATCH net-next 2/9] sit: charge ip_tunnel_prl_entry allocations to memcg Eric Dumazet
2026-09-07 12:35 ` Lorenzo Bianconi
2026-09-07 7:58 ` [PATCH net-next 3/9] ip_tunnel: use WRITE_ONCE in ip_tunnel_encap_setup Eric Dumazet
2026-09-07 15:12 ` Lorenzo Bianconi
2026-09-08 11:00 ` netdev-bot+sashiko
2026-09-07 7:58 ` [PATCH net-next 4/9] sit: annotate data-races around tunnel->fwmark Eric Dumazet
2026-09-07 15:12 ` Lorenzo Bianconi
2026-09-08 11:00 ` netdev-bot+sashiko
2026-09-07 7:58 ` [PATCH net-next 5/9] sit: convert 6RD configuration to RCU protection Eric Dumazet
2026-09-07 13:00 ` Lorenzo Bianconi
2026-09-08 11:00 ` netdev-bot+sashiko
2026-09-07 7:58 ` [PATCH net-next 6/9] sit: implement ipip6_get_iflink() Eric Dumazet
2026-09-07 13:01 ` Lorenzo Bianconi
2026-09-07 7:58 ` [PATCH net-next 7/9] sit: dynamically allocate struct ip_tunnel_parm_kern Eric Dumazet
2026-09-07 13:16 ` Lorenzo Bianconi
2026-09-07 13:34 ` Artem Lytkin
2026-09-07 13:48 ` Eric Dumazet
2026-09-08 11:00 ` netdev-bot+sashiko
2026-09-07 7:58 ` [PATCH net-next 8/9] sit: convert configuration to RCU protection Eric Dumazet
2026-09-07 14:32 ` Lorenzo Bianconi
2026-09-07 14:42 ` Eric Dumazet
2026-09-08 11:00 ` netdev-bot+sashiko [this message]
2026-09-07 7:58 ` [PATCH net-next 9/9] sit: no longer rely on RTNL in ipip6_fill_info() Eric Dumazet
2026-09-07 15:04 ` Lorenzo Bianconi
2026-09-11 1:40 ` [PATCH net-next 0/9] sit: convert configuration to RCU and lockless fill_info patchwork-bot+netdevbpf
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=178886525919.219967.16743451973276511375@kernel.org \
--to=netdev-bot+sashiko@kernel.org \
--cc=andrew+netdev@lunn.ch \
--cc=davem@davemloft.net \
--cc=edumazet@google.com \
--cc=eric.dumazet@gmail.com \
--cc=horms@kernel.org \
--cc=idosch@nvidia.com \
--cc=iprintercanon@gmail.com \
--cc=kuba@kernel.org \
--cc=kuniyu@google.com \
--cc=lorenzo.bianconi@oss.qualcomm.com \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
/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.