Cloudanix VulnDB

CVE-2026-99127

None

CVSS

—

EPSS

0.2%

Published

Oct 28, 2026

CISA due date

—

Cloudanix analysis

Next patch cycle SSVC: Track

A Linux networking bug can crash servers when certain packet-processing features are active and normal network traffic arrives.

Exploitation
Remote Unauthenticated
Attacker needs
Low Privilege
Complexity
Moderate
Impact
Denial Of Service
Component
OS kernel
Class
Memory Corruption
Remediation
Patch
Effort
Medium
Patch risk
Low

What it actually does

page_pool_alloc_frag_netmem fails to align frag_offset for odd-sized requests on architectures where dma_get_cache_alignment returns 1; subsequent skb_pp_cow_data allocations produce misaligned skb->head buffers whose skb_shinfo()->dataref atomic straddles a cache line, triggering fatal split-lock faults in __skb_clone on x86.

Why it matters to the business

Systems running generic XDP experience kernel panics during ordinary UDP traffic such as DNS, causing immediate reboots, service outages, and loss of in-flight network state.

How an attack unfolds

An attacker or benign high-volume UDP source sends datagrams while a generic-mode XDP program is attached to an interface; skb_pp_cow_data requests raw packet lengths from the shared per-cpu page pool, leaving frag_offset misaligned; later napi_build_skb callers receive the misaligned head, and skb_clone's atomic_inc on dataref at offset 0x20 straddles a cache line, panicking the kernel with split-lock detection.

How to fix it

Apply the upstream fix that rounds requested fragment size up to at least the alignment required by struct skb_shared_info before calling page_pool_alloc_frag_netmem; rebuild and boot the resulting kernel. Architectures with larger DMA alignment retain their existing rounding.

How to confirm the fix worked

Boot the patched kernel, re-attach a generic XDP program, replay the UDP workload, and confirm zero misaligned skb->head values and zero split-lock faults; also verify that page_pool_alloc_frag_netmem now always returns offsets congruent to the required alignment.

Typical attack path

  1. Attach generic XDP program (e.g., XDP_PASS) to loopback or any interface
  2. Generate or receive UDP datagrams larger than max_head_size (ordinary DNS suffices)
  3. skb_pp_cow_data performs page_pool_dev_alloc with unrounded size
  4. frag_offset becomes misaligned for subsequent allocations from the same page
  5. napi_build_skb installs misaligned skb->head
  6. skb_clone executes lock incl across cache-line boundary
  7. Split-lock detection fires and kernel panics

How to detect it

Search kernel logs for 'Oops: Split lock detected' with RIP pointing inside skb_clone, especially on hosts running generic XDP; correlate with raw_local_deliver and UDP receive paths; inspect page_pool tracepoints for repeated odd-sized requests followed by misaligned frag_offset values.

  • Split lock detected
  • skb_clone+0x154
  • skb_shinfo()->dataref at line offset >60
  • page_pool_alloc_frag_netmem.*requested size & 7
  • frag_offset & 7

What your security team should do

  • Patch and reboot all systems exposing generic XDP within the next maintenance window
  • Add kernel oops monitoring for 'Split lock detected' and 'skb_clone' to SIEM
  • Temporarily disable generic XDP on high-availability UDP paths if patching is delayed
  • Track kernel changelog for the exact commit that enforces skb_shared_info alignment

The record

In the Linux kernel, the following vulnerability has been resolved: page_pool: keep frag_offset aligned for odd-sized requests page_pool_alloc_frag_netmem() rounds the requested fragment size with size = ALIGN(size, dma_get_cache_alignment()); dma_get_cache_alignment() returns 1 unless the architecture defines ARCH_DMA_MINALIGN, which DMA-coherent architectures such as x86 do not. There the ALIGN() is a no-op and pool->frag_offset advances by the raw, unrounded size. A single caller asking for an odd size then leaves frag_offset misaligned for every fragment carved out of that page afterwards. The pool is shared, so the damage is not confined to the caller that caused it. The per-cpu system_page_pool used by generic XDP hits this. skb_pp_cow_data() allocates its fragments with the raw packet length: size = min_t(u32, len, PAGE_SIZE); truesize = size; page = page_pool_dev_alloc(pool, &page_off, &truesize); leaving frag_offset odd for whatever is carved out of that page next. Its own head allocation is already aligned -- SKB_HEAD_ALIGN(size) plus the XDP_PACKET_HEADROOM its callers pass -- so it is a later user of the shared pool that pays: page_pool_dev_alloc_va() returns a misaligned buffer, napi_build_skb() installs it as skb->head, and skb_shinfo(skb) == skb->head + skb->end is misaligned with it. skb_shinfo()->dataref is a 4-byte atomic_t at offset 0x20, so the atomic_inc() in __skb_clone() straddles a cache line. On x86 with split lock detection -- fatal for kernel split locks by default -- this panics the machine: Oops: Split lock detected RIP: 0010:skb_clone+0x154/0x1e0 Call Trace: <IRQ> raw_local_deliver+0x1ed/0x2c0 ip_protocol_deliver_rcu+0x54/0x1c0 ip_local_deliver_finish+0x85/0x100 ip_local_deliver+0x67/0x100 __netif_receive_skb_one_core+0x85/0xa0 process_backlog+0x87/0x130 Reproduced by attaching any generic-mode XDP program to loopback and opening a RAW IPPROTO_UDP socket, which makes raw_local_deliver() clone every locally delivered UDP packet; ordinary DNS traffic then triggers it, roughly once per 2500 clones. Observed on 6.12.101 and 7.1.8. Tracing page_pool_alloc_frag_netmem() over one such run shows the amplification -- two odd-sized requests, nine misaligned offsets: requested size & 7: 0: 17035 5: 1 7: 1 frag_offset & 7: 0: 17028 3: 1 4: 1 5: 1 6: 1 7: 5 and skb_pp_cow_data() returning heads that were aligned on entry: head 0xffff8f4c86aeac00 -> 0xffff8f4c53a9a9c4 (&7=4) head 0xffff8f4d6a8a42c0 -> 0xffff8f4c4f7b7a45 (&7=5) Round the fragment size up to at least the alignment struct skb_shared_info requires, so fragments are always suitably aligned for the objects callers build on them. Architectures needing a larger DMA alignment keep it. This also makes the remainder computed in page_pool_alloc_netmem(), *size = max_size - *offset; aligned, since max_size is a power of two -- which fixes the matching misalignment of skb->end. Verified with a controlled A/B under QEMU/KVM: same tree, same config, same compiler, same rootfs and identical traffic, differing only by this patch. A SEC("xdp.frags") XDP_PASS program on lo plus UDP datagrams larger than max_head_size drives skb_pp_cow_data()'s fragment loop, which passes raw packet lengths to the pool. Measured at the return of skb_pp_cow_data(): unpatched patched skb_pp_cow_data calls 40800 40800 misaligned skb->head 1120 0 dataref at line offset >60 80 0 The last row counts the accesses that actually fault: skb_shinfo()->dataref sits at head+end+0x20 and is a 4-byte atomic, so `lock incl` splits a 64-byte cache line only when that address lands at offset 61..63. All 80 occurrences were at offset 61; the panic reported above was at offset 62. Eliminating the misalignment removes every one of them. Same class of bug as commit 3bed3cc4156e ("net: Do not allocate page fragments t ---truncated---

Affected packages

Ecosystem Package Introduced Fixed