不可執行 mfd 簡介¶
- 作者:
Daniel Verkamp <dverkamp@chromium.org> Jeff Xu <jeffxu@chromium.org>
- 貢獻者:
Aleksa Sarai <cyphar@cyphar.com>
自從 Linux 引入 memfd 功能以來,memfd 始終設定了其執行位,並且 memfd_create() 系統呼叫不允許以不同的方式設定它。
然而,在預設安全的系統中,例如 ChromeOS(其中所有可執行檔案都應來自受驗證啟動保護的 rootfs),memfd 的這種可執行性質為 NoExec 繞過打開了一扇門,並啟用了“confused deputy attack”(混淆代理攻擊)。 例如,在 VRP 漏洞 [1] 中:cros_vm 程序建立了一個 memfd 以與外部程序共享內容,但是 memfd 被覆蓋並用於執行任意程式碼和 root 提權。[2] 列出了更多此類 VRP。
另一方面,可執行 memfd 有其合法的用途:runc 使用 memfd 的 seal 和可執行功能來複制二進位制檔案的內容,然後執行它們。 對於這樣的系統,我們需要一種解決方案來區分 runc 對可執行 memfd 的使用和攻擊者的使用 [3]。
- 為了解決以上問題
允許 memfd_create() 在建立時設定 X 位。
當 NX 被設定時,允許 memfd 被密封以修改 X 位。
新增一個新的 pid 名稱空間 sysctl:vm.memfd_noexec,以幫助應用程式遷移和強制執行不可執行的 MFD。
使用者 API¶
int memfd_create(const char *name, unsigned int flags)
MFD_NOEXEC_SEAL當
flags中設定了 MFD_NOEXEC_SEAL 位時,memfd 使用 NX 建立。 設定 F_SEAL_EXEC,並且 memfd 無法被修改以稍後新增 X。 MFD_ALLOW_SEALING 也被暗示。 這是應用程式使用 memfd 的最常見情況。MFD_EXEC當
flags中設定了 MFD_EXEC 位時,memfd 使用 X 建立。- 注意
MFD_NOEXEC_SEAL意味著MFD_ALLOW_SEALING。 如果應用程式不希望密封,則可以在建立後新增 F_SEAL_SEAL。
Sysctl:¶
pid 名稱空間 sysctl vm.memfd_noexec
新的 pid 名稱空間 sysctl vm.memfd_noexec 有 3 個值
- 0:MEMFD_NOEXEC_SCOPE_EXEC
沒有 MFD_EXEC 或 MFD_NOEXEC_SEAL 的 memfd_create() 行為就像設定了 MFD_EXEC 一樣。
- 1:MEMFD_NOEXEC_SCOPE_NOEXEC_SEAL
沒有 MFD_EXEC 或 MFD_NOEXEC_SEAL 的 memfd_create() 行為就像設定了 MFD_NOEXEC_SEAL 一樣。
- 2:MEMFD_NOEXEC_SCOPE_NOEXEC_ENFORCED
沒有 MFD_NOEXEC_SEAL 的 memfd_create() 將被拒絕。
該 sysctl 允許對未設定可執行位的舊軟體進行更精細的 memfd_create 控制; 例如,vm.memfd_noexec=1 的容器意味著舊軟體將預設建立不可執行的 memfd,而新軟體可以透過設定 MFD_EXEC 來建立可執行的 memfd。
vm.memfd_noexec 的值在建立時傳遞給子名稱空間。 此外,該設定是分層的,即在 memfd_create 期間,我們將從當前 ns 搜尋到 root ns,並使用最嚴格的設定。
[2] https://bugs.chromium.org/p/chromium/issues/list?q=type%3Dbug-security%20memfd%20escalation&can=1