[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20250711191007.3591938-5-kuniyu@google.com>
Date: Fri, 11 Jul 2025 19:06:09 +0000
From: Kuniyuki Iwashima <kuniyu@...gle.com>
To: "David S. Miller" <davem@...emloft.net>, Eric Dumazet <edumazet@...gle.com>,
Jakub Kicinski <kuba@...nel.org>, Paolo Abeni <pabeni@...hat.com>, David Ahern <dsahern@...nel.org>
Cc: Simon Horman <horms@...nel.org>, Kuniyuki Iwashima <kuniyu@...gle.com>,
Kuniyuki Iwashima <kuni1840@...il.com>, netdev@...r.kernel.org
Subject: [PATCH v1 net-next 04/14] neighbour: Move neigh_find_table() to neigh_get().
neigh_valid_get_req() calls neigh_find_table() to fetch neigh_tables[].
neigh_find_table() uses rcu_dereference_rtnl(), but RTNL actually does
not protect it at all; neigh_table_clear() can be called without RTNL
and only waits for RCU readers by synchronize_rcu().
Fortunately, there is no bug because IPv4 is built-in, IPv6 cannot be
unloaded, and DECNET was removed.
To fetch neigh_tables[] by rcu_dereference() later, let's move
neigh_find_table() from neigh_valid_get_req() to neigh_get().
Signed-off-by: Kuniyuki Iwashima <kuniyu@...gle.com>
---
net/core/neighbour.c | 39 ++++++++++++++++++++-------------------
1 file changed, 20 insertions(+), 19 deletions(-)
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index df5938b6020f1..ad79f173e6229 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -2911,10 +2911,9 @@ static int neigh_dump_info(struct sk_buff *skb, struct netlink_callback *cb)
}
static struct ndmsg *neigh_valid_get_req(const struct nlmsghdr *nlh,
- struct neigh_table **tbl, void **dst,
+ struct nlattr **tb,
struct netlink_ext_ack *extack)
{
- struct nlattr *tb[NDA_MAX + 1];
struct ndmsg *ndm;
int err, i;
@@ -2949,13 +2948,6 @@ static struct ndmsg *neigh_valid_get_req(const struct nlmsghdr *nlh,
if (err < 0)
goto err;
- *tbl = neigh_find_table(ndm->ndm_family);
- if (!*tbl) {
- NL_SET_ERR_MSG(extack, "Unsupported family in header for neighbor get request");
- err = -EAFNOSUPPORT;
- goto err;
- }
-
for (i = 0; i <= NDA_MAX; ++i) {
switch (i) {
case NDA_DST:
@@ -2964,13 +2956,6 @@ static struct ndmsg *neigh_valid_get_req(const struct nlmsghdr *nlh,
err = -EINVAL;
goto err;
}
-
- if (nla_len(tb[i]) != (int)(*tbl)->key_len) {
- NL_SET_ERR_MSG(extack, "Invalid network address in neighbor get request");
- err = -EINVAL;
- goto err;
- }
- *dst = nla_data(tb[i]);
break;
default:
if (!tb[i])
@@ -3011,16 +2996,17 @@ static int neigh_get(struct sk_buff *in_skb, struct nlmsghdr *nlh,
{
struct net *net = sock_net(in_skb->sk);
u32 pid = NETLINK_CB(in_skb).portid;
+ struct nlattr *tb[NDA_MAX + 1];
struct net_device *dev = NULL;
- struct neigh_table *tbl = NULL;
u32 seq = nlh->nlmsg_seq;
+ struct neigh_table *tbl;
struct neighbour *neigh;
struct sk_buff *skb;
struct ndmsg *ndm;
- void *dst = NULL;
+ void *dst;
int err;
- ndm = neigh_valid_get_req(nlh, &tbl, &dst, extack);
+ ndm = neigh_valid_get_req(nlh, tb, extack);
if (IS_ERR(ndm))
return PTR_ERR(ndm);
@@ -3031,6 +3017,21 @@ static int neigh_get(struct sk_buff *in_skb, struct nlmsghdr *nlh,
if (!skb)
return -ENOBUFS;
+ tbl = neigh_find_table(ndm->ndm_family);
+ if (!tbl) {
+ NL_SET_ERR_MSG(extack, "Unsupported family in header for neighbor get request");
+ err = -EAFNOSUPPORT;
+ goto err;
+ }
+
+ if (nla_len(tb[NDA_DST]) != (int)tbl->key_len) {
+ NL_SET_ERR_MSG(extack, "Invalid network address in neighbor get request");
+ err = -EINVAL;
+ goto err;
+ }
+
+ dst = nla_data(tb[NDA_DST]);
+
if (ndm->ndm_ifindex) {
dev = __dev_get_by_index(net, ndm->ndm_ifindex);
if (!dev) {
--
2.50.0.727.gbf7dc18ff4-goog
Powered by blists - more mailing lists