* [PATCH net] ipv4: use RCU protection in inet_netconf_get_devconf()
@ 2026-10-09 7:49 Eric Dumazet
2026-10-09 7:54 ` netdev-bot+sinfo
0 siblings, 1 reply; 5+ messages in thread
From: Eric Dumazet @ 2026-10-09 7:49 UTC (permalink / raw)
To: David S . Miller, Jakub Kicinski, Paolo Abeni
Cc: Simon Horman, David Ahern, Ido Schimmel, Kuniyuki Iwashima,
netdev, Eric Dumazet, Baul Lee
inet_netconf_get_devconf() runs without RTNL. It uses dev_get_by_index()
and in_dev_get() to pin the device and its in_device while the reply is
allocated and filled.
in_dev_get() is not safe for a lockless caller. Since commit 9d40c84cf5bc
("net: devinet: Reduce refcount before grace period"), inetdev_destroy()
drops the final reference before the RCU grace period. A reader can load
dev->ip_ptr, then call refcount_inc() on a zero refcount after
in_dev_free_rcu() has been queued, and keep using the in_device once it
has been freed.
None of these references are needed. An in_device is freed after an RCU
grace period, ipv4_devconf is embedded in it, and
inet_netconf_fill_devconf() does not sleep.
Allocate the skb first, then perform the lookup and the fill under
rcu_read_lock(), using dev_get_by_index_rcu() and __in_dev_get_rcu(),
like inet_netconf_dump_devconf() already does.
Fixes: bbcf91053bb6 ("inet: do not use RTNL in inet_netconf_get_devconf()")
Reported-by: Baul Lee <baul.lee@xbow.com>
Closes: https://lore.kernel.org/netdev/20260815172032.79740-1-baul.lee@xbow.com/
Signed-off-by: Eric Dumazet <edumazet@kernel.org>
---
Sorry for a resend, I did a mistake, using edumazet@google.com instead of
edumazet@kernel.org, not enough sleep I guess.
net/ipv4/devinet.c | 35 +++++++++++++++++------------------
1 file changed, 17 insertions(+), 18 deletions(-)
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index 5b6b11c943e453742b4893f1c9bd9e70d3d37a6f..f9a361621f74b420276006b13de94926e13af18e 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -2379,8 +2379,8 @@ static int inet_netconf_get_devconf(struct sk_buff *in_skb,
struct net *net = sock_net(in_skb->sk);
struct nlattr *tb[NETCONFA_MAX + 1];
const struct ipv4_devconf *devconf;
- struct in_device *in_dev = NULL;
- struct net_device *dev = NULL;
+ struct in_device *in_dev;
+ struct net_device *dev;
struct sk_buff *skb;
int ifindex;
int err;
@@ -2392,7 +2392,13 @@ static int inet_netconf_get_devconf(struct sk_buff *in_skb,
if (!tb[NETCONFA_IFINDEX])
return -EINVAL;
+ skb = nlmsg_new(inet_netconf_msgsize_devconf(NETCONFA_ALL), GFP_KERNEL);
+ if (!skb)
+ return -ENOBUFS;
+
ifindex = nla_get_s32(tb[NETCONFA_IFINDEX]);
+
+ rcu_read_lock();
switch (ifindex) {
case NETCONFA_IFINDEX_ALL:
devconf = net->ipv4.devconf_all;
@@ -2402,36 +2408,29 @@ static int inet_netconf_get_devconf(struct sk_buff *in_skb,
break;
default:
err = -ENODEV;
- dev = dev_get_by_index(net, ifindex);
- if (dev)
- in_dev = in_dev_get(dev);
+ dev = dev_get_by_index_rcu(net, ifindex);
+ if (!dev)
+ goto out_unlock;
+ in_dev = __in_dev_get_rcu(dev);
if (!in_dev)
- goto errout;
+ goto out_unlock;
devconf = &in_dev->cnf;
break;
}
- err = -ENOBUFS;
- skb = nlmsg_new(inet_netconf_msgsize_devconf(NETCONFA_ALL), GFP_KERNEL);
- if (!skb)
- goto errout;
-
err = inet_netconf_fill_devconf(skb, ifindex, devconf,
NETLINK_CB(in_skb).portid,
nlh->nlmsg_seq, RTM_NEWNETCONF, 0,
NETCONFA_ALL);
+out_unlock:
+ rcu_read_unlock();
if (err < 0) {
/* -EMSGSIZE implies BUG in inet_netconf_msgsize_devconf() */
WARN_ON(err == -EMSGSIZE);
kfree_skb(skb);
- goto errout;
+ return err;
}
- err = rtnl_unicast(skb, net, NETLINK_CB(in_skb).portid);
-errout:
- if (in_dev)
- in_dev_put(in_dev);
- dev_put(dev);
- return err;
+ return rtnl_unicast(skb, net, NETLINK_CB(in_skb).portid);
}
static int inet_netconf_dump_devconf(struct sk_buff *skb,
--
2.53.0
^ permalink raw reply related [flat|nested] 5+ messages in thread* Re: [PATCH net] ipv4: use RCU protection in inet_netconf_get_devconf()
2026-10-09 7:49 [PATCH net] ipv4: use RCU protection in inet_netconf_get_devconf() Eric Dumazet
@ 2026-10-09 7:54 ` netdev-bot+sinfo
0 siblings, 0 replies; 5+ messages in thread
From: netdev-bot+sinfo @ 2026-10-09 7:54 UTC (permalink / raw)
To: Eric Dumazet
Cc: David S . Miller, Jakub Kicinski, Paolo Abeni, Simon Horman,
David Ahern, Ido Schimmel, Kuniyuki Iwashima, netdev, Baul Lee
Hi!
This is an automated message. This series looks like a fix, but its
commit messages seem to be missing some information:
- Whether the issue was actually triggered, or is only theoretical
(e.g. found by code inspection). If it was triggered please include
the symptoms, like the stack trace or error messages.
Please do not repost the series just to address the above. Instead,
reply to this email with the missing information, so that reviewers
can take it into account. If the series needs another revision for
other reasons, please include the information in the commit messages
then.
The evaluation is done by an LLM so it may be wrong, if you think
that is the case please reply and explain.
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH net] ipv4: use RCU protection in inet_netconf_get_devconf()
@ 2026-10-09 7:44 Eric Dumazet
2026-10-09 7:50 ` netdev-bot+sinfo
2026-10-09 9:28 ` Cen Zhang
0 siblings, 2 replies; 5+ messages in thread
From: Eric Dumazet @ 2026-10-09 7:44 UTC (permalink / raw)
To: David S . Miller, Jakub Kicinski, Paolo Abeni
Cc: Simon Horman, David Ahern, Ido Schimmel, Kuniyuki Iwashima,
netdev, Eric Dumazet, Baul Lee, Cen Zhang
From: Eric Dumazet <edumazet@google.com>
inet_netconf_get_devconf() runs without RTNL. It uses dev_get_by_index()
and in_dev_get() to pin the device and its in_device while the reply is
allocated and filled.
in_dev_get() is not safe for a lockless caller. Since commit 9d40c84cf5bc
("net: devinet: Reduce refcount before grace period"), inetdev_destroy()
drops the final reference before the RCU grace period. A reader can load
dev->ip_ptr, then call refcount_inc() on a zero refcount after
in_dev_free_rcu() has been queued, and keep using the in_device once it
has been freed.
None of these references are needed. An in_device is freed after an RCU
grace period, ipv4_devconf is embedded in it, and
inet_netconf_fill_devconf() does not sleep.
Allocate the skb first, then perform the lookup and the fill under
rcu_read_lock(), using dev_get_by_index_rcu() and __in_dev_get_rcu(),
like inet_netconf_dump_devconf() already does.
Fixes: bbcf91053bb6 ("inet: do not use RTNL in inet_netconf_get_devconf()")
Reported-by: Baul Lee <baul.lee@xbow.com>
Closes: https://lore.kernel.org/netdev/20260815172032.79740-1-baul.lee@xbow.com/
Signed-off-by: Eric Dumazet <edumazet@google.com>
Cc: Cen Zhang <zzzccc427@gmail.com>
---
net/ipv4/devinet.c | 35 +++++++++++++++++------------------
1 file changed, 17 insertions(+), 18 deletions(-)
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index 5b6b11c943e453742b4893f1c9bd9e70d3d37a6f..f9a361621f74b420276006b13de94926e13af18e 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -2379,8 +2379,8 @@ static int inet_netconf_get_devconf(struct sk_buff *in_skb,
struct net *net = sock_net(in_skb->sk);
struct nlattr *tb[NETCONFA_MAX + 1];
const struct ipv4_devconf *devconf;
- struct in_device *in_dev = NULL;
- struct net_device *dev = NULL;
+ struct in_device *in_dev;
+ struct net_device *dev;
struct sk_buff *skb;
int ifindex;
int err;
@@ -2392,7 +2392,13 @@ static int inet_netconf_get_devconf(struct sk_buff *in_skb,
if (!tb[NETCONFA_IFINDEX])
return -EINVAL;
+ skb = nlmsg_new(inet_netconf_msgsize_devconf(NETCONFA_ALL), GFP_KERNEL);
+ if (!skb)
+ return -ENOBUFS;
+
ifindex = nla_get_s32(tb[NETCONFA_IFINDEX]);
+
+ rcu_read_lock();
switch (ifindex) {
case NETCONFA_IFINDEX_ALL:
devconf = net->ipv4.devconf_all;
@@ -2402,36 +2408,29 @@ static int inet_netconf_get_devconf(struct sk_buff *in_skb,
break;
default:
err = -ENODEV;
- dev = dev_get_by_index(net, ifindex);
- if (dev)
- in_dev = in_dev_get(dev);
+ dev = dev_get_by_index_rcu(net, ifindex);
+ if (!dev)
+ goto out_unlock;
+ in_dev = __in_dev_get_rcu(dev);
if (!in_dev)
- goto errout;
+ goto out_unlock;
devconf = &in_dev->cnf;
break;
}
- err = -ENOBUFS;
- skb = nlmsg_new(inet_netconf_msgsize_devconf(NETCONFA_ALL), GFP_KERNEL);
- if (!skb)
- goto errout;
-
err = inet_netconf_fill_devconf(skb, ifindex, devconf,
NETLINK_CB(in_skb).portid,
nlh->nlmsg_seq, RTM_NEWNETCONF, 0,
NETCONFA_ALL);
+out_unlock:
+ rcu_read_unlock();
if (err < 0) {
/* -EMSGSIZE implies BUG in inet_netconf_msgsize_devconf() */
WARN_ON(err == -EMSGSIZE);
kfree_skb(skb);
- goto errout;
+ return err;
}
- err = rtnl_unicast(skb, net, NETLINK_CB(in_skb).portid);
-errout:
- if (in_dev)
- in_dev_put(in_dev);
- dev_put(dev);
- return err;
+ return rtnl_unicast(skb, net, NETLINK_CB(in_skb).portid);
}
static int inet_netconf_dump_devconf(struct sk_buff *skb,
--
2.53.0
^ permalink raw reply related [flat|nested] 5+ messages in thread* Re: [PATCH net] ipv4: use RCU protection in inet_netconf_get_devconf()
2026-10-09 7:44 Eric Dumazet
@ 2026-10-09 7:50 ` netdev-bot+sinfo
2026-10-09 9:28 ` Cen Zhang
1 sibling, 0 replies; 5+ messages in thread
From: netdev-bot+sinfo @ 2026-10-09 7:50 UTC (permalink / raw)
To: Eric Dumazet
Cc: David S . Miller, Jakub Kicinski, Paolo Abeni, Simon Horman,
David Ahern, Ido Schimmel, Kuniyuki Iwashima, netdev,
Eric Dumazet, Baul Lee, Cen Zhang
Hi!
This is an automated message. This series looks like a fix, but its
commit messages seem to be missing some information:
- How the issue was discovered, e.g. hit in production, hit during
development, syzbot report, manual code inspection, LLM or static
analysis tool scan.
- Whether the issue was actually triggered, or is only theoretical
(e.g. found by code inspection). If it was triggered please include
the symptoms, like the stack trace or error messages.
Please do not repost the series just to address the above. Instead,
reply to this email with the missing information, so that reviewers
can take it into account. If the series needs another revision for
other reasons, please include the information in the commit messages
then.
The evaluation is done by an LLM so it may be wrong, if you think
that is the case please reply and explain.
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH net] ipv4: use RCU protection in inet_netconf_get_devconf()
2026-10-09 7:44 Eric Dumazet
2026-10-09 7:50 ` netdev-bot+sinfo
@ 2026-10-09 9:28 ` Cen Zhang
1 sibling, 0 replies; 5+ messages in thread
From: Cen Zhang @ 2026-10-09 9:28 UTC (permalink / raw)
To: Eric Dumazet
Cc: David S . Miller, Jakub Kicinski, Paolo Abeni, Simon Horman,
David Ahern, Ido Schimmel, Kuniyuki Iwashima, netdev,
Eric Dumazet, Baul Lee
Eric Dumazet <edumazet@kernel.org> 于2026年10月9日周五 15:44写道:
>
> From: Eric Dumazet <edumazet@google.com>
>
> inet_netconf_get_devconf() runs without RTNL. It uses dev_get_by_index()
> and in_dev_get() to pin the device and its in_device while the reply is
> allocated and filled.
>
> in_dev_get() is not safe for a lockless caller. Since commit 9d40c84cf5bc
> ("net: devinet: Reduce refcount before grace period"), inetdev_destroy()
> drops the final reference before the RCU grace period. A reader can load
> dev->ip_ptr, then call refcount_inc() on a zero refcount after
> in_dev_free_rcu() has been queued, and keep using the in_device once it
> has been freed.
>
> None of these references are needed. An in_device is freed after an RCU
> grace period, ipv4_devconf is embedded in it, and
> inet_netconf_fill_devconf() does not sleep.
>
> Allocate the skb first, then perform the lookup and the fill under
> rcu_read_lock(), using dev_get_by_index_rcu() and __in_dev_get_rcu(),
> like inet_netconf_dump_devconf() already does.
>
> Fixes: bbcf91053bb6 ("inet: do not use RTNL in inet_netconf_get_devconf()")
> Reported-by: Baul Lee <baul.lee@xbow.com>
> Closes: https://lore.kernel.org/netdev/20260815172032.79740-1-baul.lee@xbow.com/
> Signed-off-by: Eric Dumazet <edumazet@google.com>
> Cc: Cen Zhang <zzzccc427@gmail.com>
> ---
> net/ipv4/devinet.c | 35 +++++++++++++++++------------------
> 1 file changed, 17 insertions(+), 18 deletions(-)
>
> diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
> index 5b6b11c943e453742b4893f1c9bd9e70d3d37a6f..f9a361621f74b420276006b13de94926e13af18e 100644
> --- a/net/ipv4/devinet.c
> +++ b/net/ipv4/devinet.c
> @@ -2379,8 +2379,8 @@ static int inet_netconf_get_devconf(struct sk_buff *in_skb,
> struct net *net = sock_net(in_skb->sk);
> struct nlattr *tb[NETCONFA_MAX + 1];
> const struct ipv4_devconf *devconf;
> - struct in_device *in_dev = NULL;
> - struct net_device *dev = NULL;
> + struct in_device *in_dev;
> + struct net_device *dev;
> struct sk_buff *skb;
> int ifindex;
> int err;
> @@ -2392,7 +2392,13 @@ static int inet_netconf_get_devconf(struct sk_buff *in_skb,
> if (!tb[NETCONFA_IFINDEX])
> return -EINVAL;
>
> + skb = nlmsg_new(inet_netconf_msgsize_devconf(NETCONFA_ALL), GFP_KERNEL);
> + if (!skb)
> + return -ENOBUFS;
> +
> ifindex = nla_get_s32(tb[NETCONFA_IFINDEX]);
> +
> + rcu_read_lock();
> switch (ifindex) {
> case NETCONFA_IFINDEX_ALL:
> devconf = net->ipv4.devconf_all;
> @@ -2402,36 +2408,29 @@ static int inet_netconf_get_devconf(struct sk_buff *in_skb,
> break;
> default:
> err = -ENODEV;
> - dev = dev_get_by_index(net, ifindex);
> - if (dev)
> - in_dev = in_dev_get(dev);
> + dev = dev_get_by_index_rcu(net, ifindex);
> + if (!dev)
> + goto out_unlock;
> + in_dev = __in_dev_get_rcu(dev);
> if (!in_dev)
> - goto errout;
> + goto out_unlock;
> devconf = &in_dev->cnf;
> break;
> }
>
> - err = -ENOBUFS;
> - skb = nlmsg_new(inet_netconf_msgsize_devconf(NETCONFA_ALL), GFP_KERNEL);
> - if (!skb)
> - goto errout;
> -
> err = inet_netconf_fill_devconf(skb, ifindex, devconf,
> NETLINK_CB(in_skb).portid,
> nlh->nlmsg_seq, RTM_NEWNETCONF, 0,
> NETCONFA_ALL);
> +out_unlock:
> + rcu_read_unlock();
> if (err < 0) {
> /* -EMSGSIZE implies BUG in inet_netconf_msgsize_devconf() */
> WARN_ON(err == -EMSGSIZE);
> kfree_skb(skb);
> - goto errout;
> + return err;
> }
> - err = rtnl_unicast(skb, net, NETLINK_CB(in_skb).portid);
> -errout:
> - if (in_dev)
> - in_dev_put(in_dev);
> - dev_put(dev);
> - return err;
> + return rtnl_unicast(skb, net, NETLINK_CB(in_skb).portid);
> }
>
> static int inet_netconf_dump_devconf(struct sk_buff *skb,
> --
> 2.53.0
>
Tested-by: Cen Zhang <zzzccc427@gmail.com>
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-10-09 9:28 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-09 7:49 [PATCH net] ipv4: use RCU protection in inet_netconf_get_devconf() Eric Dumazet
2026-10-09 7:54 ` netdev-bot+sinfo
-- strict thread matches above, loose matches on Subject: below --
2026-10-09 7:44 Eric Dumazet
2026-10-09 7:50 ` netdev-bot+sinfo
2026-10-09 9:28 ` Cen Zhang
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox