diff mbox series

[net-next,10/20] rtnetlink: Update rtnl_stats_dump for strict data checking

Message ID 20181004213355.14899-11-dsahern@kernel.org
State Changes Requested, archived
Delegated to: David Miller
Headers show
Series rtnetlink: Add support for rigid checking of data in dump request | expand

Commit Message

David Ahern Oct. 4, 2018, 9:33 p.m. UTC
From: David Ahern <dsahern@gmail.com>

Update rtnl_stats_dump for strict data checking. If the flag is set,
the dump request is expected to have an if_stats_msg struct as the header.
All elements of the struct are expected to be 0 except filter_mask which
must be non-0 (legacy behavior). No attributes are supported.

Signed-off-by: David Ahern <dsahern@gmail.com>
---
 net/core/rtnetlink.c | 24 ++++++++++++++++++++++--
 1 file changed, 22 insertions(+), 2 deletions(-)

Comments

Christian Brauner Oct. 7, 2018, 10:38 a.m. UTC | #1
On Thu, Oct 04, 2018 at 02:33:45PM -0700, David Ahern wrote:
> From: David Ahern <dsahern@gmail.com>
> 
> Update rtnl_stats_dump for strict data checking. If the flag is set,
> the dump request is expected to have an if_stats_msg struct as the header.
> All elements of the struct are expected to be 0 except filter_mask which
> must be non-0 (legacy behavior). No attributes are supported.
> 
> Signed-off-by: David Ahern <dsahern@gmail.com>
> ---
>  net/core/rtnetlink.c | 24 ++++++++++++++++++++++--
>  1 file changed, 22 insertions(+), 2 deletions(-)
> 
> diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
> index d2c8d41a6fbc..6cdd9251771a 100644
> --- a/net/core/rtnetlink.c
> +++ b/net/core/rtnetlink.c
> @@ -4643,6 +4643,7 @@ static int rtnl_stats_get(struct sk_buff *skb, struct nlmsghdr *nlh,
>  
>  static int rtnl_stats_dump(struct sk_buff *skb, struct netlink_callback *cb)
>  {
> +	struct netlink_ext_ack *extack = cb->extack;
>  	int h, s_h, err, s_idx, s_idxattr, s_prividx;
>  	struct net *net = sock_net(skb->sk);
>  	unsigned int flags = NLM_F_MULTI;
> @@ -4659,13 +4660,32 @@ static int rtnl_stats_dump(struct sk_buff *skb, struct netlink_callback *cb)
>  
>  	cb->seq = net->dev_base_seq;
>  
> -	if (nlmsg_len(cb->nlh) < sizeof(*ifsm))
> +	if (nlmsg_len(cb->nlh) < sizeof(*ifsm)) {
> +		NL_SET_ERR_MSG(extack, "Invalid header");
>  		return -EINVAL;
> +	}
>  
>  	ifsm = nlmsg_data(cb->nlh);
> +
> +	/* only requests using NLM_F_DUMP_PROPER_HDR can pass data to
> +	 * influence the dump. The legacy exception is filter_mask.
> +	 */
> +	if (cb->strict_check) {
> +		if (ifsm->pad1 || ifsm->pad2 || ifsm->ifindex) {
> +			NL_SET_ERR_MSG(extack, "Invalid values in header for dump request");
> +			return -EINVAL;
> +		}
> +		if (cb->nlh->nlmsg_len > nlmsg_msg_size(sizeof(*ifsm))) {

Nit: \n appreciated :)

> +			NL_SET_ERR_MSG(extack, "Invalid attributes after header");
> +			return -EINVAL;
> +		}
> +	}
> +
>  	filter_mask = ifsm->filter_mask;
> -	if (!filter_mask)
> +	if (!filter_mask) {
> +		NL_SET_ERR_MSG(extack, "Invalid filter_mask");

Nit: probably better to have this read "Invalid filter mask".

>  		return -EINVAL;
> +	}
>  
>  	for (h = s_h; h < NETDEV_HASHENTRIES; h++, s_idx = 0) {
>  		idx = 0;
> -- 
> 2.11.0
>
diff mbox series

Patch

diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index d2c8d41a6fbc..6cdd9251771a 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -4643,6 +4643,7 @@  static int rtnl_stats_get(struct sk_buff *skb, struct nlmsghdr *nlh,
 
 static int rtnl_stats_dump(struct sk_buff *skb, struct netlink_callback *cb)
 {
+	struct netlink_ext_ack *extack = cb->extack;
 	int h, s_h, err, s_idx, s_idxattr, s_prividx;
 	struct net *net = sock_net(skb->sk);
 	unsigned int flags = NLM_F_MULTI;
@@ -4659,13 +4660,32 @@  static int rtnl_stats_dump(struct sk_buff *skb, struct netlink_callback *cb)
 
 	cb->seq = net->dev_base_seq;
 
-	if (nlmsg_len(cb->nlh) < sizeof(*ifsm))
+	if (nlmsg_len(cb->nlh) < sizeof(*ifsm)) {
+		NL_SET_ERR_MSG(extack, "Invalid header");
 		return -EINVAL;
+	}
 
 	ifsm = nlmsg_data(cb->nlh);
+
+	/* only requests using NLM_F_DUMP_PROPER_HDR can pass data to
+	 * influence the dump. The legacy exception is filter_mask.
+	 */
+	if (cb->strict_check) {
+		if (ifsm->pad1 || ifsm->pad2 || ifsm->ifindex) {
+			NL_SET_ERR_MSG(extack, "Invalid values in header for dump request");
+			return -EINVAL;
+		}
+		if (cb->nlh->nlmsg_len > nlmsg_msg_size(sizeof(*ifsm))) {
+			NL_SET_ERR_MSG(extack, "Invalid attributes after header");
+			return -EINVAL;
+		}
+	}
+
 	filter_mask = ifsm->filter_mask;
-	if (!filter_mask)
+	if (!filter_mask) {
+		NL_SET_ERR_MSG(extack, "Invalid filter_mask");
 		return -EINVAL;
+	}
 
 	for (h = s_h; h < NETDEV_HASHENTRIES; h++, s_idx = 0) {
 		idx = 0;