Commit 931ae86f authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'kcm-data-races'



Eric Dumazet says:

====================
kcm: annotate data-races

This series address two different syzbot reports for KCM.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents c99f0f7e 0c745b51
Loading
Loading
Loading
Loading
+15 −8
Original line number Diff line number Diff line
@@ -162,7 +162,8 @@ static void kcm_rcv_ready(struct kcm_sock *kcm)
	/* Buffer limit is okay now, add to ready list */
	list_add_tail(&kcm->wait_rx_list,
		      &kcm->mux->kcm_rx_waiters);
	kcm->rx_wait = true;
	/* paired with lockless reads in kcm_rfree() */
	WRITE_ONCE(kcm->rx_wait, true);
}

static void kcm_rfree(struct sk_buff *skb)
@@ -178,7 +179,7 @@ static void kcm_rfree(struct sk_buff *skb)
	/* For reading rx_wait and rx_psock without holding lock */
	smp_mb__after_atomic();

	if (!kcm->rx_wait && !kcm->rx_psock &&
	if (!READ_ONCE(kcm->rx_wait) && !READ_ONCE(kcm->rx_psock) &&
	    sk_rmem_alloc_get(sk) < sk->sk_rcvlowat) {
		spin_lock_bh(&mux->rx_lock);
		kcm_rcv_ready(kcm);
@@ -237,7 +238,8 @@ static void requeue_rx_msgs(struct kcm_mux *mux, struct sk_buff_head *head)
		if (kcm_queue_rcv_skb(&kcm->sk, skb)) {
			/* Should mean socket buffer full */
			list_del(&kcm->wait_rx_list);
			kcm->rx_wait = false;
			/* paired with lockless reads in kcm_rfree() */
			WRITE_ONCE(kcm->rx_wait, false);

			/* Commit rx_wait to read in kcm_free */
			smp_wmb();
@@ -280,10 +282,12 @@ static struct kcm_sock *reserve_rx_kcm(struct kcm_psock *psock,
	kcm = list_first_entry(&mux->kcm_rx_waiters,
			       struct kcm_sock, wait_rx_list);
	list_del(&kcm->wait_rx_list);
	kcm->rx_wait = false;
	/* paired with lockless reads in kcm_rfree() */
	WRITE_ONCE(kcm->rx_wait, false);

	psock->rx_kcm = kcm;
	kcm->rx_psock = psock;
	/* paired with lockless reads in kcm_rfree() */
	WRITE_ONCE(kcm->rx_psock, psock);

	spin_unlock_bh(&mux->rx_lock);

@@ -310,7 +314,8 @@ static void unreserve_rx_kcm(struct kcm_psock *psock,
	spin_lock_bh(&mux->rx_lock);

	psock->rx_kcm = NULL;
	kcm->rx_psock = NULL;
	/* paired with lockless reads in kcm_rfree() */
	WRITE_ONCE(kcm->rx_psock, NULL);

	/* Commit kcm->rx_psock before sk_rmem_alloc_get to sync with
	 * kcm_rfree
@@ -1240,7 +1245,8 @@ static void kcm_recv_disable(struct kcm_sock *kcm)
	if (!kcm->rx_psock) {
		if (kcm->rx_wait) {
			list_del(&kcm->wait_rx_list);
			kcm->rx_wait = false;
			/* paired with lockless reads in kcm_rfree() */
			WRITE_ONCE(kcm->rx_wait, false);
		}

		requeue_rx_msgs(mux, &kcm->sk.sk_receive_queue);
@@ -1793,7 +1799,8 @@ static void kcm_done(struct kcm_sock *kcm)

	if (kcm->rx_wait) {
		list_del(&kcm->wait_rx_list);
		kcm->rx_wait = false;
		/* paired with lockless reads in kcm_rfree() */
		WRITE_ONCE(kcm->rx_wait, false);
	}
	/* Move any pending receive messages to other kcm sockets */
	requeue_rx_msgs(mux, &sk->sk_receive_queue);