On Sun, Oct 07, 2018 at 08:16:41PM -0700, David Ahern wrote:
> From: David Ahern <dsah...@gmail.com>
> 
> Update inet_netconf_dump_devconf, inet6_netconf_dump_devconf, and
> mpls_netconf_dump_devconf for strict data checking. If the flag is set,
> the dump request is expected to have an netconfmsg struct as the header.
> The struct only has the family member and no attributes can be appended.
> 
> Signed-off-by: David Ahern <dsah...@gmail.com>

Acked-by: Christian Brauner <christ...@brauner.io>

> ---
>  net/ipv4/devinet.c  | 22 +++++++++++++++++++---
>  net/ipv6/addrconf.c | 22 +++++++++++++++++++---
>  net/mpls/af_mpls.c  | 18 +++++++++++++++++-
>  3 files changed, 55 insertions(+), 7 deletions(-)
> 
> diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
> index 6f2bbd04e950..d122ebbe5980 100644
> --- a/net/ipv4/devinet.c
> +++ b/net/ipv4/devinet.c
> @@ -2086,6 +2086,7 @@ static int inet_netconf_get_devconf(struct sk_buff 
> *in_skb,
>  static int inet_netconf_dump_devconf(struct sk_buff *skb,
>                                    struct netlink_callback *cb)
>  {
> +     const struct nlmsghdr *nlh = cb->nlh;
>       struct net *net = sock_net(skb->sk);
>       int h, s_h;
>       int idx, s_idx;
> @@ -2093,6 +2094,21 @@ static int inet_netconf_dump_devconf(struct sk_buff 
> *skb,
>       struct in_device *in_dev;
>       struct hlist_head *head;
>  
> +     if (cb->strict_check) {
> +             struct netlink_ext_ack *extack = cb->extack;
> +             struct netconfmsg *ncm;
> +
> +             if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(*ncm))) {
> +                     NL_SET_ERR_MSG(extack, "ipv4: Invalid header for 
> netconf dump request");
> +                     return -EINVAL;
> +             }
> +
> +             if (nlmsg_attrlen(nlh, sizeof(*ncm))) {
> +                     NL_SET_ERR_MSG(extack, "ipv4: Invalid data after header 
> in netconf dump request");
> +                     return -EINVAL;
> +             }
> +     }
> +
>       s_h = cb->args[0];
>       s_idx = idx = cb->args[1];
>  
> @@ -2112,7 +2128,7 @@ static int inet_netconf_dump_devconf(struct sk_buff 
> *skb,
>                       if (inet_netconf_fill_devconf(skb, dev->ifindex,
>                                                     &in_dev->cnf,
>                                                     
> NETLINK_CB(cb->skb).portid,
> -                                                   cb->nlh->nlmsg_seq,
> +                                                   nlh->nlmsg_seq,
>                                                     RTM_NEWNETCONF,
>                                                     NLM_F_MULTI,
>                                                     NETCONFA_ALL) < 0) {
> @@ -2129,7 +2145,7 @@ static int inet_netconf_dump_devconf(struct sk_buff 
> *skb,
>               if (inet_netconf_fill_devconf(skb, NETCONFA_IFINDEX_ALL,
>                                             net->ipv4.devconf_all,
>                                             NETLINK_CB(cb->skb).portid,
> -                                           cb->nlh->nlmsg_seq,
> +                                           nlh->nlmsg_seq,
>                                             RTM_NEWNETCONF, NLM_F_MULTI,
>                                             NETCONFA_ALL) < 0)
>                       goto done;
> @@ -2140,7 +2156,7 @@ static int inet_netconf_dump_devconf(struct sk_buff 
> *skb,
>               if (inet_netconf_fill_devconf(skb, NETCONFA_IFINDEX_DEFAULT,
>                                             net->ipv4.devconf_dflt,
>                                             NETLINK_CB(cb->skb).portid,
> -                                           cb->nlh->nlmsg_seq,
> +                                           nlh->nlmsg_seq,
>                                             RTM_NEWNETCONF, NLM_F_MULTI,
>                                             NETCONFA_ALL) < 0)
>                       goto done;
> diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
> index ce071d85ad00..2496b12bf721 100644
> --- a/net/ipv6/addrconf.c
> +++ b/net/ipv6/addrconf.c
> @@ -666,6 +666,7 @@ static int inet6_netconf_get_devconf(struct sk_buff 
> *in_skb,
>  static int inet6_netconf_dump_devconf(struct sk_buff *skb,
>                                     struct netlink_callback *cb)
>  {
> +     const struct nlmsghdr *nlh = cb->nlh;
>       struct net *net = sock_net(skb->sk);
>       int h, s_h;
>       int idx, s_idx;
> @@ -673,6 +674,21 @@ static int inet6_netconf_dump_devconf(struct sk_buff 
> *skb,
>       struct inet6_dev *idev;
>       struct hlist_head *head;
>  
> +     if (cb->strict_check) {
> +             struct netlink_ext_ack *extack = cb->extack;
> +             struct netconfmsg *ncm;
> +
> +             if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(*ncm))) {
> +                     NL_SET_ERR_MSG_MOD(extack, "Invalid header for netconf 
> dump request");
> +                     return -EINVAL;
> +             }
> +
> +             if (nlmsg_attrlen(nlh, sizeof(*ncm))) {
> +                     NL_SET_ERR_MSG_MOD(extack, "Invalid data after header 
> in netconf dump request");
> +                     return -EINVAL;
> +             }
> +     }
> +
>       s_h = cb->args[0];
>       s_idx = idx = cb->args[1];
>  
> @@ -692,7 +708,7 @@ static int inet6_netconf_dump_devconf(struct sk_buff *skb,
>                       if (inet6_netconf_fill_devconf(skb, dev->ifindex,
>                                                      &idev->cnf,
>                                                      
> NETLINK_CB(cb->skb).portid,
> -                                                    cb->nlh->nlmsg_seq,
> +                                                    nlh->nlmsg_seq,
>                                                      RTM_NEWNETCONF,
>                                                      NLM_F_MULTI,
>                                                      NETCONFA_ALL) < 0) {
> @@ -709,7 +725,7 @@ static int inet6_netconf_dump_devconf(struct sk_buff *skb,
>               if (inet6_netconf_fill_devconf(skb, NETCONFA_IFINDEX_ALL,
>                                              net->ipv6.devconf_all,
>                                              NETLINK_CB(cb->skb).portid,
> -                                            cb->nlh->nlmsg_seq,
> +                                            nlh->nlmsg_seq,
>                                              RTM_NEWNETCONF, NLM_F_MULTI,
>                                              NETCONFA_ALL) < 0)
>                       goto done;
> @@ -720,7 +736,7 @@ static int inet6_netconf_dump_devconf(struct sk_buff *skb,
>               if (inet6_netconf_fill_devconf(skb, NETCONFA_IFINDEX_DEFAULT,
>                                              net->ipv6.devconf_dflt,
>                                              NETLINK_CB(cb->skb).portid,
> -                                            cb->nlh->nlmsg_seq,
> +                                            nlh->nlmsg_seq,
>                                              RTM_NEWNETCONF, NLM_F_MULTI,
>                                              NETCONFA_ALL) < 0)
>                       goto done;
> diff --git a/net/mpls/af_mpls.c b/net/mpls/af_mpls.c
> index 0458c8aa5c11..7f891ffffc05 100644
> --- a/net/mpls/af_mpls.c
> +++ b/net/mpls/af_mpls.c
> @@ -1263,6 +1263,7 @@ static int mpls_netconf_get_devconf(struct sk_buff 
> *in_skb,
>  static int mpls_netconf_dump_devconf(struct sk_buff *skb,
>                                    struct netlink_callback *cb)
>  {
> +     const struct nlmsghdr *nlh = cb->nlh;
>       struct net *net = sock_net(skb->sk);
>       struct hlist_head *head;
>       struct net_device *dev;
> @@ -1270,6 +1271,21 @@ static int mpls_netconf_dump_devconf(struct sk_buff 
> *skb,
>       int idx, s_idx;
>       int h, s_h;
>  
> +     if (cb->strict_check) {
> +             struct netlink_ext_ack *extack = cb->extack;
> +             struct netconfmsg *ncm;
> +
> +             if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(*ncm))) {
> +                     NL_SET_ERR_MSG_MOD(extack, "Invalid header for netconf 
> dump request");
> +                     return -EINVAL;
> +             }
> +
> +             if (nlmsg_attrlen(nlh, sizeof(*ncm))) {
> +                     NL_SET_ERR_MSG_MOD(extack, "Invalid data after header 
> in netconf dump request");
> +                     return -EINVAL;
> +             }
> +     }
> +
>       s_h = cb->args[0];
>       s_idx = idx = cb->args[1];
>  
> @@ -1286,7 +1302,7 @@ static int mpls_netconf_dump_devconf(struct sk_buff 
> *skb,
>                               goto cont;
>                       if (mpls_netconf_fill_devconf(skb, mdev,
>                                                     
> NETLINK_CB(cb->skb).portid,
> -                                                   cb->nlh->nlmsg_seq,
> +                                                   nlh->nlmsg_seq,
>                                                     RTM_NEWNETCONF,
>                                                     NLM_F_MULTI,
>                                                     NETCONFA_ALL) < 0) {
> -- 
> 2.11.0
> 

Reply via email to