常見問題

我可以使用執行緒嗎?

是, Sandbox2 支援執行緒。

所有執行緒都必須採用沙箱機制

基於 Linux 的運作方式,seccomp-bpf 政策只會套用到目前的執行緒:這表示這項政策不會套用至其他現有的執行緒,但未來的執行緒會沿用這項政策:

  • 如果您在 execve() 之前就已經啟用沙箱,而在使用第一個模式時使用 Sandbox2,所有執行緒都會繼承這項政策,沒有任何問題。這是比較建議使用的沙箱模式。
  • 如果您使用第二個模式,且執行者有 set_enable_sandbox_before_exec(false),且 Sandboxee 會在想透過 SandboxMeHere() 採用沙箱機制時通知執行者,請確認篩選器已套用至所有執行緒。否則將有沙箱逸出的風險:惡意程式碼可能會從沙箱執行緒遷移至無沙箱防護的執行緒。

如何編譯 Sandboxee?

如果不小心,很容易繼承許多依附元件和副作用 (額外系統呼叫、檔案存取,甚至是網路連線),這讓沙箱作業更加困難 (追蹤所有連帶效果),也較不安全 (因為系統呼叫和檔案政策較寬)。部分編譯選項有助於減少這類問題:

  • 靜態編譯 Sandboxee 二進位檔,避免動態連結使用大量 sys 呼叫 (open/openatmmap 等)。
  • 由於 Bazel 預設會新增 pie,但靜態與靜態項目不相容,請考慮使用功能旗標,透過下列 cc_binary 規則中的選項強制關閉:

    linkstatic = 1,
    features = [
        "fully_static_link",  # link libc statically
        "-pie",
    ],
    

不過:使用靜態物件有缺點,可降低 ASLR 堆積熵 (從 30 位元到 8 位元),也能輕鬆利用。請根據沙箱的實作方式和政策,審慎決定要採用哪種做法:

  • 非靜態:理想的堆積 ASLR,可能較難執行初始程式碼,但代價是較低的沙箱政策,因此可能更容易脫離。
  • static:不良堆積 ASLR,較容易執行初始程式碼,但更有效率的沙箱政策,可能更難以入侵。

由於編譯器不支援靜態 PIE (位置獨立執行檔),因此建議您這麼做。PIE 的實作方法是將二進位檔指定為動態物件,而動態載入器會在執行前在隨機位置進行對應。然後,由於堆積傳統會放在二進位的基準位址後方 (並以 brk 系統呼叫展開) 之後的隨機偏移量,這表示對靜態二進位檔而言,堆積 ASLR 熵只是此偏移值,因為沒有 PIE。

如需這些編譯選項的範例,請參閱靜態範例 BUILD.bazelstatic_bin.cc 是以靜態方式編譯,這可讓我們制定非常緊密的系統呼叫政策。這種做法也適用於沙箱機制的第三方二進位檔。

我可以使用沙箱 32 位元 x86 二進位檔嗎?

Sandbox2 只能採用與編譯時相同的架構。

此外, Sandbox2 不再支援 32 位元 x86。如果您嘗試使用 64 位元 x86 執行程式對 32 位元 x86 二進位檔或 64 位元 x86 二進位檔建立 32 位元系統呼叫 (透過 int 0x80),兩者都會產生沙箱違規事件,以供架構標籤 [X86-32] 識別。

這個行為背後的原因是,不同架構之間的系統呼叫數字會有所差異,而且由於系統呼叫政策是以執行程式的架構寫入,因此允許沙箱測試不同的架構會很危險。的確,這可能導致系統允許看似無害的系統呼叫,實際上代表另一個有害的系統呼叫可能會導致沙箱逃離沙箱。

執行者程序可要求的沙箱數量是否有任何限制?

系統會為每個 Sandboxee 執行個體 (從 forkserver 產生的新程序) 建立新的執行緒,這是達到上限的階段。

執行者可要求建立多個沙箱嗎?

否。其中存在 1:1 關係,執行者執行個體會儲存 Sandboxee 的 PID、管理與沙箱執行個體的 Comms 執行個體等等。

為什麼我在 forkserver.cc 中會看到「函式未實作」?

Sandbox2 僅支援在合理的新核心上執行。我們目前的截止點為 3.19 版,但日後可能會改變。這是因為我們使用相對新的核心功能,包括使用者名稱空間以及使用 TSYNC 旗標的 seccomp。

如果是在實際工作環境中執行,由於幾乎所有機群都在執行新的核心,因此這應該不會造成問題。如有任何相關問題,請與我們聯絡。

如果是在 Debian 或 Ubuntu 上執行,更新核心也很容易就能執行:

sudo apt-get install linux-image-<RECENT_VERSION>