x86 No Execute támogatás

Címkék

Molnár Ingo bejelentése szerint mostantól elérhető a támogatás az AMD hardverből megvalósított ``no execute'' (NX) technológiájához az x86 platformon. A Linux kernel teljes mértékben támogatni fogja ezt a védelmi mechanizmust.Az AMD úgy reklámozza az új funkciót, mint egy erősített vírus védelmet (Enhanced Virus Protection - EVP).

A technológia védelmet nyújthat az puffer túlcsordulásos (buffer overflow) exploitok ellen. Ez a technológia már régebb óta jelen van más platformokon, de az x86 gépeken az AMD mutatta be először. A NX funkciót már bejelentette az Intel is, és a VIA és a Transmeta is jelezte, hogy támogatni fogják. A Microsoft Windows operációs rendszerek is támogatják majd ezt a technológiát a következő service pack-ektől kezdve.

Az i386 gépeken ilyen funkció nincs, itt a ``no-execute'' funkciót szoftveres úton próbálják több-kevesebb sikerrel megoldani (pl. PaX).

Ingo bejelentése itt.

Hozzászólások

ojje, ezt mondhattad volna elobb is, akkor egyszerubben valaszolok ;-). a szegmentalas hasznalatarol meg azert roviden: sokfele modon lehet hasznalni, minden OS-ben van valami csavarintas. amivel jellemezni lehet egy adott OS-t az kb. az, hogy

1. hany GDT/TSS/LDT/IDT van (per proci, per taszk, stb).

2. milyen deszkriptorok vannak a *DT-kben es ezek hogyan valtoznak futasidoben (mar ha egyaltalan).

amikor egy OS-re azt mondjak, hogy 'flat mode' szegmenseket hasznal, az altalaban arra utal, hogy (legalabbis) a userland kod/adat/verem szegmensek mind 0 bazisuak es 4GB (vagy valami hasonlo 'nagy' cim) a limitjuk. ebbol a szempontol asszem az osszes linux egyforma, a userland kod/adat szegmensek mind 0 bazisuak es 3 vagy 4GB a limitjuk (ha jol latom az lxr-en, akkor a 2.2 elott 3GB volt), ami vegulis mindegy, mert a 3GB folott a lapozo logika ugyis supervisor lapokat allit be. ami igazan valtozott a 2.2-ben az az, hogy a kernel modban hasznalt kod/adat szegmensek is flat-ek lettek, azelott 3GB bazisuak es 1GB limituek voltak (es ezert kellett a set_fs() igazabol, mert userland memoria eleresehez ideiglenesen mas szelektort kellett az FS szegmens regiszterbe be tolteni, amit aztan a get_user() meg hasonlok hasznaltak adatmozgatasra). mivel a kernel modban generalt logikai cimek nem voltak kozvetlenul hasznalhatok mint userland logikai cimek (a ketfele szegmens kozotti baziscim elteres miatt), ezert ez nehany helyen megbonyolitotta a kernel kodot (pl. fs/exec.c:copy_strings()), gondolom emiatt valtak meg tole (meg azert is, mert ez i386 specifikus volt). e

Ez security szempontjából jobb vagy rosszabb, mint a szoftveres megoldások? :)

Trey:

"Ez a technológia már régebb óta jelen van más platformokon, de az x86 gépeken az AMD mutatta be először."

Tudnad nekem ezt reszletezned, h pontosan mire gondolsz es mely platformon?

Elore is kosz.

uDv,

Pedro

Bizonyos architekturakon (AFAIK: sparc (csak a sun4m (limitált), sparc64 (limitált), alpha (limitált), ia64 (per page X bit), amd29k (per page X bit), hppa (per page X bit), amd64 (per page NX bit) ) a data és a bss no-exec, ez azert lehetseges, mert a hardvereken van egy ún. per-page eXecute bit. Ilyen nincs az i386-on, ezert itt hulye szegmens regiszter hacket kell csinálni (magyarul szoftverbol kell megoldani, amit mashol hardverbol tesznek). A Hammer mar tudja ezt....

De majd jon PaXTeam, o biztos jobban vagja :-D

a proci nem tart nyilvan semmi olyasmit, amit ne a kernel mondana neki. a hardver NX tamogatas pusztan annyit jelent, a 'page table entry' (PTE) formatumban van egy speci bit, ami az adott lap vegrehajthatosagat szabalyozza (es amit a proci megvizsgal minden egyes a lapbol torteno utasitaslehivas elott). de ezt a bitet ettol meg a kernel allitja be a PTE-ben. a szoftveres megoldasok (leginkabb csak a PaX, mivel itt van csak laponkenti NX bit x86 ala) annyit tesznek, hogy valamilyen trukk segitsegevel szimulaljak ezt a bitet - de a tenyleges munkat tovabbra is a proci vegzi a kernel utmutatasa alapjan. ha nem igy lenne, akkor nem lennenek ezek a megoldasok ilyen gyorsak.

hu, latom te is kevered a dolgokat egy csoppet ;-). szoval, sparc (sun4m/sun4d)/sparc64/alpha/ia64/parisc/ppc/amd64/sh5/armv6 gond nelkul tud NX-et, vagy azert mert a hardvare PTE formatum eleve tamogatja, vagy mert szoftveres a TLB kezelo es van szabad PTE bit amit fel lehet erre a celra hasznalni (sparc/sparc64 jo pelda ez utobbira). az x86 trukkos, mert itt egyik modszer sem jarhato (nincs NX PTE bit ill. a TLB is hardverbol toltodik), viszont lehet trukkozni massal. a durva (nem laponkenti) NX-hez eleg a kod szegmens hataraval jatszani, a finom (laponkenti) NX-hez meg az kell, amit a PaX is csinal (van ra ketfele mod is, reszletek a doksiban).

