diff options
| author | Thomas Gleixner <tglx@linutronix.de> | 2018-06-22 21:20:35 +0200 | 
|---|---|---|
| committer | Thomas Gleixner <tglx@linutronix.de> | 2018-06-22 21:20:35 +0200 | 
| commit | 7731b8bc94e599c9a79e428f3359ff2c34b7576a (patch) | |
| tree | 879f18ccbe274122f2d4f095b43cbc7f953e0ada /net/core/rtnetlink.c | |
| parent | 48e315618dc4dc8904182cd221e3d395d5d97005 (diff) | |
| parent | 9ffc59d57228d74809700be6f7ecb1db10292f05 (diff) | |
Merge branch 'linus' into x86/urgent
Required to queue a dependent fix.
Diffstat (limited to 'net/core/rtnetlink.c')
| -rw-r--r-- | net/core/rtnetlink.c | 34 | 
1 files changed, 25 insertions, 9 deletions
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 45936922d7e2..5ef61222fdef 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -59,6 +59,9 @@  #include <net/rtnetlink.h>  #include <net/net_namespace.h> +#define RTNL_MAX_TYPE		48 +#define RTNL_SLAVE_MAX_TYPE	36 +  struct rtnl_link {  	rtnl_doit_func		doit;  	rtnl_dumpit_func	dumpit; @@ -389,6 +392,11 @@ int rtnl_link_register(struct rtnl_link_ops *ops)  {  	int err; +	/* Sanity-check max sizes to avoid stack buffer overflow. */ +	if (WARN_ON(ops->maxtype > RTNL_MAX_TYPE || +		    ops->slave_maxtype > RTNL_SLAVE_MAX_TYPE)) +		return -EINVAL; +  	rtnl_lock();  	err = __rtnl_link_register(ops);  	rtnl_unlock(); @@ -785,13 +793,15 @@ int rtnl_put_cacheinfo(struct sk_buff *skb, struct dst_entry *dst, u32 id,  		       long expires, u32 error)  {  	struct rta_cacheinfo ci = { -		.rta_lastuse = jiffies_delta_to_clock_t(jiffies - dst->lastuse), -		.rta_used = dst->__use, -		.rta_clntref = atomic_read(&(dst->__refcnt)),  		.rta_error = error,  		.rta_id =  id,  	}; +	if (dst) { +		ci.rta_lastuse = jiffies_delta_to_clock_t(jiffies - dst->lastuse); +		ci.rta_used = dst->__use; +		ci.rta_clntref = atomic_read(&dst->__refcnt); +	}  	if (expires) {  		unsigned long clock; @@ -2256,6 +2266,10 @@ static int do_setlink(const struct sk_buff *skb,  	const struct net_device_ops *ops = dev->netdev_ops;  	int err; +	err = validate_linkmsg(dev, tb); +	if (err < 0) +		return err; +  	if (tb[IFLA_NET_NS_PID] || tb[IFLA_NET_NS_FD] || tb[IFLA_IF_NETNSID]) {  		struct net *net = rtnl_link_get_net_capable(skb, dev_net(dev),  							    tb, CAP_NET_ADMIN); @@ -2619,10 +2633,6 @@ static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh,  		goto errout;  	} -	err = validate_linkmsg(dev, tb); -	if (err < 0) -		goto errout; -  	err = do_setlink(skb, dev, ifm, extack, tb, ifname, 0);  errout:  	return err; @@ -2900,13 +2910,16 @@ replay:  	}  	if (1) { -		struct nlattr *attr[ops ? ops->maxtype + 1 : 1]; -		struct nlattr *slave_attr[m_ops ? m_ops->slave_maxtype + 1 : 1]; +		struct nlattr *attr[RTNL_MAX_TYPE + 1]; +		struct nlattr *slave_attr[RTNL_SLAVE_MAX_TYPE + 1];  		struct nlattr **data = NULL;  		struct nlattr **slave_data = NULL;  		struct net *dest_net, *link_net = NULL;  		if (ops) { +			if (ops->maxtype > RTNL_MAX_TYPE) +				return -EINVAL; +  			if (ops->maxtype && linkinfo[IFLA_INFO_DATA]) {  				err = nla_parse_nested(attr, ops->maxtype,  						       linkinfo[IFLA_INFO_DATA], @@ -2923,6 +2936,9 @@ replay:  		}  		if (m_ops) { +			if (m_ops->slave_maxtype > RTNL_SLAVE_MAX_TYPE) +				return -EINVAL; +  			if (m_ops->slave_maxtype &&  			    linkinfo[IFLA_INFO_SLAVE_DATA]) {  				err = nla_parse_nested(slave_attr,  | 
