Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

libbpf, xsk: Init all ring members in xsk_umem__create and xsk_socket__create

Fix a sharp edge in xsk_umem__create and xsk_socket__create. Almost all of
the members of the ring buffer structs are initialized, but the "cached_xxx"
variables are not all initialized. The caller is required to zero them.
This is needlessly dangerous. The results if you don't do it can be very bad.
For example, they can cause xsk_prod_nb_free and xsk_cons_nb_avail to return
values greater than the size of the queue. xsk_ring_cons__peek can return an
index that does not refer to an item that has been queued.

I have confirmed that without this change, my program misbehaves unless I
memset the ring buffers to zero before calling the function. Afterwards,
my program works without (or with) the memset.

Signed-off-by: Fletcher Dunn <fletcherd@valvesoftware.com>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Acked-by: Magnus Karlsson <magnus.karlsson@intel.com>
Link: https://lore.kernel.org/bpf/85f12913cde94b19bfcb598344701c38@valvesoftware.com

authored by

Fletcher Dunn and committed by
Daniel Borkmann
291cfe36 2cf69d3f

+14 -2
+14 -2
tools/lib/bpf/xsk.c
··· 280 280 fill->consumer = map + off.fr.consumer; 281 281 fill->flags = map + off.fr.flags; 282 282 fill->ring = map + off.fr.desc; 283 - fill->cached_cons = umem->config.fill_size; 283 + fill->cached_prod = *fill->producer; 284 + /* cached_cons is "size" bigger than the real consumer pointer 285 + * See xsk_prod_nb_free 286 + */ 287 + fill->cached_cons = *fill->consumer + umem->config.fill_size; 284 288 285 289 map = mmap(NULL, off.cr.desc + umem->config.comp_size * sizeof(__u64), 286 290 PROT_READ | PROT_WRITE, MAP_SHARED | MAP_POPULATE, umem->fd, ··· 301 297 comp->consumer = map + off.cr.consumer; 302 298 comp->flags = map + off.cr.flags; 303 299 comp->ring = map + off.cr.desc; 300 + comp->cached_prod = *comp->producer; 301 + comp->cached_cons = *comp->consumer; 304 302 305 303 *umem_ptr = umem; 306 304 return 0; ··· 678 672 rx->consumer = rx_map + off.rx.consumer; 679 673 rx->flags = rx_map + off.rx.flags; 680 674 rx->ring = rx_map + off.rx.desc; 675 + rx->cached_prod = *rx->producer; 676 + rx->cached_cons = *rx->consumer; 681 677 } 682 678 xsk->rx = rx; 683 679 ··· 699 691 tx->consumer = tx_map + off.tx.consumer; 700 692 tx->flags = tx_map + off.tx.flags; 701 693 tx->ring = tx_map + off.tx.desc; 702 - tx->cached_cons = xsk->config.tx_size; 694 + tx->cached_prod = *tx->producer; 695 + /* cached_cons is r->size bigger than the real consumer pointer 696 + * See xsk_prod_nb_free 697 + */ 698 + tx->cached_cons = *tx->consumer + xsk->config.tx_size; 703 699 } 704 700 xsk->tx = tx; 705 701