Subject: xdp/xsk.c: missing read memory barrier in xsk_poll()

From: Yewon Choi <[email-masked]>
Date: Fri, 24 Nov 2023 16:00:06 +0900

Hello, 

We found some possibility of missing read memory barrier in xsk_poll(),
so we would like to ask to check it.

commit e6762c8b adds two smp_rmb() in xsk_mmap(), which are paired with
smp_wmb() in XDP_UMEM_REG and xsk_init_queue each. The later one is
added in order to prevent reordering between reading of q and reading
of q->ring.
One example in simplied code is:

xsk_mmap():
	if (offset == XDP_PGOFF_RX_RING) {
		q = READ_ONCE(xs->rx);
	}
	...
	if (!q)
		return -EINVAL;

	/* Matches the smp_wmb() in xsk_init_queue */
	smp_rmb();
	...
	return remap_vmalloc_range(vma, q->ring, 0);

Also, the similar logic exists in xsk_poll() without smp_rmb().

xsk_poll():
	...
	if (xs->rx && !xskq_prod_is_empty(xs->rx))
		mask |= EPOLLIN | EPOLLRDNORM;
	if (xs->tx && xsk_tx_writeable(xs))
		mask |= EPOLLOUT | EPOLLWRNORM;

xskq_prod_is_empty():
	return READ_ONCE(q->ring->consumer) && ...

To be consistent, I think that smp_rmb() is needed between
xs->rx and !xsq_prod_is_empty() and the same applies for xs->tx.

Could you check this please?
If a patch is needed, we will send them.

Best Regards,
Yewon Choi