Linux ACL 權限之進階篇


筆者在《Linux ACL 權限》一文中介紹了 Linux ACL 權限的基本用法,本文筆者將嘗試探究 ACL 中的基本概念和實現原理,希望能夠通過進一步的加深對 Linux 權限系統的理解。說明:本文的演示環境為 ubuntu 16.04。

ACL 中的基本概念

ACL 的類型

  • access ACL:我們可以認為每一個對象(文件/目錄)都可以關聯一個 ACL 來控制其訪問權限,這樣的 ACL 被稱為 access ACL。
  • default ACL:目錄也可以關聯一個 ACL 來控制在該目錄中創建的對象的默認 ACL,這樣的 ACL(目錄關聯的 ACL)被稱為 default ACL。

ACL 條目
一個 ACL 由多個 ACL 條目組成。一個 ACL 條目指定一個用戶或者一組用戶對所關聯對象的讀、寫、執行權限。下圖展示了 ACL 條目的類型及含義:

ACL 權限與 ugo 權限的對應關系

ACL 定義的權限是 ugo 權限的超集。

  • 文件的 owner 權限對應於 ACL 權限中的 ACL_USER_OBJ 條目。
  • 當 ACL 權限中具有 ACL_MASK 條目時,文件的 group 權限對應於 ACL 權限中的 ACL_MASK 條目。否則,當 ACL 權限中具沒有 ACL_MASK 條目時,文件的 group 權限對應於 ACL 權限中的 ACL_GROUP_OBJ 條目。
  • 文件的 other 權限對應於 ACL 權限中的 ACL_OTHER_OBJ 條目。

文件的 ugo 權限總是與對應的 ACL 條目保持一致。修改文件的 ugo 權限會導致修改相關的 ACL 條目,同樣的,修改這些 ACL 條目會導致修改對應的 guo 權限。

新建文件的 default ACL

一個文件的 access ACL 會在通過 creat()、mkdir()、mknod()、mkfifo() 和 open() 函數創建該文件時被初始化。

如果一個目錄被設置了 default ACL,那么將會由文件創建函數的 mode 參數和目錄的 default ACL 共通決定新文件的 ACL 權限:

  • 新的文件繼承父目錄的 default ACL 作為自己的 access ACL。
  • 修改與 ugo 權限對應的 access ACL 條目,使其不包含文件創建函數的 mode 參數不包含的權限。

說明:此時 umask 被忽略。

如果一個目錄沒有被設置 default ACL,那么將由文件創建函數的 mode 參數和 umask 共同決定新文件的 ACL 權限:

  • 新建文件的 access ACL 包含 ACL_USER_OBJ, ACL_GROUP_OBJ, 和 ACL_OTHER 條目。這些條目的權限被設置為由 umask 決定的權限。
  • 修改與 ugo 權限對應的 access ACL 條目,使其不包含文件創建函數的 mode 參數不包含的權限。

文件權限檢查的算法(Access Check Algorithm)

當一個進程訪問(讀、寫、執行)一個被 ACL 保護的文件時,文件權限檢查的算法決定了是否授權給進程訪問該文件。
下面我們以 下面我們以偽代碼的方式來解釋文件權限檢查的算法。
第一步:if 進程的 effective user ID 與文件 owner 匹配
                  if ACL 的 ACL_USER_OBJ 條目包含了請求所需的權限,此時就被授權訪問文件
                  else 訪問被拒絕
第二步:else if 進程的 effective user ID 匹配文件 ACL 權限中任何一個 ACL_USER 條目中的 user
                  if 匹配的 ACL_USER 條目和 ACL_MASK 條目包含了請求所需的權限,此時就被授權訪問文件
                  else 訪問被拒絕
第三步:else if 進程的 effective group ID 或者任何一個補充的(supplementary) group ID 匹配文件的 group 或 ACL 權限中任何一個 ACL_GROUP 條目的 group
                  if ACL 權限包含 ACL_MASK 條目
                      if ACL_MASK 條目和匹配的任何 ACL_GROUP_OBJ 或 ACL_GROUP 條目包含了請求所需的權限,此時就被授權訪問文件
                         (注釋:ACL_MASK 與其它項是 and 的關系,用來控制最大權限)
                      else 訪問被拒絕
                  else (注意:沒有 ACL_MASK 條目,就沒有 ACL_GROUP 條目)         
                      if ACL_GROUP_OBJ 條目包含了請求所需的權限,此時就被授權訪問文件
                      else 訪問被拒絕
第四步:else if ACL_OTHER 條目包含了請求所需的權限,此時就被授權訪問文件
第五步:else 訪問被拒絕

ACL 的文本描述格式

有兩種格式來描述 ACL 條目,分別是長格式和短格式。它們非常類似,都是通過兩個冒號把一個 ACL 條目分為三個部分:
ACL 條目的類型:ACL 條目 qualifier:權限信息

我們在前面已經介紹過 ACL 條目的類型,權限信息就是用 rwx 來表示的信息,不支持某個權限的話可以使用 - 表示。這里介紹一下 ACL 條目 qualifier(不知道該咋翻譯這貨)。

  • 當 ACL 條目的類型為 ACL_USER 或 ACL_GROUP 時,ACL 條目 qualifier 包含與 ACL 條目關聯的用戶和組的標識符。
  • 當 ACL 條目的類型為其它時,ACL 條目 qualifier 為空。

其中的用戶標識符可以是用戶名也可以是 user ID,組標識符可以是組名也可以是 group ID。

下面是一組長格式的示例:
user::rw-
user:tester:rw- #effective:r--
group::r--
group:tester1:rw- #effective:r--
mask::r--
other::r--

