On Wed, Apr 23, 2014 at 11:17:15AM +0200, Jiri Pirko wrote: > Wed, Apr 23, 2014 at 09:21:05AM CEST, david@gibson.dropbear.id.au wrote: > >Since 115c9b81928360d769a76c632bae62d15206a94a (rtnetlink: Fix problem with > >buffer allocation), RTM_NEWLINK messages only contain the IFLA_VFINFO_LIST > >attribute if they were solicited by a GETLINK message containing an > >IFLA_EXT_MASK attribute with the RTEXT_FILTER_VF flag. > > > >That was done because some user programs broke when they received more data > >than expected - because IFLA_VFINFO_LIST contains information for each VF > >it can become large if there are many VFs. > > > >However, the IFLA_VF_PORTS attribute, supplied for devices which implement > >ndo_get_vf_port (currently the 'enic' driver only), has the same problem. > >It supplies per-VF information and can therefore become large, but it is > >not currently conditional on the IFLA_EXT_MASK value. > > > >Worse, it interacts badly with the existing EXT_MASK handling. When > >IFLA_EXT_MASK is not supplied, the buffer for netlink replies is fixed at > >NLMSG_GOODSIZE. If the information for IFLA_VF_PORTS exceeds this, then > >rtnl_fill_ifinfo() returns -EMSGSIZE on the first message in a packet. > >netlink_dump() will misinterpret this as having finished the listing and > >omit data for this interface and all subsequent ones. That can cause > >getifaddrs(3) to enter an infinite loop. > > > >This patch addresses the problem by only supplying IFLA_VF_PORTS when > >IFLA_EXT_MASK is supplied with the RTEXT_FILTER_VF flag set. > > > >Signed-off-by: David Gibson > >--- > > net/core/rtnetlink.c | 16 ++++++++++------ > > 1 file changed, 10 insertions(+), 6 deletions(-) > > > >diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c > >index 5331db2..32a1287 100644 > >--- a/net/core/rtnetlink.c > >+++ b/net/core/rtnetlink.c > >@@ -774,7 +774,8 @@ static inline int rtnl_vfinfo_size(const struct net_device *dev, > > return 0; > > } > > > >-static size_t rtnl_port_size(const struct net_device *dev) > >+static size_t rtnl_port_size(const struct net_device *dev, > >+ u32 ext_filter_mask) > > { > > size_t port_size = nla_total_size(4) /* PORT_VF */ > > + nla_total_size(PORT_PROFILE_MAX) /* PORT_PROFILE */ > >@@ -790,7 +791,8 @@ static size_t rtnl_port_size(const struct net_device *dev) > > size_t port_self_size = nla_total_size(sizeof(struct nlattr)) > > + port_size; > > > >- if (!dev->netdev_ops->ndo_get_vf_port || !dev->dev.parent) > >+ if (!dev->netdev_ops->ndo_get_vf_port || !dev->dev.parent > >+ || !(ext_filter_mask & RTEXT_FILTER_VF)) > > Do not start line with || Ah, sorry, I'm getting my project codingstyles mixed up. Will fix. -- David Gibson | I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_ | _way_ _around_! http://www.ozlabs.org/~dgibson