forked from mirrors/linux
		
	net: rtnetlink: rtnl_fill_statsinfo(): Permit non-EMSGSIZE error returns
Obtaining stats for the IFLA_STATS_LINK_OFFLOAD_XSTATS nest involves a HW access, and can fail for more reasons than just netlink message size exhaustion. Therefore do not always return -EMSGSIZE on the failure path, but respect the error code provided by the callee. Set the error explicitly where it is reasonable to assume -EMSGSIZE as the failure reason. Signed-off-by: Petr Machata <petrm@nvidia.com> Signed-off-by: Ido Schimmel <idosch@nvidia.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
		
							parent
							
								
									05415bccbb
								
							
						
					
					
						commit
						216e690631
					
				
					 1 changed files with 16 additions and 6 deletions
				
			
		| 
						 | 
					@ -5177,8 +5177,10 @@ static int rtnl_fill_statsinfo(struct sk_buff *skb, struct net_device *dev,
 | 
				
			||||||
		attr = nla_reserve_64bit(skb, IFLA_STATS_LINK_64,
 | 
							attr = nla_reserve_64bit(skb, IFLA_STATS_LINK_64,
 | 
				
			||||||
					 sizeof(struct rtnl_link_stats64),
 | 
										 sizeof(struct rtnl_link_stats64),
 | 
				
			||||||
					 IFLA_STATS_UNSPEC);
 | 
										 IFLA_STATS_UNSPEC);
 | 
				
			||||||
		if (!attr)
 | 
							if (!attr) {
 | 
				
			||||||
 | 
								err = -EMSGSIZE;
 | 
				
			||||||
			goto nla_put_failure;
 | 
								goto nla_put_failure;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		sp = nla_data(attr);
 | 
							sp = nla_data(attr);
 | 
				
			||||||
		dev_get_stats(dev, sp);
 | 
							dev_get_stats(dev, sp);
 | 
				
			||||||
| 
						 | 
					@ -5191,8 +5193,10 @@ static int rtnl_fill_statsinfo(struct sk_buff *skb, struct net_device *dev,
 | 
				
			||||||
			*idxattr = IFLA_STATS_LINK_XSTATS;
 | 
								*idxattr = IFLA_STATS_LINK_XSTATS;
 | 
				
			||||||
			attr = nla_nest_start_noflag(skb,
 | 
								attr = nla_nest_start_noflag(skb,
 | 
				
			||||||
						     IFLA_STATS_LINK_XSTATS);
 | 
											     IFLA_STATS_LINK_XSTATS);
 | 
				
			||||||
			if (!attr)
 | 
								if (!attr) {
 | 
				
			||||||
 | 
									err = -EMSGSIZE;
 | 
				
			||||||
				goto nla_put_failure;
 | 
									goto nla_put_failure;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			err = ops->fill_linkxstats(skb, dev, prividx, *idxattr);
 | 
								err = ops->fill_linkxstats(skb, dev, prividx, *idxattr);
 | 
				
			||||||
			nla_nest_end(skb, attr);
 | 
								nla_nest_end(skb, attr);
 | 
				
			||||||
| 
						 | 
					@ -5214,8 +5218,10 @@ static int rtnl_fill_statsinfo(struct sk_buff *skb, struct net_device *dev,
 | 
				
			||||||
			*idxattr = IFLA_STATS_LINK_XSTATS_SLAVE;
 | 
								*idxattr = IFLA_STATS_LINK_XSTATS_SLAVE;
 | 
				
			||||||
			attr = nla_nest_start_noflag(skb,
 | 
								attr = nla_nest_start_noflag(skb,
 | 
				
			||||||
						     IFLA_STATS_LINK_XSTATS_SLAVE);
 | 
											     IFLA_STATS_LINK_XSTATS_SLAVE);
 | 
				
			||||||
			if (!attr)
 | 
								if (!attr) {
 | 
				
			||||||
 | 
									err = -EMSGSIZE;
 | 
				
			||||||
				goto nla_put_failure;
 | 
									goto nla_put_failure;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			err = ops->fill_linkxstats(skb, dev, prividx, *idxattr);
 | 
								err = ops->fill_linkxstats(skb, dev, prividx, *idxattr);
 | 
				
			||||||
			nla_nest_end(skb, attr);
 | 
								nla_nest_end(skb, attr);
 | 
				
			||||||
| 
						 | 
					@ -5233,8 +5239,10 @@ static int rtnl_fill_statsinfo(struct sk_buff *skb, struct net_device *dev,
 | 
				
			||||||
		*idxattr = IFLA_STATS_LINK_OFFLOAD_XSTATS;
 | 
							*idxattr = IFLA_STATS_LINK_OFFLOAD_XSTATS;
 | 
				
			||||||
		attr = nla_nest_start_noflag(skb,
 | 
							attr = nla_nest_start_noflag(skb,
 | 
				
			||||||
					     IFLA_STATS_LINK_OFFLOAD_XSTATS);
 | 
										     IFLA_STATS_LINK_OFFLOAD_XSTATS);
 | 
				
			||||||
		if (!attr)
 | 
							if (!attr) {
 | 
				
			||||||
 | 
								err = -EMSGSIZE;
 | 
				
			||||||
			goto nla_put_failure;
 | 
								goto nla_put_failure;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		err = rtnl_offload_xstats_fill(skb, dev, prividx,
 | 
							err = rtnl_offload_xstats_fill(skb, dev, prividx,
 | 
				
			||||||
					       off_filter_mask, extack);
 | 
										       off_filter_mask, extack);
 | 
				
			||||||
| 
						 | 
					@ -5253,8 +5261,10 @@ static int rtnl_fill_statsinfo(struct sk_buff *skb, struct net_device *dev,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		*idxattr = IFLA_STATS_AF_SPEC;
 | 
							*idxattr = IFLA_STATS_AF_SPEC;
 | 
				
			||||||
		attr = nla_nest_start_noflag(skb, IFLA_STATS_AF_SPEC);
 | 
							attr = nla_nest_start_noflag(skb, IFLA_STATS_AF_SPEC);
 | 
				
			||||||
		if (!attr)
 | 
							if (!attr) {
 | 
				
			||||||
 | 
								err = -EMSGSIZE;
 | 
				
			||||||
			goto nla_put_failure;
 | 
								goto nla_put_failure;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		rcu_read_lock();
 | 
							rcu_read_lock();
 | 
				
			||||||
		list_for_each_entry_rcu(af_ops, &rtnl_af_ops, list) {
 | 
							list_for_each_entry_rcu(af_ops, &rtnl_af_ops, list) {
 | 
				
			||||||
| 
						 | 
					@ -5298,7 +5308,7 @@ static int rtnl_fill_statsinfo(struct sk_buff *skb, struct net_device *dev,
 | 
				
			||||||
	else
 | 
						else
 | 
				
			||||||
		nlmsg_end(skb, nlh);
 | 
							nlmsg_end(skb, nlh);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return -EMSGSIZE;
 | 
						return err;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static size_t if_nlmsg_stats_size(const struct net_device *dev,
 | 
					static size_t if_nlmsg_stats_size(const struct net_device *dev,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue