M05 · 階梯 2 · L2
SIP / rootless 與 SSV
為何 root 寫不進 /System——csr bitmask、SF_RESTRICTED、SIP 作為獨立 MAC 閘(DAC 之外),以及 SSV authenticated-root 的「開機期 seal vs 執行期 MAC」兩層獨立。
root 不是神
Unix 直覺:root(uid 0)無所不能。在現代 macOS 上,錯。你 sudo 進 root,照樣寫不進 /System:
# sudo touch /System/Library/x
touch: /System/Library/x: Operation not permitted ← EPERM,不是 EACCES
關鍵在 EPERM(不是權限不足的 EACCES)。DAC(POSIX 擁有者/權限)那關 root 過了——是另一道獨立的閘擋下的:SIP(System Integrity Protection / rootless),一個核心層的 MAC(Mandatory Access Control)。
這是 M09「六道閘門」的第一個預習:通過 DAC ≠ 整體放行。權限是多道閘 deny-overrides 疊出來的,任一道擋下就 EPERM/EACCES。
SIP / rootless 實驗室
csr = 0x0
System Integrity Protection status: enabled.
/System 帶 SF_RESTRICTED → SIP MAC 保護。
- DAC (POSIX)uid 0(root)滿足擁有者寫入權 → DAC 通過。注意:root 仍須經過 DAC,只是通常會過。
- SIP (MAC)對 restricted 路徑寫入、非授權的 rootless 二進位 → EPERM。連 root 都擋。
重點:DAC 過了(你是 root),但 SIP 這道獨立 MAC 閘擋下 → EPERM。「root 寫不進 /System」就是這個原因,不是 DAC。
開機期 seal(authenticated-root / SSV)
開機時以 Merkle tree 的 root hash 驗整個系統卷快照的封印(seal)。磁碟上改一個 byte → 算出的 root hash 不符 → 無法開機(除非關掉 authenticated-root)。
與執行期 SIP 無關:可以 SIP 關、但 seal 仍開。
執行期 MAC(SIP / rootless)
系統執行中,MACF policy 擋對 SF_RESTRICTED 路徑的修改,連 uid 0 都擋。
與開機 seal 兩層獨立:本機實測即 SIP disabled 但 Authenticated Root enabled。
本機實測:SIP disabled 但 Authenticated Root enabled、Snapshot Sealed: Yes — 正是兩層獨立的活證據。
模型邊界:兩閘 deny-overrides 是 M09 六閘的預習教學模型,非核心 MACF 逐位元評估順序。csr 位元、restricted 旗標、SSV 雙層皆為實測(見章末真機卡);驗證於 macOS 26.3.1。
csr-active-config:一個 bitmask 決定鬆緊
SIP 的鬆緊由 NVRAM 變數 csr-active-config 的位元決定(csrutil 改的就是它)。0x0 = 全部保護開啟(預設)。每個位元關掉一類保護:
| bit | 旗標 | 關掉後 |
|---|---|---|
0x002 | ALLOW_UNRESTRICTED_FS | 可寫 restricted 路徑(SIP-FS 解除) |
0x001 | ALLOW_UNTRUSTED_KEXTS | 載入未受信任 kext |
0x004 | ALLOW_TASK_FOR_PID | 對任意程序 task_for_pid |
0x800 | ALLOW_UNAUTHENTICATED_ROOT | 開機未封印(unsealed)系統卷 |
上面實驗室左欄逐位元切換,即時看 csrutil status 會怎麼說。注意 csrutil disable 不是設單一位元,而是一組 allow 位元一起開(canonical 值 0x77)。
⚠ 平台邊界:Intel NVRAM vs Apple Silicon LocalPolicy(DESIGN.md §11):
csr-active-config這個 NVRAM bitmask 是 Intel/T2 的模型。Apple Silicon(本課主目標)的 SIP 狀態其實寫在簽章的 LocalPolicy(recoveryOS/1TR 設定),nvram csr-active-config常常是空的——本機就是csrutil status: disabled,但那個 NVRAM 變數根本不存在。所以這裡的 csr 位元面板是教學抽象:位元語意對,但 Apple Silicon 的真實來源是 LocalPolicy。判斷 SIP 一律以csrutil status為準,別看 NVRAM 有沒有值。
SF_RESTRICTED:哪些路徑被 SIP 保護
SIP 保護的不是「所有系統路徑」,而是帶 SF_RESTRICTED 旗標的檔案/目錄(ls -ldO 看得到 restricted)。本機實測:
restricted /System
restricted,hidden /usr (但 /usr/local 不在內)
restricted,hidden /bin
sunlnk /Applications ← 只 sunlnk,非 restricted
sunlnk /usr/local ← 只 sunlnk
restricted(SF_RESTRICTED):SIP 的 MAC 保護目標,連 root 都不能改(除非是帶com.apple.rootless.*權限的 Apple 平台二進位,系統更新走這條)。sunlnk(SF_NOUNLINK):不能 unlink/改名,但不是 SIP-restricted——所以你能安裝 App 到/Applications、Homebrew 能寫/usr/local。
實驗室中欄選不同路徑 + uid + 操作,看兩閘怎麼判:選 /System/... + root + write + 第三方 → DAC 過、SIP 擋 → EPERM。把 SIP 關掉或設 ALLOW_UNRESTRICTED_FS → 放行。
SSV:開機期 seal 與執行期 MAC 是兩層
很多人把 SIP 和 SSV 混為一談。它們是兩層獨立防線:
- 執行期 MAC(SIP / rootless):系統跑著的時候,MACF policy 擋對 restricted 路徑的修改。
- 開機期 seal(authenticated-root / SSV,Signed System Volume):開機時用 Merkle tree 的 root hash 驗整個系統卷快照的封印。磁碟上改一個 byte → root hash 不符 → 開不了機。
⚠ 兩層獨立(DESIGN.md §11):本機實測就是活證據——
csrutil status顯示 SIP disabled,但csrutil authenticated-root status顯示 enabled、diskutil apfs list顯示 Snapshot Sealed: Yes。SIP 關了,seal 還在。所以「關 SIP」≠「關 SSV」;要改開機系統卷得另外關 authenticated-root(ALLOW_UNAUTHENTICATED_ROOT),且系統會以唯讀快照開機、改動需重建 seal。
🟡 真機操作卡
csrutil status # SIP 狀態(enabled / disabled / custom)
csrutil authenticated-root status # SSV seal 是否啟用
ls -ldO /System /usr /usr/local /bin # 看 restricted / sunlnk 旗標
ls -lO /System/Library/CoreServices/SystemVersion.plist # 單檔 restricted
diskutil apfs list | grep -iE "Sealed|Snapshot" # SSV 封印與快照
nvram csr-active-config # 讀 csr bitmask(Intel/T2);Apple Silicon 常為空,一律以 csrutil status 為準
sudo touch /System/x # 觀察 EPERM(別硬幹,看到錯誤即可)
⚠ 改 SIP/SSV 需 recoveryOS(
csrutil disable/csrutil authenticated-root disable)且降低整機安全;本章只示範唯讀觀察與在模擬器裡玩。任何停用見 DESIGN.md §10 風險警示。csrutil本身在一般開機環境只能查、不能改。
下一步:M06 TCC 隱私框架 — SIP 保護系統檔,TCC 保護你的資料(相機、麥克風、文件、全磁碟)。看 tccd 怎麼用 audit token 與 csreq 釘選判定每一次授權。