diff options
Diffstat (limited to 'net/core/dev.c')
| -rw-r--r-- | net/core/dev.c | 60 | 
1 files changed, 54 insertions, 6 deletions
diff --git a/net/core/dev.c b/net/core/dev.c index 0ebaea16632..f91abf80016 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1172,6 +1172,7 @@ static int __dev_open(struct net_device *dev)  		net_dmaengine_get();  		dev_set_rx_mode(dev);  		dev_activate(dev); +		add_device_randomness(dev->dev_addr, dev->addr_len);  	}  	return ret; @@ -2133,6 +2134,9 @@ netdev_features_t netif_skb_features(struct sk_buff *skb)  	__be16 protocol = skb->protocol;  	netdev_features_t features = skb->dev->features; +	if (skb_shinfo(skb)->gso_segs > skb->dev->gso_max_segs) +		features &= ~NETIF_F_GSO_MASK; +  	if (protocol == htons(ETH_P_8021Q)) {  		struct vlan_ethhdr *veh = (struct vlan_ethhdr *)skb->data;  		protocol = veh->h_vlan_encapsulated_proto; @@ -3155,6 +3159,23 @@ void netdev_rx_handler_unregister(struct net_device *dev)  }  EXPORT_SYMBOL_GPL(netdev_rx_handler_unregister); +/* + * Limit the use of PFMEMALLOC reserves to those protocols that implement + * the special handling of PFMEMALLOC skbs. + */ +static bool skb_pfmemalloc_protocol(struct sk_buff *skb) +{ +	switch (skb->protocol) { +	case __constant_htons(ETH_P_ARP): +	case __constant_htons(ETH_P_IP): +	case __constant_htons(ETH_P_IPV6): +	case __constant_htons(ETH_P_8021Q): +		return true; +	default: +		return false; +	} +} +  static int __netif_receive_skb(struct sk_buff *skb)  {  	struct packet_type *ptype, *pt_prev; @@ -3164,14 +3185,27 @@ static int __netif_receive_skb(struct sk_buff *skb)  	bool deliver_exact = false;  	int ret = NET_RX_DROP;  	__be16 type; +	unsigned long pflags = current->flags;  	net_timestamp_check(!netdev_tstamp_prequeue, skb);  	trace_netif_receive_skb(skb); +	/* +	 * PFMEMALLOC skbs are special, they should +	 * - be delivered to SOCK_MEMALLOC sockets only +	 * - stay away from userspace +	 * - have bounded memory usage +	 * +	 * Use PF_MEMALLOC as this saves us from propagating the allocation +	 * context down to all allocation sites. +	 */ +	if (sk_memalloc_socks() && skb_pfmemalloc(skb)) +		current->flags |= PF_MEMALLOC; +  	/* if we've gotten here through NAPI, check netpoll */  	if (netpoll_receive_skb(skb)) -		return NET_RX_DROP; +		goto out;  	orig_dev = skb->dev; @@ -3191,7 +3225,7 @@ another_round:  	if (skb->protocol == cpu_to_be16(ETH_P_8021Q)) {  		skb = vlan_untag(skb);  		if (unlikely(!skb)) -			goto out; +			goto unlock;  	}  #ifdef CONFIG_NET_CLS_ACT @@ -3201,6 +3235,9 @@ another_round:  	}  #endif +	if (sk_memalloc_socks() && skb_pfmemalloc(skb)) +		goto skip_taps; +  	list_for_each_entry_rcu(ptype, &ptype_all, list) {  		if (!ptype->dev || ptype->dev == skb->dev) {  			if (pt_prev) @@ -3209,13 +3246,18 @@ another_round:  		}  	} +skip_taps:  #ifdef CONFIG_NET_CLS_ACT  	skb = handle_ing(skb, &pt_prev, &ret, orig_dev);  	if (!skb) -		goto out; +		goto unlock;  ncls:  #endif +	if (sk_memalloc_socks() && skb_pfmemalloc(skb) +				&& !skb_pfmemalloc_protocol(skb)) +		goto drop; +  	rx_handler = rcu_dereference(skb->dev->rx_handler);  	if (vlan_tx_tag_present(skb)) {  		if (pt_prev) { @@ -3225,7 +3267,7 @@ ncls:  		if (vlan_do_receive(&skb, !rx_handler))  			goto another_round;  		else if (unlikely(!skb)) -			goto out; +			goto unlock;  	}  	if (rx_handler) { @@ -3235,7 +3277,7 @@ ncls:  		}  		switch (rx_handler(&skb)) {  		case RX_HANDLER_CONSUMED: -			goto out; +			goto unlock;  		case RX_HANDLER_ANOTHER:  			goto another_round;  		case RX_HANDLER_EXACT: @@ -3268,6 +3310,7 @@ ncls:  		else  			ret = pt_prev->func(skb, skb->dev, pt_prev, orig_dev);  	} else { +drop:  		atomic_long_inc(&skb->dev->rx_dropped);  		kfree_skb(skb);  		/* Jamal, now you will not able to escape explaining @@ -3276,8 +3319,10 @@ ncls:  		ret = NET_RX_DROP;  	} -out: +unlock:  	rcu_read_unlock(); +out: +	tsk_restore_flags(current, pflags, PF_MEMALLOC);  	return ret;  } @@ -4801,6 +4846,7 @@ int dev_set_mac_address(struct net_device *dev, struct sockaddr *sa)  	err = ops->ndo_set_mac_address(dev, sa);  	if (!err)  		call_netdevice_notifiers(NETDEV_CHANGEADDR, dev); +	add_device_randomness(dev->dev_addr, dev->addr_len);  	return err;  }  EXPORT_SYMBOL(dev_set_mac_address); @@ -5579,6 +5625,7 @@ int register_netdevice(struct net_device *dev)  	dev_init_scheduler(dev);  	dev_hold(dev);  	list_netdevice(dev); +	add_device_randomness(dev->dev_addr, dev->addr_len);  	/* Notify protocols, that a new device appeared. */  	ret = call_netdevice_notifiers(NETDEV_REGISTER, dev); @@ -5942,6 +5989,7 @@ struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name,  	dev_net_set(dev, &init_net);  	dev->gso_max_size = GSO_MAX_SIZE; +	dev->gso_max_segs = GSO_MAX_SEGS;  	INIT_LIST_HEAD(&dev->napi_list);  	INIT_LIST_HEAD(&dev->unreg_list);  |