diff options
| author | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2021-08-09 09:03:47 +0200 | 
|---|---|---|
| committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2021-08-09 09:03:47 +0200 | 
| commit | bd935a7b21340e2e37f51a7f2d3188145e2fcf1f (patch) | |
| tree | ac8af4e6ea552d32839c415b2f36d416ee327ea4 /net/core/skmsg.c | |
| parent | 96ba6c6e8922e89ca4908c650072d8f8d7b39cbc (diff) | |
| parent | 36a21d51725af2ce0700c6ebcb6b9594aac658a6 (diff) | |
Merge 5.14-rc5 into driver-core-next
We need the driver core fixes in here as well.
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'net/core/skmsg.c')
| -rw-r--r-- | net/core/skmsg.c | 39 | 
1 files changed, 28 insertions, 11 deletions
| diff --git a/net/core/skmsg.c b/net/core/skmsg.c index 15d71288e741..2d6249b28928 100644 --- a/net/core/skmsg.c +++ b/net/core/skmsg.c @@ -584,29 +584,42 @@ static int sk_psock_handle_skb(struct sk_psock *psock, struct sk_buff *skb,  	return sk_psock_skb_ingress(psock, skb);  } -static void sock_drop(struct sock *sk, struct sk_buff *skb) +static void sk_psock_skb_state(struct sk_psock *psock, +			       struct sk_psock_work_state *state, +			       struct sk_buff *skb, +			       int len, int off)  { -	sk_drops_add(sk, skb); -	kfree_skb(skb); +	spin_lock_bh(&psock->ingress_lock); +	if (sk_psock_test_state(psock, SK_PSOCK_TX_ENABLED)) { +		state->skb = skb; +		state->len = len; +		state->off = off; +	} else { +		sock_drop(psock->sk, skb); +	} +	spin_unlock_bh(&psock->ingress_lock);  }  static void sk_psock_backlog(struct work_struct *work)  {  	struct sk_psock *psock = container_of(work, struct sk_psock, work);  	struct sk_psock_work_state *state = &psock->work_state; -	struct sk_buff *skb; +	struct sk_buff *skb = NULL;  	bool ingress;  	u32 len, off;  	int ret;  	mutex_lock(&psock->work_mutex); -	if (state->skb) { +	if (unlikely(state->skb)) { +		spin_lock_bh(&psock->ingress_lock);  		skb = state->skb;  		len = state->len;  		off = state->off;  		state->skb = NULL; -		goto start; +		spin_unlock_bh(&psock->ingress_lock);  	} +	if (skb) +		goto start;  	while ((skb = skb_dequeue(&psock->ingress_skb))) {  		len = skb->len; @@ -621,9 +634,8 @@ start:  							  len, ingress);  			if (ret <= 0) {  				if (ret == -EAGAIN) { -					state->skb = skb; -					state->len = len; -					state->off = off; +					sk_psock_skb_state(psock, state, skb, +							   len, off);  					goto end;  				}  				/* Hard errors break pipe and stop xmit. */ @@ -722,6 +734,11 @@ static void __sk_psock_zap_ingress(struct sk_psock *psock)  		skb_bpf_redirect_clear(skb);  		sock_drop(psock->sk, skb);  	} +	kfree_skb(psock->work_state.skb); +	/* We null the skb here to ensure that calls to sk_psock_backlog +	 * do not pick up the free'd skb. +	 */ +	psock->work_state.skb = NULL;  	__sk_psock_purge_ingress_msg(psock);  } @@ -773,8 +790,6 @@ static void sk_psock_destroy(struct work_struct *work)  void sk_psock_drop(struct sock *sk, struct sk_psock *psock)  { -	sk_psock_stop(psock, false); -  	write_lock_bh(&sk->sk_callback_lock);  	sk_psock_restore_proto(sk, psock);  	rcu_assign_sk_user_data(sk, NULL); @@ -784,6 +799,8 @@ void sk_psock_drop(struct sock *sk, struct sk_psock *psock)  		sk_psock_stop_verdict(sk, psock);  	write_unlock_bh(&sk->sk_callback_lock); +	sk_psock_stop(psock, false); +  	INIT_RCU_WORK(&psock->rwork, sk_psock_destroy);  	queue_rcu_work(system_wq, &psock->rwork);  } | 
