【論文筆記】SeaK: Rethinking the Design of a Secure Allocator for OS Kernel

近年來針對 Linux 核心堆疊記憶體漏洞的攻擊頻繁,雖然說核心內部已包含修補與預防措施,但這些措施不是只能防禦特定攻擊就是效能成本太高。本篇論文給出了另一種看待此問題的角度。

SeaK

SeaK

本篇論文的作者認為,造成效能成本高的原因就是核心想要保護所有資料結構的記憶體,實際上真正重要、需要被保護的資料結構可能不多,著重保護這些資料結構就可以了。因此作者提出一種基於 eBPF 的保護措施 SeaK,透過更改重要資料結構的配置與釋放行為來保護特定資料結構。

Linux 核心中保護核心記憶體的措施可分為三類:

  1. 預設開啟:包含可用列表隨機化、可用列表混淆以及記憶體清零等,但這些只能防特定攻擊,而不能 UAF 等攻擊。
  2. 預設關閉:如 KFENCE 會在記憶體分頁週遭加上 guard page,但因為會使用大量記憶體,所以 KFENCE 一般使用時只會抽樣(小於百分之一)加上 guard page,導致保護效果不佳。
  3. slub-debug:可以偵測記憶體存取錯誤,雖然對於除錯而言成本算低,但是對於日常使用而言成本還是過高。

下表是作者使用兩種 micro-benchmark 與 macro-benchmark 測量三種保護措施的效能成本,可看出效能成本低的都是保護效果不佳的,而保護效果好的效能成本都過高。

Linux 原生保護效能分析

SeaK 的想法是有效的保護具有高效能成本的原因來自於核心想要保護所有資料結構,如果只保護特定資料結構,並且使用各種最有效的保護措施,是不是就能降低效能成本呢?

SeaK 的做法是將 eBPF 程式插入至要保護的資料結構的配置與釋放函式,由 SeaK 代為管理記憶體。Seak 使用的保護措施包含 guard page 與偏移隨機化,日後也可針對不同攻擊增加新的保護措施。使用情境是系統管理員知道一個漏洞存在且核心尚未發布修補時,可先使用 SeaK 暫時修補,等到核心修補發佈時再更新核心。

SeaK 展現出的效能和記憶體成本都很理所當然,論文結果表示效能與記憶體成本最高都只有約 2%,畢竟它只保護特定的資料結構。

想法

精妙的切入點

很多研究都專注於如何降低保護措施效能損失的同時達到最高的保護效果,但是這篇論文從另一個維度——保護範圍來達成這個目標,我個人認為這種研究太帥了,我也想要做這種研究。

效能測試效度

雖說論文中的效能測試表現良好,但是論文測試時是在只有保護一個資料結構如 struct seq_operations 的情況下,它使用 LMbench 測試 simple syscall 等場景,但是這個結構又不一定每次 syscall 都會被配置或釋放,更不用說 SeaK 此時只有保護一個結構,效能當然會很好,因此我質疑論文中的效能測試效度。

可擴展性效度

論文測試了 SeaK 同時保護多個資料結構的可擴展性如下,一個資料結構對應至一個 AA。但是和效能測試效度同理,我懷疑的是 64 個 AA 在核心中是算多還是少?足夠保護作業系統嗎?論文中並沒有提及這一點,畢竟如果不足以保護的話,那麼效能再好也沒有用。

可擴展性分析