Just use a supported kernel

Ez annyira jó, hogy muszáj róla egy blog bejegyzést írnom...

Történt ugyanis, hogy Pierre Ynard beküldött egy hibajegyet debian bugtrackerbe, miszerint a vlc-cache-gen a vlc-nox csomagban "Segmentation fault" hibával elszáll frissítés közben, ha PaX patchelt kernelen történik az upgrade. A bejelentő okosan megemlíti, hogy nyugodtan továbbítsák a hibát, ha nem megfelelő helyen került említésre, de felveti az alábbi kérdést is (két másik közt):

- miért száll el a dinamikus betöltő, ahelyett, hogy kezelné a hibát?

PaXTeam készségesen válaszol a kérdésre és leírja, hogy ez egy régóta jelenlévő hiba, amely a GNU C függvénykönyvtárának dinamikus betöltőjét érinti, és nem vizsgálja a RELRO szekciót (azaz a relokáció után csak olvasható - read-only - szegmenst), hogy átállítható írhatóra vagy sem.

Pierre-t nem hagyja nyugodni a dolog és ezért patchet készít a problémára, amelyet be is küld a bugzillába.

Mivel nem történik semmi, ezért beküldi a problémát következő hónapban a Sourceware Bugzillába, ahol Ulrich Drepper - a GNU C library karbantartója -, a közismert terelő stílusával elküldi azzal, hogy "csak használjon támogatott rendszermagot" és lezárja a hibát WONTFIX hibajeggyel.

Szerencsére PaXTeam bácsit nem ejtették a fejére és újra megnyitotta a problémát (REOPENED), amelyben leírja, hogy bármit is jelentsen a "támogatott rendszermag", az mprotect() függvény vissza kell hogy adjon hibát, így a visszatérési érték vizsgálatának elmulasztása szimplán egy rossz programozói gyakorlat.

Diplomatikus válaszában arra ki sem tért, hogy mivel Ulrich Drepper POSIX bizottsági tag, ezért tisztában kellene, hogy legyen azzal, hogy ennek az mprotect() függvénynek a visszatérési értékét vizsgálnia kellene kötelező módon a GNU C fügvénykönyvtár forráskódjában (azaz a Glibc-ben), amelynek már régóta karbantartója...

Hozzászólások

Mintha a nagy linux hívők szokták időnként említeni, hogy hú de jó a változatosság...

----------------
Lvl86 Troll

"szimplán egy rossz programozói gyakorlat" ?

Nem egeszen, a program hiba eseten azt csinalja ami elvarhato volt, kilepett. Es meg hiba uzenet is lett SIGSEGV fomalyaban :)
A patch hatasara mas hiba uzenetet tol ki plusz egy unlikely() nelkuli if-fel, es nem a szigurub return ellenorzessel (!=) .
Siman valalhato ilyen reszen a nem ellenorzes.

Erdekesebb kerdes, hogy at lehet -e irni a dinamikus betoltest(dlopen) ugy, hogy ne kelljen feloldani csak a PROT_READ -et mikozben nem szenved el teljesitmenybeli visszaesest, vagy a PaX -nak elmagyarazni, hogy ez a helyzet kivetel.

Amit nem lehet megirni assemblyben, azt nem lehet megirni.

A patch korul lathato kodreszletben is jol latszik, hogy __builtin_expect -eket szeretik hasznalni :)

A FreeBSD esetben erdekes lehet, hogy milyen "erdekes" kornyezeti valtozo kezeles lehet, ami ilyet tud eredmenyezni, de a gyereknek atadja.

Ez azert mas, mert mint ahogy itt latjuk, ha az _mprotect nem csinal semmit, akkor sem tortonhet katasztrofalis dolog, nem fog tudni irni es arra dob egy szabalyos hatast.
A FreeBSD eseten meg konkretan elat hallal kerdes, hogy az helyes legyen.

Az olyan arcok akkik __builtin_expect ekkel dobaloznak, altalaban vegig gondoljak az ilyesmit.

Amit nem lehet megirni assemblyben, azt nem lehet megirni.

A patch korul lathato kodreszletben is jol latszik, hogy __builtin_expect -eket szeretik hasznalni

láthatólag nem ezt kifogásolta Drepper

Az olyan arcok akkik __builtin_expect ekkel dobaloznak, altalaban vegig gondoljak az ilyesmit.

ne kacagtass turul... ezek a giga arcok, annyira végiggondolják a dolgokat, hogy egy másik kihagyott ellenőrzés miatt remek local root exploitok születhetnek.

szia turul16@hup, latom a PAE-t feladtad, es ratertel az altalanos programozoi szakertesre ;).

