LWN:針對特殊文件的擴(kuò)展屬性!
關(guān)注了就能看到更多這么棒的文章哦~
Extended attributes for special files
By Jonathan Corbet
September 9, 2021
DeepL assisted translation
https://lwn.net/Articles/868505/
Linux 的擴(kuò)展屬性(extended-attribute)機(jī)制是用來給文件系統(tǒng)中的文件增加 metadata(元數(shù)據(jù))的。這個功能往往很少被使用,尤其是如果沒有 SELinux 這類安全模塊(security module)的情況下。不過,人們對這些屬性的工作機(jī)制很感興趣,這一點(diǎn)可以從 Vivek Goyal 發(fā)布的一個 patch 的最新修訂版引出的討論看得出來,該 patch 試圖對擴(kuò)展屬性和特殊文件相關(guān)的規(guī)則做一個看起來很小的變動。
具體來說,擴(kuò)展屬性(通常被稱為 "xattrs")都是可以跟文件綁定的一些鍵值對(name-value pair)。擴(kuò)展屬性的 name 被分為兩部分,一部分是指明命名空間(namespace),另一部分是在這個命名空間中的標(biāo)識符。命名空間目前可以是 security、system、user、或 trusted 中的一個。每個命名空間都有自己特有的一些規(guī)則。system 和 trsuted 這兩個很少在一般情況下使用。相應(yīng)地,security 命名空間則在許多 Linux 安全模塊中有使用到。security 屬性的例子可以簡單通過在一個設(shè)置好了 SELinux 的系統(tǒng)上運(yùn)行 getfattr 命令來查看到:
cd /; getfattr -d -m - .
# file: .
security.selinux="system_u:object_r:root_t:s0"
這就是 SELinux 標(biāo)簽(label),用于確定這個目錄應(yīng)該使用哪些訪問策略(access policies)。一個進(jìn)程必須有 CAP_SYS_ADMIN 的 capability 才能修改 security 命名空間的屬性。更進(jìn)一步地來說,系統(tǒng)中正在運(yùn)行的安全模塊可能還不一定同意此進(jìn)程提出的改動。
user 命名空間完全沒有特權(quán)。用戶可以為他們有權(quán)寫入的文件隨意分配任何他們喜歡的屬性。但有一個例外:不可以將 user 擴(kuò)展屬性附加到符號鏈接或設(shè)備文件這種特殊文件上。man 手冊中將這個限制的原因解釋了一下,是為了控制資源消耗。如果任何可以寫入/dev/null 的進(jìn)程都可以給它設(shè)置一個附加擴(kuò)展屬性,那么磁盤很快就會被這些無限多的屬性數(shù)據(jù)填滿。有相應(yīng)權(quán)限的進(jìn)程仍然有可能給這些文件附加 security 擴(kuò)展屬性。
Goyal 的 patch 稍微放寬了一下這個限制。改動后,符號鏈接或設(shè)備特殊文件的 owner 進(jìn)程就有權(quán)給該文件設(shè)置 user 擴(kuò)展屬性了。這使得用戶可以改變他們所控制的文件,同時又避免了/dev/null 問題。在許多人看來,這似乎是一個合理的改變,但 Andreas Gruenbacher 表示了反對:
user.* xattrs 設(shè)計時希望在進(jìn)行設(shè)置的權(quán)限方面,它就類比于文件內(nèi)容。根據(jù)這個原則,符號鏈接和特殊文件不能有 user.* xattrs。這已經(jīng)是多年來的行為模式了,應(yīng)用程序可能正按照這些語義來實(shí)現(xiàn),所以我們不能簡單地改變這里的行為。
確實(shí)需要避免用這種微妙之處的改動來破壞用戶空間程序。Goyal 建議可以將新的行為作為可選項(xiàng)來加入,就能避免產(chǎn)生這種意外。但更大的癥結(jié)在于這個功能預(yù)期是如何使用。內(nèi)核開發(fā)者通常會問為什么需要一個新的行為,這些信息在評估所實(shí)現(xiàn)的解決方案是否確實(shí)是解決問題的最佳方式時是非常必要的。在這個話題中,并非所有的人都對答案感到滿意。
Goyal 正在研究虛擬化,特別是研究 guest 想與 host 共享同一個文件系統(tǒng)的用例。內(nèi)核的 virtiofs 文件系統(tǒng)就是為這種應(yīng)用場景而設(shè)計的,它是一種基于 Virtio 的 FUSE 文件系統(tǒng),所以它的效果相當(dāng)不錯。在 host 端,virtiofsd 守護(hù)進(jìn)程會真正進(jìn)行客戶端提出的文件系統(tǒng)訪問申請。
Virtiofsd 希望能放棄盡可能多的 capability,只保留那些必須要用的 capability,確保能夠操作任何用戶和組 ID 所擁有的文件。它目前工作的非常好,除了一個小問題:security 擴(kuò)展屬性。guest 可能想在文件系統(tǒng)中操作這些屬性,但 host 可能會阻止 virtiofsd 進(jìn)行這些更改。尤其是如果 host 正在運(yùn)行像 SELinux 這樣的安全模塊的話,這個安全模塊會對這些屬性按自己的判斷來進(jìn)行解釋,它很可能不贊同 virtiofsd 所提出的改動。改變這些擴(kuò)展屬性都是需要 CAP_SYS_ADMIN 這個 capability 的,而 virtiofsd 沒有這種 capability 卻還在進(jìn)行這種改動。
要解決這個問題,自然的做法是再加一層抽象層。如果配置得當(dāng)?shù)脑?,virtiofsd 能夠在 guest 和 host 之間將擴(kuò)展屬性進(jìn)行一下對應(yīng)轉(zhuǎn)換。例如,它可以把 guest 這里管理的 security 屬性都轉(zhuǎn)換成 host 上的 user 屬性。virtiofsd 改變 user 屬性并不需要任何權(quán)限,所以一切都能正常使用。
準(zhǔn)確地說,絕大多數(shù)情況下都很正常。Goyal 指出,當(dāng) guest 進(jìn)行莫名其妙的 relable (重新標(biāo)記)狀態(tài)時(SELinux 似乎時不時地會做這些事),就會產(chǎn)生錯誤。這里的問題在于設(shè)置特殊文件的 user 擴(kuò)展屬性時的限制,guest 正試圖重新對某個設(shè)備文件設(shè)置 label,但 host 不同意將這些 label(已經(jīng)被重新映射改為 user 擴(kuò)展屬性了)設(shè)置到這個特殊文件之上。這個問題就是推動 Goyal 來實(shí)現(xiàn) patch 放寬限制的原因,用了這個 patch 之后,這個使用場景就沒有問題了。
Casey Schaufler 聲明說,他對給特殊文件分配 user 擴(kuò)展屬性沒有問題。但他認(rèn)為 virtiofsd 中的重映射機(jī)制是 "不合理的":
正如我以前所說,這引入了一個安全漏洞。它允許 host 上的非特權(quán)進(jìn)程操縱 guest 的 security 狀態(tài)。這是個徹底錯誤的做法。將這個漏洞淡化,認(rèn)為只有在配置錯誤的情況下才能被利用,這樣是不行的。不要做這個 remapping 機(jī)制。
Schaufler 和 Goyal 在這組 patch 的三個修訂版中,已經(jīng)在這個話題上翻來覆去討論了無數(shù)次。Schaufler 認(rèn)為,處理這種情況的唯一安全的方法是,host 方的更改需要與 guest 方的特權(quán)水平要相同。舉例來說,將 security 擴(kuò)展屬性重新映射到受信任的命名空間(這也就需要 CAP_SYS_ADMIN 了)是可以接受的。與此同時,Goyal 繼續(xù)在尋找一個不需要 virtiofsd 擁有額外權(quán)限的解決方案。
這個解決方案,最終可能會采取略微有些不同的方式,這個想法靈感來自于 David Alan Gilbert 的這個看法:
我認(rèn)為真正的問題在于,user/trusted/system/security 的 "命名空間" 是一種隨意的比較 hack 的實(shí)現(xiàn)方法,而不是一個允許你創(chuàng)建新的(嵌套的)命名空間并將權(quán)限與每個命名空間聯(lián)系起來。
每個命名空間都背負(fù)有一些實(shí)現(xiàn)上特有的包袱(在 NFS 上不被信任,用戶。在符號鏈接上有特殊的規(guī)則等等)。
Miklos Szeredi 建議,下一步(最初是由 Eric Biederman 提出的)可以調(diào)整 trusted 擴(kuò)展屬性,讓其能在 user 名字空間中使用。如果某個 user 命名空間的擁有者是 user ID 1000,那么此命名空間中的 trusted.foo 將會在此命名空間初始化的時候就被存儲成為(并可被讀取到)類似 trusted<1000>.foo 這樣的內(nèi)容。Virtiofsd 可以在 user 命名空間中運(yùn)行,并使用 trusted 擴(kuò)展屬性,而不需要有什么額外權(quán)限,host 上的安全模塊仍然可以最終決定這些屬性應(yīng)該如何設(shè)置。Goyal 同意這種方法可能是可行的。
唯一的問題是,必須要有人來實(shí)現(xiàn) user 命名空間的這個新的行為,這是系統(tǒng)中一個很復(fù)雜的部分,搞不好就容易出現(xiàn) security 錯誤。Biederman 已經(jīng)指出了 nested namespace 相關(guān)的一個潛在問題。但是,假設(shè)這個功能可以最終被安全地提供出來的話,Goyal 的原始問題應(yīng)該是可以得到解決的。這就是為什么內(nèi)核開發(fā)者經(jīng)??偸菍τ谀硞€改動的原始出發(fā)點(diǎn)和使用場景更加關(guān)注:一個問題的最佳解決方案往往不是所想到的第一個方案。
全文完
LWN 文章遵循 CC BY-SA 4.0 許可協(xié)議。
長按下面二維碼關(guān)注,關(guān)注 LWN 深度文章以及開源社區(qū)的各種新近言論~