mas. abbol, hogy lehet NX-t hasznalni egy adott architekturan meg nem kovetkezik, hogy tenylegesen ki is van hasznalva, ez mindig attol fugg, hogy a userland mit akar kezdeni vele. szoval a .data/.bss attol lesz NX, mert (ELF alapu rendszerek eseten) az a PT_LOAD szegmens amiben ok vannak NX-szel van megjelolve. tessek megnezni egy 'readelf -l' kimenetet valamin, abban altalaban a masodik LOAD szegmens tartalmazza a .data/.bss-t (meg egyebeket) es tipikusan (i386 alatt kvazi mindig) RW jogok vannak ra (vagyis csak irhato/olvashato, de nem vegrehajthato).

amugy meg ez az egesz 'NX az opteronon 32 bites kernel alatt' inkabb csak porhintes: ha mar valakinek 64 bites procija van, akkor eleg ritkan akarja 32 bites kernellel hasznalni, a 64 bites kernel alatt meg mar eddig is csont nelkul volt NX (en legalabbis ezen megfontolasok miatt nem raktam be a PaX-ba).

architekturatol meg OS-tol fugg. pl. sparc/sparc64 eseten a TLB-t szoftverbol kell tolteni, ezert ennek sebessege fontos. az NX bithez kb. 2 extra utasitasra van szukseg a TLB tolto rutin 'fast path'-jan, ami linux eseten a 7-bol 9-t csinal, ha jol emlekszem. a TLB-t hardverbol tolto prociknal gondolom mikrokodbol megy mindez, es gyanitom, hogy sokkal gyorsabb nem lehet, mint egy jol optimalizalt szoftveres TLB tolto rutin (mert akkor mindenki hardverbol csinalna). az i386/PaX eseten az eredo teljesitmenyromlas attol fugg, hogy mit csinal egy adott program (memoria hasznalatot illetoen) ill. hogy a ket NX megvalositas kozul melyik az aktiv (es mi a proci pontos tipusa). az en P3-asomon egy kernel forditas 2-3% korul lassul le (ebben ugye sok fork/execve/brk/mmap van), mas terhelesek eseten aranyosan kevesebb/tobb.

Kedves PaXTeam,

Koszonom a valaszod. Lenne egy kerdesem. Lehet, h hulyeseget kerdezek, akkor bocs.

En ugy tudom, h az x86-os rendszerekben mar van ilyen vedelem csak nem a lapozo rendszerben, hanem szegmentalas eseten. Itt ugyebar az adat es a stack szegmensek automatikusan nem futtathatoak.

A linux miert dobta a szegmentalast?

En ugy gondolom, bar lehet, h tevedek es hulyeseget beszelek, de szerintem egy jo dolog es kar volt a linux-nak mindenfele portolhatosagi okokbol dobnia.

Egyebkent nekem a cegnel most lett egy AMD64 3000+. Ha szukseges, tudok segiteni teszetelni.

A szegmentalas nagyon lassitana a rendszert a lapozassal egyutt?

uDv,

Pedro

megsaccolom, hogy az intel IA-32 kezikonyvekkel meg nem kerultel kozelebbi baratsagba, ezert megprobalom leegyszerusitve elmagyarazni, bar ez igy eleg pongyola lesz.