szoval nezzuk az eheti okossagod. aszondod, hogy 'a program hiba eseten azt csinalja ami elvarhato volt, kilepett'. ebben 'csupan' az alabbi dolgok nem stimmelnek:

1. ugy altalaban hiba eseten nem elvarhato, hogy kilep egy program (pl. eleg rosszul esne, ha a bongeszod kilepne, ha epp nem tud feloldani egy domain nevet, vagy ha egy malloc NULL-t ad vissza, mert nincs eleg nagy szabad lyuk a virtualis cimterben). plane akkor nem, ha mindez egy konyvtarban van, annak illik visszaadni a hibat a hivonak, fel egeszen a programig (igen, a glibc/ld.so eleve rosszul csinalja, de ez most mellekes).

2. ha megis kilepest valaszt egy program(ozo), akkor a minimum, hogy azt az adott kornyezetben erre kitalalt modon tegye (exit(), valami hibakod, jobb helyeken hibauzenet, log, hogy a felhasznalo tudja, mi a franc van megis). a SIGSEGV nem ilyen, nem erre van kitalalva (keresztkerdes: mi van, ha az adott programban van SIGSEGV handler, ami nem lep ki? sok minden, csak konzisztens viselkedes nem ;)

3. ennyi erovel a fuggvenyek visszateresi erteket folosleges vizsgalni, max majd elszall tole a program, 'elvarhato' modon. haxorok jo sokaig meg is eltek ezekbol (l. 80-as/90-es evek tanulmanyait a UNIX utility-krol. igen, a fuzzing mar legalabb olyan regi moka).

> A patch hatasara mas hiba uzenetet tol ki[...]

nem mas uzenetet tol ki, hanem egyaltalan valamit. SIGSEGV eseten max a szulo shell meg a kernel logol, es persze nekik fogalmuk sincs az igazi hibaokrol, tehat a felhasznalo nem lesz okosabb.

> Siman valalhato ilyen reszen a nem ellenorzes.

ojje, erre most sok mindent lehetne irni, maradjunk annyiban, hogy remelem, nem vagy programozo.

> Erdekesebb kerdes, hogy at lehet -e irni a dinamikus betoltest(dlopen) ugy, hogy ne kelljen feloldani csak a PROT_READ -et mikozben nem szenved el teljesitmenybeli visszaesest

mi az, hogy 'feloldani csak a PROT_READ-et'? milyen teljesitmenybeli visszaesesrol beszelsz?

> vagy a PaX -nak elmagyarazni, hogy ez a helyzet kivetel.

PaX koszoni szepen, jol van, te viszont elolvashatod a debian bugzillaba leirtakat, ott van, hogy mit es hogyan kene javitani.

> szia turul16@hup, latom a PAE-t feladtad, es ratertel az altalanos programozoi szakertesre ;).
Hetvegen vissza terek ra, valoszinuleg igazat fogok neked adni :)

1. Alapvetoen igazad van, de pl. ha malloc NULL -t addna vissza az esetek 99.99% nem erdemes jobbat tenni, mint kilepni.

2. Ha adott program eldontotte mit tegyen SIGSEGV -re azt okkal tette, nem kell, hogy ez zavarjon.
Kilepes jo strategia,rendkivul varatlan helyzetekre. Itt pl. a keszito siman gondolhatta azt, hogy ilyemi csak kernel BUG eseten lehetne.
Veszett fejsze nyele.

3. Nem kell minden fugvenyt vizsgalni, pl. printf viszteresi erteket ritkan vizsgaljak.
Egyebkent ha a hibekezelesei strategidaban benne van, hogy egy-ket visszatereesi ertek nem kezelese eseten is helyesen fog mukodni a program akkor azt illik kommentelni, hogy miert nem kovetted az okol szabalyt.
Ilyenkor mas hiba, mas, de vart helyen jelentkezni fog.
Az ottani hiba kezelonek tudnia kell kezelni a masutt nem vizsgalt hiba eshetoseget is.
Ugye nyilvan nem ugy optimalizalunk, hogy hibak eseten legyen gyors a program.
(exception dobos nyelveknel gyakran latunk hasonlot)
Hibat akkor sem feltetlen nezzuk meg, ha egy nem kritikus lepes ki fog maradni pl. nem dinget egyet letoltes kezelod amikor kesz van.
Vagy pl. nem feltetlen kezeljuk a logger hibak loggerjenek loggerjet egy ujabb loggerel.

>> Siman valalhato ilyen reszen a nem ellenorzes.

>ojje, erre most sok mindent lehetne irni, maradjunk annyiban, hogy remelem, nem vagy programozo.

