mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-09-04 20:19:47 +08:00
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@google.com> Link: https://patch.msgid.link/20250716221221.442239-5-kuniyu@google.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
parent
3dfe0b57dc
commit
0e5ac19c78
@ -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;
|
||||
|
||||
@ -2945,12 +2944,6 @@ static struct ndmsg *neigh_valid_get_req(const struct nlmsghdr *nlh,
|
||||
if (err < 0)
|
||||
return ERR_PTR(err);
|
||||
|
||||
*tbl = neigh_find_table(ndm->ndm_family);
|
||||
if (!*tbl) {
|
||||
NL_SET_ERR_MSG(extack, "Unsupported family in header for neighbor get request");
|
||||
return ERR_PTR(-EAFNOSUPPORT);
|
||||
}
|
||||
|
||||
for (i = 0; i <= NDA_MAX; ++i) {
|
||||
switch (i) {
|
||||
case NDA_DST:
|
||||
@ -2958,12 +2951,6 @@ static struct ndmsg *neigh_valid_get_req(const struct nlmsghdr *nlh,
|
||||
NL_SET_ERR_ATTR_MISS(extack, NULL, NDA_DST);
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
if (nla_len(tb[i]) != (int)(*tbl)->key_len) {
|
||||
NL_SET_ERR_MSG(extack, "Invalid network address in neighbor get request");
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
*dst = nla_data(tb[i]);
|
||||
break;
|
||||
default:
|
||||
if (!tb[i])
|
||||
@ -3001,16 +2988,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);
|
||||
|
||||
@ -3021,6 +3009,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_free_skb;
|
||||
}
|
||||
|
||||
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_free_skb;
|
||||
}
|
||||
|
||||
dst = nla_data(tb[NDA_DST]);
|
||||
|
||||
if (ndm->ndm_ifindex) {
|
||||
dev = __dev_get_by_index(net, ndm->ndm_ifindex);
|
||||
if (!dev) {
|
||||
|
Loading…
Reference in New Issue
Block a user