Skip to content

Commit 0e5ac19

Browse files
q2venkuba-moo
authored andcommitted
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 <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
1 parent 3dfe0b5 commit 0e5ac19

File tree

1 file changed

+20
-17
lines changed

1 file changed

+20
-17
lines changed

net/core/neighbour.c

Lines changed: 20 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2911,10 +2911,9 @@ static int neigh_dump_info(struct sk_buff *skb, struct netlink_callback *cb)
29112911
}
29122912

29132913
static struct ndmsg *neigh_valid_get_req(const struct nlmsghdr *nlh,
2914-
struct neigh_table **tbl, void **dst,
2914+
struct nlattr **tb,
29152915
struct netlink_ext_ack *extack)
29162916
{
2917-
struct nlattr *tb[NDA_MAX + 1];
29182917
struct ndmsg *ndm;
29192918
int err, i;
29202919

@@ -2945,25 +2944,13 @@ static struct ndmsg *neigh_valid_get_req(const struct nlmsghdr *nlh,
29452944
if (err < 0)
29462945
return ERR_PTR(err);
29472946

2948-
*tbl = neigh_find_table(ndm->ndm_family);
2949-
if (!*tbl) {
2950-
NL_SET_ERR_MSG(extack, "Unsupported family in header for neighbor get request");
2951-
return ERR_PTR(-EAFNOSUPPORT);
2952-
}
2953-
29542947
for (i = 0; i <= NDA_MAX; ++i) {
29552948
switch (i) {
29562949
case NDA_DST:
29572950
if (!tb[i]) {
29582951
NL_SET_ERR_ATTR_MISS(extack, NULL, NDA_DST);
29592952
return ERR_PTR(-EINVAL);
29602953
}
2961-
2962-
if (nla_len(tb[i]) != (int)(*tbl)->key_len) {
2963-
NL_SET_ERR_MSG(extack, "Invalid network address in neighbor get request");
2964-
return ERR_PTR(-EINVAL);
2965-
}
2966-
*dst = nla_data(tb[i]);
29672954
break;
29682955
default:
29692956
if (!tb[i])
@@ -3001,16 +2988,17 @@ static int neigh_get(struct sk_buff *in_skb, struct nlmsghdr *nlh,
30012988
{
30022989
struct net *net = sock_net(in_skb->sk);
30032990
u32 pid = NETLINK_CB(in_skb).portid;
2991+
struct nlattr *tb[NDA_MAX + 1];
30042992
struct net_device *dev = NULL;
3005-
struct neigh_table *tbl = NULL;
30062993
u32 seq = nlh->nlmsg_seq;
2994+
struct neigh_table *tbl;
30072995
struct neighbour *neigh;
30082996
struct sk_buff *skb;
30092997
struct ndmsg *ndm;
3010-
void *dst = NULL;
2998+
void *dst;
30112999
int err;
30123000

3013-
ndm = neigh_valid_get_req(nlh, &tbl, &dst, extack);
3001+
ndm = neigh_valid_get_req(nlh, tb, extack);
30143002
if (IS_ERR(ndm))
30153003
return PTR_ERR(ndm);
30163004

@@ -3021,6 +3009,21 @@ static int neigh_get(struct sk_buff *in_skb, struct nlmsghdr *nlh,
30213009
if (!skb)
30223010
return -ENOBUFS;
30233011

3012+
tbl = neigh_find_table(ndm->ndm_family);
3013+
if (!tbl) {
3014+
NL_SET_ERR_MSG(extack, "Unsupported family in header for neighbor get request");
3015+
err = -EAFNOSUPPORT;
3016+
goto err_free_skb;
3017+
}
3018+
3019+
if (nla_len(tb[NDA_DST]) != (int)tbl->key_len) {
3020+
NL_SET_ERR_MSG(extack, "Invalid network address in neighbor get request");
3021+
err = -EINVAL;
3022+
goto err_free_skb;
3023+
}
3024+
3025+
dst = nla_data(tb[NDA_DST]);
3026+
30243027
if (ndm->ndm_ifindex) {
30253028
dev = __dev_get_by_index(net, ndm->ndm_ifindex);
30263029
if (!dev) {

0 commit comments

Comments
 (0)