保護與安全

能力(capability)

想想一張演唱會門票。它不寫你是誰;它只說「持票人可進入 B 廳、14 號座位」。你拿著它就進得去;你把它交給朋友,換他進去。場館不會去賓客名單上查你——它只檢查票是不是真的。能力就是這張票的計算版本:一個不可偽造的權杖,指名一個物件,以及持有者可在其上行使的權限。持有即許可。

把存取矩陣沿「列」切,每個域就得到一份「它可以碰哪些物件、被允許哪些操作」的清單——這份清單就是一組能力。一個能力通常是「對某物件的參照」加上「一組權限」捆在一起,並做成不可偽造,使程式無法憑空捏造一個、也無法竄改它所帶的權限。系統以不同方式達成不可偽造:把能力放進受保護的核心表裡,使用者程式只能以索引去指名它(真正的權杖從不存在於使用者可寫的記憶體中),或把權杖做成一個無法猜測或更改的大型隨機值或經密碼學簽署的值。要使用資源時你出示能力;系統檢查權杖、授予恰好列出的權限,從不問你是誰。Unix 的檔案描述符是一個熟悉但有限的例子:行程一旦成功開啟某檔案,它手中的那個小整數就是一種能力——透過這個把柄它可以讀或寫,而不必重複做權限檢查,甚至能把這把柄傳給子行程。

能力在最小權限原則與「委派」上特別出色:交給某人單一個能力,就是給他恰好一項狹窄的權力、別無其他,而且他能把它轉交出去,無須你維護一張龐大的中央清單。經典的難題是撤銷——把權限收回來。因為持有者實際握著那個權杖,你沒辦法輕易伸手到他口袋裡撕掉它;系統只能訴諸技巧,例如透過一個可撤銷的中介項做間接、或讓底層物件失效。這正好和存取控制清單形成鏡像式的取捨:在 ACL 那邊撤銷很容易(改清單就好),但那邊自然回答的問題是「誰可以碰這個物件」,而非「這個主體可以碰什麼」。

某行程開啟 /var/log/app.log,拿到檔案描述符 5。自此它呼叫 write(5, buf, n) 而不再做任何權限查核——fd 5 就是那個已開啟檔案的一個能力。它甚至能透過 fork 把 fd 5 傳給子行程,等於把同一項權限交了出去。

持有權杖即是許可;系統檢查的是權杖,而非你的身分。

其定義性的性質是不可偽造——若使用者程式能捏造或編輯一個能力,它就能給自己任意權限。和 ACL 相反的經典弱點是:要「選擇性地撤銷一個已經發出去的能力」確實很困難。

又称
capability tokenunforgeable token權能能力權杖