In the Linux kernel, the following vulnerability has been resolved:
skbuff: Fix a race between coalescing and releasing SKBs
Commit 1effe8ca4e34 ("skbuff: fix coalescing for page_pool fragment recycling") allowed coalescing to proceed with non page pool page and page pool page when @from is cloned, i.e.
to->pprecycle --> false from->pprecycle --> true skb_cloned(from) --> true
However, it actually requires skbcloned(@from) to hold true until coalescing finishes in this situation. If the other cloned SKB is released while the merging is in process, fromshinfo->nr_frags will be set to 0 toward the end of the function, causing the increment of frag page _refcount to be unexpectedly skipped resulting in inconsistent reference counts. Later when SKB(@to) is released, it frees the page directly even though the page pool page is still in use, leading to use-after-free or double-free errors. So it should be prohibited.
The double-free error message below prompted us to investigate: BUG: Bad page state in process swapper/1 pfn:0e0d1 page:00000000c6548b28 refcount:-1 mapcount:0 mapping:0000000000000000 index:0x2 pfn:0xe0d1 flags: 0xfffffc0000000(node=0|zone=1|lastcpupid=0x1fffff) raw: 000fffffc0000000 0000000000000000 ffffffff00000101 0000000000000000 raw: 0000000000000002 0000000000000000 ffffffffffffffff 0000000000000000 page dumped because: nonzero _refcount
CPU: 1 PID: 0 Comm: swapper/1 Tainted: G E 6.2.0+ Call Trace: <IRQ> dumpstacklvl+0x32/0x50 badpage+0x69/0xf0 freepcpprepare+0x260/0x2f0 freeunrefpage+0x20/0x1c0 skbreleasedata+0x10b/0x1a0 napiconsumeskb+0x56/0x150 netrxaction+0xf0/0x350 ? _napischedule+0x79/0x90 _dosoftirq+0xc8/0x2b1 _irqexitrcu+0xb9/0xf0 commoninterrupt+0x82/0xa0 </IRQ> <TASK> asmcommoninterrupt+0x22/0x40 RIP: 0010:defaultidle+0xb/0x20