Make sure NETLINK_GET_STRICT_CHK influences both GETSTATS doit
as well as the dump.

Signed-off-by: Jakub Kicinski <jakub.kicin...@netronome.com>
---
 net/core/rtnetlink.c | 58 ++++++++++++++++++++++++++++----------------
 1 file changed, 37 insertions(+), 21 deletions(-)

diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 5ea1bed08ede..08f142b59403 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -4901,6 +4901,36 @@ static size_t if_nlmsg_stats_size(const struct 
net_device *dev,
        return size;
 }
 
+static int rtnl_valid_stats_req(const struct nlmsghdr *nlh, bool strict_check,
+                               bool is_dump, struct netlink_ext_ack *extack)
+{
+       struct if_stats_msg *ifsm;
+
+       if (nlh->nlmsg_len < sizeof(*ifsm)) {
+               NL_SET_ERR_MSG(extack, "Invalid header for stats dump");
+               return -EINVAL;
+       }
+
+       if (!strict_check)
+               return 0;
+
+       ifsm = nlmsg_data(nlh);
+
+       /* only requests using strict checks can pass data to influence
+        * the dump. The legacy exception is filter_mask.
+        */
+       if (ifsm->pad1 || ifsm->pad2 || (is_dump && ifsm->ifindex)) {
+               NL_SET_ERR_MSG(extack, "Invalid values in header for stats dump 
request");
+               return -EINVAL;
+       }
+       if (nlmsg_attrlen(nlh, sizeof(*ifsm))) {
+               NL_SET_ERR_MSG(extack, "Invalid attributes after stats header");
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
 static int rtnl_stats_get(struct sk_buff *skb, struct nlmsghdr *nlh,
                          struct netlink_ext_ack *extack)
 {
@@ -4912,8 +4942,10 @@ static int rtnl_stats_get(struct sk_buff *skb, struct 
nlmsghdr *nlh,
        u32 filter_mask;
        int err;
 
-       if (nlmsg_len(nlh) < sizeof(*ifsm))
-               return -EINVAL;
+       err = rtnl_valid_stats_req(nlh, netlink_strict_get_check(skb),
+                                  false, extack);
+       if (err)
+               return err;
 
        ifsm = nlmsg_data(nlh);
        if (ifsm->ifindex > 0)
@@ -4965,27 +4997,11 @@ 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)) {
-               NL_SET_ERR_MSG(extack, "Invalid header for stats dump");
-               return -EINVAL;
-       }
+       err = rtnl_valid_stats_req(cb->nlh, cb->strict_check, true, extack);
+       if (err)
+               return err;
 
        ifsm = nlmsg_data(cb->nlh);
-
-       /* only requests using strict checks 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 
stats dump request");
-                       return -EINVAL;
-               }
-               if (nlmsg_attrlen(cb->nlh, sizeof(*ifsm))) {
-                       NL_SET_ERR_MSG(extack, "Invalid attributes after stats 
header");
-                       return -EINVAL;
-               }
-       }
-
        filter_mask = ifsm->filter_mask;
        if (!filter_mask) {
                NL_SET_ERR_MSG(extack, "Filter mask must be set for stats 
dump");
-- 
2.19.2

Reply via email to