From: Eric Dumazet <edumazet@google.com>
To: "David S . Miller" <davem@davemloft.net>,
Jakub Kicinski <kuba@kernel.org>,
Paolo Abeni <pabeni@redhat.com>
Cc: Simon Horman <horms@kernel.org>,
Andrew Lunn <andrew+netdev@lunn.ch>,
Ido Schimmel <idosch@nvidia.com>,
Kuniyuki Iwashima <kuniyu@google.com>,
Lorenzo Bianconi <lorenzo.bianconi@oss.qualcomm.com>,
Artem Lytkin <iprintercanon@gmail.com>,
netdev@vger.kernel.org, eric.dumazet@gmail.com,
Eric Dumazet <edumazet@google.com>
Subject: [PATCH net-next 7/9] sit: dynamically allocate struct ip_tunnel_parm_kern
Date: Mon, 7 Sep 2026 07:58:44 +0000 [thread overview]
Message-ID: <20260907075846.2913645-8-edumazet@google.com> (raw)
In-Reply-To: <20260907075846.2913645-1-edumazet@google.com>
In preparation for converting SIT configuration parameters to RCU,
dynamically allocate struct ip_tunnel_parm_kern as sit_parms in
struct ip_tunnel.
Signed-off-by: Eric Dumazet <edumazet@google.com>
---
include/net/ip_tunnels.h | 1 +
net/ipv6/sit.c | 152 +++++++++++++++++++++++----------------
2 files changed, 92 insertions(+), 61 deletions(-)
diff --git a/include/net/ip_tunnels.h b/include/net/ip_tunnels.h
index 7fff59bab53b682ac0d1efd1f47082ba7d633fd2..f464c4480edaf35f9ace1c5081c564ce51fed636 100644
--- a/include/net/ip_tunnels.h
+++ b/include/net/ip_tunnels.h
@@ -190,6 +190,7 @@ struct ip_tunnel {
#endif
struct ip_tunnel_prl_entry __rcu *prl; /* potential router list */
unsigned int prl_count; /* # of entries in PRL */
+ struct ip_tunnel_parm_kern *sit_parms;
unsigned int ip_tnl_net_id;
struct gro_cells gro_cells;
__u32 fwmark;
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c
index 35c6695909014a2c335f1de7afb48f07b7c91c39..dc37c7109af5324f2ced0301b289e7622dd1a55f 100644
--- a/net/ipv6/sit.c
+++ b/net/ipv6/sit.c
@@ -108,24 +108,24 @@ static struct ip_tunnel *ipip6_tunnel_lookup(struct net *net,
int ifindex = dev ? dev->ifindex : 0;
for_each_ip_tunnel_rcu(t, sitn->tunnels_r_l[h0 ^ h1]) {
- if (local == t->parms.iph.saddr &&
- remote == t->parms.iph.daddr &&
- (!dev || !t->parms.link || ifindex == t->parms.link ||
- sifindex == t->parms.link) &&
+ if (local == t->sit_parms->iph.saddr &&
+ remote == t->sit_parms->iph.daddr &&
+ (!dev || !t->sit_parms->link || ifindex == t->sit_parms->link ||
+ sifindex == t->sit_parms->link) &&
(t->dev->flags & IFF_UP))
return t;
}
for_each_ip_tunnel_rcu(t, sitn->tunnels_r[h0]) {
- if (remote == t->parms.iph.daddr &&
- (!dev || !t->parms.link || ifindex == t->parms.link ||
- sifindex == t->parms.link) &&
+ if (remote == t->sit_parms->iph.daddr &&
+ (!dev || !t->sit_parms->link || ifindex == t->sit_parms->link ||
+ sifindex == t->sit_parms->link) &&
(t->dev->flags & IFF_UP))
return t;
}
for_each_ip_tunnel_rcu(t, sitn->tunnels_l[h1]) {
- if (local == t->parms.iph.saddr &&
- (!dev || !t->parms.link || ifindex == t->parms.link ||
- sifindex == t->parms.link) &&
+ if (local == t->sit_parms->iph.saddr &&
+ (!dev || !t->sit_parms->link || ifindex == t->sit_parms->link ||
+ sifindex == t->sit_parms->link) &&
(t->dev->flags & IFF_UP))
return t;
}
@@ -157,7 +157,7 @@ __ipip6_bucket(struct sit_net *sitn, struct ip_tunnel_parm_kern *parms)
static inline struct ip_tunnel __rcu **ipip6_bucket(struct sit_net *sitn,
struct ip_tunnel *t)
{
- return __ipip6_bucket(sitn, &t->parms);
+ return __ipip6_bucket(sitn, t->sit_parms);
}
static void ipip6_tunnel_unlink(struct sit_net *sitn, struct ip_tunnel *t)
@@ -236,10 +236,11 @@ static int ipip6_tunnel_create(struct net_device *dev)
if (err < 0)
goto out;
- __dev_addr_set(dev, &t->parms.iph.saddr, 4);
- memcpy(dev->broadcast, &t->parms.iph.daddr, 4);
+ t->parms = *t->sit_parms;
+ __dev_addr_set(dev, &t->sit_parms->iph.saddr, 4);
+ memcpy(dev->broadcast, &t->sit_parms->iph.daddr, 4);
- if (test_bit(IP_TUNNEL_SIT_ISATAP_BIT, t->parms.i_flags))
+ if (test_bit(IP_TUNNEL_SIT_ISATAP_BIT, t->sit_parms->i_flags))
dev->priv_flags |= IFF_ISATAP;
dev->rtnl_link_ops = &sit_link_ops;
@@ -270,9 +271,9 @@ static struct ip_tunnel *ipip6_tunnel_locate(struct net *net,
for (tp = __ipip6_bucket(sitn, parms);
(t = rtnl_dereference(*tp)) != NULL;
tp = &t->next) {
- if (local == t->parms.iph.saddr &&
- remote == t->parms.iph.daddr &&
- parms->link == t->parms.link) {
+ if (local == t->sit_parms->iph.saddr &&
+ remote == t->sit_parms->iph.daddr &&
+ parms->link == t->sit_parms->link) {
if (create)
return NULL;
else
@@ -299,7 +300,10 @@ static struct ip_tunnel *ipip6_tunnel_locate(struct net *net,
nt = netdev_priv(dev);
nt->net = net;
- nt->parms = *parms;
+ nt->sit_parms = kmalloc_obj(*nt->sit_parms);
+ if (!nt->sit_parms)
+ goto failed_free;
+ *nt->sit_parms = *parms;
if (ipip6_tunnel_create(dev) < 0)
goto failed_free;
@@ -602,12 +606,12 @@ static int ipip6_err(struct sk_buff *skb, u32 info)
if (type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED) {
ipv4_update_pmtu(skb, dev_net(skb->dev), info,
- t->parms.link, iph->protocol);
+ t->sit_parms->link, iph->protocol);
err = 0;
goto out;
}
if (type == ICMP_REDIRECT) {
- ipv4_redirect(skb, dev_net(skb->dev), t->parms.link,
+ ipv4_redirect(skb, dev_net(skb->dev), t->sit_parms->link,
iph->protocol);
err = 0;
goto out;
@@ -618,10 +622,10 @@ static int ipip6_err(struct sk_buff *skb, u32 info)
!ip6_err_gen_icmpv6_unreach(skb, iph->ihl * 4, type, data_len))
goto out;
- if (t->parms.iph.daddr == 0)
+ if (t->sit_parms->iph.daddr == 0)
goto out;
- if (t->parms.iph.ttl == 0 && type == ICMP_TIME_EXCEEDED)
+ if (t->sit_parms->iph.ttl == 0 && type == ICMP_TIME_EXCEEDED)
goto out;
if (time_before(jiffies, READ_ONCE(t->err_time) + IPTUNNEL_ERR_TIMEO))
@@ -722,8 +726,8 @@ static int ipip6_rcv(struct sk_buff *skb)
tunnel = ipip6_tunnel_lookup(dev_net(skb->dev), skb->dev,
iph->saddr, iph->daddr, sifindex);
if (tunnel) {
- if (tunnel->parms.iph.protocol != IPPROTO_IPV6 &&
- tunnel->parms.iph.protocol != 0)
+ if (tunnel->sit_parms->iph.protocol != IPPROTO_IPV6 &&
+ tunnel->sit_parms->iph.protocol != 0)
goto out;
skb->mac_header = skb->network_header;
@@ -798,8 +802,8 @@ static int sit_tunnel_rcv(struct sk_buff *skb, u8 ipproto)
if (tunnel) {
const struct tnl_ptk_info *tpi;
- if (tunnel->parms.iph.protocol != ipproto &&
- tunnel->parms.iph.protocol != 0)
+ if (tunnel->sit_parms->iph.protocol != ipproto &&
+ tunnel->sit_parms->iph.protocol != 0)
goto drop;
if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb))
@@ -938,9 +942,9 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb,
struct net_device *dev)
{
struct ip_tunnel *tunnel = netdev_priv(dev);
- const struct iphdr *tiph = &tunnel->parms.iph;
+ const struct iphdr *tiph = &tunnel->sit_parms->iph;
const struct ipv6hdr *iph6 = ipv6_hdr(skb);
- u8 tos = tunnel->parms.iph.tos;
+ u8 tos = tunnel->sit_parms->iph.tos;
__be16 df = tiph->frag_off;
struct rtable *rt; /* Route to the other host */
struct net_device *tdev; /* Device to other host */
@@ -966,7 +970,7 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb,
if (!dst && !ipip6_tunnel_dst_find(skb, &dst, false))
goto tx_error;
- flowi4_init_output(&fl4, tunnel->parms.link, READ_ONCE(tunnel->fwmark),
+ flowi4_init_output(&fl4, tunnel->sit_parms->link, READ_ONCE(tunnel->fwmark),
tos & INET_DSCP_MASK, RT_SCOPE_UNIVERSE,
IPPROTO_IPV6, 0, dst, tiph->saddr, 0, 0,
sock_net_uid(tunnel->net, NULL));
@@ -1014,7 +1018,7 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb,
df = 0;
}
- if (tunnel->parms.iph.daddr)
+ if (tunnel->sit_parms->iph.daddr)
skb_dst_update_pmtu_no_confirm(skb, mtu);
if (skb->len > mtu && !skb_is_gso(skb)) {
@@ -1083,7 +1087,7 @@ 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->parms.iph;
+ const struct iphdr *tiph = &tunnel->sit_parms->iph;
if (iptunnel_handle_offloads(skb, SKB_GSO_IPXIP4))
goto tx_error;
@@ -1138,7 +1142,7 @@ static void ipip6_tunnel_bind_dev(struct net_device *dev)
const struct iphdr *iph;
struct flowi4 fl4;
- iph = &tunnel->parms.iph;
+ iph = &tunnel->sit_parms->iph;
if (iph->daddr) {
struct rtable *rt = ip_route_output_ports(tunnel->net, &fl4,
@@ -1147,7 +1151,7 @@ static void ipip6_tunnel_bind_dev(struct net_device *dev)
0, 0,
IPPROTO_IPV6,
iph->tos & INET_DSCP_MASK,
- tunnel->parms.link);
+ tunnel->sit_parms->link);
if (!IS_ERR(rt)) {
tdev = rt->dst.dev;
@@ -1156,8 +1160,8 @@ static void ipip6_tunnel_bind_dev(struct net_device *dev)
dev->flags |= IFF_POINTOPOINT;
}
- if (!tdev && tunnel->parms.link)
- tdev = __dev_get_by_index(tunnel->net, tunnel->parms.link);
+ if (!tdev && tunnel->sit_parms->link)
+ tdev = __dev_get_by_index(tunnel->net, tunnel->sit_parms->link);
if (tdev && !netif_is_l3_master(tdev)) {
int mtu;
@@ -1171,30 +1175,41 @@ static void ipip6_tunnel_bind_dev(struct net_device *dev)
dev->needed_headroom = ip_tunnel_limit_headroom(t_hlen + hlen);
}
-static void ipip6_tunnel_update(struct ip_tunnel *t,
- struct ip_tunnel_parm_kern *p,
- __u32 fwmark)
+static int ipip6_tunnel_update(struct ip_tunnel *t,
+ struct ip_tunnel_parm_kern *p,
+ __u32 fwmark)
{
struct net *net = t->net;
struct sit_net *sitn = net_generic(net, sit_net_id);
+ struct ip_tunnel_parm_kern *new_p, *old_p;
+ old_p = t->sit_parms;
+ new_p = kmalloc_obj(*new_p);
+ if (!new_p)
+ return -ENOMEM;
+ *new_p = *old_p;
+ new_p->iph.saddr = p->iph.saddr;
+ new_p->iph.daddr = p->iph.daddr;
+ new_p->iph.ttl = p->iph.ttl;
+ 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->parms.iph.saddr = p->iph.saddr;
- t->parms.iph.daddr = p->iph.daddr;
+ t->sit_parms = new_p;
+ 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);
- t->parms.iph.ttl = p->iph.ttl;
- t->parms.iph.tos = p->iph.tos;
- t->parms.iph.frag_off = p->iph.frag_off;
- if (t->parms.link != p->link || t->fwmark != fwmark) {
- t->parms.link = p->link;
+ 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);
+ return 0;
}
#ifdef CONFIG_IPV6_SIT_6RD
@@ -1326,7 +1341,7 @@ ipip6_tunnel_get(struct net_device *dev, struct ip_tunnel_parm_kern *p)
t = ipip6_tunnel_locate(t->net, p, 0);
if (!t)
t = netdev_priv(dev);
- memcpy(p, &t->parms, sizeof(*p));
+ memcpy(p, t->sit_parms, sizeof(*p));
return 0;
}
@@ -1371,7 +1386,9 @@ ipip6_tunnel_change(struct net_device *dev, struct ip_tunnel_parm_kern *p)
t = netdev_priv(dev);
}
- ipip6_tunnel_update(t, p, t->fwmark);
+ err = ipip6_tunnel_update(t, p, t->fwmark);
+ if (err)
+ return err;
}
return 0;
@@ -1448,7 +1465,7 @@ static int ipip6_get_iflink(const struct net_device *dev)
{
struct ip_tunnel *tunnel = netdev_priv(dev);
- return READ_ONCE(tunnel->parms.link);
+ return READ_ONCE(tunnel->sit_parms->link);
}
static const struct net_device_ops ipip6_netdev_ops = {
@@ -1470,6 +1487,8 @@ static void ipip6_dev_free(struct net_device *dev)
RCU_INIT_POINTER(tunnel->ip6rd, NULL);
kfree(ip6rd);
#endif
+ kfree(tunnel->sit_parms);
+ tunnel->sit_parms = NULL;
if (tunnel->dst_cache.cache) {
dst_cache_destroy(&tunnel->dst_cache);
tunnel->dst_cache.cache = NULL;
@@ -1512,7 +1531,7 @@ static int ipip6_tunnel_init(struct net_device *dev)
int err;
tunnel->dev = dev;
- strscpy(tunnel->parms.name, dev->name);
+ strscpy(tunnel->sit_parms->name, dev->name);
ipip6_tunnel_bind_dev(dev);
@@ -1528,15 +1547,9 @@ static int ipip6_tunnel_init(struct net_device *dev)
static void __net_init ipip6_fb_tunnel_init(struct net_device *dev)
{
struct ip_tunnel *tunnel = netdev_priv(dev);
- struct iphdr *iph = &tunnel->parms.iph;
struct net *net = dev_net(dev);
struct sit_net *sitn = net_generic(net, sit_net_id);
- iph->version = 4;
- iph->protocol = IPPROTO_IPV6;
- iph->ihl = 5;
- iph->ttl = 64;
-
rcu_assign_pointer(sitn->tunnels_wc[0], tunnel);
}
@@ -1623,6 +1636,7 @@ static int ipip6_newlink(struct net_device *dev,
#ifdef CONFIG_IPV6_SIT_6RD
struct ip_tunnel_6rd ip6rd;
#endif
+ struct ip_tunnel_parm_kern p;
struct net *net;
int err;
@@ -1636,11 +1650,16 @@ static int ipip6_newlink(struct net_device *dev,
return err;
}
- ipip6_netlink_parms(data, &nt->parms, &nt->fwmark);
+ ipip6_netlink_parms(data, &p, &nt->fwmark);
- if (ipip6_tunnel_locate(net, &nt->parms, 0))
+ if (ipip6_tunnel_locate(net, &p, 0))
return -EEXIST;
+ nt->sit_parms = kmalloc_obj(*nt->sit_parms);
+ if (!nt->sit_parms)
+ return -ENOMEM;
+ *nt->sit_parms = p;
+
err = ipip6_tunnel_create(dev);
if (err < 0) {
ipip6_dev_free(dev);
@@ -1707,7 +1726,9 @@ static int ipip6_changelink(struct net_device *dev, struct nlattr *tb[],
} else
t = netdev_priv(dev);
- ipip6_tunnel_update(t, &p, fwmark);
+ err = ipip6_tunnel_update(t, &p, fwmark);
+ if (err)
+ return err;
#ifdef CONFIG_IPV6_SIT_6RD
if (ipip6_netlink_6rd_parms(data, &ip6rd))
@@ -1762,7 +1783,7 @@ static size_t ipip6_get_size(const struct net_device *dev)
static int ipip6_fill_info(struct sk_buff *skb, const struct net_device *dev)
{
struct ip_tunnel *tunnel = netdev_priv(dev);
- struct ip_tunnel_parm_kern *parm = &tunnel->parms;
+ struct ip_tunnel_parm_kern *parm = tunnel->sit_parms;
#ifdef CONFIG_IPV6_SIT_6RD
const struct ip_tunnel_6rd_parm *ip6rd;
#endif
@@ -1935,6 +1956,17 @@ static int __net_init sit_init_net(struct net *net)
t = netdev_priv(sitn->fb_tunnel_dev);
t->net = net;
+ t->sit_parms = kzalloc_obj(*t->sit_parms);
+ if (!t->sit_parms) {
+ err = -ENOMEM;
+ goto err_reg_dev;
+ }
+ t->sit_parms->iph.version = 4;
+ t->sit_parms->iph.protocol = IPPROTO_IPV6;
+ t->sit_parms->iph.ihl = 5;
+ t->sit_parms->iph.ttl = 64;
+ strscpy(t->sit_parms->name, sitn->fb_tunnel_dev->name);
+ t->parms = *t->sit_parms;
err = ipip6_tunnel_clone_6rd(sitn->fb_tunnel_dev, sitn);
if (err < 0)
@@ -1945,8 +1977,6 @@ static int __net_init sit_init_net(struct net *net)
goto err_reg_dev;
ipip6_fb_tunnel_init(sitn->fb_tunnel_dev);
-
- strscpy(t->parms.name, sitn->fb_tunnel_dev->name);
return 0;
err_reg_dev:
--
2.55.0.979.g7e5102b832-goog
next prev parent reply other threads:[~2026-09-07 7:59 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 ` Eric Dumazet [this message]
2026-09-07 13:16 ` [PATCH net-next 7/9] sit: dynamically allocate struct ip_tunnel_parm_kern 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
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=20260907075846.2913645-8-edumazet@google.com \
--to=edumazet@google.com \
--cc=andrew+netdev@lunn.ch \
--cc=davem@davemloft.net \
--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.