( PaXTeam | 2010. 03. 05., p – 14:03 )

nem irtam senkirol, hogy hulye, csak a tenyeket, hogy mi es miert volt. mellesleg lorian ugyanugy tevedett (mindjart leirom akkor reszletesebben), mint ahogy a tobbiek is, akkor most ezert o is hulye lenne? szerintem egy szoval nem allitottam ilyet.

na de a lenyeg. minden procinak mas es mas lehetosegei vannak a virtualis->fizikai memoria lekepezes megvalositasara. az ezt a lekepezest kihasznalni akaro kodot eleve nem lehet architektura fuggetlenre megirni (tessek megnezni, hogy mi tortenik RISC prociknal a futasidoben generalt PLT stub-ok irasakor: cache flush, ami asm kodot igenyel, az az eletben nem lesz architektura fuggetlen, megis az ELF alapu userland-ek eleg sok procin elfutkaroznak). amit lorian szeretett volna az egy futasideju alacsony szintu vedelem a suhosin konfiguraciojara (marmint arra, amit abbol a memoriaban tarol). hogy ez az egesz egy ertelmes cel-e vagy sem, most lenyegtelen (szerintem amugy nem, mert van kismillio mas dolog, amit egy memoriat irni kepes hiban keresztul ki lehet hasznalni, sot akar az egesz mprotect alapu vedelem visszacsinalhato), az izgalmasabb kerdes, hogy mi modon lehet ezt elerni.

a megoldas erre a fent emlitett lekepezes kihasznalasa ugy, hogy a kerdeses memoriateruletet csak olvashatova tesszuk (az, hogy ezt egyaltalan meg lehet tenni, mar eleve feltetelez bizonyos processzor meg kernel kepessegeket, nem veletlen, hogy a POSIX-ban is opcionalis a mmap es tarsai tamogatasa). a kovetkezo kerdes az, hogyan lehet ezt megtenni. erre alapvetoen a kernel belso mmap/mprotect interface-e valo, de oda tobb ut is vezet.

az egyik, amit lorian eredeti megoldasa hasznalt, az ELF loaderen keresztul volt: minden ELF file-ban a PT_LOAD szegmensekhez tartozik tobbek kozott egy hozzaferesi jog (rwx valamilyen kombinacioja) ill. egy alignment mezo. minden ilyen PT_LOAD szegmenst a kernel (a fo exe meg ld.so eseten) vagy az ld.so (konyvtarak eseten) tolt be memoriaba a mmap() segitsegevel, ahol a parameterek osszeallitasakor figyelembe veszi a PT_LOAD mezoket (tehat pl. a vegrehajthato kodot tartalmazo PT_LOAD-ot azert mmap-eli PROT_EXEC jogot (is) kerve, mert ennek a PT_LOAD szegmensnek r-x a hozzaferesi jogokat tartalmazo mezoje, readelf -l szepen megmutatja, akit erdekel). az alignment mezo arra jo, hogy biztositsa, hogy az ilyet igenylo adatstrukturak valamilyen 2 hatvany tobbszorosenek megfelelo cimre keruljenek a virtualis memoriaban (pl. lebegopontos szamok szeretnek 8/16 byte-os hatarra esni). a suhosin konfiguracio eseteben azt csinalta lorian, hogy a konfiguraciot tartalmazo (es lap meretu) valtozot explicite laphatarra kerte igazitani a toolchain-tol (gcc/linker/kernel/ld.so egyuttmukodese mind szukseges ehhez). ezek utan egy egyszeru mprotect (ami laphatarra igazitott cimet var el) az adott valtozora szepen csak olvashatova tette az egeszet, mission accomplished. vagy legalabbis ez volt az elkepzeles, ami x86-on (meg ugy altalaban 4k-s lapokat hasznalo architekturakon) szepen mukodott, nagyobb lapmeretek eseten meg tulbuzgo modon mas, irhatonak szant valtozokat is csak olvashatova tett (amik pechjukre epp a suhosin konfiguracioja utan voltak a memoriaban), amit a kernel sigsegv-vel honoralt az elso irasi kiserletnel (ez lett volna a debian bugreport lenyege). meg egy aprosag ehhez a megoldashoz: a konfiguraciot tartalmazo valtozo globalis valtozo, ezert minden eleres hozza egy pointeren keresztul tortenik, amit a GOT tarol. ezt a pointert nem a C szintu kod hozza letre, hanem a fordito/linker maga (PIC-hez szukseges), de alapvetoen ugyanazt a szerepet tolti be, mint a mindjart leirt masik megoldasban az explicit pointer. es persze ugyanugy tamadhato lenne, ha nem letezne a RELRO vedelem.

a masik megoldas hasonlo az elozohoz, annyi elteressel, hogy a konfiguraciot tarolo memoriat nem implicite a toolchain allokalja, hanem C szintu kod direkt mmap hivassal, aminek megvan az az elonye, hogy pontos lapmerettel lehet kerni, igy elkerulheto a nem kivant atlapolodas mas valtozokkal. cserebe viszont a valtozo eleresehez direkt pointer valtozo kell, amit viszont nem lehet a (RELRO eseten irasvedett) GOT-ba tuszkolni (az a toolchain belugye), igy mas vedelem kell, erre talaltak ki a XOR-olast (ezt is lehetett volna maskepp csinalni, de most mindegy).

na akkor most a kritika az egeszrol: az elso modszer megcsinalhato tetszoleges lapmerettel, es mivel a php/suhosin veges sok architekturan fut, nem (lett volna) nagy kunszt megtalalni a legnagyobb tamogatando lapmeretet, ranezesre 64k ment volna mindenhol (vagy be lehetett volna tenni par ifdef-et, a lenyegen nem valtoztat). a pointer titkositas meg nem security, hanem obscurity (mint az ASLR), annal sokkal jobb lett volna, ha a GOT/RELRO modszernel marad, vagy legalabb leellenorzi, hogy a celmemoria tenyleg read-only-e es a konfigot tartalmazza.