Skip to content

Commit 291cfe3

Browse files
zpostfactoborkmann
authored andcommitted
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 <[email protected]> Signed-off-by: Daniel Borkmann <[email protected]> Acked-by: Magnus Karlsson <[email protected]> Link: https://lore.kernel.org/bpf/[email protected]
1 parent 2cf69d3 commit 291cfe3

File tree

1 file changed

+14
-2
lines changed

1 file changed

+14
-2
lines changed

tools/lib/bpf/xsk.c

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -280,7 +280,11 @@ int xsk_umem__create_v0_0_4(struct xsk_umem **umem_ptr, void *umem_area,
280280
fill->consumer = map + off.fr.consumer;
281281
fill->flags = map + off.fr.flags;
282282
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;
284288

285289
map = mmap(NULL, off.cr.desc + umem->config.comp_size * sizeof(__u64),
286290
PROT_READ | PROT_WRITE, MAP_SHARED | MAP_POPULATE, umem->fd,
@@ -297,6 +301,8 @@ int xsk_umem__create_v0_0_4(struct xsk_umem **umem_ptr, void *umem_area,
297301
comp->consumer = map + off.cr.consumer;
298302
comp->flags = map + off.cr.flags;
299303
comp->ring = map + off.cr.desc;
304+
comp->cached_prod = *comp->producer;
305+
comp->cached_cons = *comp->consumer;
300306

301307
*umem_ptr = umem;
302308
return 0;
@@ -672,6 +678,8 @@ int xsk_socket__create(struct xsk_socket **xsk_ptr, const char *ifname,
672678
rx->consumer = rx_map + off.rx.consumer;
673679
rx->flags = rx_map + off.rx.flags;
674680
rx->ring = rx_map + off.rx.desc;
681+
rx->cached_prod = *rx->producer;
682+
rx->cached_cons = *rx->consumer;
675683
}
676684
xsk->rx = rx;
677685

@@ -691,7 +699,11 @@ int xsk_socket__create(struct xsk_socket **xsk_ptr, const char *ifname,
691699
tx->consumer = tx_map + off.tx.consumer;
692700
tx->flags = tx_map + off.tx.flags;
693701
tx->ring = tx_map + off.tx.desc;
694-
tx->cached_cons = xsk->config.tx_size;
702+
tx->cached_prod = *tx->producer;
703+
/* cached_cons is r->size bigger than the real consumer pointer
704+
* See xsk_prod_nb_free
705+
*/
706+
tx->cached_cons = *tx->consumer + xsk->config.tx_size;
695707
}
696708
xsk->tx = tx;
697709

0 commit comments

Comments
 (0)