Separating the VF stats out of IFLA_VF_INFO appears to be the least
impact way of resolving the nlattr overflow bug in IFLA_VFINFO_LIST.

Since changing the hierarchy does constitute an ABI change, it must
be explicitly requested via RTEXT_FILTER_VF_SEPARATE_STATS. Otherwise,
the old location is maintained for compatibility.

A new container type, namely IFLA_VFSTATS_LIST, is introduced to group
the stats objects into an ordered list that corresponds with the order
of VFs in IFLA_VFINFO_LIST.

Fixes: 3b766cd83232 ("net/core: Add reading VF statistics through the PF 
netdevice")
Fixes: c5a9f6f0ab40 ("net/core: Add drop counters to VF statistics")
Signed-off-by: Edwin Peer <edwin.p...@broadcom.com>
---
 include/uapi/linux/if_link.h   |  1 +
 include/uapi/linux/rtnetlink.h |  1 +
 net/core/rtnetlink.c           | 24 +++++++++++++++++++++---
 3 files changed, 23 insertions(+), 3 deletions(-)

diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h
index 2bd0d8bbcdb2..db12ffd2bffd 100644
--- a/include/uapi/linux/if_link.h
+++ b/include/uapi/linux/if_link.h
@@ -341,6 +341,7 @@ enum {
        IFLA_ALT_IFNAME, /* Alternative ifname */
        IFLA_PERM_ADDRESS,
        IFLA_PROTO_DOWN_REASON,
+       IFLA_VFSTATS_LIST,
        __IFLA_MAX
 };
 
diff --git a/include/uapi/linux/rtnetlink.h b/include/uapi/linux/rtnetlink.h
index b841caa4657e..f2f4f9b4d595 100644
--- a/include/uapi/linux/rtnetlink.h
+++ b/include/uapi/linux/rtnetlink.h
@@ -789,6 +789,7 @@ enum {
 #define RTEXT_FILTER_MRP       (1 << 4)
 #define RTEXT_FILTER_CFM_CONFIG        (1 << 5)
 #define RTEXT_FILTER_CFM_STATUS        (1 << 6)
+#define RTEXT_FILTER_VF_SEPARATE_STATS (1 << 7)
 
 /* End of information exported to user level */
 
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 95564fd12f24..cddd3945bc11 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -933,6 +933,8 @@ static inline int rtnl_vfinfo_size(const struct net_device 
*dev,
                         nla_total_size(sizeof(struct ifla_vf_rss_query_en)) +
                         nla_total_size(sizeof(struct ifla_vf_trust)));
                if (~ext_filter_mask & RTEXT_FILTER_SKIP_STATS) {
+                       if (ext_filter_mask & RTEXT_FILTER_VF_SEPARATE_STATS)
+                               size += nla_total_size(0); /* IFLA_VFSTATS_LIST 
*/
                        size += num_vfs *
                                (nla_total_size(0) + /* nest IFLA_VF_STATS */
                                 /* IFLA_VF_STATS_RX_PACKETS */
@@ -1368,7 +1370,8 @@ static noinline_for_stack int rtnl_fill_vfinfo(struct 
sk_buff *skb,
                goto nla_put_vf_failure;
        }
        nla_nest_end(skb, vfvlanlist);
-       if (~ext_filter_mask & RTEXT_FILTER_SKIP_STATS) {
+       if (~ext_filter_mask & RTEXT_FILTER_SKIP_STATS &&
+           ~ext_filter_mask & RTEXT_FILTER_VF_SEPARATE_STATS) {
                if (rtnl_fill_vfstats(skb, dev, vfs_num))
                        goto nla_put_vf_failure;
        }
@@ -1386,7 +1389,7 @@ static noinline_for_stack int rtnl_fill_vf(struct sk_buff 
*skb,
                                           struct net_device *dev,
                                           u32 ext_filter_mask)
 {
-       struct nlattr *vfinfo;
+       struct nlattr *vfinfo, *vfstats;
        int i, num_vfs;
 
        if (!dev->dev.parent || ((ext_filter_mask & RTEXT_FILTER_VF) == 0))
@@ -1407,8 +1410,23 @@ static noinline_for_stack int rtnl_fill_vf(struct 
sk_buff *skb,
                if (rtnl_fill_vfinfo(skb, dev, i, vfinfo, ext_filter_mask))
                        return -EMSGSIZE;
        }
-
        nla_nest_end(skb, vfinfo);
+
+       if (~ext_filter_mask & RTEXT_FILTER_SKIP_STATS &&
+           ext_filter_mask & RTEXT_FILTER_VF_SEPARATE_STATS) {
+               vfstats = nla_nest_start_noflag(skb, IFLA_VFSTATS_LIST);
+               if (!vfstats)
+                       return -EMSGSIZE;
+
+               for (i = 0; i < num_vfs; i++) {
+                       if (rtnl_fill_vfstats(skb, dev, i)) {
+                               nla_nest_cancel(skb, vfstats);
+                               return -EMSGSIZE;
+                       }
+               }
+               nla_nest_end(skb, vfstats);
+       }
+
        return 0;
 }
 
-- 
2.30.0

Attachment: smime.p7s
Description: S/MIME Cryptographic Signature

Reply via email to