下面是一組短格式的示例:
u::rw-,u:tester:rw-,g::r--,g:tester1:rw-,m::r--,o::r--
g:tester1:rw,u:tester:rw,u::wr,g::r,o::r,m::r

解釋幾個常見的權限變化的例子

前文我們的重點是介紹 ACL 權限的基本用法。有了本文前面介紹的基礎內容,我們就可以解釋前文中出現的一些比較怪異的現象。
創建用戶 tester, tester1:

$ sudo adduser tester
$ sudo adduser tester1

先創建文件 aclfile,檢查其默認的 ACL 權限信息:

然后為 tester 用戶賦予讀寫 aclfile 文件的權限:

$ setfacl -m u:tester:rw aclfile

此時查看 aclfile 文件的權限:

$ ll aclfile

貌似並沒有發生什么變化,只是在描述權限的地方多出了一個 "+" 號。下面再看看 acl 權限:

$ getfacl aclfile

上圖的黃框中出現了 ACL_MASK 條目,這就是我們的第一個問題:
**************************************************************
我們並沒有顯式的設置 ACL_MASK 條目,為什么它出現了?
An ACL that contains entries of ACL_USER or ACL_GROUP tag types must contain exactly one entry of the ACL_MASK tag type. If an ACL contains no entries of ACL_USER or ACL_GROUP tag types, the ACL_MASK entry is optional.
上面的解釋大意是當添加了 ACL_USER 或 ACL_GROUP 后,必須有一個對應的 ACL_MASK 條目。在當前的情況下,ACL_MASK 是被自動創建的,它的權限被設置成了 group(其實是 group class) 的權限即 rw-。
**************************************************************

下面我們接着更新 aclfile 的 ACL 權限:

$ setfacl -m u:tester:rwx,g:tester1:r aclfile

查看文件權限:

在修改了 tester 的權限並添加了 tester1 group 的權限后,我們看到的組權限居然變成了 rwx !
這是我們的第二個問題:
**************************************************************
為什么 aclfile 文件的組權限變成了 rwx?
這是因為我們設置了  u:tester:rwx 導致的:
在設置了 ACL 權限后,group 顯示的權限為 ACL_MASK 條目中的權限。而 ACL_MASK 條目中的權限表示 ACL_USER、ACL_GROUP_OBJ 和 ACL_GROUP 條目能夠被授予的最大權限,所以當 tester 被設置了 rwx 權限時,ACL_MASK 條目中的權限也發生了相應的變化。並最終導致我們看到了上面的結果:-rw-rwxr--+。
**************************************************************

接下來我們看看 acl 權限:

用戶 tester 具有 aclfile 的讀寫執行權限,tester1 group 具有 aclfile 的讀權限,但是這里的 mask 卻變成了 rwx!
這是我們的第三個問題:
**************************************************************
上面的設置並沒有顯式的指定 mask 項,為什么 mask 的值卻變了?
其實我們在第二個問題中已經回答了這個問題,是因為 tester 被設置了 rwx 權限,最終導致 ACL_MASK 條目中的權限也發生了相應的變化。

這里我們可以思考一下:ACL 權限中為什么需要 ACL_MASK 條目?
這是一個需要從長計議的話題,我們應該從 ACL 權限與 ugo 權限的對應說起。在 ugo 權限模型中,定義了 3 個 class 來表示 owner、group、other 的權限。Owner class 表示文件所有者具有的訪問權限,group class 表示 owner group 具有的訪問權限,other class 表示其它用戶所具有的訪問權限。在沒有顯式的設置 ACL 權限時,文件的 ACL 權限與 ugo 權限的對應關系如下圖所示:

我們把重點放在 group class 上,此時 group class 的權限和 owner group 的權限是完全一樣的。

但是在我們添加了 ACL 權限之后,情況就變得有些復雜了:

此時 group class 中還可能包含 ACL_USER 和 ACL_GROUP 條目中的權限。這樣就會出現 owner group 權限與 group class 不一致的情況。
解決的辦法就是為 ACL 權限引入 ACL_MASK 條目:

  • 沒有設置 ACL 權限時,group class 的權限和 owner group 的權限是完全一樣的。
  • 設置 ACL 權限后,group class 的權限映射到了 ACL_MASK 條目的權限,ACL_GROUP_OBJ 條目僅僅用來表示 owner group 的權限。

**************************************************************

最后我們再來設置一下 aclfile 的 mask:

$ setfacl -m mask::r aclfile
$ getfacl aclfile

ACL 權限的最后一道防線就是 mask 。它決定了一個用戶或組能夠得到的最大的權限。上圖中的 #effective 顯示了對應行的實際權限。文件權限也反應了上面的變化:

我們的最后一個問題:
**************************************************************
為什么需要 effective 權限?
ACL_MASK 條目 限制的是 ACL_USER、ACL_GROUP_OBJ 和 ACL_GROUP 條目的最大權限,所以在應用了 ACL_MASK 條目后,需要通過 effective 權限來獲得 ACL_USER、ACL_GROUP_OBJ 和 ACL_GROUP 條目的真正權限(如上圖所示)。當 ACL_USER、ACL_GROUP_OBJ 和 ACL_GROUP 條目包含不包含在 ACL_MASK 條目中的權限,則該條目后面會有一個 "#" 號和字符串 "effective",以及該條目的有效訪問權限。
但是 mask 只對 ACL_USER、ACL_GROUP_OBJ 和 ACL_GROUP 條目有影響(紅框中的內容),對 owner 和 other 的權限是沒有任何影響的。
**************************************************************

總結

本文先介紹了 ACL 權限中的基本概念,然后解釋了筆者在使用 ACL 權限過程中碰到的一些疑問。希望這些內容可以幫助大家更好的理解和使用 ACL 權限。

參考:
acl man page
POSIX Access Control Lists on Linux


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM