diff options
Diffstat (limited to 'net/core')
| -rw-r--r-- | net/core/rtnetlink.c | 33 | 
1 files changed, 22 insertions, 11 deletions
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 64ad17d077ed..9837bebf93ce 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))  		return 0;  	if (dev_num_vf(dev->dev.parent))  		return port_self_size + vf_ports_size + @@ -826,7 +828,7 @@ static noinline size_t if_nlmsg_size(const struct net_device *dev,  	       + nla_total_size(ext_filter_mask  			        & RTEXT_FILTER_VF ? 4 : 0) /* IFLA_NUM_VF */  	       + rtnl_vfinfo_size(dev, ext_filter_mask) /* IFLA_VFINFO_LIST */ -	       + rtnl_port_size(dev) /* IFLA_VF_PORTS + IFLA_PORT_SELF */ +	       + rtnl_port_size(dev, ext_filter_mask) /* IFLA_VF_PORTS + IFLA_PORT_SELF */  	       + rtnl_link_get_size(dev) /* IFLA_LINKINFO */  	       + rtnl_link_get_af_size(dev) /* IFLA_AF_SPEC */  	       + nla_total_size(MAX_PHYS_PORT_ID_LEN); /* IFLA_PHYS_PORT_ID */ @@ -888,11 +890,13 @@ static int rtnl_port_self_fill(struct sk_buff *skb, struct net_device *dev)  	return 0;  } -static int rtnl_port_fill(struct sk_buff *skb, struct net_device *dev) +static int rtnl_port_fill(struct sk_buff *skb, struct net_device *dev, +			  u32 ext_filter_mask)  {  	int err; -	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))  		return 0;  	err = rtnl_port_self_fill(skb, dev); @@ -1079,7 +1083,7 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,  		nla_nest_end(skb, vfinfo);  	} -	if (rtnl_port_fill(skb, dev)) +	if (rtnl_port_fill(skb, dev, ext_filter_mask))  		goto nla_put_failure;  	if (dev->rtnl_link_ops || rtnl_have_link_slave_info(dev)) { @@ -1198,6 +1202,7 @@ static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)  	struct hlist_head *head;  	struct nlattr *tb[IFLA_MAX+1];  	u32 ext_filter_mask = 0; +	int err;  	s_h = cb->args[0];  	s_idx = cb->args[1]; @@ -1218,11 +1223,17 @@ static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)  		hlist_for_each_entry_rcu(dev, head, index_hlist) {  			if (idx < s_idx)  				goto cont; -			if (rtnl_fill_ifinfo(skb, dev, RTM_NEWLINK, -					     NETLINK_CB(cb->skb).portid, -					     cb->nlh->nlmsg_seq, 0, -					     NLM_F_MULTI, -					     ext_filter_mask) <= 0) +			err = rtnl_fill_ifinfo(skb, dev, RTM_NEWLINK, +					       NETLINK_CB(cb->skb).portid, +					       cb->nlh->nlmsg_seq, 0, +					       NLM_F_MULTI, +					       ext_filter_mask); +			/* If we ran out of room on the first message, +			 * we're in trouble +			 */ +			WARN_ON((err == -EMSGSIZE) && (skb->len == 0)); + +			if (err <= 0)  				goto out;  			nl_dump_check_consistent(cb, nlmsg_hdr(skb));  | 
