Portál AbcLinuxu, 19. března 2024 06:08

Jaderné noviny – 16. 8. 2018: Jak je důležité míti šum

29. 8. 2018 | David Kolibáč
Články - Jaderné noviny – 16. 8. 2018: Jak je důležité míti šum  

Stav vydání jádra. Citát týdne: J. Bruce Fields. Jak je důležité míti šum.

Stav vydání jádra

Kernel release status. Jonathan Corbet. 15. srpna 2018

Aktuální jádro je 4.18 vydané 12. srpna. Linus řekl: „Byl to velmi klidný týden a dá se říct, že jsem k vydání mohl přistoupit už minulý týden podle obvyklého plánu, ale došlo na nějaké menší aktualizace.“

Stěžejní změny v tomto vydání zahrnují připojování souborových systémů bez práv, restartovatelné sekvence, nové API přijímání dat přes TCP bez kopírování, podporu správu režimů aktivity v doménách napájení, mechanismus AF_XDP pro náročný síťový provoz, jádro implementace filtrování paketů bpfilter a další. Podrobnosti naleznete na stránce KernelNewbies o vydání 4.18.

Stabilní aktualizace: 4.17.14, 4.14.62, 4.9.119, 4.4.147 a 3.18.118 byly vydány 9. srpna. Další aktualizace, obsahující opravy L1TF, 4.18.1, 4.17.15, 4.14.63, 4.9.120 a 4.4.148 byly v době psaní článku revidovány a vyšly 16. srpna.

Citáty týdne

Quote of the week. Jonathan Corbet. 15. srpna 2018

Každý má nějakého koníčka. Ten můj jsou patologické případy zamykání v posixu…

J. Bruce Fields

Jak je důležité míti šum

The importance of being noisy. Jonathan Corbet. 13. srpna 2018

Každý měsíc se podaří opravit (přinejmenším) stovky chyb v jádře. S ohledem na privilegovanou roli jádra v systému má poměrně velká část těchto chyb dopady na bezpečnost. Řady chyb je celkem snadné si všimnout, když k nim dojde, a tak jsou opraveny. Ale některé chyby je těžké detekovat a podoba API v jádře to může ještě zhoršit. Na stole je návrh změny fungování přístupu z uživatelského prostoru, která by snad pomohla ozřejmit, jak je to s jedním druhem nenápadných chyb.

Mnoho systémových volání pracuje s adresami předávanými mezi uživatelským prostorem a jádrem – od jádra se očekává, že z těchto adres bude číst nebo na ně zapisovat. Pokud má volající proces práva k přístupu k dané adrese v paměti, všechno je v pořádku. Ale když uživatelský prostor předá adresu dat, kam by přistupovat neměl být schopen – může to být například ukazatel do prostoru jádra – může nastat problém.

Jádro se chybným (či zákeřným) adresám z uživatelského prostoru brání mechanismem o dvou krocích. První z nich je makro access_ok():

int access_ok(type, address, size);

Tato funkce vrátí nenulovou hodnotu, když přístup daného typu (type buď VERIFY_READ, nebo VERIFY_WRITE) k size bajtům paměti na adrese address dává smysl, tj. když daný rozsah spadá do paměti, ke které by tento uživatelský prostor měl přistupovat. Na většině architektur je jejím úkolem odfiltrovat pokusy o přístup k paměti v prostoru jádra. Když access_ok() vrátí nulu, neměl by proběhnout žádný pokus o dereferenci předané adresy. Jinak po splnění tohoto testu následuje druhý krok spočívající v samotném zkopírování paměti mezi uživatelským a jaderným prostorem pomocí některého primitiva, na což se vztahují obvyklé mechanismy ochrany paměti před neautorizovaným přístupem.

Přestože tyto kroky většina rozhraní pro přístup k paměti uživatelského prostoru, která jsou k dispozici uvnitř jádra, kombinuje, v některých případech tomu tak úmyslně není – obvykle za účelem optimalizace posloupnosti přístupů. Při použití těchto rozhraní může vývojář v jednom či více případů zapomenout zavolat access_ok(), v důsledku čehož jádro přistoupí k paměti v jaderném prostoru přes adresu danou uživatelským prostorem, a to nikdy není dobrý nápad. Výsledkem jsou zranitelnosti jako CVE-2017-5123 či nedávné problémy s bsg.

