From mboxrd@z Thu Jan 1 00:00:00 1970 From: David Ahern Subject: [PATCH RFC v2 net-next 13/25] net/neighbor: Update neigh_dump_info to support NLM_F_DUMP_PROPER_HDR Date: Mon, 1 Oct 2018 17:28:39 -0700 Message-ID: <20181002002851.5002-14-dsahern@kernel.org> References: <20181002002851.5002-1-dsahern@kernel.org> Cc: christian@brauner.io, jbenc@redhat.com, stephen@networkplumber.org, David Ahern To: netdev@vger.kernel.org, davem@davemloft.net Return-path: Received: from mail.kernel.org ([198.145.29.99]:35334 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726554AbeJBHJU (ORCPT ); Tue, 2 Oct 2018 03:09:20 -0400 In-Reply-To: <20181002002851.5002-1-dsahern@kernel.org> Sender: netdev-owner@vger.kernel.org List-ID: From: David Ahern Update neigh_dump_info to check for NLM_F_DUMP_PROPER_HDR in the netlink message header. 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. Signed-off-by: David Ahern --- net/core/neighbour.c | 61 +++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 51 insertions(+), 10 deletions(-) diff --git a/net/core/neighbour.c b/net/core/neighbour.c index 9bab9ae9c98e..aaf2526e5da4 100644 --- a/net/core/neighbour.c +++ b/net/core/neighbour.c @@ -2425,13 +2425,15 @@ static int pneigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb, static int neigh_dump_info(struct sk_buff *skb, struct netlink_callback *cb) { + struct netlink_ext_ack *extack = cb->extack; const struct nlmsghdr *nlh = cb->nlh; + bool proper_hdr = !!(nlh->nlmsg_flags & NLM_F_DUMP_PROPER_HDR); struct neigh_dump_filter filter = {}; struct nlattr *tb[NDA_MAX + 1]; struct neigh_table *tbl; int t, family, s_t; int proxy = 0; - int err; + int err, i; family = ((struct rtgenmsg *)nlmsg_data(nlh))->rtgen_family; @@ -2442,19 +2444,58 @@ 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, NULL); - 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 (proper_hdr) { + struct ndmsg *ndm; + + if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(*ndm))) { + NL_SET_ERR_MSG(extack, "Invalid header"); + 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 dump request"); + return -EINVAL; } - if (tb[NDA_MASTER]) { - if (nla_len(tb[NDA_MASTER]) != sizeof(u32)) + } + + err = nlmsg_parse(nlh, sizeof(struct ndmsg), tb, NDA_MAX, NULL, extack); + if (err < 0) { + if (proper_hdr) { + NL_SET_ERR_MSG(extack, "Failed to parse link attributes"); + return -EINVAL; + } + goto walk_entries; + } + + for (i = 0; i <= NDA_MAX; ++i) { + if (!tb[i]) + continue; + switch (i) { + case NDA_IFINDEX: + if (nla_len(tb[i]) != sizeof(u32)) { + NL_SET_ERR_MSG(extack, "Invalid IFINDEX attribute"); + 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"); return -EINVAL; - filter.master_idx = nla_get_u32(tb[NDA_MASTER]); + } + filter.master_idx = nla_get_u32(tb[i]); + break; + default: + if (proper_hdr) { + NL_SET_ERR_MSG(extack, "Unsupported attribute in dump request"); + return -EINVAL; + } } } + +walk_entries: s_t = cb->args[0]; for (t = 0; t < NEIGH_NR_TABLES; t++) { -- 2.11.0