A Rust for Linux kezdeményezés története 2020-ra megy vissza, amikor Miguel Ojeda és néhány lelkes fejlesztő elkezdte kísérletezni azzal, hogy a Rust nyelvet be lehet-e vonni a kernel fejlesztésébe kritikus biztonsági hibák (use-after-free, buffer overflow, null pointer dereferencing) elkerülése végett. A projekt évekig out-of-tree patch-sorozatként élt, amíg 2022 végén, a 6.1-es kernelben végre landolt az alapinfrastruktúra: a rust/ könyvtár, a build system integrációja, és néhány triviális minta-modul.

Visszatekintés: hogyan jutottunk ide

A legelső, mainline-ba került Rust-kód még csak bizonyítéka volt annak, hogy a fordítási lánc működik: egy helloworld jellegű karakteres device driver, illetve néhány absztrakciós réteg a kernel core API-jaihoz (allokátorok, szinkronizációs primitívek, típusos wrapperek a C oldali struktúrák fölött). A cél sosem az volt, hogy a teljes kernelt Rustra írják át — ez irreális és senki nem is akarja —, hanem hogy új driverek és modulok írhatók legyenek egy memóriabiztos nyelven, miközben a meglévő C-kód érintetlen marad.

Megjegyzés

A Rust for Linux nem egy „Rust kernel”, hanem egy második nyelv a meglévő C kernel mellett. A két nyelv oda-vissza hívja egymást FFI-n keresztül, a bindgen és kézzel írt biztonságos wrapperek segítségével.

A jelenlegi kernel verziók állapota

A 6.1 LTS után a 6.2 és a 6.3 kernel is bővítette a Rust absztrakciós réteget: bekerültek finomabb szinkronizációs primitívek, jobb hibakezelési típusok, és stabilizálódott néhány makró, amit a driver-írók használnak. A 6.4-es kernel — ami épp most van a véglegesítés fázisában — további absztrakciókat hoz a PCI és a platform device rendszerekhez, ami előfeltétele annak, hogy komolyabb hardveres drivereket lehessen írni.

Fontos hangsúlyozni: a Rust támogatás a kernelben továbbra is experimentális, CONFIG_RUST egy opt-in kapcsoló, és a build alapértelmezés szerint ki van kapcsolva. Ez tudatos döntés — a maintainerek nem akarják, hogy a Rust-kód instabilitása bárkit is érintsen, aki nem kér belőle.

Milyen driverek és modulok készülnek Rustban

A legismertebb, éles használatra szánt projekt az Android Binder driver Rust-implementációja, amelyen Google mérnökei dolgoznak — ez az IPC mechanizmus, amit az Android rendszer minden folyamatközi kommunikációhoz használ, így a memóriabiztonság itt különösen sokat jelent.

Másik nagy figyelmet kapó munka az Apple Silicon (AGX) GPU driver, amit Asahi Lina fejleszt a Asahi Linux projekt keretében — ez talán a legkomplexebb, valódi hardvert vezérlő Rust kód, amit eddig írtak a kernelhez, és jó reklámja annak, hogy a nyelv nem csak trivialitásokra alkalmas.

További kísérletek futnak:

  • egy NVMe driver prototípus, ami a PCI absztrakciókat teszi próbára,
  • a PuzzleFS, egy tartalom-alapú, réteges fájlrendszer, amit részben Rustban írnak,
  • és apróbb, oktatási célú minta-drivere, amik a dokumentációt gazdagítják.
Tipp

Ha ki akarod próbálni a Rust for Linux buildet, érdemes a projekt saját rust-for-linux GitHub organizációjában lévő ágakat követni — a mainline kernel dokumentációja (Documentation/rust/) lépésről lépésre leírja a szükséges toolchain-verziót és a rustup component add rust-src típusú lépéseket.

Linus Torvalds és a maintainerek álláspontja

Linus Torvalds több alkalommal is kifejezte, hogy támogatja a kísérletet, bár realista hangot üt meg: szerinte évekig fog tartani, mire a Rust-kód aránya érdemben megnő a fában, és semmiképp sem lesz kötelező senkinek Rustban írnia. A legfontosabb feltétel, amit ő és a subsystem-maintainerek megszabtak, hogy a Rust-kód ne törje meg a meglévő C build folyamatot azoknak, akik nem kapcsolják be a CONFIG_RUST-ot.

Vannak azonban kritikus hangok is — néhány régi maintainer szkeptikus a második nyelv bevezetésével kapcsolatban, félve a fenntarthatósági terhektől és attól, hogy két nyelven kell majd karbantartani ugyanazokat a subsystemeket. Ez a feszültség rendszeresen felszínre kerül a levelezőlistákon, de a konszenzus jelenleg az, hogy a kísérlet folytatódik, míg bizonyítja a hasznosságát.

A toolchain-függőség problémája

A legnagyobb technikai kihívás jelenleg a toolchain-függőség. A kernel Rust-kódja számos olyan nightly-only feature-re támaszkodik (pl. alloc_error_handler, egyedi core/alloc build no_std környezetben, egyes lint-beállítások), amik a stabil Rust 1.70-ben még nem elérhetők. Ez azt jelenti, hogy a kernel fejlesztői egy pontosan meghatározott nightly toolchain-verzióhoz vannak kötve — ha az upstream Rust valamit megváltoztat egy nightly feature-ben, a kernel build eltörhet, amíg a Rust for Linux csapat frissíti a kódot.

