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 >