Odebrany

CVE-2026-99127

opublikowano:
modyfikacja:
Ocena CVSS
n/a
Brak oceny

>_ Opis

Tłumaczenie automatyczne – może zawierać nieścisłości.

W jądrze Linuksa usunięto następującą lukę:

page_pool: wyrównaj frag_offset w przypadku żądań o nieparzystej wielkości

page_pool_alloc_frag_netmem() zaokrągla żądany rozmiar fragmentu za pomocą

rozmiar = ALIGN(rozmiar, dma_get_cache_alignment());

dma_get_cache_alignment() zwraca 1, chyba że architektura tak definiuje
ARCH_DMA_MINALIGN, czego nie mają architektury spójne z DMA, takie jak x86.
Tam funkcja ALIGN() nie daje żadnego efektu, a pula->frag_offset postępuje w sposób surowy,
niezaokrąglony rozmiar.

Pojedynczy obiekt wywołujący pytający o nieparzysty rozmiar pozostawia frag_offset źle wyrównany
za każdy fragment wyryty później na tej stronie. Basen jest wspólny,
więc szkoda nie ogranicza się do dzwoniącego, który ją spowodował.

System_page_pool na procesor używany przez ogólny XDP osiąga to.
skb_pp_cow_data() przydziela swoje fragmenty z surową długością pakietu:

rozmiar = min_t(u32, dł., PAGE_SIZE);
truesize = rozmiar;
strona = page_pool_dev_alloc(pool, &page_off, &truesize);

pozostawienie frag_offset nieparzystego dla tego, co zostanie wyryte na następnej stronie. Jego
własny przydział głowicy jest już wyrównany - SKB_HEAD_ALIGN(rozmiar) plus
XDP_PACKET_HEADROOM jego wywołujący przechodzą - więc jest to późniejszy użytkownik udostępniony
pula, która płaci: page_pool_dev_alloc_va() zwraca źle wyrównany bufor,
napi_build_skb() instaluje go jako skb->head i skb_shinfo(skb) ==
skb->head + skb->end jest z nim źle wyrównany.

skb_shinfo()->dataref to 4-bajtowy obiekt atomic_t z przesunięciem 0x20, więc
atomic_inc() w __skb_clone() znajduje się na linii pamięci podręcznej. Na x86 z podziałem
wykrywanie blokady - domyślnie krytyczne dla blokad podziału jądra - powoduje panikę
maszyna:

Ups: wykryto blokadę podziału
RIP: 0010:skb_clone+0x154/0x1e0
Zadzwoń do śledzenia:
<przerwanie>
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
zaległości_procesu+0x87/0x130

Reprodukowane poprzez dołączenie dowolnego programu XDP działającego w trybie ogólnym do pętli zwrotnej i
otwarcie gniazda RAW IPPROTO_UDP, co powoduje klonowanie raw_local_deliver().
każdy lokalnie dostarczony pakiet UDP; następnie uruchamia go zwykły ruch DNS,
mniej więcej raz na 2500 klonów. Obserwowano 6.12.101 i 7.1.8.

Śledzenie page_pool_alloc_frag_netmem() w jednym takim uruchomieniu pokazuje
wzmocnienie — dwa żądania o nieparzystej wielkości, dziewięć źle ustawionych przesunięć:

żądany rozmiar & 7: 0: 17035 5: 1 7: 1
frag_offset & 7: 0: 17028 3: 1 4: 1 5: 1 6: 1 7: 5

i skb_pp_cow_data() zwracające głowy, które zostały wyrównane przy wejściu:

głowa 0xffff8f4c86aeac00 -> 0xffff8f4c53a9a9c4 (&7=4)
głowa 0xffff8f4d6a8a42c0 -> 0xffff8f4c4f7b7a45 (&7=5)

Zaokrąglij rozmiar fragmentu przynajmniej do struktury wyrównania skb_shared_info
wymaga, więc fragmenty są zawsze odpowiednio dopasowane do obiektów wywołujących
na nich budować. Architektury wymagające większego wyrównania DMA zachowują to.

To również sprawia, że reszta jest obliczana w page_pool_alloc_netmem(),

*rozmiar = maksymalny_rozmiar - *przesunięcie;

wyrównane, ponieważ max_size jest potęgą dwójki - co naprawia dopasowanie
niewspółosiowość skb->end.

Zweryfikowano za pomocą kontrolowanego A/B w ramach QEMU/KVM: to samo drzewo, ta sama konfiguracja,
ten sam kompilator, te same rootfs i identyczny ruch, różniący się tylko tym
łatka. Program SEC("xdp.frags") XDP_PASS na datagramach lo i UDP
większy niż max_head_size steruje pętlą fragmentów skb_pp_cow_data(), która
przekazuje surowe długości pakietów do puli. Mierzone na powrocie
skb_pp_cow_data():

niezałatany, załatany
skb_pp_cow_data dzwoni pod numer 40800 40800
źle wyrównane skb->head 1120 0
dataref przy przesunięciu linii > 60 80 0

Ostatni wiersz zlicza dostępy, które faktycznie powodują błąd:
skb_shinfo()->dataref znajduje się na początku+końcu+0x20 i jest 4-bajtowym elementem atomowym, więc
`lock incl` dzieli 64-bajtową linię pamięci podręcznej tylko wtedy, gdy ten adres wyląduje na
przesunięcie 61..63. Wszystkie 80 wystąpień miało przesunięcie 61; – poinformowała panika
powyżej znajdowało się w przesunięciu 62. Wyeliminowanie niewspółosiowości powoduje usunięcie wszystkich
z nich.

Błąd tej samej klasy, co w przypadku zatwierdzenia 3bed3cc4156e („net: Nie przydzielaj page
fragmenty t
---obcięty---

>_ Referencje

Dane podatności pochodzą z oficjalnych źródeł (CVE® List / NVD). Opisy po polsku są tłumaczone automatycznie i mogą zawierać nieścisłości – na stronie rekordu można wyświetlić wersję angielską.

This product uses the NVD API but is not endorsed or certified by the NVD.

Copyright © 1999–2026, The MITRE Corporation. CVE is a registered trademark and the CVE logo is a registered trademark of The MITRE Corporation.

CVE Usage: MITRE hereby grants you a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, sublicense, and distribute Common Vulnerabilities and Exposures (CVE®). Any copy you make for such purposes is authorized provided that you reproduce MITRE's copyright designation and this license in any such copy. ALL DOCUMENTS AND THE INFORMATION CONTAINED THEREIN PROVIDED BY MITRE ARE PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND.

NVD Terms of Use / CVE® Terms of Use / nvd.nist.gov / cve.org