naszoval, hogy is mukodik egy proci alacsony szinten (plane ha az IA-32 csaladba tartozik)? ugye, a proci utasitasokat hajt vegre, amiket a memoriabol olvas ki, aztan analizal aztan meg 'csinal valamit', esetleg tovabbi memoria olvasasi/irasi muveleteket vegrehajtva kozben. nos, a szegmentalas meg lapozas ezen memoria eleresi muveletek soran jonnek a kepbe. egy IA-32 proci ugyanis cimtranszformacios lepeseket hajt vegre, amig a programban definialt cimbol eljut a tenyleges fizikai memoriacimig. hogy tiszta legyen: ezeket a transzformaciokat a proci MINDEN EGYES memoria eleres elott vegrehajtja, nincs kivetel [1]. az elso transzformacios lepes az un. logikai cimet (amit maga az utasitas definial, pl. mov eax,[0x12345678] eseten ez a 0x12345678 ertek lesz) alakitja at un. linearis cimme (ez utobbit virtualis cimnek is szoktak hivni mas prociknal). ezt az elso lepest a szegmentalasi logika hajtja vegre, es ezt nem lehet kikerulni (nem kapcsolhato ki/be). a masodik lepes az elozoekben kapott linearis cimet alakitja at un. fizikai cimme, amivel tenylegesen meg lehet cimezni a RAM-ot. ezt a lepest a lapozo logika iranyitja es ez ki/be kapcsolhato, bar a legtobb mai oprendszer mindig bekapcsolva tartja. azt, hogy mi is tortenik pontosan ezekben a lepesekben megtalalhatod az intel kezikonyvekben, itt most hoszzu lenne elmagyarazni.

visszaterve az eredeti kerdesedre: a szegmentalas nem lassit semmit tekintve, hogy az mindig aktiv, nem lehet kikapcsolni (ellenben a lapozas kikapcsolasa igenis gyorsitana, de egy csomo mas hatrannyal is jarna, szoval senki nem tesz ilyet altalanos celu oprendszerben).

az fentebb leirt cimtranszformaciokhoz hozzatennem, hogy mindket lepes soran a proci leellenorzi, hogy az adott hozzaferes jogosult-e vagy sem. pechunkre a ket lepes nem ugyanazokat a jogokat kepes kezelni. konkretabban, a szegmentalas kepes megakadalyozni az olvasast a kodszegmensbol (mar eleve nem irhato), ill. az irast az adat/verem szegmensekbe (ezek egyike sem vegrehajthato alapbol). a linux (meg masok) egyik korlatozast sem hasznalja. a lapozo logika kepes iras ill. az olvasas/iras megakadalyozasara (de nem a kodvegrehajtasra, az egyenlo az olvasasi joggal), ezt persze uton-utfelen kihasznaljak az oprendszerek, ettol lesz lapozos virtualis memoria bennuk.

amiert 'senki' nem hasznalja a szegmentalo logika nyujtotta lehetosegeket az az, hogy a gcc nem kepes ilyen kodot eloallitani ill. igy gyorsabb az oprendszer, mert nem kell szegmens menedzselessel foglalkoznia (aki mar nezegette a regi windows 3.1 progikat meg az NE file formatumot, az gondolom megerti ;-). a gyakorlatban ez a 'nem hasznalat' ugy tortenik, hogy mind a kod, mind az adat/verem szegmensek ugyanazt a linearis memoria tartomanyt irjak le (angolul aszongyak, hogy ez a 'flat segmented model', mert minden szegmens a teljes, 0-4GB linearis cimtartomanyra nyit ablakot), vagyis a szegmentalasi logika effektive nem vegez semmit, minden logikai cim (legyen az kod vagy adat vagy veremmutato) ugyanarra a linearis cimre fordul le.

vegezetul, azt, hogy hogyan lehet ezen lehetosegek/korlatok mellett megis non-exec lapokat csinalni, megtalalhatod a PaX doksikban (de elotte az intel doksikat el kell olvasni ;-).

1. aki valos moddal akar tudalekoskodni, az most tegye fel, hogy mar vedett modban vagyunk ;-).

Kosz a kimerito valaszt. Bar ezeket en is tudtam. Azert tettem fel igy a kerdest, mert mar tobb helyen is beszeltem masokkal errol es mindig lehurroktak a szegmentalassal kapcsolatban. Ismerem az x86 Pentium-ig bezarolag(PI). Az volt az utolso Intel konyv amit elolvastam.

Pontosan tudom, h hogyan mukodik az egesz, csak arra voltam kivancsi, h jol tudom-e a dolgokat. Az erdekesseg az, h az Understanding Linux Kernel konyvben olvastam, h allitolag a portolhatosag miatt dobtak a szegmentalast a 2.2.x kernelektol. Nem tudom, h ez igaz-e?

A vedett modot is jol(?) ismerem, bar teny, h regen foglalkoztam vele. :)