(つ`ω´)つ says to Ubuntu 台灣社群
Rust 抓不到的漏洞 (★ 164 分) Canonical 在 Ubuntu 26.04 LTS 前對 uutils 做外部稽核,公開 44 個 CVE (通用漏洞揭露編號)。uutils 是以 Rust 重寫的 GNU coreutils,自 Ubuntu 25.10 起已預設提供,但 cp、mv、rm 因為這波發現的問題,在 26.04 LTS 仍先保留 GNU 版本。作者強調,重點不是否定 Rust,而是這些漏洞都出現在正式上線的 Rust 程式碼裡,卻沒有被 borrow checker (借用檢查器)、Clippy 或 cargo audit 擋下,說明 Rust 的安全邊界主要停在記憶體安全,對檔案系統語意、Unix 行為與工具相容性造成的邏輯錯誤,仍得靠設計與經驗補上。 文章整理出數個最值得警惕的模式,其中最大宗是 TOCTOU (Time Of Check To Time Of Use,檢查與實際使用之間的競態):程式先對某條路徑做一次系統呼叫,再對同一路徑做第二次操作,攻擊者就能在中間把目標換成符號連結,讓高權限動作落到別處。Rust 標準函式庫的檔案操作多半以路徑為中心,反而容易讓人忽略這種風險,因此作者主張應盡量以檔案描述元 (file descriptor) 為錨點;建立檔案或目錄時就一次設好權限,不要事後再改;判斷是否為根目錄或同一個檔案時,也別直接比字串,必要時應比對裝置編號與 inode (索引節點)。另一類問題出現在 Unix 的位元組邊界:路徑、環境變數、命令列參數與 comm、sort 這類工具的輸入,本質上都不保證是 UTF-8,若硬轉成 String,不是把非法位元組悄悄改掉,就是在遇到非 UTF-8 時直接異常終止,最後變成資料毀損或工具不可用。 作者接著把每一次 panic 都視為 DoS (阻斷服務) 風險:只要不可信輸入能碰到 unwrap、expect、越界索引或未檢查運算,就可能讓排程工作、CI (持續整合) 或 shell 腳本整串停擺。相同地,錯誤若被 ok()、預設值或忽略式寫法吞掉,也可能讓工具回報成功,實際上卻只做了一半。文章還特別提醒,相容性本身就是安全需求,例如 uutils 曾把 kill -1 解讀成對 PID (行程識別碼) -1 送出預設訊號,在 Linux 上幾乎等於對所有可見行程動手;最嚴重的案例則是 chroot,若先切進攻擊者可控制的新根目錄,再透過 NSS (Name Service Switch,名稱服務切換機制) 解析使用者名稱,系統可能從新環境載入動態程式庫,導致本機 root 權限的任意程式執行。即便如此,作者仍認為 Rust 的價值非常明確:這份稽核沒有找出緩衝區溢位、釋放後再使用或資料競爭等經典記憶體安全問題,真正棘手的是程式與外部世界交界處那些型別系統保不住的細節。 留言區多數人認同,這批漏洞主要揭露的是 Unix 與檔案系統的老陷阱,不是 Rust 背棄了承諾;Rust 在 safe Rust 範圍內主要降低的是記憶體安全問題,不會自動消滅所有邏輯錯誤。不少人批評 uutils 團隊顯然比起 Rust 更缺乏 Unix 經驗,像錯誤碼傳遞、位元組與字串邊界、kill -1 的歷史語意,都像老牌 coreutils 開發者早年就學到的教訓;也有人替團隊緩頰,指出 uutils 本來就是 2013 年起的學習型專案,又因 MIT 與 GPL 授權區隔,不適合直接參考 GNU 原始碼。GNU coreutils 維護者也現身回應,認為 Rust 的 std::fs 確實太容易寫出 TOCTOU,最好能有類似 openat (以已開啟目錄的檔案描述元為基準操作路徑) 的介面,也有人建議自建包裝函式庫,再用 lint (靜態規則檢查) 禁止直接呼叫危險的路徑式 API;他同時補充,比起一律用 canonicalize,實務上更穩當也更有效率的作法是用 fstat 讀出裝置編號與 inode 來比對檔案身分。另有留言指出,文中稱 uutils 完全沒有同類記憶體安全問題並不精確,較接近的是曾出現過 unsoundness (型別系統不健全) 風險。整體氣氛偏向把這篇文章視為 Rust 系統程式設計的檢查清單:記憶體安全很重要,但只要牽涉檔案系統、名稱解析與舊工具相容性,工程紀律、測試與 Unix 常識依然無可取代。 👥 52 則討論、評論 💬 https://news.ycombinator.com/item?id=47943499