Clang alapú C nyelven megvalósították a pufferhatárok ellenőrzési módot.

Az Apple mérnökei bejelentették, hogy kész az „-fbounds-safety” mód forráskódú Clang fordító tesztelésére, amely biztonságos működést garantál a C nyelvű kódokban a buffer kezelése során. Ez a mód része az Apple által fenntartott LLVM fork-nak, amely a Swift projekthez kapcsolódik. A jövőben tervezik a „-fbounds-safety” funkció fokozatos átadását az LLVM/Clang fő kódalapjába.

Megjegyzendő, hogy a javasolt védelmi mechanizmus már aktívan használatban van az Apple termékeiben, mint például az XNU kernel, firmware-ek, hangmunkáló könyvtárak és képkódolók. A „-fbounds-safety” mód bekapcsolása átlagosan 5%-kal csökkenti az alkalmazások teljesítményét (terjedelem -1% és 29% között), 9,1%-kal növeli a kód méretét (terjedelem -1,4% és 38% között) és 11%-kal lassítja a fordítást.

A „-fbounds-safety” mód alkalmazása a pointerrel kapcsolatos memóriahatárok automatikus azonosításához speciális annotációk hozzáadását igényli a kódhoz, valamint a „ptrcheck.h” fejlécfájl bevonását. A javasolt védelmi módszer lényege, hogy automatikusan hozzáad ellenőrzéseket a megengedett határok betartására, amelyeket kézi annotációk vagy a fordító által ismert méretek alapján adnak hozzá.

Ellentétben a nagyobb címtartók (wide pointer) kódba való integrálásával, amelyek a cím mellett a buffer felső és alsó határainak információit is tartalmazzák, a „-fbounds-safety” mód alkalmazása nem sérti az ABI-t (Application Binary Interface), nem változtatja meg az exportált pointerek formátumát és nem igényel a projekt átdolgozását egy időben. A „-fbounds-safety” módban a kibővített pointerek csak az ABI-vel nem érintett területeken alkalmazhatók, míg az ABI-t érintő pointerek esetében normál pointereket használnak, amelyekhez annotációkból származó ellenőrzések társulnak.

Az annotációkat a struktúrák mezőiben és az objektumok tömbjére mutató függvényparamétereknél kell rögzíteni, valamint globális pointerekhez tartozó változóknál. Helyi változók esetében nem kell annotációkat hozzáadni, mivel ezek automatikusan bővített pointereként kezelendők, amelyek már tartalmazzák a megengedett határokra vonatkozó információkat. A kódbeli konstrukciókhoz szükséges annotációk hozzáadására vonatkozó javaslatokat a fordító a „-fbounds-safety” kapcsolóval való indítással adja meg.

A «-fbounds-safety» alapú védelmi modell fokozatosan, fájlról fájlra építhető be anélkül, hogy megszakítaná a teljes projekt fejlesztését. A védelem hozzáadása a projekthez annyiból áll, hogy annotációkat kell megadni egy adott kódfájlban, a fordítói figyelmeztetéseket ki kell küszöbölni, és a program működésének tesztelését el kell végezni, majd ezeket a lépéseket meg kell ismételni a következő fájlra. A hozzáadott annotációkkal ellátott kód továbbra is kompatibilis a szokásos C kóddal és az olyan fordítókkal, amelyek nem támogatják a «-fbounds-safety»-t (más fordítók általi fordítás vagy a «-fbounds-safety» jelzés nélküli fordítás során egyszerűen nem fognak további határvizsgálatokat hozzáadni).

A program futása során, ha határértékeken túli hozzáférést észlel, kivételt generál, és a program befejezi végrehajtását. Vészhelyzeti leállás akkor is bekövetkezhet, ha helytelen annotációkat adunk meg, ezért a «-fbounds-safety» használatakor további tesztelést kell végezni a program működéséről.

Az alábbi példában a «int *p» paraméterhez hozzáadjuk a «__counted_by(n)» annotációt, amely további futásidejű határvizsgálatot ad hozzá. Ha megpróbáljuk a kódot «-fbounds-safety» módban lefordítani anélkül, hogy ezt az annotációt megadnánk, a fordító figyelmeztetést fog kiadni az array határok információjának hiányáról a «p[i] = 0» kifejezés feldolgozásakor. #include void init_buf(int *__counted_by(n) p, int n) { for (int i = 0; i < n; ++i) p[i] = 0; // a «-fbounds-safety» módban a fordító automatikusan beilleszti a vizsgálatot, hasonlóan a «if (i = n) trap();» kódhoz }

A lokális változók esetében a pointerekhez a határvizsgálat automatikusan kapcsolódik, például: void foo(int i){ char *buf = (char *)malloc(10); // a buf pointerhez információkat tárolnak a határokról buf[i] = 0xff; // automatikusan beillesztésre kerül a vizsgálat «if (buf + i = buf + 10) trap();» }

A fordító lehetőség szerint optimalizálja a kódot, és mellőzi a felesleges kód hozzáadását, ha a kódban már léteznek a szükséges vizsgálatok. Például: for (size_t i = 0; i < count; ++i) { buf[i] = i; // a vizsgálat «if (i = count) trap()» nem lesz hozzáadva, mivel föntebb már van egy feltétel «i < count» és i nem lehet kisebb, mint 0. }

Főbb annotációk:

  • «__counted_by(N)» — meghatározza a puffer méretét a cél típus elemeinek számában.
  • «__sized_by(N)» — meghatározza a puffer méretét bájtokban.
  • » __ended_by(P)» — beállítja a pufferméret felső határát.
  • «__null_terminated» — figyelembe veszi a null karaktert a puffer végének.
  • «__single» — egy objektumra köti a mutatót. Alapértelmezés szerint alkalmazzák az ABI-t befolyásoló mutatók esetén, hacsak kifejezetten nem állítják be a megjegyzést.
  • «__bidi_indexable» — kiterjesztett mutató, amely információt tartalmaz a felső és alsó határokról. Alapértelmezés szerint alkalmazzák a mutatókra, amelyek nem befolyásolják az ABI-t.
  • «__indexable» — kiterjesztett mutató, amely információt tartalmaz a felső határról.
  • «__unsafe_indexable» — határellenőrzés nélküli mutató (a nem védett kóddal való hordozhatóság érdekében, például mutatók szerzése külső kódból).

Forrás: opennet.ru

Megbízható hosting vásárlása weboldalak számára, DDoS védelemmel, VPS VDS szerverek. 🔥 Megbízható webtárhely vásárlása DDoS védelemmel, VPS VDS szerverek | ProHoster