Commit 1616b38f authored by Tom Herbert's avatar Tom Herbert Committed by David S. Miller
Browse files

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: default avatarTom Herbert <tom@herbertland.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent cff6a334
Loading
Loading
Loading
Loading
+15 −5
Original line number Diff line number Diff line
@@ -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->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");
}
+8 −5
Original line number Diff line number Diff line
@@ -1477,12 +1477,13 @@ out:
	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 @@ no_reserved:
		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))