Řadu problémů, která může jádro přimět k tomu, aby se pokusilo dereferencovat nahodilý ukazatel, dokáže odhalit fuzzing. Ale když se po jaderných funkcích pro přístup k uživatelskému prostoru chce, aby zkopírovaly data na nesprávné místo či naopak z něj, tyto funkce prostě vrátí stav EFAULT, který se v tichosti předá volajícímu v uživatelském prostoru. Většinou je to tak správně, protože pravděpodobnou příčinou je chyba v programu v uživatelském prostoru. Ten mohl chtít například kopírovat data z části svého adresního rozsahu, který není namapovaný, nebo zapisovat do nějaké paměti dostupné pouze pro čtení.

Totéž se ale stane, když uživatelský prostor chce po jádru, aby zkopírovalo data na nahodilou adresu v prostoru jádra, popř. je zkopírovalo z ní. Normálně by volání access_ok() tento problém zachytilo a k pokusu o kopírování dat by nedošlo. Jenže když se access_ok() nezavolá, jádro se může pokusit na popud uživatele přistoupit k prostoru jádra. Pokud nejde o cílený útok, nahodilá adresa v prostoru jádra bude s vysokou pravděpodobností mířit na paměť, která vůbec není namapovaná, tedy aspoň na 64bitovém systému. Výsledný výpadek stránky bude vrácen jako EFAULT nerozlišitelný od libovolné jiné chyby.

Když někdo v uživatelském prostoru spouští fuzzovací program, tento EFAULT zcela zamaskuje skutečnost, že jádro se zrovna pokusilo o něco špatného. Takže vývojáři se o chybě nedozví, a tak chyba následně opravena nebude. Časem ji někdo objeví, a ten někdo nemusí mít zájem na tom, aby byla opravena.

Takový výsledek je nešťastný, protože jádro disponuje veškerými informacemi nutnými k identifikování závažné bezpečnostní chyby. Až na několik málo vzácných výjimek se funkce přístupu z uživatelského prostoru nikdy nevolají s ukazatelem do prostoru jádra. Takže když některá z těchto funkcí vyprodukuje výpadek stránky jaderného prostoru, někde se stala chyba. Dávalo by smysl na to upozornit, aby situace mohla být prozkoumána a došlo k opravě.

To je závěr, ke kterému dospěl Jann Horn, který na základě toho přispěl skupinou patchů pro architekturu x86. Cíl je prostý: když funkce uživatelského prostoru pro přístup k paměti selže s adresou prostoru jádra, přičemž volající nebyl zvlášť označen, výsledkem bude volání WARN(). Tím se vytvoří oops jádra a sledovací záznam v logu jádra. To by mělo v řadě případů přilákat pozornost, zvláště při běhu fuzzovacích nástrojů, protože ty hledají právě takové výstupy.

Reakce na skupinu patchů byly bez výjimky kladné. Samozřejmě se objevily žádosti o různá vylepšení, ale všichni by byli rádi za úspěch tohoto úsilí.

Jaderní vývojáři bývají opatrní, aby do logu jádra nedávali příliš mnoho informací. Příliš upovídané záznamy mohou přinejlepším ztížit hledání opravdu důležitých zpráv, přinejhorším je může uživatel zneužít k přetečení logu nebo jako obecný útok typu odepření přístupu. Ale jádro v aktuální konstelaci některé informace o závažných chybách skrývá, i když by je detekovat mohlo. Tomu by však měl být brzy konec. Někdy je trocha šumu ten správný krok.

Odkazy a zdroje

LWN.net
The importance of being noisy

Další články z této rubriky

Jaderné noviny – přehled za únor 2024
Jaderné noviny – přehled za leden 2024
Jaderné noviny – přehled za prosinec 2023
Jaderné noviny – přehled za listopad 2023
Jaderné noviny – přehled za říjen 2023

ISSN 1214-1267, (c) 1999-2007 Stickfish s.r.o.