Ez éles kontrasztban áll azzal, amit a felhasználói szintű Rust-ökoszisztémában megszokhattunk: ott a stabil csatorna és a kompatibilitási garanciák (SemVer, MSRV-politikák) uralják a mindennapokat. A kernelben viszont a nightly-függés miatt a Rust-kód sokkal fragilisabb a fordítói infrastruktúra szempontjából, mint a C-kód.

Figyelem

Ha helyi kernelt szeretnél Rust-támogatással buildelni, ne a distro rustc-jét használd — a Documentation pontosan megadja, melyik nightly verzió a kompatibilis, és eltérés esetén kriptikus fordítási hibákat kapsz.

A fenntarthatóság kérdése is releváns: jelenleg viszonylag kevés ember érti mélyen mind a kernel belső API-jait, mind a Rust nyelvet olyan szinten, hogy biztonságos absztrakciókat írjon. Ez a szűk keresztmetszet lassítja az új subsystem-ek Rust-lefedettségét.

Amit a felhasználói szintű Rust már ma is tud

Érdemes megjegyezni, hogy miközben a kernelben a nightly feature-ök dominálnak, a stabil Rust 1.70 már számos olyan nyelvi elemet tartalmaz, amik jól illusztrálják azt a stílust, amit a kernel-fejlesztők is preferálnak: explicit hibakezelés, minimális rejtett allokáció, erős típusrendszer.

A let-else szintaxis (stabil 1.65 óta) tökéletesen illik ahhoz a defenzív programozási stílushoz, amit a kernel driverek megkövetelnek:

fn parse_register_value(raw: &str) -> Option<u32> {
    let Ok(value) = raw.trim().parse::<u32>() else {
        eprintln!("hibás regiszterérték: {raw}");
        return None;
    };

    Some(value)
}

fn main() {
    let sample = "0x"; // szándékosan hibás bemenet
    match parse_register_value(sample) {
        Some(v) => println!("beolvasott érték: {v}"),
        None => println!("a feldolgozás megszakadt"),
    }
}

A GAT-ok (Generic Associated Types), amik 1.65 óta stabilak, olyan absztrakciókat tesznek lehetővé, amikhez korábban kerülőutakra volt szükség — ez pontosan az a fajta rugalmasság, amire egy driver-absztrakciós rétegnek szüksége lehet:

trait BufferProvider {
    type Buf<'a>: AsRef<[u8]> where Self: 'a;

    fn borrow_buffer<'a>(&'a self) -> Self::Buf<'a>;
}

struct StaticBuffer {
    data: Vec<u8>,
}

impl BufferProvider for StaticBuffer {
    type Buf<'a> = &'a [u8];

    fn borrow_buffer<'a>(&'a self) -> Self::Buf<'a> {
        &self.data
    }
}

fn main() {
    let buf = StaticBuffer { data: vec![1, 2, 3, 4] };
    let slice = buf.borrow_buffer();
    println!("buffer hossza: {}", slice.as_ref().len());
}

Az OnceCell (a std::cell::OnceCell, stabil 1.70 óta) pedig pont azt a lusta, egyszeri inicializálási mintát adja, amit sok kernel-szintű globális állapot igényel — bár a kernelben magában erre saját, no_std-kompatibilis megfelelőket használnak, a minta ugyanaz:

use std::cell::OnceCell;

struct DriverConfig {
    name: String,
    max_queue_depth: u32,
}

fn load_config() -> DriverConfig {
    DriverConfig {
        name: "virtio-net-rs".to_string(),
        max_queue_depth: 256,
    }
}

thread_local! {
    static CONFIG: OnceCell<DriverConfig> = OnceCell::new();
}

fn get_config() -> DriverConfig {
    // egyszerűsített demonstráció: valós kódban referenciát adnánk vissza
    load_config()
}

fn main() {
    CONFIG.with(|c| {
        let cfg = c.get_or_init(load_config);
        println!("driver: {}, queue depth: {}", cfg.name, cfg.max_queue_depth);
    });
    let _ = get_config();
}

Ezek a felhasználói szintű minták jól mutatják, milyen irányba fejlődik a nyelv, és miért olyan vonzó a kernel-fejlesztők számára — még ha a kernel maga jelenleg még a nightly csatornára van kényszerítve.

Összefoglalás

2023 közepén a Rust for Linux projekt egy izgalmas, de még messze nem lezárt kísérlet állapotában van. Az infrastruktúra a mainline kernelben él, komoly driverek (Binder, AGX GPU) készülnek rajta, és Linus Torvalds támogatása biztosítja a projekt jövőjét — de a toolchain-függőség és a nightly feature-ökre való rászorultság még hosszú távú kihívás marad. Ha érdekel a rendszerprogramozás és szereted a Rust nyelv biztonsági garanciáit, most van itt az ideje, hogy közelebbről is megnézd ezt a területet — a levelezőlisták és a rust-for-linux repó tele van tanulási lehetőséggel.