diff options
Diffstat (limited to 'net/core')
| -rw-r--r-- | net/core/devmem.c | 27 | ||||
| -rw-r--r-- | net/core/filter.c | 3 | 
2 files changed, 26 insertions, 4 deletions
diff --git a/net/core/devmem.c b/net/core/devmem.c index d9de31a6cc7f..1d04754bc756 100644 --- a/net/core/devmem.c +++ b/net/core/devmem.c @@ -17,6 +17,7 @@  #include <net/page_pool/helpers.h>  #include <net/page_pool/memory_provider.h>  #include <net/sock.h> +#include <net/tcp.h>  #include <trace/events/page_pool.h>  #include "devmem.h" @@ -357,7 +358,8 @@ struct net_devmem_dmabuf_binding *net_devmem_get_binding(struct sock *sk,  							 unsigned int dmabuf_id)  {  	struct net_devmem_dmabuf_binding *binding; -	struct dst_entry *dst = __sk_dst_get(sk); +	struct net_device *dst_dev; +	struct dst_entry *dst;  	int err = 0;  	binding = net_devmem_lookup_dmabuf(dmabuf_id); @@ -366,16 +368,35 @@ struct net_devmem_dmabuf_binding *net_devmem_get_binding(struct sock *sk,  		goto out_err;  	} +	rcu_read_lock(); +	dst = __sk_dst_get(sk); +	/* If dst is NULL (route expired), attempt to rebuild it. */ +	if (unlikely(!dst)) { +		if (inet_csk(sk)->icsk_af_ops->rebuild_header(sk)) { +			err = -EHOSTUNREACH; +			goto out_unlock; +		} +		dst = __sk_dst_get(sk); +		if (unlikely(!dst)) { +			err = -ENODEV; +			goto out_unlock; +		} +	} +  	/* The dma-addrs in this binding are only reachable to the corresponding  	 * net_device.  	 */ -	if (!dst || !dst->dev || dst->dev->ifindex != binding->dev->ifindex) { +	dst_dev = dst_dev_rcu(dst); +	if (unlikely(!dst_dev) || unlikely(dst_dev != binding->dev)) {  		err = -ENODEV; -		goto out_err; +		goto out_unlock;  	} +	rcu_read_unlock();  	return binding; +out_unlock: +	rcu_read_unlock();  out_err:  	if (binding)  		net_devmem_dmabuf_binding_put(binding); diff --git a/net/core/filter.c b/net/core/filter.c index 76628df1fc82..fa06c5a08e22 100644 --- a/net/core/filter.c +++ b/net/core/filter.c @@ -3877,7 +3877,8 @@ static inline int __bpf_skb_change_head(struct sk_buff *skb, u32 head_room,  	u32 new_len = skb->len + head_room;  	int ret; -	if (unlikely(flags || (!skb_is_gso(skb) && new_len > max_len) || +	if (unlikely(flags || (int)head_room < 0 || +		     (!skb_is_gso(skb) && new_len > max_len) ||  		     new_len < skb->len))  		return -EINVAL;  | 
