概述
在本文中,瞭解通過文件、目錄權限和所有權的正確使用控制文件訪問。學習:
- 管理普通和特殊文件及目錄的訪問權限
- 使用訪問模式,如 suid、sgid 和粘貼位(sticky bit),維護安全性
- 變更文件創建屏蔽
- 向組成員授予訪問權限
除非特別指出,本文中的例子使用 2.6.34 內核的 Fedora 13。您在其他系統上得到的結果可能有所不同。
先決條件
爲了最有效地利用本系列中的文章,您應該具有基本的 Linux 知識,並需要準備一個 Linux 系統,用於練習本文介紹的命令。有時候不同版本的程序輸出格式不同,因此您所得到的結果未必總是與這裏所示的清單和圖相同。
用戶和組
現在,您瞭解了 Linux 是一個多用戶的系統,每個用戶屬於一個主要 組,也可能是附加組。也可以作爲一個用戶登錄,然後使用 su
或者 sudo -s
命令變爲另一個用戶。Linux
的文件所有權和訪問授權是與用戶 id 和組密切相關的,所以我們要複習一下基本的用戶和組信息。
如果沒有切換到其他用戶,您的 id 就是登錄時的。如果切換到其他用戶,在本文的大多數例子中,您的提示中就會包括您的用戶 id。如果您的提示沒有包括用戶 id,可以使用 whoami
命令來檢查您當前有效的
id。清單 1 顯示了一些例子,說明了提示字符串(來自 PS1 環境變量)與本文中的其他例子不同。在提示字符串中包含您的 id 是一個有用的功能。
清單 1. 決定有效的用戶 id
/home/ian$ whoami tom /home/ian$ exit exit $ whoami ian
我在什麼組中?
類似的,您可以使用 groups
命令找出您在什麼組中。使用 id
命令,您可以找出用戶和組信息。添加一個用戶
id 參數到 groups
或者 id
來查看該用戶
id 的信息,而並非當前用戶 id。查看 清單 2 中的示例。請注意,沒有用戶 id,id
命令也會顯示
SELinux 上下文和基本 id 信息。
清單 2. 決策組成員
[ian@echidna ~]$ id uid=1000(ian) gid=1000(ian) groups=1000(ian),505(development),8093(editor) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 [ian@echidna ~]$ id ian uid=1000(ian) gid=1000(ian) groups=1000(ian),8093(editor),505(development) [ian@echidna ~]$ groups ian development editor [ian@echidna ~]$ id tom uid=1012(tom) gid=1012(tom) groups=1012(tom),505(development) [ian@echidna ~]$ groups tom tom : tom development [ian@echidna ~]$ su tom Password: [tom@echidna ian]$ groups tom development [tom@echidna ian]$ groups ian ian : ian editor development
文件的所有權和權限
如果每個用戶都有 id 並且是主要組的成員,那麼 Linux 系統上的每個文件都有一個所有者和與其相關的組。
普通文件
使用 ls -l
命令顯示所有者和組。
清單 3. 決定文件所有權
[ian@echidna ~]$ ls -l /bin/bash .bashrc helloworld.C
-rw-r--r--. 1 ian ian 124 Mar 31 2010 .bashrc
-rwxr-xr-x. 1 root root 943360 May 21 2010 /bin/bash
-rw-rw-r--. 1 ian development 116 Nov 30 10:21 helloworld.C
在這個特殊的例子中,用戶 ian 的 .bashrc 文件由他自己所有,並且屬於 ian 的主要組。類似的,/bin/bash 由用戶 root 所有,並且位於組 root。但是,helloworld.C 由用戶 ian 所有,但是屬於組 development。用戶名和組名來自不同的名稱空間,所以給定的名稱可能同時是用戶名和組名。事實上,很多版本默認爲每個新用戶創建一個匹配的組。
Linux 權限模型每個文件系統對象有 3 種類型。這些權限就是讀(r),寫(w)和執行(x)。寫權限包括修改和刪除對象的能力。此外,這些權限被分別指定給文件所有者、文件組成員和其他人。
回到清單 3 第一列,注意,它包括一個 11 個字符的字符串。這第 11 個字符是最近才添加的。我們稍後再討論。第一個字母描述了對象的類型(-
在這個例子中表示普通文件),剩下的
9 個字母每三個字母爲一組。第一組表示文件所有者的讀、寫和執行權限。-
表示相應的權限沒有被授予。因此,用戶
ian 就可以讀和寫 .bashrc 文件,但是不能執行它;而 root 可以讀、寫 和 執行 /bin/bash 文件。第二組表示文件組的讀、寫和執行權限。development 組的成員能夠讀或者寫 ian 的 helloworld.C 文件,而其他人只能讀。類似的,root
組中的成員和其他人能夠讀或者執行 /bin/bash 文件。
目錄
目錄和常規文件一樣使用相同的權限標識,但是它們的翻譯不同。目錄的讀權限允許用戶使用該權限列出目錄內容。寫權限意味着用戶使用該權限能夠在目錄中創建或者刪除文件。執行權限允許用戶輸入目錄並訪問任意子目錄。沒有執行權限,目錄下的文件系統對象就是不可訪問的。沒有讀權限,目錄下的文件系統對象在目錄清單下就是不可見的,但是如果知道磁盤上對象的完整路徑,這些對象仍是可訪問的。清單 4 是說明這些問題的非常人工的例子。
清單 4. 權限和目錄
[ian@echidna ~]$ ls -l /home total 32 drwxr-x---. 38 editor editor 12288 Nov 30 10:49 editor drwxr-x---. 4 greg development 4096 Nov 30 12:44 greg drwx------. 21 gretchen gretchen 4096 Nov 30 11:26 gretchen drwxr-xr-x. 41 ian ian 4096 Nov 30 10:51 ian drwx------. 21 ianadmin ianadmin 4096 May 28 2010 ianadmin d-wx--x--x. 21 tom tom 4096 Nov 30 11:30 tom [ian@echidna ~]$ ls -a ~greg/.ba* /home/greg/.bash_history /home/greg/.bash_profile /home/greg/.bash_logout /home/greg/.bashrc [ian@echidna ~]$ ls -a ~gretchen ls: cannot open directory /home/gretchen: Permission denied [ian@echidna ~]$ ls -a ~tom ls: cannot open directory /home/tom: Permission denied [ian@echidna ~]$ head -n 3 ~tom/.bashrc # .bashrc # Source global definitions
長清單的第一個字母表示對象的類型(d
表示目錄)。用戶
greg 的主目錄有 development 組成員的讀和寫權限,因此用戶 tom 和 ian 能夠列出目錄。用戶 gretchen 的主目錄沒有 gretchen 組或者其他用戶的讀和執行權限,所以用戶 ian 不能訪問它。用戶 tom 的主目錄有執行權限,但是沒有讀權限,所以用戶 ian 不能列出內容,但是如果知道對象存在,就可以訪問目錄下的對象。
其他文件系統對象
ls -l
的輸出可能包含文件系統對象,而不是文件和目錄,如清單中第一個字母所示。在後面的文章中我們還會見到更多,但是現在,只是說明可能的對象類型。
表 1. 文件系統對象類型
代碼 | 對象類型 |
---|---|
- | 常規文件 |
d | 目錄 |
l | 符號鏈接 |
c | 字符特殊設備 |
b | 模塊特殊設備 |
p | FIFO |
s | 套接字 |
第 11 個字符
來自 ls
命令中長清單的第
11 個字符是最近纔出現的,所以部分版本仍只顯示頭 10 個字符。在其他情況下,第 11 個字符是一個空格,所以您可能沒有注意到。這個字符表示是否有替換的訪問方法應用到文件。當跟隨文件模式位的字符是空格時,就表示沒有替換訪問方法。當是一個可打印字符時,就有替換方法。這個方法可能是例子的訪問控制清單。GNU ls
使用一個
‘.’(點)來表示文件只有一個 SELinux 安全上下文。有其他替換訪問方法的文件用 ‘+’(加號)表示。
變更權限
添加權限
假設您創建一個 “Hello world” 的 shell 腳本。當您第一次創建腳本時,它通常是不可執行的。使用 chmod
命令和 +x
選項添加執行權限,如清單
5 所示。
清單 5. 創建可執行的 shell 腳本
[ian@echidna ~]$ echo 'echo "Hello world!"'>hello.sh [ian@echidna ~]$ ls -l hello.sh -rw-rw-r--. 1 ian ian 20 Nov 30 13:05 hello.sh [ian@echidna ~]$ ./hello.sh bash: ./hello.sh: Permission denied [ian@echidna ~]$ chmod +x hello.sh [ian@echidna ~]$ ./hello.sh Hello world! [ian@echidna ~]$ ls -l hello.sh -rwxrwxr-x. 1 ian ian 20 Nov 30 13:05 hello.sh
您可以按類似的方法使用 +r
來設置讀權限,使用 +w
設置寫權限。事實上,您可以聯合使用 r
、w
和 x
。例如,使用 chmod
+rwx
將會設置文件的所有讀、寫和執行權限。chmod
會添加尚未設置的權限。
可選性
您在上面的例子中可能已經注意到,執行權限被設置給所有者、組 和 其他。爲了更具可選性,您可以給模式描述加前綴 u
來設置用戶權限,g
來設置組權限,還有 o
爲其他人設置。需要指出的是 a
設置所有用戶的權限,這就相當於忽略它。清單
6 顯示瞭如何添加用戶和組寫和執行權限到 shell 腳本的其他副本。
清單 6. 有選擇性地添加權限
[ian@echidna ~]$ echo 'echo "Hello world!"'>hello2.sh [ian@echidna ~]$ chmod ug+xw hello2.sh [ian@echidna ~]$ ls -l hello2.sh -rwxrwxr--. 1 ian ian 20 Nov 30 13:08 hello2.sh
刪除權限
有時您需要刪除權限,而不單單是添加。簡單地將 +
改變爲 -
,就能刪除任何已設置的指定權限。清單
7 顯示瞭如何刪除兩個 shell 腳本上的其他用戶的所有權限。
清單 7. 刪除權限
[ian@echidna ~]$ ls -l hello*.sh -rwxrwxr--. 1 ian ian 20 Nov 30 13:08 hello2.sh -rwxrwxr-x. 1 ian ian 20 Nov 30 13:05 hello.sh [ian@echidna ~]$ chmod o-xrw hello*.sh [ian@echidna ~]$ ls -l hello*.sh -rwxrwx---. 1 ian ian 20 Nov 30 13:08 hello2.sh -rwxrwx---. 1 ian ian 20 Nov 30 13:05 hello.sh
請注意,您可以一次改變一個或者多個文件的權限。正如在 topic 103 的文章中看到其他命令一樣,您甚至可以使用 -R
(或者 --recursive
)選項在目錄和文件上進行遞歸操作。
設置權限
現在已經可以添加或者刪除權限了,您可能會想,怎樣才能只設置一些特殊權限。使用 =
替換 +
或者 -
來完成這個動作。要在上述腳本中設置權限,這樣其他用戶就沒有訪問權利,您可以使用 chmod
o= hello*
替換我們用於刪除權限的命令。
如果您想對用戶、組合或其他設置不同的權限,您可以通過逗號分隔不同的表達;例如,ug=rwx,o=rx
,或者您可以使用稍後提到的數字權限。
八進制權限
目前爲止,您都是使用符號(ugoa 和 rxw)來指定權限。每組中有三個可能的權限。您還可以使用八進制取代符號設置權限。按這種方法設置的權限使用高達 4 位八進制數字。討論屬性時,我們會查看第 1 個數字。第 2 個數字定義了用戶權限,第 3 個是組權限,第 4 個是其他權限。這三個數字中的每一個都通過添加所需的權限設置來構建:讀(4),寫(2)和執行(1)。在 清單 5 中的 hello.sh 例子中,創建的腳本有權限 -rw-r--r--,相當於八進制 644。設置每個人的執行權限將模式改爲 755。
當您想要一次設置所有權限,而不給予每個組相同權限時,設置使用數字權限非常方便。使用 表 2 作爲一個方便的八進制權限參考。
表 2. 數字權限
符號 | 八進制 |
---|---|
rwx |
7 |
rw- |
6 |
r-x |
5 |
r-- |
4 |
-wx |
3 |
-w- |
2 |
--x |
1 |
--- |
0 |
suid 和 sgid
Linux 權限模型有兩個特殊的訪問模式,名爲 suid(設置用戶 id)和 sgid(設置組 id)。當可執行的程序設置爲 suid 訪問模式,它就會開始運行,好像是由文件所有者啓動而不是由真正啓動它的用戶啓動。類似的,設置爲 sgid 訪問模式,程序就會運行,好像啓動用戶屬於文件組,而不屬於他所有的組。可以單獨或者同時設置兩個訪問模式。
清單 8 顯示了可執行的 passwd
由
root 所有:
清單 8. /usr/bin/passwd 上的 suid 訪問模式
[ian@echidna ~]$ ls -l /usr/bin/passwd
-rwsr-xr-x. 1 root root 34368 Apr 6 2010 /usr/bin/passwd
請注意,在用戶的權限三件套中 x
的位置上有一個 s
。這就表示,對這個特定的程序來說,suid
和可執行位已經被設置。所以,當 passwd
運行時,它就會像
root 用戶使用完全的 superuser 訪問一樣加載它運行,而不是作爲想運行該程序的用戶。因爲 passwd
和 root
訪問一起運行,所以它可以修改
/etc/passwd。
suid 和 sgid 位與長目錄清單中用戶和組的 x
佔據相同的空間。如果文件是可執行的,suid
或 sgid 位如果已設置,將會顯示爲小寫的 s
,否則就顯示爲大寫的 S
。
雖然 suid 和 sgid 很便利,甚至在很多環境下是必需的,但是這些訪問模式不適當的使用會造成系統安全上的漏洞。您要儘量少地使用 suid 程序。passwd
命令是少數 必須 爲
suid 的命令之一。
設置 suid 和 sgid
suid 和 sgid 位使用字母 s
在符號上進行設置和重設;例如,u+s
設置
suid 訪問模式,g-s
刪除
sgid 模式。在八進制格式中,suid 在第一位(高階)爲值 4,而 sgid 是值 2。
目錄和 sgid
當一個目錄使用 sgid 模式時,在這個目錄中創建的任何文件和目錄將會繼承目錄的組 id。這個對那些被從事同一項目的一組人使用的目錄樹極爲有用。 清單 9 顯示了用戶 greg 任何設置一個 development 組所有用戶都能使用的目錄,以及一個示例,用戶 gretchen 如何在目錄上創建一個文件。正如所創建的,文件 gretchen.txt 允許組成員編輯文件,因此 gretchen 使用 chmod g-w
來取消組的寫功能。
清單 9. sgid 訪問模式和目錄
[greg@echidna ~]$ mkdir lpi101 [greg@echidna ~]$ chmod g+ws lpi101 [greg@echidna ~]$ ls -ld lpi101 drwxrwsr-x. 2 greg development 4096 Nov 30 13:30 lpi101/ [greg@echidna ~]$ su - gretchen Password: [gretchen@echidna ~]$ touch ~greg/lpi101/gretchen.txt [gretchen@echidna ~]$ ls -l ~greg/lpi101/gretchen.txt -rw-rw-r--. 1 gretchen development 0 Nov 30 14:12 /home/greg/lpi101/gretchen.txt [gretchen@echidna ~]$ chmod g-w ~greg/lpi101/gretchen.txt [gretchen@echidna ~]$ ls -l ~greg/lpi101/gretchen.txt -rw-r--r--. 1 gretchen development 0 Nov 30 14:12 /home/greg/lpi101/gretchen.txt
development 組的任何成員現在都能夠在用戶 greg 的 lpi101 目錄上創建文件了。正如 清單 10 所示,組的其他用戶不能升級文件 gretchen.txt。但是,他們有對目錄的寫權限,因此可以刪除文件。
清單 10. sgid 訪問模式和文件所有權
[gretchen@echidna ~]$ su - tom Password: [tom@echidna ~]$ echo "something" >> ~greg/lpi101/gretchen.txt -bash: /home/greg/lpi101/gretchen.txt: Permission denied [tom@echidna ~]$ rm ~greg/lpi101/gretchen.txt rm: remove write-protected regular empty file `/home/greg/lpi101/gretchen.txt'? y [tom@echidna ~]$ ls -l ~greg/lpi101/ total 0
粘貼位
您剛看到了任何有目錄寫權限的人如何刪除目錄中的文件。這對一個工作組項目是可接受的,但是對全球共享的文件空間,例如 /tmp 目錄,是不希望的。幸運的是,有解決方案。
剩下的訪問模式爲就稱爲粘貼 位。用符號表示就是 t
,用數字表示就是八進制位的高階爲
1。它顯示在其他用戶的可執行標識中(最後的字符)的長目錄清單,而且 suid 和 sgid 的大小寫意義相同。如果設置一個目錄,它只允許有所有權的用戶或者 superuser(root)刪除或者解除文件鏈接。清單 11 顯示了用戶 greg 如何在他的 lpi101 目錄上設置粘貼位,還顯示了這個位設置用於 /tmp。
清單 11. 粘貼目錄
[greg@echidna ~]$ chmod +t lpi101 [greg@echidna ~]$ ls -ld lpi101 /tmp drwxrwsr-t. 2 greg development 4096 Nov 30 14:16 lpi101 drwxrwxrwt. 24 root root 12288 Nov 30 14:22 /tmp
在以前,UNIX® 系統曾在文件上使用粘貼位在交換空間囤積可執行文件,避免重新加載。現代 Linux 內核忽略了粘貼位,如果它是設置給文件的。
訪問模式的總結
表 3 總結了這裏討論的 3 種訪問模式的符號和八進制表示。
表 3. 訪問模式
訪問模式 | 符號 | 八進制 |
---|---|---|
suid |
s with u |
4000 |
sgid |
s with g |
2000 |
sticky |
t |
1000 |
將這些和早先的權限信息結合在一起,您可以看到對應 greg 的 lpi101 權限和 drwxrwsr-t 訪問模式的完整的八進制表示是 3775。雖然 ls
命令不顯示八進制權限,您可以使用 find
命令進行顯示,如清單
12清單 12 所示。
清單 12. 可打印的符號和八進制權限
[greg@echidna ~]$ find . -name lpi101 -printf "%M %m %f\n"
drwxrwsr-t 3775 lpi101
不可變文件
訪問模式和權限提供了廣泛的控制,限制了誰可以在文件和目錄上做什麼。但是,它們對有些事情也不能避免,如 root 用戶對文件的無心刪除。雖然這不在 LPI Topic 104.5 的範圍內,但是在提供額外功能的文件系統上還是有些可用的附加屬性。其中之一就是不可變 屬性。設置完成後,即使是 root 用戶也不能刪除文件,直到屬性解除。
使用 lsattr
命令查看文件或者目錄是否設置了不可變標識(或者任何其他屬性)。要將一個文件設置爲不可變,使用 chattr
命令和 -i
標識。
清單 13清單 13 顯示了用戶 root 可以創建一個不可變文件,但是不能刪除它,直到不可變標識被刪除。
清單 13. 不可變文件
[root@echidna ~]# touch keep.me [root@echidna ~]# chattr +i keep.me [root@echidna ~]# lsattr keep.me ----i--------e- keep.me [root@echidna ~]# rm -f keep.me rm: cannot remove `keep.me': Operation not permitted [root@echidna ~]# chattr -i keep.me [root@echidna ~]# rm -f keep.me
變更不可變標識需要 root 授權,或者最少 CAP_LINUX_IMMUTABLE 功能。使文件不可變通常是安全或者入侵檢測工作的一部分。見功能使用頁面(man capabilities
)瞭解更多信息。
文件創建屏蔽
創建一個新文件時,創建進程就會指明新文件的權限。通常,所需的模式是 0666,它使文件可由任何人讀和寫。目錄默認爲 0777。但是,這個寬鬆的創建會受到 umask 值的影響,這個值指明瞭用戶不想自動授予新創建的文件或者目錄什麼權限。系統使用
umask 值來減少原始請求的權限。您可以使用 umask
查看
umask 設置,如清單 14清單 14 所示。
清單 14. 顯示八進制 umask
[ian@echidna ~]$ umask
0002
請記得,umask 指定了那個權限不被授予。在 Linux 系統上,用戶沒有專用組的的情況下,umask 通常默認爲 0022,它可以從新文件中刪除組和其他寫權限。用戶有專用組的情況下(例如這些例子中使用的在
Fedora 系統上),umask 通常默認爲 0002,它刪除了其他用戶的寫權限。使用 -S
選項來從符號上顯示
umask,以顯示哪個權限被允許的形式。
使用 umask
命令設置一個
unmask 並顯示。所以,如果您想要保持文件更專有,並且不允許所有組或者其他人訪問新創建的文件,就是可以使用 umask 值 0077。或者從符號上,使用 umask
u=rwx,g=,o=
進行設置,如清單 15清單 14 所示。
清單 15. 設置 umask
[ian@echidna ~]$ umask -S u=rwx,g=rwx,o=rx [ian@echidna ~]$ umask u=rwx,g=,o= [ian@echidna ~]$ umask 0077 [ian@echidna ~]$ touch newfile [ian@echidna ~]$ ls -l newfile -rw-------. 1 ian ian 0 Nov 30 15:40 newfile
設置文件所有者和組
文件組
要變更文件的組,使用 chgrp
命令和組名,以及一個或者多個文件名。如果您喜歡,還可以使用組編號。普通用戶必須擁有文件,同時是文件要變更到的組的組員。root
用戶可以將文件變更到任意組。清單 16清單 16 顯示了一個例子。
清單 16. 變更組的所有權
[ian@echidna ~]$ touch file{1,2} [ian@echidna ~]$ ls -l file* -rw-rw-r--. 1 ian ian 0 Nov 30 15:54 file1 -rw-rw-r--. 1 ian ian 0 Nov 30 15:54 file2 [ian@echidna ~]$ chgrp development file1 [ian@echidna ~]$ chgrp 505 file2 [ian@echidna ~]$ ls -l file* -rw-rw-r--. 1 ian development 0 Nov 30 15:54 file1 -rw-rw-r--. 1 ian development 0 Nov 30 15:54 file2
正如該教程中的許多其他命令,chgrp
有一個 -R
選項,允許將變更遞歸應用到所有所選的的文件和子目錄中。
默認組
當您學習之前的 訪問模式 時,您就瞭解了在目錄上設置 sgid 模式如何導致創建在該目錄下的新文件屬於目錄的組,而不是屬於創建該文件的用戶所在的組。
您還可以使用 newgrp
命令來暫時地將您的初級組變更到您所在的其他組。創建一個新的
shell,當您退出 shell 時,之前的組就能恢復,如清單 17清單 17 所示。
清單 17. 使用 newgrp 來暫時改變默認組
[ian@echidna ~]$ groups ian development editor [ian@echidna ~]$ newgrp development [ian@echidna ~]$ groups development ian editor [ian@echidna ~]$ touch file3 [ian@echidna ~]$ ls -l file3 -rw-r--r--. 1 ian development 0 Nov 30 16:00 file3 [ian@echidna ~]$ exit [ian@echidna ~]$ groups ian development editor
文件所有者
root 用戶可以使用 chown
命令變更文件的所有權。在它最簡單的形式中,語法和 chgrp
命令類似,除了使用用戶名或者數字
id,而不是組名或者 id。文件的組也可能通過在用戶名或者 id 之後添加一個冒號和組名或者 id 來同時變更。如果只有給出冒號,那麼就使用用戶的默認組。一般來說,-R
選項會遞歸地應用變更。清單
18清單 18 給出了一個例子。
清單 18. 使用 chown 變更文件所有權
[ian@echidna ~]$ touch file4 [ian@echidna ~]$ su - Password: [root@echidna ~]# ls -l ~ian/file4 -rw-rw-r--. 1 ian ian 0 Nov 30 16:04 /home/ian/file4 [root@echidna ~]# chown greg ~ian/file4 [root@echidna ~]# ls -l ~ian/file4 -rw-rw-r--. 1 greg ian 0 Nov 30 16:04 /home/ian/file4 [root@echidna ~]# chown tom:gretchen ~ian/file4 [root@echidna ~]# ls -l ~ian/file4 -rw-rw-r--. 1 tom gretchen 0 Nov 30 16:04 /home/ian/file4 [root@echidna ~]# chown :tom ~ian/file4 [root@echidna ~]# ls -l ~ian/file4 -rw-rw-r--. 1 tom tom 0 Nov 30 16:04 /home/ian/file4
指定用戶和組的較早版本使用點,而不是冒號。因爲當名稱中包含點時,這個可能會造成誤解,所以已經不再推薦。
Linux 上的文件和目錄權限介紹就到此爲止。