Kas slypi „Intel“ dizaino trūkume, verčiančiame daugybę pataisų?

Kas slypi „Intel“ dizaino trūkume, verčiančiame daugybę pataisų?

„Intel“

Tiek „Windows“, tiek „Linux“ gauna reikšmingus saugos naujinimus, kurie blogiausiu atveju gali sumažinti našumą perpus ir apsisaugoti nuo problemos, kuri dar nėra iki galo atskleista.

„Linux“ branduolio pataisymai per pastaruosius keletą savaičių varvėjo. „Microsoft“ buvo „Windows“ naujinimų testavimas „Insider“ programoje nuo lapkričio mėnir tikimasi, kad pakeitimai bus įtraukti į pagrindinius „Windows“ kūrinius „Patch“ kitos savaitės antradienį. „Microsoft Azure“ planuoja techninę priežiūrą kitą savaitę, o „Amazon“ AWS planuojama prižiūrėti penktadienį – tikėtina, kad tai susiję.

Nuo tada, kai pirmą kartą paaiškėjo „Linux“ pleistrai, atsirado aiškesnis vaizdas, kas atrodo blogai. Nors „Linux“ ir „Windows“ skiriasi daugeliu aspektų, pagrindiniai elementai, kaip šios dvi operacinės sistemos – ir visos kitos x86 operacinės sistemos, tokios kaip „FreeBSD“ ir „macOS“—Tvarkykite sistemos atmintį, nes šios operacinės sistemos dalys yra taip tvirtai sujungtos su procesoriaus galimybėmis.

Adresų stebėjimas

Kiekvienas sistemos atminties baitas yra netiesiogiai sunumeruotas, šie skaičiai yra kiekvieno baito adresas. Ankstyviausios operacinės sistemos veikė naudodamos fizinės atminties adresus, tačiau fizinės atminties adresai yra nepatogūs dėl daugelio priežasčių. Pavyzdžiui, dažnai yra spragų adresuose, ir (ypač 32 bitų sistemose) fizinius adresus gali būti nepatogu tvarkyti, reikalaujant 36 ar net didesnių numerių.

Atitinkamai visos šiuolaikinės operacinės sistemos priklauso nuo plačios koncepcijos, vadinamos virtualia atmintimi. Virtualioji atminties sistema leidžia ir programoms, ir patiems branduoliams veikti paprastoje, švarioje, vienodoje aplinkoje. Vietoj fizinių adresų su jų spragomis ir kitomis keistenybėmis kiekviena programa ir pats branduolys naudoja virtualius adresus, kad galėtų pasiekti atmintį. Šie virtualūs adresai yra gretimi – nereikia jaudintis dėl spragų – ir yra patogūs, kad jais būtų lengva manipuliuoti. 32 bitų programos mato tik 32 bitų adresus, net jei fiziniam adresui reikia 36 ar daugiau numeracijos.

Nors šis virtualus adresavimas yra skaidrus beveik kiekvienai programinei įrangai, procesorius galiausiai turi žinoti, į kurią fizinę atmintį nurodo virtualus adresas. Yra susiejimas nuo virtualių adresų su fiziniais adresais, ir tai saugoma didelėje duomenų struktūroje, vadinamoje puslapio lentele. Operacinės sistemos kuria puslapio lentelę naudodamos procesoriaus nustatytą išdėstymą, o procesorius ir operacinė sistema kartu naudoja puslapio lentelę, kai reikia konvertuoti iš virtualių ir fizinių adresų.

Visas šis susiejimo procesas yra toks svarbus ir esminis šiuolaikinėms operacinėms sistemoms ir procesoriams, kad procesorius turi specialią talpyklą – vertimo išvaizdos buferį arba TLB -, kurioje saugomas tam tikras skaičius virtualių ir fizinių susiejimų, kad būtų išvengta visiško naudojimo puslapio lentelę kiekvieną kartą.

Naudojant virtualią atmintį, mums suteikiama daugybė naudingų funkcijų, išskyrus paprastą kreipimąsi. Tarp jų svarbiausia yra tai, kad kiekvienai atskirai programai suteikiamas savas virtualių adresų rinkinys su savo virtualių ir fizinių susiejimų rinkiniu. Tai yra pagrindinė „saugomos atminties“ teikimo technika; viena programa negali sugadinti ar sugadinti kitos programos atminties, nes kitos programos atmintis paprasčiausiai nėra pirmosios programos atvaizdavimo dalis.

Tačiau šie individualaus žemėlapio panaudojimo procesui ir todėl papildomų puslapių lentelių panaudojimai daro spaudimą TLB talpyklai. TLB nėra labai didelis – paprastai iš viso keli šimtai susiejimų – ir kuo daugiau puslapių lentelių naudoja sistema, tuo mažesnė tikimybė, kad į TLB bus įtrauktas koks nors konkretus vertimas iš virtualaus į fizinį.

Pusė ir pusė

Siekiant kuo geriau išnaudoti TLB, kiekviena pagrindinė operacinė sistema padalija virtualiųjų adresų diapazoną į dvi dalis. Pusė adresų naudojama kiekvienai programai; kita pusė naudojama branduoliui. Perjungiant procesus keičiasi tik pusė puslapio lentelės įrašų – tie, kurie priklauso programai. Branduolio pusė yra bendra kiekvienai programai (nes yra tik vienas branduolys), todėl kiekvienam procesui ji gali naudoti tą patį puslapio lentelės atvaizdavimą. Tai labai padeda TLB; nors ji vis tiek turi išmesti susiejimus, priklausančius pusei atminties adresų, ji gali išsaugoti branduolio pusę.

Šis dizainas nėra visiškai akmuo. Buvo atliktas darbas su „Linux“, kad 32 bitų procesui būtų suteikta visa adresų sritis, nesidalijant branduolio ir kiekvienos programos puslapių lentele. Nors tai suteikė programoms daugiau adresų vietos, tai kainavo našumą, nes TLB kiekvieną kartą, kai reikėjo paleisti, turėjo perkrauti branduolio puslapio lentelės įrašus. Atitinkamai šis požiūris niekada nebuvo plačiai naudojamas x86 sistemose.

Vienas sprendimo trūkumas padalinti virtualią adresų erdvę tarp branduolio ir kiekvienos programos yra tas, kad silpnėja atminties apsauga. Jei branduolys turėtų savo puslapių lentelių ir virtualių adresų rinkinį, jam būtų suteikta ta pati apsauga, kaip ir skirtingose ​​programose; branduolio atmintis būtų tiesiog nematoma. Tačiau padalijus adresavimą, vartotojo programos ir branduolys naudoja tą patį adresų diapazoną ir iš esmės vartotojo programa galėtų skaityti ir rašyti branduolio atmintį.

Norėdami išvengti šios akivaizdžiai nepageidaujamos situacijos, procesorius ir virtuali adresavimo sistema turi „žiedų“ arba „režimų“ sąvoką. „x86“ procesoriai turi daug žiedų, tačiau šiai problemai aktualūs tik du: „vartotojas“ (3 žiedas) ir „prižiūrėtojas“ (0 žiedas). Vykdant įprastas vartotojo programas, procesorius įjungiamas į vartotojo režimą, 3 žiedą. Paleidžiant branduolio kodą, procesorius yra 0 žiedo, prižiūrėtojo režime, taip pat žinomas kaip branduolio režimas.

Šie žiedai naudojami apsaugoti branduolio atmintį nuo vartotojo programų. Puslapių lentelės susiejamos ne tik su virtualiaisiais su fiziniais adresais; juose taip pat yra tų adresų metaduomenys, įskaitant informaciją apie tai, kurie žiedai gali pasiekti adresą. Visi branduolio puslapio lentelės įrašai pažymėti kaip prieinami tik 0 žiedui; programos įrašai pažymėti kaip pasiekiami iš bet kurio žiedo. Jei bandoma pasiekti 0 žiedo atmintį, kol yra 3 žiede, procesorius blokuoja prieigą ir sukuria išimtį. To rezultatas – vartotojo programos, veikiančios 3 žiede, neturėtų nieko sužinoti apie branduolį ir jo 0 žiedo atmintį.

