Rust成爲C的接班人 或將開發Linux驅動

Rust 是由 Mozilla 主導開發的專注於安全、速度和併發的系統級編程語言,目前已經逐漸走向成熟。最近,英特爾首席工程師 Josh Triplett 在 2019 年開源技術峯會(OSTS)上發表了主題爲“英特爾和 Rust:系統編程的未來”的演講。他就開發人員是否可以用Rust開發驅動程序這一問題詢問了Linux內核穩定版維護者 Greg Kroah-Hartman。

Kroah-Hartman 表示願意接受用 Rust 開發Linux內核的驅動程序,但有兩個條件。其一,以可選的方式存在,而不是默認啓用,這樣其他開發者就不需要使用Rust去構建內核;其二,Rust 驅動需要展現出比 C 驅動更具優勢的特性,比如針對內核API的安全封裝器。看樣子,大家未來有很大的機會使用Rust編寫Linux驅動。

在很長一段時間裏,Linux內核和驅動程序開發,基本上都是用C語言編寫的。

然而,C寫driver的主要缺陷在於C賦予程序員的自由度過大,所謂能力越大責任越大,程序員需要小心處理各種細節以保證driver的安全。在一些情況下,程序員容易因爲疏忽大意寫出不安全的代碼。例如申請的內存忘記釋放(內存泄漏),使用了已經被釋放的指針(use-after-free),數組越界訪問(buffer overflow)等等。這些錯誤大多歸因爲C是一門不安全的語言。

前段時間,隨着微軟計劃用Rust取代C和C++新聞的曝出,Rust被認爲是C/C++的接班人。由Mozilla開發的Rust被認爲具有較強的安全性。同時,由於特殊的類型系統,Rust不需要垃圾收集,也被認爲是高效的。Rust程序運行速度極快,可防止段錯誤並保證線程安全。這些屬性使該語言極大地吸引了專注於應用程序安全性的開發人員。香港中文大學系統安全系博士李卓華指出,Rust主要通過嚴格的語法和安全檢查來限制程序員,“逼迫”程序員寫出更安全的代碼。例如Rust的ownership特性保證任何時刻,一個對象最多隻有一個可變引用,且在其生命期結束後編譯器會自動將其內存釋放,從而避免了內存泄漏和use-after-free的問題。

《Rust編程之道》作者張漢東表示,Rust的優勢在於內存安全和併發安全,以及現代化的類型系統,更能保證程序的正確性。並且擁有現代化的工具鏈,比如對SIMD、WASM等的支持。現在已經有人用Rust寫了WASM的虛擬機(Wasmer),允許在 Linux 內核中實現安全的 WebAssembly 運行環境,這樣可以避免如系統調用(上下文切換)、用戶態/內核態數據複製等性能損耗(當前評測情況是提升10%)。看得出來,使用Rust擴展Linux內核,會帶來更多的可能性。

北美華人安全論壇BASec創始人韋韜認爲,Rust有着出色的性能表現,不過對於普通業務而言,性能不是關鍵,穩定性纔是。這個恰恰是Rust的最強項。就穩定性而言,Rust碾壓大部分語言,包括C,C++,Go,Python,PHP等等。但是沒有免費的午餐,Rust的穩定性來自於Borrow Checker的"嚴苛",Ownership機制對於Rust入門者有一定的門檻。但大部分情況下,配合上基本的編程規範(嚴格限制unsafe/unwrap/…等),只要Rust編譯器點頭,程序運行起來就沒什麼問題。需要注意的是,Rust保障的內存安全不包括防止內存泄露。因爲內存泄露的語義和具體應用邏輯強相關,所以還需要做額外的內存泄露檢查,但這方面的工具比較現成,一般不是大問題。但即使如此,Rust寫驅動也不太樂觀,主要是兩個原因。一是需要把底層的unsafe仔細封裝,因爲在驅動場景下,很多操作不滿足Rust safe的要求,一旦代碼裏混雜了很多unsafe,那麼因常規安全檢驗工具的缺乏,Rust反而會不如C。二是硬件廠家的工程師從C改爲Rust更漫長,廣泛的硬件驅動支持纔是Linux生態繁榮昌盛的根基,這個生態挑戰比單純的技術挑戰更大。

就Rust目前開發Linux驅動的落地難點問題,李卓華列出以下幾點:

  1. Linux內核中定義的函數,結構體衆多,想要在Rust中使用需要將它們重新改寫成對應的Rust版本,這一點人工完成的話工作量極大,自動完成的話(用bindgen將C翻譯成Rust)代碼醜陋雜亂,且缺乏安全抽象。
  2. Linux內核使用的很多C的特性沒有對應的Rust實現,例如C結構體的bitfield。
  3. Driver主要是底層的代碼,有時需要Rust的unsafe特性,無法保證安全性。
  4. 編寫Driver主要是提供一組回調函數(callback function),由內核負責在合適的時候調用。這就需要回調函數必須用FFI(Foreign Function Interface)編寫(因爲Linux內核只提供C的函數原型),且必須是全局的(因爲要讓Linux內核可以找到它們),這就限制了開發者封裝和組織風格良好的代碼。
  5. 調用內核函數也是unsafe的,除非爲其提供一層安全抽象。
  6. Linux不保證API和ABI的穩定性,因此難以封裝內核函數和數據結構。

在此前InfoQ發表的文章中,有些讀者評論Rust的生態尚未建立,可能會成爲落地的阻礙。對此,韋韜表示,Crate雖然還不夠豐富,但現在逐漸在改善;其實更大的問題是低質量的Crate混雜其中,會破壞Rust應用的穩定性和安全性。但相比較而言,Rust的crate包管理比C/C++強太多,已經有很多落地實踐表明是完全可行的。

關於人們關心的如何爲Linux的內核函數提供一層安全的抽象的問題。專家認爲,這裏存在不少挑戰,但是是一個正確的方向,這個方向如果成功,會極大的提升Linux內核的安全性和穩定性。

感興趣的Rust開發人員不必從頭開始。目前至少有一個Github項目已經存在,它適用於內核模塊的框架,有關該項目的背景信息可以在2019年Linux北美安全峯會的演示文稿中獲取。

相關鏈接:
Rust 未來可用於開發 Linux 驅動
Rust-Module im Linux-Kernel vorstellbar

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章