mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	kcm: Fix locking issue
Lock the lower socket in kcm_unattach. Release during call to strp_done since that function cancels the RX timers and work queue with sync. Also added some status information in psock reporting. Signed-off-by: Tom Herbert <tom@herbertland.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
		
							parent
							
								
									cff6a334e6
								
							
						
					
					
						commit
						1616b38f20
					
				
					 2 changed files with 23 additions and 10 deletions
				
			
		| 
						 | 
				
			
			@ -173,14 +173,24 @@ static void kcm_format_psock(struct kcm_psock *psock, struct seq_file *seq,
 | 
			
		|||
	if (psock->strp.rx_stopped)
 | 
			
		||||
		seq_puts(seq, "RxStop ");
 | 
			
		||||
 | 
			
		||||
	if (psock->strp.rx_paused)
 | 
			
		||||
		seq_puts(seq, "RxPause ");
 | 
			
		||||
 | 
			
		||||
	if (psock->tx_kcm)
 | 
			
		||||
		seq_printf(seq, "Rsvd-%d ", psock->tx_kcm->index);
 | 
			
		||||
 | 
			
		||||
	if (psock->ready_rx_msg)
 | 
			
		||||
		seq_puts(seq, "RdyRx ");
 | 
			
		||||
	if (!psock->strp.rx_paused && !psock->ready_rx_msg) {
 | 
			
		||||
		if (psock->sk->sk_receive_queue.qlen) {
 | 
			
		||||
			if (psock->strp.rx_need_bytes)
 | 
			
		||||
				seq_printf(seq, "RxWait=%u ",
 | 
			
		||||
					   psock->strp.rx_need_bytes);
 | 
			
		||||
			else
 | 
			
		||||
				seq_printf(seq, "RxWait ");
 | 
			
		||||
		}
 | 
			
		||||
	} else  {
 | 
			
		||||
		if (psock->strp.rx_paused)
 | 
			
		||||
			seq_puts(seq, "RxPause ");
 | 
			
		||||
 | 
			
		||||
		if (psock->ready_rx_msg)
 | 
			
		||||
			seq_puts(seq, "RdyRx ");
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	seq_puts(seq, "\n");
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1477,12 +1477,13 @@ static int kcm_attach_ioctl(struct socket *sock, struct kcm_attach *info)
 | 
			
		|||
	return err;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Lower socket lock held */
 | 
			
		||||
static void kcm_unattach(struct kcm_psock *psock)
 | 
			
		||||
{
 | 
			
		||||
	struct sock *csk = psock->sk;
 | 
			
		||||
	struct kcm_mux *mux = psock->mux;
 | 
			
		||||
 | 
			
		||||
	lock_sock(csk);
 | 
			
		||||
 | 
			
		||||
	/* Stop getting callbacks from TCP socket. After this there should
 | 
			
		||||
	 * be no way to reserve a kcm for this psock.
 | 
			
		||||
	 */
 | 
			
		||||
| 
						 | 
				
			
			@ -1514,7 +1515,10 @@ static void kcm_unattach(struct kcm_psock *psock)
 | 
			
		|||
 | 
			
		||||
	write_unlock_bh(&csk->sk_callback_lock);
 | 
			
		||||
 | 
			
		||||
	/* Call strp_done without sock lock */
 | 
			
		||||
	release_sock(csk);
 | 
			
		||||
	strp_done(&psock->strp);
 | 
			
		||||
	lock_sock(csk);
 | 
			
		||||
 | 
			
		||||
	bpf_prog_put(psock->bpf_prog);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1564,6 +1568,8 @@ static void kcm_unattach(struct kcm_psock *psock)
 | 
			
		|||
		fput(csk->sk_socket->file);
 | 
			
		||||
		kmem_cache_free(kcm_psockp, psock);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	release_sock(csk);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int kcm_unattach_ioctl(struct socket *sock, struct kcm_unattach *info)
 | 
			
		||||
| 
						 | 
				
			
			@ -1749,11 +1755,8 @@ static void release_mux(struct kcm_mux *mux)
 | 
			
		|||
	/* Release psocks */
 | 
			
		||||
	list_for_each_entry_safe(psock, tmp_psock,
 | 
			
		||||
				 &mux->psocks, psock_list) {
 | 
			
		||||
		if (!WARN_ON(psock->unattaching)) {
 | 
			
		||||
			lock_sock(psock->strp.sk);
 | 
			
		||||
		if (!WARN_ON(psock->unattaching))
 | 
			
		||||
			kcm_unattach(psock);
 | 
			
		||||
			release_sock(psock->strp.sk);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (WARN_ON(mux->psocks_cnt))
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue