Wind River Support Network

HomeDefectsLIN1022-18366
Acknowledged

LIN1022-18366 : Security Advisory - linux - CVE-2022-50483

Created: Oct 10, 2025    Updated: Oct 17, 2025
Found In Version: 10.22.33.1
Severity: Standard
Applicable for: Wind River Linux LTS 22
Component/s: Kernel

Description

In the Linux kernel, the following vulnerability has been resolved:[EOL][EOL]net: enetc: avoid buffer leaks on xdp_do_redirect() failure[EOL][EOL]Before enetc_clean_rx_ring_xdp() calls xdp_do_redirect(), each software[EOL]BD in the RX ring between index orig_i and i can have one of 2 refcount[EOL]values on its page.[EOL][EOL]We are the owner of the current buffer that is being processed, so the[EOL]refcount will be at least 1.[EOL][EOL]If the current owner of the buffer at the diametrically opposed index[EOL]in the RX ring (i.o.w, the other half of this page) has not yet called[EOL]kfree(), this page's refcount could even be 2.[EOL][EOL]enetc_page_reusable() in enetc_flip_rx_buff() tests for the page[EOL]refcount against 1, and [ if it's 2 ] does not attempt to reuse it.[EOL][EOL]But if enetc_flip_rx_buff() is put after the xdp_do_redirect() call,[EOL]the page refcount can have one of 3 values. It can also be 0, if there[EOL]is no owner of the other page half, and xdp_do_redirect() for this[EOL]buffer ran so far that it triggered a flush of the devmap/cpumap bulk[EOL]queue, and the consumers of those bulk queues also freed the buffer,[EOL]all by the time xdp_do_redirect() returns the execution back to enetc.[EOL][EOL]This is the reason why enetc_flip_rx_buff() is called before[EOL]xdp_do_redirect(), but there is a big flaw with that reasoning:[EOL]enetc_flip_rx_buff() will set rx_swbd->page = NULL on both sides of the[EOL]enetc_page_reusable() branch, and if xdp_do_redirect() returns an error,[EOL]we call enetc_xdp_free(), which does not deal gracefully with that.[EOL][EOL]In fact, what happens is quite special. The page refcounts start as 1.[EOL]enetc_flip_rx_buff() figures they're reusable, transfers these[EOL]rx_swbd->page pointers to a different rx_swbd in enetc_reuse_page(), and[EOL]bumps the refcount to 2. When xdp_do_redirect() later returns an error,[EOL]we call the no-op enetc_xdp_free(), but we still haven't lost the[EOL]reference to that page. A copy of it is still at rx_ring->next_to_alloc,[EOL]but that has refcount 2 (and there are no concurrent owners of it in[EOL]flight, to drop the refcount). What really kills the system is when[EOL]we'll flip the rx_swbd->page the second time around. With an updated[EOL]refcount of 2, the page will not be reusable and we'll really leak it.[EOL]Then enetc_new_page() will have to allocate more pages, which will then[EOL]eventually leak again on further errors from xdp_do_redirect().[EOL][EOL]The problem, summarized, is that we zeroize rx_swbd->page before we're[EOL]completely done with it, and this makes it impossible for the error path[EOL]to do something with it.[EOL][EOL]Since the packet is potentially multi-buffer and therefore the[EOL]rx_swbd->page is potentially an array, manual passing of the old[EOL]pointers between enetc_flip_rx_buff() and enetc_xdp_free() is a bit[EOL]difficult.[EOL][EOL]For the sake of going with a simple solution, we accept the possibility[EOL]of racing with xdp_do_redirect(), and we move the flip procedure to[EOL]execute only on the redirect success path. By racing, I mean that the[EOL]page may be deemed as not reusable by enetc (having a refcount of 0),[EOL]but there will be no leak in that case, either.[EOL][EOL]Once we accept that, we have something better to do with buffers on[EOL]XDP_REDIRECT failure. Since we haven't performed half-page flipping yet,[EOL]we won't, either (and this way, we can avoid enetc_xdp_free()[EOL]completely, which gives the entire page to the slab allocator).[EOL]Instead, we'll call enetc_xdp_drop(), which will recycle this half of[EOL]the buffer back to the RX ring.
Live chat
Online