Skip to content

Commit e51a0be

Browse files
mfijalkoKernel Patches Daemon
authored andcommitted
xdp: update xdp_rxq_info's mem type in XDP generic hook
Currently, generic XDP hook uses xdp_rxq_info from netstack Rx queues which do not have its XDP memory model registered. There is a case when XDP program calls bpf_xdp_adjust_tail() BPF helper that releases underlying memory. This happens when it consumes enough amount of bytes and when XDP buffer has fragments. For this action the memory model knowledge passed to XDP program is crucial so that core can call suitable function for freeing/recycling the page. For netstack queues it defaults to MEM_TYPE_PAGE_SHARED (0) due to lack of mem model registration. The problem we're fixing here is when kernel copied the skb to new buffer backed by system's page_pool and XDP buffer is built around it. Then when bpf_xdp_adjust_tail() calls __xdp_return(), it acts incorrectly due to mem type not being set to MEM_TYPE_PAGE_POOL and causes a page leak. For this purpose introduce a small helper, xdp_update_mem_type(), that could be used on other callsites such as veth which are open to this problem as well. Here we call it right before executing XDP program in generic XDP hook. This problem was triggered by syzbot as well as AF_XDP test suite which is about to be integrated to BPF CI. Reported-by: [email protected] Closes: https://lore.kernel.org/netdev/[email protected]/ Fixes: e6d5dbd ("xdp: add multi-buff support for xdp running in generic mode") Tested-by: Ihor Solodrai <[email protected]> Co-developed-by: Octavian Purdila <[email protected]> Signed-off-by: Octavian Purdila <[email protected]> # whole analysis, testing, initiating a fix Signed-off-by: Maciej Fijalkowski <[email protected]> # commit msg and proposed more robust fix
1 parent 4b68031 commit e51a0be

File tree

2 files changed

+9
-0
lines changed

2 files changed

+9
-0
lines changed

include/net/xdp.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -336,6 +336,13 @@ xdp_update_skb_shared_info(struct sk_buff *skb, u8 nr_frags,
336336
skb->pfmemalloc |= pfmemalloc;
337337
}
338338

339+
static inline void
340+
xdp_update_mem_type(struct xdp_buff *xdp)
341+
{
342+
xdp->rxq->mem.type = page_pool_page_is_pp(virt_to_page(xdp->data)) ?
343+
MEM_TYPE_PAGE_POOL : MEM_TYPE_PAGE_SHARED;
344+
}
345+
339346
/* Avoids inlining WARN macro in fast-path */
340347
void xdp_warn(const char *msg, const char *func, const int line);
341348
#define XDP_WARN(msg) xdp_warn(msg, __func__, __LINE__)

net/core/dev.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5269,6 +5269,8 @@ u32 bpf_prog_run_generic_xdp(struct sk_buff *skb, struct xdp_buff *xdp,
52695269
orig_bcast = is_multicast_ether_addr_64bits(eth->h_dest);
52705270
orig_eth_type = eth->h_proto;
52715271

5272+
xdp_update_mem_type(xdp);
5273+
52725274
act = bpf_prog_run_xdp(xdp_prog, xdp);
52735275

52745276
/* check if bpf_xdp_adjust_head was used */

0 commit comments

Comments
 (0)