pedit COW (CVE-2026-46331): Linux branduolys perrašo svetimo failo talpyklą — ir vietinis vartotojas tampa root
pedit COW (CVE-2026-46331): Linux branduolys perrašo svetimo failo talpyklą — ir vietinis vartotojas tampa root
2026 m. gegužės pabaigoje netdev pašto sąraše pasirodė pataisymas su tema „net/sched: fix pedit partial COW leading to page cache corruption”. Nieko įtartino — eilinis duomenų sugadinimo taisymas srauto valdymo posistemyje. Jokio CVE, jokios saugumo žymos. Pataisymas viešai buvo diskutuojamas kelias savaites. Birželio 16-ąją, sujungus jį į mainline branduolį, branduolio CNA automatiškai suteikė identifikatorių — CVE-2026-46331. Kitą dieną, birželio 17-ąją, GitHub pasirodė veikiantis išnaudojimas. Saugumo komandos, kurios neseka netdev pašto sąrašo, sužinojo apie tai tik tada, kai gavo pranešimus iš klientų.
CVE-2026-46331, pavadintas pedit COW — tai pažeidžiamumas Linux branduolio srauto valdymo posistemyje (tc), konkrečiai funkcijoje tcf_pedit_act(). Techniškai tai out-of-bounds write (CWE-787), leidžiantis neprivilegijuotam vietiniam vartotojui įrašyti duomenis į bet kurio nuskaityti prieinamo failo page cache. Įrašyti ten, kur negalima. Įskaitant kešuotą setuid dvejetainio failo — pavyzdžiui, /usr/bin/su — vaizdą atmintyje. NVD paskelbimo metu nebuvo galutinai nustatęs CVSS vertinimo; Red Hat vertina pažeidžiamumą kaip Important su vietiniu atakos vektoriumi, maža sudėtingumu ir be jokio vartotojo sąveikos poreikio. Viešas veikiantis išnaudojimas egzistuoja RHEL 10, Debian 13 ir Ubuntu 24.04. Red Hat išleido errata RHEL 8, 9 ir 10. Debian užtaisė trixie. Ubuntu dar neišleido pataisyto branduolio palaikomoms versijoms.
KAS YRA TC IR ACT_PEDIT
Įrankis tc (traffic control) — tai Linux branduolio integruotas tinklo srauto valdymo įrankis. Juo galima valdyti paketų eiles, riboti pralaidumą, nustatyti prioritetus ir — kas svarbiausia šiam pažeidžiamumui — perrašyti paketų antraštes tiesiai branduolyje, neišeinant į userspace. Tipiniai naudojimo atvejai: DSCP žymėjimas, VLAN žymų keitimas, IP adresų perrašymas be conntrack.
Antraščių perrašymą atlieka veiksmas act_pedit (packet edit). Jis priima raktų sąrašą — kiekvienas raktas aprašo poslinkį pakete ir naują reikšmę, kurią reikia ten įrašyti. Poslinkiai būna dviejų tipų: statiniai, žinomi konfigūravimo metu, ir tipizuoti, kurių tikrasis poslinkis nustatomas vykdymo metu pagal paketo antraščių struktūrą — pavyzdžiui, ar yra IP antraštė. Būtent šis skirtumas ir tapo pažeidžiamumo priežastimi.
Svarbu: act_pedit nereikalauja root teisių. Neprivilegijuotas vartotojas gali sukurti user namespace, jame gauti tinklo privilegijas (CAP_NET_ADMIN) ir įkelti act_pedit modulį. Ši kombinacija — user namespaces ir act_pedit — sudaro atakos kelią.
KAIP VEIKIA KLAIDA
Prieš rašydama ką nors, tcf_pedit_act() turi užtikrinti, kad tikslinė atminties sritis yra privati kopija — tokia, kuri nėra bendrai naudojama su kitais procesais. Įsivaizduokite bibliotekos knygą: skaityti ją gali visi, tačiau jei norite rašyti pastabas paraštėse — bibliotekininkas pirmiausia padaro fotokopiją, kad nesugadintumėte originalo. Tai ir yra copy-on-write (COW): prieš rašymą branduolys padaro privatų reikalingų atminties puslapių kopiją. Tam kviečiama skb_ensure_writable(), kuriai perduodamas keistinų baitų diapazonas.
Problema ta, kad šis diapazonas apskaičiuojamas vieną kartą prieš pradedant raktų ciklą, naudojant lauką tcfp_off_max_hint. Šiame lauke yra didžiausias poslinkis iš statinių raktų — tų, kurių poslinkiai žinomi iš anksto. Tačiau tipizuotiems raktams tikrasis poslinkis apskaičiuojamas vėliau, kiekvieno konkretaus paketo apdorojimo metu. Jei šis vykdymo laiko poslinkis išeina už diapazono, perduoto skb_ensure_writable(), atitinkamas atminties puslapis nebuvo nukopijuotas privačiai. Įrašas patenka į bendrą puslapį — tiesiai į page cache.
Pataisymas perkelia skb_ensure_writable() kvietimą į raktų ciklą, kad diapazonas būtų perskaičiuojamas pagal kiekvieno rakto tikrąjį poslinkį. Taip pat pridedama perpildymo patikra poslinkių aritmetikoje ir neigiamų poslinkių apdorojimas — pavyzdžiui, redaguojant Ethernet antraštes įeinant — per skb_cow().
KAIP TAI IŠNAUDOJAMA
Ataka grindžiama tuo, kad page cache yra globalus — failo puslapiai talpykloje bendrinami tarp visų procesų, kurie jį skaito. Jei užpuolikas gali įrašyti duomenis į kešuotą failo puslapį, kitas šio failo execve() vykdys apnuodytą vaizdą iš talpyklos, o ne originalą iš disko. Failo vientisumo patikrinimai nieko nepraneš — failas diske nepasikeitė.
Konkreti mechanika: užpuolikas atidaro lizdą loopback sąsajoje, sukuria TCP ryšį į 127.0.0.1:4445 ir sukonfigūruoja tc taisyklę su act_pedit, naudojančiu tipizuotą raktą, kurio vykdymo laiko poslinkis išeina už COW diapazono. Duomenys perduodami per sendfile() — ir tai esminis pasirinkimas. Skirtingai nuo įprasto read() + write(), sendfile perduoda failo puslapius tiesiai iš page cache į lizdą, aplenkdamas userspace. Būtent tai suteikia branduoliui tiesioginį vaizdą į tikruosius failo talpyklos puslapius, kai jie eina per act_pedit. Kai paketas apdorojamas, įrašas patenka į šaltinio failo page cache, o ne į privatią kopiją. Pakanka O_RDONLY deskriptoriaus — failo nereikia atidaryti rašymui.
Taikinys — bet kuris setuid dvejetainis failas, prieinamas skaitymui: /usr/bin/su, /usr/bin/passwd arba bet kas kitas su setuid bitu. Įrašęs naudingąją apkrovą į talpyklą, užpuolikas paleidžia failą ir gauna root apvalkalą — tol, kol apnuodytas vaizdas lieka talpykloje. Talpyklos išvalymas (echo 3 > /proc/sys/vm/drop_caches) pašalina apnuodytą vaizdą, tačiau jau atidaryto root apvakalo neuždaro.
KAS NUTINKA TOLIAU — PRIKLAUSO NUO KONFIGŪRACIJOS
Du sąlygos lemia sistemos išnaudojamumą: ar act_pedit gali būti įkeltas ir ar neprivilegijuoti user namespaces yra atviri. RHEL 10 ir Debian 13 abu sąlygos įvykdomos pagal nutylėjimą — išnaudojimas veikia be papildomų vėliavėlių. Ubuntu 24.04 AppArmor riboja neprivilegijuotų user namespaces kūrimą, tačiau tyrėjai patvirtino apėjimą per esamus AppArmor profilius, leidžiančius user namespaces — ataka veikia, tiesiog reikia šiek tiek daugiau pasiruošimo. Ubuntu 26.04 blokuoja šį kelią savo numatytosiomis AppArmor konfigūracijomis, tačiau esantis po jomis branduolys lieka pažeidžiamas.
Sistemose, kuriose išjungti neprivilegijuoti user namespaces (user.max_user_namespaces=0 RHEL, kernel.unprivileged_userns_clone=0 Debian/Ubuntu), viešas išnaudojimas neveikia — užpuolikui nėra iš kur gauti CAP_NET_ADMIN. Tai ir yra pagrindinis workaround tiems, kas negali iš karto įdiegti pataisymo. Kaina: neveiks rootless konteineriai, kai kurie CI smėlio dėžės ir naršyklės su izoliuotais procesais. Gamybiniame serveryje be rootless Docker ar Podman tai paprastai priimtina kompromisas.
CHRONOLOGIJA
2026 m. gegužės pabaiga — pataisymas pasirodė netdev pašto sąraše kaip duomenų sugadinimo taisymas, be CVE ir be saugumo žymėjimo. Išnaudojamos klaidos techninės detalės gulėjo viešame archyve kelias savaites. Gegužės 13 d. — CVE-2026-46331 rezervavo branduolio CNA. Birželio 16 d. — sujungimas į mainline, CVE paskelbtas. Birželio 17 d. — veikiantis PoC GitHub. Red Hat išleido pirmuosius errata (RHSA-2026:27288 RHEL 10) per kelias dienas po CVE paskelbimo. Debian išleido DSA-6355-1 trixie. AlmaLinux gavo ALSA-2026:27353 versijai 8.
TuxCare savo ataskaitoje rašė: „We did not catch this one through our own monitoring. It came in through a customer escalation — it was never on oss-security, and the kernel CNA stream is not currently on our watchlist.” Tai ne vienos įmonės pripažinimas — tai sisteminė branduolio saugumo stebėjimo problema. Pirminio branduolio pataisymai dažnai eina be aiškios saugumo žymos, o CVE priskiriamas tik sujungimo metu. Atotrūkis tarp „pataisymas viešai prieinamas” ir „saugumo komandos sužinojo” gali trukti savaites.
KODĖL TAI SVARBU
pedit COW tęsia page cache corruption LPE seriją, kuri 2026 m. tapo pastebima tendencija Linux branduolyje: Dirty Frag, Copy Fail, dabar pedit COW. Visos trys išnaudoja tą patį principą — branduolys rašo į bendrą atminties puslapį vietoj privatios kopijos, apnuodydamas vykdomojo failo talpyklą. COW mechanizmas egzistuoja branduolyje nuo pradžių — ir kaskart paaiškėja, kad kažkur diapazonas apskaičiuotas ne ten arba ne taip.
Red Hat vertina pažeidžiamumą kaip Important — vietinis atakos vektorius, nereikia privilegijų, nereikia vartotojo sąveikos. Praktiškai tai reiškia: užpuolikas, gavęs apvalkalą jūsų serveryje — per pažeidžiamą žiniatinklio paslaugą, per pažeistą konteinerį, per bet kurį kitą vektorių — gali naudoti CVE-2026-46331 kaip tramplyną į root. Tai ypač aktualu CI/CD runneriams, build workeriams, bendriems tyrimų įrenginiams ir bet kokioms sistemoms, kuriose vietinę prieigą turi keli vartotojai arba automatizuoti procesai.
Yra ir dar viena rizika: failo vientisumo stebėjimas šios atakos nepastebės. Failas diske nesikeičia. AIDE, Tripwire, bet koks FIM, dirbantis su failų kontrolinėmis sumomis diske, nieko įtartino nepamatys. Apnuodytas vaizdas egzistuoja tik atmintyje — kol talpykla nėra išvaloma arba sistema nepaleidžiama iš naujo. Dėl to ataka yra neįprastai švari: jokių pėdsakų diske, root prieiga jau turima. Incidento tyrimui tai reiškia, kad failų sistemos kriminalistikos analizė nieko nepasakys apie kompromitacijos momentą. Rekonstruoti chronologiją bus galima tik pagal tinklo žurnalus, auditd sisteminių kvietimų įrašus arba vykdomų procesų metaduomenis.
ATNAUJINIMAS
Patikimiausias kelias — įdiegti pataisytą branduolį ir paleisti sistemą iš naujo. Paleidimas iš naujo svarbus: kartu įkeltas pataisytas branduolys ir išvaloma page cache, pašalinant bet kokius potencialiai apnuodytus puslapius. Prieš taikant modulio blokavimo workaround, patikrinkite ar act_pedit iš viso naudojamas jūsų konfigūracijoje — jei išvestis tuščia, modulis aktyviai nenaudojamas:
tc actions list action pedit
Patikrinkite dabartinę branduolio versiją komanda uname -r ir palyginkite su pataisytomis versijomis savo distribucijoje.
RHEL 8 pataisymas yra RHSA-2026:27353, RHEL 8.8 EUS/TUS — RHSA-2026:27355, RHEL 9 — RHSA-2026:27789, RHEL 10 — RHSA-2026:27288. AlmaLinux 8 gavo ALSA-2026:27353. Tikslios branduolio paketų versijos nurodytos kiekvieno errata puslapyje adresu access.redhat.com. Debian 13 (trixie) — DSA-6355-1, pažeidžiama versija 6.12.90+deb13.1, pataisyta — 6.12.94-1 ir naujesnė. Ubuntu paskelbimo metu dar neišleido pataisytų branduolių palaikomoms versijoms — sekite Ubuntu Security Notices (USN). PoC autorius patvirtino išnaudojimą RHEL 10.0 su branduoliu 6.12.0-228.el10 ir Debian 13 su branduoliu 6.12.90+deb13.1 — abi versijos pažeidžiamos.
Po atnaujinimo patikrinkite, kad įkeltas naujas branduolys. RHEL ir AlmaLinux sistemose įdiegtų branduolio versijų sąrašas — aktyvi pažymėta žvaigždute:
rpm -q kernel
Debian ir Ubuntu sistemose patikrinkite veikiančio branduolio versiją ir įsitikinkite, kad įdiegtas pataisytas paketas:
uname -r
dpkg -l linux-image-* | grep ^ii
# RHEL / AlmaLinux
dnf update kernel && systemctl reboot
# Debian 13
apt update && apt install linux-image-$(uname -r) && reboot
Jei iš karto atnaujinti neįmanoma — du workaround nutraukia išnaudojimo grandinę. Pirmasis: užblokuoti act_pedit įkėlimą, jei nenaudojate tc pedit taisyklių. Patikrinkite komanda lsmod | grep act_pedit — jei išvestis tuščia, užblokuokite:
echo 'install act_pedit /bin/true' | sudo tee /etc/modprobe.d/disable-act_pedit.conf
Antrasis: išjungti neprivilegijuotus user namespaces. Debian ir Ubuntu reikalingi abu parametrai:
# Debian / Ubuntu
echo 'kernel.unprivileged_userns_clone=0' | sudo tee /etc/sysctl.d/99-userns.conf
echo 'user.max_user_namespaces=0' | sudo tee -a /etc/sysctl.d/99-userns.conf
sudo sysctl -p /etc/sysctl.d/99-userns.conf
RHEL šeimynos sistemose pakanka vieno parametro:
# RHEL / AlmaLinux
echo 'user.max_user_namespaces=0' | sudo tee /etc/sysctl.d/99-userns.conf
sudo sysctl -p /etc/sysctl.d/99-userns.conf
Prieš taikant antrą workaround patikrinkite, ar nenaudojamas rootless Docker, Podman ar panašūs įrankiai — jie priklauso nuo neprivilegijuotų user namespaces. Gamybiniame serveryje be rootless konteinerių apribojimas paprastai saugus.
IŠVADOS
pedit COW — trečioji page cache LPE Linux branduolyje 2026 m., ir mechanika visur ta pati: neteisingai apskaičiuotas COW diapazonas, įrašas į bendrą puslapį, kešuoto failo apnuodijimas. Dirty Frag gyveno IPsec. Copy Fail — crypto. Dabar act_pedit tc posistemyje. Ta pati klaida skirtingose vietose rodo, kad problema sisteminė, o ne lokalinė.
CVE-2026-46331 atėjo iš viešo pataisymo netdev be jokio saugumo signalo. PoC pasirodė dieną po CVE paskelbimo. Tarp „pataisymas prieinamas bet kam” ir „dauguma saugumo komandų sužinojo apie problemą” praėjo kelios savaitės. Jei jūsų branduolio saugumo stebėjimas apsiriboja prenumerata oss-security ir tiekėjų advisory — apie tokius dalykus sužinote vėluodami. Netdev pašto sąrašas, kernel git žymos, upstream stable pastabos — visa tai taip pat verta stebėti.
Atnaujinkite branduolį, paleiskite sistemą iš naujo. Jei jūsų distribucija dar neišleido pataisymo — užblokuokite act_pedit arba išjunkite unprivileged userns iki atnaujinimo.
