We will remove RTNL for neigh_get() and run it under RCU instead. neigh_get() returns -EINVAL in the following cases: * NDA_DST is not specified * Both ndm->ndm_ifindex and NTF_PROXY are not specified These validations do not require RCU. Let's move them to neigh_valid_get_req(). While at it, the extack string for the first case is replaced with NL_SET_ERR_ATTR_MISS(). Signed-off-by: Kuniyuki Iwashima --- v3: Use NL_SET_ERR_ATTR_MISS() for NDA_DST --- net/core/neighbour.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/net/core/neighbour.c b/net/core/neighbour.c index eb074d602ed08..babedf5e68c44 100644 --- a/net/core/neighbour.c +++ b/net/core/neighbour.c @@ -2935,6 +2935,11 @@ static struct ndmsg *neigh_valid_get_req(const struct nlmsghdr *nlh, return ERR_PTR(-EINVAL); } + if (!(ndm->ndm_flags & NTF_PROXY) && !ndm->ndm_ifindex) { + NL_SET_ERR_MSG(extack, "No device specified"); + return ERR_PTR(-EINVAL); + } + err = nlmsg_parse_deprecated_strict(nlh, sizeof(struct ndmsg), tb, NDA_MAX, nda_policy, extack); if (err < 0) @@ -2947,11 +2952,13 @@ static struct ndmsg *neigh_valid_get_req(const struct nlmsghdr *nlh, } for (i = 0; i <= NDA_MAX; ++i) { - if (!tb[i]) - continue; - switch (i) { case NDA_DST: + if (!tb[i]) { + 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); @@ -2959,6 +2966,9 @@ static struct ndmsg *neigh_valid_get_req(const struct nlmsghdr *nlh, *dst = nla_data(tb[i]); break; default: + if (!tb[i]) + continue; + NL_SET_ERR_MSG(extack, "Unsupported attribute in neighbor get request"); return ERR_PTR(-EINVAL); } @@ -3051,11 +3061,6 @@ static int neigh_get(struct sk_buff *in_skb, struct nlmsghdr *nlh, } } - if (!dst) { - NL_SET_ERR_MSG(extack, "Network address not specified"); - return -EINVAL; - } - if (ndm->ndm_flags & NTF_PROXY) { struct pneigh_entry *pn; @@ -3068,11 +3073,6 @@ static int neigh_get(struct sk_buff *in_skb, struct nlmsghdr *nlh, nlh->nlmsg_seq, tbl); } - if (!dev) { - NL_SET_ERR_MSG(extack, "No device specified"); - return -EINVAL; - } - neigh = neigh_lookup(tbl, dst, dev); if (!neigh) { NL_SET_ERR_MSG(extack, "Neighbour entry not found"); -- 2.50.0.727.gbf7dc18ff4-goog