第 7 章 安全模型
Fayger 的安全模型由兩條線索組成:
- 來源可信:BuF 製品本身可被簽章,載入時檢核來源與完整性。
- 執行可控:BuF_Instance 在執行期只能使用被顯式授予的能力,未宣告的能力一律不可見。
兩條線索分別在載入層與適配層落地,並在第 6 章的錯誤模型與第 4 章的故障隔離中得到加強。
7.1 來源可信:簽章與摘要
摘要
每個 Section 在 BuF_Manifest 中都宣告了 digest。載入鏈中的 Verify Digest 階段對每個 Section 重新計算摘要並比對:
- 任一段不匹配回傳
LDR_DIGEST_MISMATCH。 - 錯誤 context 包含失敗的
section_id。
Trailer 中的 manifest_digest 同時檢核 Manifest 自身沒有被截斷或修改。
簽章作用範圍
簽章涵蓋的位元組範圍:
Header || Manifest_minus_signature || Section_Index
設計意圖:
- 即便攻擊者在簽章後修改 Manifest 的任意欄位(除 signature 區塊本身),簽章都會失效。
- 調整 Section 偏移、長度、摘要也會讓簽章失效,因為 Section_Index 在簽章範圍內。
- Section 段體本身不直接涵蓋在簽章內,但每段的
digest都在 Manifest 內,轉而間接涵蓋。
這種「簽 manifest,digest 鏈 sections」的方式與 OCI Image 簽章的取捨相同:簽章輸入大小可控,驗證速度可預測。
支援的簽章演算法(第一階段)
ed25519ecdsa-p256rsa-pss-sha256
演算法識別與公鑰參照都在 Manifest 的 signature 區塊中顯式宣告,避免基於 ASN.1 / X.509 隱式協商。
簽章檢核決策表
| 條件 | 期望結果 |
|---|---|
| 強制簽章模式開啟 ∧ 無簽章 | Err(LDR_SIGNATURE_FAIL),原因 MissingSignature |
| 有簽章 ∧ 驗證失敗 | Err(LDR_SIGNATURE_FAIL),原因 InvalidSignature |
| 有簽章 ∧ 驗證通過 | Ok |
| 強制簽章模式關閉 ∧ 無簽章 | Ok(開發便利模式) |
7.2 強制簽章模式
強制簽章模式(enforce signature)是一個載入策略開關,由 LoaderPolicy.require_signature 控制:
struct LoaderPolicy {
require_signature: bool
trusted_roots: TrustedRootSet
allowed_schema_versions: VersionRange
}
行為約束:
- 開啟時:任何 BuF 必須攜帶簽章且簽章驗證通過,否則拒絕載入。
- 關閉時:未攜帶簽章的 BuF 仍可載入(開發便利);攜帶但無效簽章的 BuF 仍被拒絕(不允許「假裝簽了」)。
發布場景(生產、可信發布通道)建議在設定層把 require_signature 預設置為 true。
7.3 信任根管理
interface TrustStore {
current_roots() -> TrustedRootSet
update(roots: TrustedRootSet)
enforce_signature() -> bool
}
更新可見性約束:
- 對一組操作序列
Ops(混合Update(roots)與Load(buf)),每次Load(buf)在簽章驗證時使用的信任根集合必須等於該 Load 之前最後一次Update所設定的 roots。 - 這一約束讓「在載入到一半時根集合發生切換」的競態在語意上不可能發生。
實作策略:
- 在每次
LoaderPipeline.load入口處對TrustStore拍快照,整次載入使用該快照。 - 顯式拒絕在載入期間共享可變信任根集合。
7.4 執行可控:能力安全模型
適配層採用 capability-based security(與 WASI 一致)。BuF 在 Manifest 中宣告能力請求,Platform_Adapter 與宿主策略共同決定授予。
形式化:
granted = requested ∩ available ∩ host_policy
denied = requested \ granted
啟動門控
如果 manifest.required_capabilities \ granted ≠ ∅:
start()必須回傳錯誤。- 錯誤 context.missing 等於差集。
- 實例不進入 Running。
這是「能力不足時禁止啟動」的硬約束。
預設拒絕
- 未宣告的能力對 BuF 不可見。
- Platform_Adapter 不應因「反正能力位看起來對就放過去」而提供未宣告的能力。
- 未識別的 Universal_Instruction 類別一律回傳
ADP_UNSUPPORTED_INSTRUCTION,不「沉默放行」。
7.5 能力分類與裁剪要點(按宿主)
| 宿主類別 | 典型可用能力 | 典型不可用能力 | 說明 |
|---|---|---|---|
| 桌面 | io.*、net.*、ui.*、time、random、crypto、proc.*、host.* | 取決於具體平台與權限 | 能力近似全集 |
| 伺服器 | io.*、net.*、time、random、crypto、proc.* | ui.* 全部停用 | 預設無 GUI |
| 瀏覽器 | net.fetch、net.websocket、ui.dom、time、random、crypto 子集 | proc.*、大部分 io.* | 強裁剪 |
| In-App | 由宿主顯式注入 | 預設全部停用 | 最嚴格,宿主擁有最終決定權 |
7.6 資源隔離作為安全屏障
資源隔離不僅是穩定性需求,也是安全屏障的一部分:
- 單個 BuF_Instance 的故障不會擴散到其他實例(見第 4 章的故障隔離性質)。
- 配額超限會觸發暫停,避免一個實例耗盡宿主資源。
- 不同實例的 RuntimeDataArea 互不可見,避免側通道資訊洩漏在資料層面發生。
7.7 安全 / 錯誤的互動
簽章與能力相關的失敗必須以統一錯誤模型對外回傳:
- 簽章失敗:
LDR_SIGNATURE_FAIL,附MissingSignature/InvalidSignature等原因。 - 能力被拒:
ADP_CAPABILITY_DENIED,附被拒能力集合。 - 啟動門控失敗:複用
ADP_CAPABILITY_DENIED,context.missing 給出差集。
錯誤鏈與第 6 章一致:底層錯誤置入 cause,上層錯誤標註自己的 source_layer,呼叫方可沿鏈定位。
7.8 安全稽核建議
雖然稽核本身不在 Fayger 內部範疇,但 Fayger 的事件匯流排、Lifecycle 事件與 Loader 事件已經為外部稽核系統提供了足夠錨點:
- 載入鏈每一階段的成功 / 失敗事件可作為來源檢核的稽核點。
- Lifecycle 事件記錄每個實例的啟動 / 暫停 / 終止時間軸。
- 能力裁剪結果可作為安全決策的稽核點。
- 簽章檢核失敗、能力被拒、配額超限事件都可被外部 SIEM / 稽核 Pipeline 訂閱。
