Pravděpodobně znáte zavaděč GRUB, který je součástí většiny linuxových distribucí a zajišťuje funkce potřebné pro úplný začátek startu operačního systému. GRUB je výkonný, flexibilní a plně vybavený zavaděč, který se používá na mnoha architekturách: x86_64, aarch64, ppc64le s OpenFirmware a dalších.
Přestože je GRUB poměrně univerzální a schopný, jeho komplexní funkce vytvářejí složitost, kterou je podle vývojářů obtížné udržovat a která navíc duplikuje systémové funkce a kód a ke všemu zaostává za linuxovým jádrem. Tím zároveň vytváří četné bezpečnostní díry.
Na druhé straně tu máme linuxové jádro, které má velkou vývojářskou základnu, těží z rychlého vývoje funkcí, rychlé reakce na zranitelnosti a větší kontroly výsledného kódu. Vývojáři z Red Hatu proto chtějí zavaděč nahradit samotným linuxovým jádrem. Na konferenci DevConf.cz o tom mluvila ve své přednášce Marta Lewandowská ze společnosti Red Hat.
Co dělá zavaděč
Při zapnutí počítače je cílem dostat se do plnohodnotně běžícího operačního systému, na kterém pak budeme moci spouštět své programy. Při této činnosti, nazvané jednoduše boot, je zapojena celá řada různých softwarových komponent a zavaděč je první z nich.
Jeho cílem je najít na disku obraz systémového jádra a obraz startovacího ramdisku a oba nahrát do paměti. Poté musí připravit vše pro budoucí běh operačního systému a ve správnou chvíli mu předat řízení. V principu je to vlastně jednoduchá úloha, vše je uloženo místně na disku a není třeba dělat nic složitého.
Tvůrci linuxových distribucí ale musejí podporovat spoustu velmi různorodých konfigurací zahrnujících mnoho architektur, firmwarů, souborových systémů a různých sestav diskových úložišť. Kromě toho je možné bootovat ze sítě pomocí NFS nebo třeba HTTP. Je spousta věcí, které se přitom můžou pokazit,
říká Lewandowská.
Secure boot
Do toho všeho přichází ještě koncept Secure boot, tedy zabezpečeného startu operačního systému. Ten dává uživateli jistotu, že do procesu nebyl vložen žádný nechtěný kód (malware). Je to zajištěno pomocí elektronických podpisů a řetězce důvěry, který začíná už v hardware a jeho firmware. Už tento vestavěný kód odmítne nastartovat zavaděč, který není důvěryhodný a podepsaný správným klíčem.
Zavaděč pak musí v řetězci pokračovat a jeho úkolem je hlídat, že načítané jádro je také důvěryhodné. Dnes je to realizováno tak, že součástí zaváděcí sekvence je jednoduchý nástroj Shim, který je podepsaný správným klíčem a jeho úkolem je jen načíst, ověřit a spustit další krok. Jeho jediným účelem je být podepsaný. Je to přechod mezi důvěryhodným bodem v hardware a důvěryhodným bodem v operačním systému,
vysvětluje Lewandowská.
Tímto dalším krokem je dnes zavaděč GRUB, který už nabízí uživatelské rozhraní, umožňuje v nabídce zvolit operační systém, změnit jeho parametry a po ověření jeho podpisu mu předat řízení. Tím konečně začne boot skutečného operačního systému, na jehož konci je spuštění uživatelských procesů.
Abychom nemuseli pro každý hardware kompilovat vlastní linuxové jádro, vznikl koncept inicializačního ramdisku. Jde o obraz dočasného operačního systému, který je vytvářen dynamicky pro daný počítač a zavaděč jej do paměti nahrává společně s jádrem. Ramdisk obsahuje dodatečné moduly, ovladače a nástroje potřebné k rozběhnutí hlavního operačního systému. Je to také největší bezpečnostní díra do Secure bootu,
varuje Lewandowská.
Ramdisk totiž není podepsán a není tedy ani kontrolována jeho důvěryhodnost. I když máme celý proces správně, pořád tu bohužel máme tuhle bezpečnostní díru, která by nám měla dělat starosti,
říká vývojářka.
GRUB
Dnešní linuxové distribuce používají už zmíněný GRUB, který je v linuxovém světě už nejméně dvě dekády synonymem pro zavaděč. Umí toho opravdu hodně, dokáže načíst různé operační systémy, rozumí velmi komplexním diskovým úložištím, pracuje s mnoha souborovými systémy a poradí si i se sítí. Vedle toho potřebuje také podporu více jazyků, fontů nebo rozložení klávesnic. Kvůli tomu je ale také velmi komplikovaný, vlastně je to malý samostatný operační systém.
Už po zavaděči totiž chceme, aby uměl řadu věcí, které pak budeme potřebovat i v samotném operačním systému. Tím se duplikuje kód a vytváří se prostor pro bezpečnostní problémy. Objevuje se spousta složitých chyb týkajících se úložišť, souborových systémů nebo práce s pamětí,
říká Lewandowská.
Tyto problémy samozřejmě stojí čas vývojářů, kteří se jim musejí věnovat. Často jde o chyby, které jsou v jádře dávno opravené, ale my je musíme opravit ještě jednou v zavaděči.
V řadě případů jde navíc o chyby bezpečnostní, velmi komplexní a obtížně řešitelné. Nemáme dost lidí, abychom opravovali všechny chyby okamžitě, opravíme je v jádře a pak se musíme věnovat ještě zavaděči. Ten bude vždycky o kus pozadu,
varuje Lewandowská.
Projekt GRUB je navíc už nějakou dobu neaktivní, takže vývojáři distribucí musejí opravy zařazovat sami. Když si rozbalíte GRUB, najdete tam stovky námi přidaných a udržovaných oprav. Snažíme se opravovat všechno, ale je to ohromný úkol a jde to pomalu.
No More Boot Loader
Vývojáři proto začali pracovat na projektu nmbl (no more boot loader). V zásadě jde o obraz ve formátu UKI (Unified Kernel Image), který obsahuje samotné jádro, příkazovou řádku, inicializační ramdisk a EFI stub. Poslední jmenovaná komponenta je vstupním bodem pro EFI a všechno to balí do spustitelné podoby, která může být přímo zavedena z firmware UEFI.
Celá tahle sestava se pak chová jako jedna komponenta, může být jako celek digitálně podepsána a může rovnou sloužit jako zavaděč. Můžeme tak vynechat celou jednu fázi startu, jejímž úkolem je načíst linuxové jádro. Už ho máme k dispozici a ono rovnou načte samo sebe,
vysvětluje Lewandowská.
Zatím jde jen o úvodní myšlenku a představu o nové koncepci. Výhodou je, že většina komponent už existuje a stačí je jen spojit a přidat trochu nového kódu. Jako EFI stub může být využit existující systemd-stub a pro menu se dá použít grub-emu, takže z uživatelského hlediska bude výsledek stále vypadat jako GRUB. Mělo by to ale fungovat lépe a bezpečněji.
Existují dva způsoby, jak je možné v současné době nmbl nasadit. Zjednodušená varianta předpokládá, že chceme rovnou startovat to jádro, na kterém je v danou chvíli nmbl postaven. Pak stačí z UEFI načíst Shim, tím ověřit obraz se všemi součástmi a rovnou jej zavést a přejít do uživatelského prostoru. Startuje to velmi rychle, ale nemá to žádné menu,
popisuje Lewandowská.
V některých případech ale potřebuje uživatel zavádět jiné jádro, než které je právě součástí nmbl. V takové situaci je začátek stejný, UEFI načte Shim, který zavede nmbl. Pak se ale postup liší a po spuštění uživatelského prostoru se uživateli ukáže menu známé ze zavaděče GRUB. V něm je možné vybrat si jádro, které je pak načteno pomocí volání kexec. Výsledkem je pak načtení druhého požadovaného jádra a dokončení zavádění operačního systému.
Jde zatím o experiment
Zatím je vše ve fázi pokusů a ověřování celého konceptu. To podstatné se děje v repozitáři na GitHubu a vývojáři ocení zpětnou vazbu od uživatelů, kteří si nový způsob bootování vyzkoušejí. Podrobnosti najdete také na blogu Marty Lewandowské.
Stále je potřeba udělat spoustu věcí. V první řadě bude potřeba nmbl integrovat do nástrojů používaných k sestavení jádra pro Fedoru. Tím bude možné automaticky vytvořit také obraz pro zavedení systému s každým novým jádrem a bude možné systém takto startovat prvním zmíněným způsobem. Tohle by mělo být k dispozici poměrně brzy a z uživatelského hlediska bude stačit nainstalovat RPM balíček.
Vývojáři také pracují na možnosti vrátit se při problémech během startu k předchozímu úspěšně zavedenému jádru. V případě problému při instalaci nové verze nástroje Shim nebo jiných potížích, bude možné v EFI automaticky nastartovat předchozí funkční variantu, která umožní standardní boot a pozdější nápravu situace.
Současná koncepce je určena pro UEFI, ale vývojáři by chtěli mít možnost stejnou věc nasadit také na jiných architekturách. Přemýšlíme nad tím a děláme na tom,
uzavřela svou přednášku Lewandowská.