Elsore korai initcilazalskori hibanak tunt, sebbeseg kritikus reszen.
De nem az, ugyhogy jogos lenne kezelni, ha kerneledtol varhato a viszsa utasitas.

> mi az, hogy 'feloldani csak a PROT_READ-et'? milyen teljesitmenybeli visszaesesrol beszelsz?
>> vagy a PaX -nak elmagyarazni, hogy ez a helyzet kivetel.

Nyilvan nem a szoban forgo patch a megoldas, valamelyik szereplot komolyabban meg kell valtoztatni.

Amit nem lehet megirni assemblyben, azt nem lehet megirni.

> 1. Alapvetoen igazad van, de pl. ha malloc NULL -t addna vissza az esetek 99.99% nem erdemes jobbat tenni, mint kilepni.

biztos vagy benne, hogy elolvastad, mirol szol ez az egesz? *nem* az az alapproblema, hogy az ld.so kilep azon a ponton (bar nem szep dolog, de sok mas helyen is megteszi, raadasul rendesen hibauzenettel, szoval ez onmagaban nem ujdonsag), hanem annak a *modja*. SIGSEGV minden, csak nem elfogadhato. pl. tudod mi tortenik egy exit() hivasakor, ami SIGSEGV-nel meg nem?

> 2. Ha adott program eldontotte mit tegyen SIGSEGV -re azt okkal tette, nem kell, hogy ez zavarjon.

mi van akkor, ha a program a sajat maga altal tudatosan generalt SIGSEGV-t akarja kezelni csak? l. jvm meg stack guard page. nem szep dolog belekavarni, plane nem egy tok fuggetlen konyvtarbol. nem szandekolt SIGSEGV = szarvashiba, ezen nincs mit spekulalni meg okoskodni.

> Kilepes jo strategia,rendkivul varatlan helyzetekre.

ez itt nem rendkivul varatlan helyzet.

> Itt pl. a keszito siman gondolhatta azt, hogy ilyemi csak kernel BUG eseten lehetne.

nem gondolhatta, mert az mprotect barmikor adhat hibat vissza (ebben a konkret helyzetben a normal kernel alatt is). de meg ha tenyleg nem is adhatna hibat vissza, akkor sem SIGSEGV a kezeles modja (glibc/ld.so eleg alapprogram ahhoz, hogy elvarjon tole az ember nemi robosztussagot, nem beszelve arrol, hogy ugyanezen kod kornyzete szamos hasonlo hibat rendesen lekezel, egyszeruen nincs kifogas arra, hogy pont itt miert nem).

> Nem kell minden fugvenyt vizsgalni, pl. printf viszteresi erteket ritkan vizsgaljak.

te valami masrol beszelsz most mar megint. az eredeti logikad szerint nem, hogy nem kell minden fuggveny visszateresi erteket vizsgalni, hanem extrem modon semelyiket sem, mondvan majd max elszall a program, ami szerinted elvarhato viselkedes. orvendek, hogy megse igy gondolod ;).

> Vagy pl. nem feltetlen kezeljuk a logger hibak loggerjenek loggerjet egy ujabb loggerel.

ez speciel nem jo pelda. ahol tenyleg szamit a log, ott azonnal megall a teljes rendszer az elso log hibanal (ha jol remlik, orange book is eloirta mar), ahol meg nem szamit, ott akkor nem erdekes az eredeti log se, meg se probalunk loggolni rola. tehat amirol irtal, nos ilyen allat nincs.

> De nem az, ugyhogy jogos lenne kezelni, ha kerneledtol varhato a viszsa utasitas.

semmi koze az mprotect hibanak a PaX-hoz, mas kernelen is adhat vissza hibat ugy altalaban, de meg az adott esetben is.

Olvass visza:
"Elsore korai initcilazalskori hibanak tunt, sebbeseg kritikus reszen.
De nem az, ugyhogy jogos lenne kezelni, ha kerneledtol varhato a viszsa utasitas."

"pl. tudod mi tortenik egy exit() hivasakor"
atexit, .dtors

Javits ki, ha tevednek de a vanilla Linux kernel akkor adna itt vissza hibat, ha elfogyott volna kernel memoriaja/eroforrasa vagy, ha valami beleirt volna olyan memoria teruletre (user reszen) ahova neki nem lett volna szabad. pl. atirta olyan teruletet amibol az mprotect a paramtereit veszi. Vagy "rosszul" ugrott be ide . Vagy esetleg nagyon hulye volt egy munmap hivasakor..

