VirtualBox E1000 Guest-to-Host Escape 0day

Video demó:

VirtualBox E1000 Guest-to-Host Escape from Sergey Zelenyuk on Vimeo.

Sebezhetőség leírás, workaround stb. itt.

Hozzászólások

Ez kemény. Hajmeresztően bonyolult algoritmussal próbálják *közvetetten* garantálni, hogy az X méretű pufferbe ne lehessen nagyobb méretű adatot beletolni, amit hogy - hogy nem, valahogy mégis csak át lehet verni, ahelyett, hogy valami értelmes adatstruktúrával és ellenőrzéssel garantálnák *közvetlenül* írás előtt, hogy X méretű pufferbe X méretű adat megy. Mert annyira rossz performanciája vagy PR-ja lett volna egy látszólag redundáns plusz ellenőrzésnek? Ezért szeretjük a C-t, hogy ezt simán megengedi :).

Ez így ebben a formában nem igaz, lásd még Rustban írt Linux kernel modul.

Egy modern kernelben viszonylag kicsi az a rész, ahol közvetlenül a HW-val kell beszélgetni, azt meg el lehet zárni szép interfészek mögé, a többi részt meg lehet olyan nyelven írni, ami jobban fogja a programozó kezét.

Jelenleg olyan jók már a C++ fordítók, hogy minimális azoknak a projekteknek a száma, amit technikai okok miatt nem lehet C++-ban megírni (pl. mert nincs GCC vagy Clang támogatás az adott architektúrán).

C++-ban sem kötelező öröklődést, virtuális metódusokat, template-eket ... stb. használni, ellenben olyan kontrollt ad a programozó kezébe erőforráskezelésben (RAII minta), ami miatt nagyon elegánsan és biztonságosan lehet benne programozni.

Emiatt én azt gondolom, még akkor is, ha az OO funkciókat nem használod valami miatt C++-ból, jobban megéri C++-szal kezdeni dolgozni C helyett egy új projekten.

Ha már C++-t használunk, akkor miért nem valami modernebb nyelvet? A C++ nagyon sokoldalú, pl. lehet OO, procedurális vagy akár funkcionális nyelvként is használni. Szabadon eldöntheted a memóriakezelést (kézi, reference counted, garbage collection), ... stb. A legtöbb nyelv általában ezeket a döntéseket nem bízza a programozóra, hanem a nyelv tervezése során eldöntik. Pl. a Go egy garbage collectort használó nyelv. Ez azt jelenti, hogy olyan helyen, ahol a determinisztikus teljesítmény fontos, nem lesz ideális a Go, mert a garbage collector bármikor beüthet és elrontja az időzítéseket. C++-ban a fejlesztő dönthet egy reference counted megoldás mellett, ami kellően determinisztikus teljesítményt nyújt. Ez inkább a beágyazott világra jellemző, de pl. az Apple hagyományosan ezért részesíti előnyben a reference counting alapú memóriakezelést a GC-vel szemben. (Rossz nyelvek szerint meg azért, mert nem tudtak jó GC-t írni... :D )

Pont azért, mert a C++ ennyire általános nyelv, a projekt kezdetén sokkal több mindent a fejlesztőcsapatnak kell eldöntenie, nem mondhatják azt, mint pl. Java-nál, hogy használjuk a best practice-t, mert C++-nál sok különböző irány van - különböző előnyökkel és hátrányokkal.

Viszont ha a fejlesztőcsapat jól elvégzi ezt a munkát, és pl. bekonfigurál egy statikus kódelemzőt a build folyamatba, valamint megtiltja a nem biztonságos funkciók használatát (természetesen automatizált ellenőrzéssel), akkor a C és C++ -ra jellemző hibák túlnyomó részét ki lehet küszöbölni. Tény, hogy sok helyen nem használják ki ezt a lehetőséget (mi sem annyira, mint szeretném), ami viszont könnyen vezet rossz minőségű kódhoz, és banális hibákhoz.

TLDR: Ha találsz olyan nyelvet, ami jobban megfelel az igényeidnek, használd azt (feltéve, ha a csapatod hajlandó és képes az adott nyelvvel dolgozni). Ezzel együtt C++-ban is lehet biztonságosan és produktívan fejleszteni.

Nem értek hozzá, ezért kérdezem: mekkora effort? Az ökoszisztémát kell 1x jól belőni, vagy minden egyes projekt/program esetén nulláról kell kezdeni. És ha nulláról kell kezdeni akkor fél óra vagy fél hónap? Templétezhető, automatizálható, van-e reuse lehetőség korábbi projektekből?

Az egyszer megcsinálás még hagyján, utána a karbantartás... Legyen SCM, legyen valami management rendszer körülötte, ami kezeli a taskokat, pull requesteket. Ok, ezt mondjuk egy Github tudja. De akkor legyen már CI, ami builde, unit tesztel, integrációs tesztel, ahhoz kell mondjuk dockerben felhúzni imageket, persze valahova a docker/random egyéb nyelv packageinek is kerülnie kell, valahol futnia kell annak is, ezekből artifactot gyártani, valahova ki is kell települnie cloudba/fizikai vasra, legyen teszt környezet, éles környezet, automatikusan tudjon, legyen automatizált DB migráció, meg legyen már monitoring, ezeket mind-mind össze kell reszelni, stb.

Hónapokat el lehet ezzel tölteni és kifejezetten időt el lehet feccölni azzal is, hogy teszem azt valami nem támogat valamit és mind az ansible-s mind a terraformos plugin bugos valahogy te meg keresed a lehetőséget, hogy ne már shell scriptekkel kelljen összecelluxolni az egészet, mert az még egyszer kártyavárként fog összedőlni a picsába.

Ok, nyilván, az amiről beszélek, az most egy komplett infrastruktúra, de azért ha jól akarja ezt valaki csinálni, akkor ez nagyon sok komponens.

----------------
Lvl86 Troll, "hobbifejlesztő" - Think Wishfully™

A C-t ma már nincs kb. semmi értelme használni (kivétel, ha csak C fordító van). Ha 1-2 dologra az ember odafigyel, akkor a C kódot egy az egyben le lehet fordítani C++ fordítóval. Pár dolgot kicserélve (malloc helyett new, stb.) teljesen valid C++ programunk lesz.

C++-hoz pedig lehet csinálni osztályokat, amik meggátolják, hogy a buffer túlcsordulást hackelésre lehessen használni. Pár szabályt betartva simán lehet olyan programot írni, ami a túlcsordulást úgy kezeli, hogy elszáll (a helyett, hogy valami más területre ráír). Ez a pár szabály olyanokat tartalmaz, hogy ne használjunk sehol naked pointereket. Nincs memcpy, és minden naked pointer helyett egy pici osztály legyen, amiben el van tárolva az is, hogy a terület meddig érvényes (ez persze háromszorosára növelné a pointer méretét). Így minden memóriahozzáférést le lehet ellenőrizni. Ez megköti valamennyire a programozó kezét, de simán lehetne így is C++ programot írni. Csak ugye minden használt librarynak így kellene működnie.

A hátránya ennek az, hogy valamennyivel lassabb lesz a futás, és több memória kell. Itt kérdés, hogy ez vajon hogyan viszonyul az általad említett nyelvekhez. Simán lehet, hogy az ilyen módon megírt C++ program már lassabb, mint a Go/Rust, és több memóriát kér.

Lassan újra lehet gondolni a HW-t (pl. Spectre/Meltdown) és az SW-t is.

--
robyboy