net/neighbor: Update neigh_dump_info for strict data checking
Update neigh_dump_info for strict data checking. If the flag is set, the dump request is expected to have an ndmsg struct as the header potentially followed by one or more attributes. Any data passed in the header or as an attribute is taken as a request to influence the data returned. Only values supported by the dump handler are allowed to be non-0 or set in the request. At the moment only the NDA_IFINDEX and NDA_MASTER attributes are supported. Existing code does not fail the dump if nlmsg_parse fails. That behavior is kept for non-strict checking. Signed-off-by: David Ahern <dsahern@gmail.com> Acked-by: Christian Brauner <christian@brauner.io> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
e8ba330ac0
commit
51183d233b
@ -2426,11 +2426,73 @@ out:
|
||||
|
||||
}
|
||||
|
||||
static int neigh_valid_dump_req(const struct nlmsghdr *nlh,
|
||||
bool strict_check,
|
||||
struct neigh_dump_filter *filter,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct nlattr *tb[NDA_MAX + 1];
|
||||
int err, i;
|
||||
|
||||
if (strict_check) {
|
||||
struct ndmsg *ndm;
|
||||
|
||||
if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(*ndm))) {
|
||||
NL_SET_ERR_MSG(extack, "Invalid header for neighbor dump request");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ndm = nlmsg_data(nlh);
|
||||
if (ndm->ndm_pad1 || ndm->ndm_pad2 || ndm->ndm_ifindex ||
|
||||
ndm->ndm_state || ndm->ndm_flags || ndm->ndm_type) {
|
||||
NL_SET_ERR_MSG(extack, "Invalid values in header for neighbor dump request");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
err = nlmsg_parse_strict(nlh, sizeof(struct ndmsg), tb, NDA_MAX,
|
||||
NULL, extack);
|
||||
} else {
|
||||
err = nlmsg_parse(nlh, sizeof(struct ndmsg), tb, NDA_MAX,
|
||||
NULL, extack);
|
||||
}
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
for (i = 0; i <= NDA_MAX; ++i) {
|
||||
if (!tb[i])
|
||||
continue;
|
||||
|
||||
/* all new attributes should require strict_check */
|
||||
switch (i) {
|
||||
case NDA_IFINDEX:
|
||||
if (nla_len(tb[i]) != sizeof(u32)) {
|
||||
NL_SET_ERR_MSG(extack, "Invalid IFINDEX attribute in neighbor dump request");
|
||||
return -EINVAL;
|
||||
}
|
||||
filter->dev_idx = nla_get_u32(tb[i]);
|
||||
break;
|
||||
case NDA_MASTER:
|
||||
if (nla_len(tb[i]) != sizeof(u32)) {
|
||||
NL_SET_ERR_MSG(extack, "Invalid MASTER attribute in neighbor dump request");
|
||||
return -EINVAL;
|
||||
}
|
||||
filter->master_idx = nla_get_u32(tb[i]);
|
||||
break;
|
||||
default:
|
||||
if (strict_check) {
|
||||
NL_SET_ERR_MSG(extack, "Unsupported attribute in neighbor dump request");
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int neigh_dump_info(struct sk_buff *skb, struct netlink_callback *cb)
|
||||
{
|
||||
const struct nlmsghdr *nlh = cb->nlh;
|
||||
struct neigh_dump_filter filter = {};
|
||||
struct nlattr *tb[NDA_MAX + 1];
|
||||
struct neigh_table *tbl;
|
||||
int t, family, s_t;
|
||||
int proxy = 0;
|
||||
@ -2445,20 +2507,10 @@ static int neigh_dump_info(struct sk_buff *skb, struct netlink_callback *cb)
|
||||
((struct ndmsg *)nlmsg_data(nlh))->ndm_flags == NTF_PROXY)
|
||||
proxy = 1;
|
||||
|
||||
err = nlmsg_parse(nlh, sizeof(struct ndmsg), tb, NDA_MAX, NULL,
|
||||
cb->extack);
|
||||
if (!err) {
|
||||
if (tb[NDA_IFINDEX]) {
|
||||
if (nla_len(tb[NDA_IFINDEX]) != sizeof(u32))
|
||||
return -EINVAL;
|
||||
filter.dev_idx = nla_get_u32(tb[NDA_IFINDEX]);
|
||||
}
|
||||
if (tb[NDA_MASTER]) {
|
||||
if (nla_len(tb[NDA_MASTER]) != sizeof(u32))
|
||||
return -EINVAL;
|
||||
filter.master_idx = nla_get_u32(tb[NDA_MASTER]);
|
||||
}
|
||||
}
|
||||
err = neigh_valid_dump_req(nlh, cb->strict_check, &filter, cb->extack);
|
||||
if (err < 0 && cb->strict_check)
|
||||
return err;
|
||||
|
||||
s_t = cb->args[0];
|
||||
|
||||
for (t = 0; t < NEIGH_NR_TABLES; t++) {
|
||||
|
Loading…
Reference in New Issue
Block a user