Hulye cimre iras/ugras eseten nem meglepo elobb-utobb egy SIGSEGV valasz.
A mostani forras szerint VM_HUGETLB flag kene ahhoz, hogy eroforras hiany miatt adjon hibat, bar a manual szerint illene keszulnie ra a hasznalonak.

30 bytot nem tunik erdemesnek itt kisporolni az egyebkent is nagy glibcbol, de nem tunik MUST -nak.

Expolitalis technikak szemopontjabol veszelyesebbek -e az igy hagyott mprotektek letezese ? Vagy aki mar tudja, hogyan ugorjon erre az mprotektre az mar valoszinuleg ugy is tud eleget ?

szerk:
http://www.gnu.org/s/libc/
"Project Goals
The GNU C library is primarily designed to be a portable and high performance C library.
"
Ja hogy, nem csak Linuxra szantak.. , en kerek elnezest.
Gyakorlatban nem csak a Linuxal egyutt jon a glibc ?

Amit nem lehet megirni assemblyben, azt nem lehet megirni.

> Olvass vissza:

olvassunk ;). ezt irtad mar a legelejen a jogos kezelesrol (es meg mindig ezt vallod):

> Nem egeszen, a program hiba eseten azt csinalja ami elvarhato volt, kilepett. Es meg hiba uzenet is lett SIGSEGV fomalyaban :)

es ez az, ami butasag, mert a SIGSEGV minden, csak nem 'jogos' ;).

> atexit, .dtors

ugy van. es mi tortenik ezekkel itt SIGSEGV eseten? erted mar, miert gaz ez, amikor a progi csak egy egyszeru dlopen()-t akart?

> Javits ki, ha tevednek de a vanilla Linux kernel akkor adna itt vissza hibat, ha elfogyott volna kernel memoriaja/eroforrasa

leginkabb ez fordulhat elo (de ez is altalaban implementacio fuggo, se glibc se mas nem hagyatkozhat ra), bar az 'elfogyott' nem egeszen pontos, HIGHMEM rendszeren elofordulhat, hogy csak lowmem nincs epp eleg, ill. ugy altalaban elofordulhat az is, hogy tul nagy a lowmem fragmentacio es a vm_area_cache-hez meg masokhoz tobb lapot akarna egyszerre foglalni a kernel es epp nincs akkora meretu szabad lyuk.

> 30 bytot nem tunik erdemesnek itt kisporolni az egyebkent is nagy glibcbol, de nem tunik MUST -nak.

meg mindig nem erted, hogy nem sporolas kerdese a SIGSEGV kaliberu hibak javitasa?

> Expolitalis technikak szempontjabol veszelyesebbek -e az igy hagyott mprotektek letezese ? Vagy aki mar tudja, hogyan ugorjon erre az mprotektre az mar valoszinuleg ugy is tud eleget ?

senkit nem erdekel, hogy ez a kod glibc-ben van egy expoit irasnal, az a teny a rossz, hogy a glibc sajat maga akarja felrugni a RELRO-t, PaX meg nem engedi meg, se glibc-nek, se masnak. de mindez tok fuggetlen a glibc hibatol, az van PaX nelkul is, csak ritkabban lehet eloidezni.

Naïve kérdés: Nem a libSDL_image-1.2.so.0 a hiba okozója? Nem azt kéne valahogy javítani?

A :-) lemaradt... És igen,e z egy általános érv szokott lenni az opensource szoftverek mellett, hogy sokan látják a forrást, sokan észrevehetik a hibákat/problémákat, sokan küldhetnek bugriportot, sőt, ha akarják ki is javíthatják maguknak. Na ez az, ami nagyon sok esetben rogyadozni látszik...

Hát, a ki is javíthatják az még mindig áll, mint ahogy az is, hogy ha jobban szem előtt lévő projekt lenne, már rég forkolták volna (a GPL határtalan lehetőségei! :)), a karbantartó kooperációképtelensége miatt - lásd a Debian esetét a cdrkittel. Azt pedig még talán RMS sem állította, hogy szabad szoftverek fejlesztésével nem fognak antiszociális arcok foglalkozni.

A műsor tovább folytatódik. Már Kees Cook, az Ubuntu Security Team tagja is beírt, hogy Dreppernek nincs igaza és még az SELinux is visszautasíthat ilyen hívásokat.

PaXTeam pedig továbbviszi a dolgot és megemlíti, hogy a másik mprotect hívásnak sem ellenőrzi a visszatérési értékét, így a RELRO (read-only) szekciót ráadásul írhatóként hagyja, amely viszont már biztonsági probléma, ezért jobb ha annak is ellenőrzi a visszatérési értékét és egyben kér egy CVE-t is a sebezhetőségre... :))