Bent jau tokia teorija. Pataisų ir atnaujinimų gausa rodo, kad kažkur tai sugedo. Čia slypi didžioji paslaptis.

Judėjimas tarp žiedų

Štai ką mes žinome. Kiekvienas šiuolaikinis procesorius atlieka tam tikrą spekuliacinį vykdymą. Pavyzdžiui, davęs kai kurias instrukcijas, kurios prideda du skaičius ir po to išsaugo rezultatą atmintyje, procesorius gali spekuliaciškai atlikti papildymą, prieš įsitikindamas, ar atminties paskirtis iš tikrųjų yra prieinama ir įrašoma. Paprastai atveju, kai vieta yra rašomas, procesorius sugebėjo sutaupyti šiek tiek laiko, nes atliko aritmetiką lygiagrečiai su tuo, kad išsiaiškino, kokia paskirtis yra atmintyje. Jei ji sužino, kad vieta nėra prieinama, pavyzdžiui, programa bando rašyti adresu, kuriame nėra žemėlapio ir nėra jokios fizinės vietos, ji sukurs išimtį ir spekuliacinis vykdymas bus švaistomas.

„Intel“ procesoriai, nors ir ne AMD, leidžia spekuliaciškai vykdyti 3 žiedo kodą, kuris rašo į 0 atmintį. Procesoriai padaryti tinkamai blokuoti rašymą, tačiau spekuliacinis vykdymas labai trikdo procesoriaus būseną, nes tam tikri duomenys bus įkeliami į talpyklą ir TLB, siekiant įsitikinti, ar rašyti reikia. Tai savo ruožtu reiškia, kad kai kurios operacijos bus keletu ciklų greitesnės arba keliais ciklais lėtesnės, atsižvelgiant į tai, ar jų duomenys vis dar yra talpykloje, ar ne. Be to, „Intel“ procesoriai turi specialių funkcijų, tokių kaip „Software Guard Extensions“ (SGX), pristatyti kartu su „Skylake“ procesoriais, šiek tiek pakeičiantys bandymus pasiekti atmintį. Vėlgi, procesorius vis tiek apsaugo 0 žiedo atmintį nuo 3 žiedo programų, tačiau vėlgi, jos talpyklos ir kita vidinė būsena yra pakeista, sukuriant išmatuojamus skirtumus.

Dar nežinome, kiek informacijos apie branduolio atmintį gali nutekėti į vartotojo programas arba kaip lengvai gali atsirasti nuotėkis. Ir kurie „Intel“ procesoriai yra paveikti? Vėlgi, tai nėra visiškai aišku, tačiau yra požymių, kad kiekvienas „Intel“ lustas su spekuliatyviu vykdymu (kuris yra visi pagrindiniai procesoriai, pristatyti nuo „Pentium Pro“, nuo 1995 m.), Gali tokiu būdu nutekinti informaciją.

Pirmasis šios problemos vėjas kilo iš Austrijos Graco technikos universiteto mokslininkų. Jų atrastas informacijos nutekėjimas buvo pakankamas, kad pakenktų branduolio režimo adresų erdvės išdėstymo atsitiktinių parinkčių (branduolio ASLR arba KASLR) atsitiktinumui. ASLR yra paskutinės pastangos užkirsti kelią buferio perpildymui. Naudojant ASLR, programos ir jų duomenys talpinami atsitiktinės atminties adresais, todėl užpuolikams šiek tiek apsunkina saugumo trūkumų išnaudojimą. KASLR tą patį atsitiktinių imčių metodą taiko branduoliui, kad branduolio duomenys (įskaitant puslapių lenteles) ir kodas būtų atsitiktinai išdėstyti.

Graco tyrėjai sukūrė „KAISER“ – „Linux“ branduolio pataisų rinkinį, kad apsisaugotų nuo šios problemos.

