第 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 簽章的取捨相同:簽章輸入大小可控,驗證速度可預測。

支援的簽章演算法(第一階段)

  • ed25519
  • ecdsa-p256
  • rsa-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.*timerandomcryptoproc.*host.*取決於具體平台與權限能力近似全集
伺服器io.*net.*timerandomcryptoproc.*ui.* 全部停用預設無 GUI
瀏覽器net.fetchnet.websocketui.domtimerandomcrypto 子集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 訂閱。