Jádro pudla (Cernobily svet) :-)

Pavel Hudecek phudecek@tiscali.cz
Pátek Březen 3 21:02:26 CET 2006


Kdepak, problém leží na daloko nižší úrovni (budu to popisovat z pohledu
x86 architektury, ale podobné ochrany mají (a měly i před nejméně 10 lety)
i další plnohodnotné platformy):

X86 disponuje dvěma úrovněmi virtualizace, správy paměti a překladu adres
 - segmenty a stránkování. Dále má 4 úrovně oprávnění  - 0 (jádro OS) až
3 (aplikace). 6 segmentových registrů CS (program), DS (implicitní data),
ES, FS, GS, SS (zásobník).

Celý adresový prostor je rozdělen na stránky (4 kB, nebo 4 MB). Každá stránka
má definovánu pozici ve fyzické paměti a několik atributů, které určují, zda je
stránka fyzicky přítomna, zda do ní lze zapisovat, jaká úroveň oprávnění je
nutná pro přístup a ještě nějaké další. Stránkování je primárně určeno ke swapování,
kdy některé z nich OS uloží na HD a nastaví, že nejsou přítomny. Když pak
program přistoupí na takové místo, vyvolá přerušení "výpadek stránky",
jeho obsluha nejprve nějakou jinou stránku uloží, potom na její místo nahraje
tu požadovanou, nastaví fyzickou pozici požadované str. na dané místo,
označí ji za přítomnou a provede iret. Stránkování je možno používat i jako
doplňkovou ochranu.

Adresa z pohledu programu se sestává ze segmentové a offsetové části.
Segment je index do tabulky, ve které je napsáno, kde který segment začíná,
jak je dlouhý, jakou má úroveň oprávnění a jakého je typu.

Typ může být:

Data - adresa je limitována shora, tzn. lze přistupovat na adresy 0-limit.
Segment lze používat ke všem operacím, kromě spouštění programu
a práce se zásobníkem. Lze zakázat zápis.
Vhodné použití: globální proměnné, hromada

Zásobník - adresa je limitována sdola, tzn. lze přistupovat na adresy
limit-4 GB. Segment lze používat ke všem operacím kromě spouštění
programu. Lze zakázat zápis.
Vhodné použití: zásobník, lokální proměnné

Program - adresa je limitována shora, tzn. lze přistupovat na adresy 0-limit.
Segment lze používat ke spouštění programu a čtení. Do segmentu nelze zapisovat,
čtení (ve smyslu třeba mov eax,CS:[123]) lze zakázat.
Vhodné použití: program, konstanty

Brána - nemá žádnou alokovanou paměť a slouží ke skokům na systémové
služby - skok/volání do segmentu brány (offsetová část se ignoruje) vede
k přečtení skutečné cílové adresy z brány - tzn. není potřeba používat nesmyslů,
jako softwarové přerušení, bran může být hodně.

Skoky a volání se změnou oprávnění lze provádět pouze směrem k číselně nižším
úrovním a to pouze přes brány, nebo přepnutím procesu, návrat pouze směrem zpět.

TSS - malý blok paměti, kam se při přepnutí procesů ukládá stav registrů.
Tamtéž se pak nachází i mapa povolených periferií. Skok/volání/návrat
do TSS vede k přepnutí procesů, s uložením stavu procesoru do původního TSS
a načtení nového stavu z cílového TSS.

Tabulky s popisovači jsou dvě - GDT a LDT. GDT je globální, LDT je lokální,
tzn. každý proces má svoji a v ní své segmenty. Jeden z bitů čísla segmetu
určuje, zda je segm. v LDT, nebo GDT. Každá tabulka může mít 8191 platných
hodnot.

Jak to celé má fungovat:

- OS v GDT vytvoří LDT a TSS procesu, v LDT vytvoří segment programu, dat
a zásobníku, které se nepřekrývají (k zápisu použije datové segmenty ze své LDT)
- Z disku nahraje program do jeho segmentu
- Přepne na TSS programu
- Program vesele běží, žádná adresa v zásobníku nezasahuje do dat, ani programu,
žádná adresa z dat nezasahuje do zásobníku, ani programu, žádná adresa programu
neleží v datech, ani zásobníku.
- Když program přistoupí mimo povolený rozsah, vyvolá přerušení "obecná chyba
ochrany". Pokud se totéž stane při práci se zásobníkem, vyvolá přerušení "výpadek
zásobníku", což může OS použít k tomu, aby mu zásobník o kousek zvětšil.
- Protože se adresové prostory nepřekrývají, program ani překladač nepotřebuje vědět
nic o tom, kde a v jakém pořadí v paměti leží, není tedy nutno nastavovat, zda
použít small, tiny, huge, ...

Jak to funguje doopravdy:

Základem je tzv. flat model, kdy segment programu, dat i zásobníku se překrývají po celé délce.
Program sice nemůže k cizím datům, ale sám sebe přepsat může a může taky jakákoli svá data
spustit jako program...

Co to má společného s ANSI C?

Pointery neobsahují segmentovou část adresy, takže C lze používat jen s flat modelem.
Zásobník nelze smysluplně limitovat, protože má-li být limit nad 2 GB (opakuji, limit zásobníku
určuje nejnižší povolenou adresu), budou pointery do něj odkazující záporné:-)

A co XP a SP2?

To je tak trochu "narovnák na vohejbák" - při spuštění programu se zásobník inicializuje
pokaždé na trochu jinou adresu, takže nemůže přetéct předem definovatelným způsobem:-)

Uf... tak pro dnešek mám dost:-)

PH

From: "Delphin" <delphin@post.cz>
>
>>> Dokonce i striktní dodržování standardů má své nesporné výhody i
>>> nebezpečné
>>> nevýhody (málo kdo např. ví, že za současné problémy se stabilitou a
>>> bezpečností
>>> Windows i Linuxu může především norma ANSI C, neboť brání důslednému
>>> oddělení paměťových prostorů systému, programu, dat a zásobníku).
>
> Stabilita je vyresena od W2K. Problemy s bezpecnosti byly identifikovany
> jako kardinalni chyby programatoru pri praci se stringy v C++. Je ale treba
> priznat, ze pri zpusobu prace se stringy v C++ se takova chyba vyrobi velice
> snadno. 




Další informace o konferenci Hw-list