Jei problema būtų tik ta, kad tai leido panaikinti ASLR, tai tikriausiai nebūtų didžiulė katastrofa. ASLR yra puiki apsauga, tačiau žinoma, kad ji yra netobula. Tai turi būti kliūtis užpuolikams, o ne neįveikiama kliūtis. Pramonės reakcija – gana esminis tiek „Windows“, tiek „Linux“ pakeitimas, sukurtas su tam tikru slaptumu – rodo, kad nugalėta ne tik ASLR ir kad sukurta bendresnė galimybė nutekinti informaciją iš branduolio. Iš tiesų tyrėjai turi pradėjo čivinti kad jie sugeba nutekinti ir perskaityti savavališkus branduolio duomenis. Kita galimybė yra ta, kad trūkumas gali būti naudojamas norint išeiti iš virtualios mašinos ir pakenkti hipervizoriui.

Sprendimas, kurį pasirinko tiek „Windows“, tiek „Linux“ kūrėjai, yra iš esmės tas pats ir gautas iš to KAISER darbo: branduolio puslapio lentelės įrašai nebebendrinami su kiekvienu procesu. „Linux“ tai vadinama Kernel Page Table Isolation (KPTI).

Su pleistrais atminties adresas vis tiek padalijamas į dvi dalis; tiesiog branduolio pusė beveik tuščia. Tai nėra visiškai tuščia, nes keletą branduolio dalių reikia visam laikui atvaizduoti, nesvarbu, ar procesorius veikia 3 žiede arba žiedas 0, bet jis tuščias. Tai reiškia, kad net jei kenkėjiška vartotojo programa bandys ištirti branduolio atmintį ir nutekinti informaciją, ji nepavyks – paprasčiausiai nėra ko nutekėti. Tikrosios branduolio puslapio lentelės naudojamos tik tada, kai pats branduolys veikia.

Tai pirmiausia pakerta pačią padalintos adreso vietos priežastį. Dabar TLB reikia išvalyti visus įrašus, susijusius su tikromis branduolio puslapių lentelėmis kiekvieną kartą, kai jis persijungia į vartotojo programą, nutraukdamas našumą, kurį įgalino skaidymas.

To poveikis priklausys nuo darbo krūvio. Kiekvieną kartą, kai programa skambina į branduolį – skaityti iš disko, siųsti duomenis į tinklą, atidaryti failą ir pan., Tas skambutis bus šiek tiek brangesnis, nes tai privers prapūsti TLB. ir tikroji branduolio puslapio lentelė, kurią reikia įkelti. Programos, kurios daug nenaudoja branduolio, gali sulaukti 2–3 procentų smūgio – vis tiek yra pridėtinių išlaidų, nes branduolys visada turi veikti kartais, kad galėtų tvarkyti tokius veiksmus kaip daugiafunkcinis darbas.

Tačiau darbo krūvis, reikalaujantis daugybės branduolių, sumažės daug didesnis našumas. Pagal etaloną – praktiškai nieko neveikianti programa kita nei paskambinti į branduolio pjūklą jo našumas sumažėjo apie 50 proc; kitaip tariant, kiekvienas iškvietimas į branduolį užtruko dvigubai ilgiau su pleistru, nei buvo be jo. Lyginamieji indeksai, naudojantys „Linux“ tinklo ryšį, taip pat mato didelį rezultatą, pavyzdžiui, šiame „Postgres“ etalone – 17 proc. Tikriems duomenų bazių darbo krūviams, naudojant tikrąjį tinklą, turėtų būti daromas mažesnis poveikis, nes naudojant tikrus tinklus, skambinant į branduolį, paprastai dominuoja faktinio tinklo naudojimo pridėtinės išlaidos.

Nors …

Parašykite komentarą

El. pašto adresas nebus skelbiamas. Būtini laukeliai pažymėti *

Previous post Kas yra „Rust“ ir kodėl jis toks populiarus?
Next post Štai ką daro Kolorado policijos reformos įstatymas