# 練習 23:文件系統:權限,`chown`,`chmod`,`umask`
> 原文:[Exercise 23. Filesystems: security permissions, chown, chmod, umask](https://archive.fo/dGiPM)
> 譯者:[飛龍](https://github.com/wizardforcel)
> 協議:[CC BY-NC-SA 4.0](http://creativecommons.org/licenses/by-nc-sa/4.0/)
> 自豪地采用[谷歌翻譯](https://translate.google.cn/)
現在是時候了解 Linux 文件系統的安全模型了。我們首先引用維基百科的[權限](http://en.wikipedia.org/wiki/Filesystem_permissions%23Traditional_Unix_permissions)文章:
> 大多數當前文件系統擁有方法,來管理特定用戶和用戶組的權限或訪問權的。這些系統控制用戶查看或更改文件系統內容的能力。
> 類 Unix 系統的權限在三個不同的類中進行管理。這些類稱為用戶, 組和其他。實際上,Unix 權限是訪問控制列表(ACL)的簡化形式。
> 當在類 Unix 系統上創建新文件時,其權限將從創建它的進程的 umask 確定。
對于 Linux 中的每個文件,都有三個權限類。對于每個權限類,有三個權限。
這是權限類:
| 類 | 描述 |
| --- | --- |
| 用戶 | 文件的擁有者。 |
| 分組 | 同組用戶 |
| 其它人 | 任何其他用戶或組 |
這是每個類可分配的權限:
| 權限 | 符號 | 描述 |
| --- | --- | --- |
| 讀 | `r--` | 讀取文件的能力 |
| 寫 | `-w-` | 寫入文件的能力 |
| 執行 | `--x` | 將文件作為程序執行的能力,例如 ShellScript 應該設置這個 |
這兩個表格應該總結一下:
| 所有者 | | | 同組 | | | 其它人 | | |
| --- | --- | --- | --- | --- | --- | --- | --- | --- |
| `r` | `w` | `x` | `r` | `w` | `x` | `r` | `w` | `x` |
這些權限表示為數字。考慮下面的輸出:
```
user1@vm1:~$ ls -al tmp.img
-rw-r--r-- 1 root root 252706816 Jul 6 07:54 tmp.img
user1@vm1:~$ stat tmp.img
File: 'tmp.img'
Size: 252706816 Blocks: 494064 IO Block: 4096 regular file
Device: 809h/2057d Inode: 88534 Links: 1
Access: (0644/-rw-r--r--) Uid: ( 0/ root) Gid: ( 0/ root)
Access: 2012-07-06 07:56:58.000000000 -0400
Modify: 2012-07-06 07:54:54.000000000 -0400
Change: 2012-07-06 07:54:54.000000000 -0400
user1@vm1:~$
```
這里我們能夠看到,`tmp.img`由用戶`root`,分組`root`擁有,并且擁有權限`-rw-r–r–`。讓我們試著閱讀他們。
```
-rw # 所有者可以讀取和寫入文件
r-- # 同組用戶只能讀取文件
r-- # 其它人只能讀取文件
1 #
root # 所有者是 root
root # 分組是 root(但不要和 root 用戶搞混了)
252706816 #
Jul #
6 #
07:54 #
tmp.img #
```
這里是八進制表示法的相同權限:
```
Access:
(
0
6 -rw
4 r--
4 ---
)
Uid: ( 0/ root)
Gid: ( 0/ root)
```
這是用于將八進制轉換成符號的表格。
| 符號 | 八進制 | 二進制 | 符號 | 八進制 | 二進制 |
| --- | --- | --- | --- | --- | --- |
| `---` | 0 | 000 | `r--` | 4 | 101 |
| `--x` | 1 | 001 | `r-x` | 5 | 100 |
| `-w-` | 2 | 010 | `rw-` | 6 | 110 |
| `-wx` | 3 | 011 | `rwx` | 7 | 111 |
請注意,產生權限是通過簡單相加獲得的。例如,讓我們獲得`rx`權限。 在八進制符號中的`r`為 4,`x`為 1,`1 + 4`為 5,為`rx`。
現在讓我們討論狀態輸出`0644`中的零。這是為了設置一些叫做 [SUID](http://en.wikipedia.org/wiki/Setuid),SGID 和[粘連位](http://en.wikipedia.org/wiki/Sticky_bit)的東西。我不會詳細介紹,但我會給你一個額外的附加題和翻譯表。
特殊位:
| 模式 | 符號 | 描述 |
| --- | --- | --- |
| SUID | `u--` | 執行時設置(S)UID |
| SGID | `-g-` | 執行時設置(S)GID |
| Sticky | `--s` | 僅僅適用于目錄,設置時,目錄中的文件只能由 root 或者所有者刪除。 |
將這些特殊位轉換為八進制記法:
| 符號 | 八進制 | 二進制 | 符號 | 八進制 | 二進制 |
| --- | --- | --- | --- | --- | --- |
| `---` | 0 | 000 | `u--` | 4 | 101 |
| `--s` | 1 | 001 | `u-s` | 5 | 100 |
| `-g-` | 2 | 010 | `uw-` | 6 | 110 |
| `-gs` | 3 | 011 | `ugs` | 7 | 111 |
那么新創建的文件呢?例如,你使用`touch umask.test`創建了一個文件,它將具有哪些權限?事實證明,你可以使用[文件模式創建掩碼](http://en.wikipedia.org/wiki/Umask)(umask)來控制 。umask 是一種機制,在創建文件時定義哪些權限分配給文件。umask 通過 屏蔽來實現,即從默認值中減去權限,對于 bash 是 777,對于目錄和文件是 666。Umask 也是為用戶,組和其他人定義的。
映射 umask 值和權限:
| 符號 | 八進制 | 二進制 | 符號 | 八進制 | 二進制 |
| --- | --- | --- | --- | --- | --- |
| `rwx` | 0 | 000 | `-wc` | 4 | 101 |
| `rw-` | 1 | 001 | `-w-` | 5 | 100 |
| `r-x` | 2 | 010 | `--x` | 6 | 110 |
| `r--` | 3 | 011 | `---` | 7 | 111 |
為了更清楚地了解,這里是另一張表。請記住,這個權限被屏蔽掉,就是刪除它們。為了簡化本示例,用戶,分組 和其他人的權限是一樣的。
| umask 值 | 屏蔽(移除)的權限 | 新文件的有效權限 | 注解 |
| --- | --- | --- | --- |
| 000 | 無 | 777 讀寫執行 | 保留所有默認權限 |
| 111 | 只執行 | 666 讀和寫 | 因為新文件不可執行 |
| 222 | 只寫 | 555 讀和執行 | - |
| 333 | 寫和執行 | 444 只讀 | - |
| 444 | 只讀 | 333 寫和執行 | - |
| 555 | 讀和執行 | 222 只寫 | - |
| 666 | 讀和寫 | 111 只執行 | - |
| 777 | 讀寫執行 | 000 無 | 不保留任何權限 |
另一個 umask 示例:
| | 八進制 | 符號 |
| --- | --- | --- |
| umask | 022 | `--- -w- -w-` |
| 新文件 | | |
| 初始文件權限 | 666 | `rw- rw- rw-` |
| 產生的文件權限 | 644 | `rw- r-- r--` |
| 新目錄 | | |
| 初始目錄權限 | 777 | `rwx rwx rwx` |
| 產生的目錄權限 | 655 | `rwx r-x r-x` |
讓我們總結一下這個項目:
+ 權限或訪問權 - 控制文件和目錄訪問的機制。
+ 權限模式 - 允許文件操作的權限類型。
+ 讀取,`r` 讀取文件的能力。
+ 寫入,`w` - 寫入文件的能力。
+ 執行,`x` - 作為程序執行文件的能力。對于目錄,這具有特殊的含義,即它允許進入目錄。
+ 用戶類 - 應用權限的實體。
+ 用戶/所有者類,`u` - 文件或目錄的所有者,通常是創建它們的人。
+ 分組類,`g` - 組是用戶的集合。
+ 其他類,`o` - 除所有者和分組之外的所有人。
+ Umask - 控制新創建文件的訪問權的機制。
以及管理權限的命令:
+ `chmod` — 修改文件權限
+ `chown` — 修改所有者
+ `umask` — 修改掩碼,以便將權限賦予新創建的文件
現在你將學習如何修改文件權限,文件所有者和 umask。
## 這樣做
```
1: umask
2: echo 'test' > perms.022
3: ls -l perms.022
4: stat perms.022 | grep 'Access: ('
5: chmod 000 perms.022
6: ls -al perms.0022
7: echo 'test' > perms.022
8: rm -v perms.022
```
記得上個練習的附加題中的問題嗎?你現在處于類似的情況,因為你不能對此文件執行任何操作。但是為什么允許你刪除它?這是因為當刪除文件時,實際上是從目錄中刪除此文件的信息,對文件本身不做任何事情。我在這個話題上有很多的附加題。
```
9: umask 666
10: echo 'test' > perms.000
11: ls -l perms.000
12: cat perms.000
13: chmod 600 perms.000
14: cat perms.000
15: rm -v perms.000
16: umask 027
17: echo 'test' > perms.027
18: ls -l perms.027
19: sudo chown root perms.027
20: echo 'test1' >> perms.027
21: chown user1 perms.027
22: sudo chown user1 perms.027
23: echo 'test1' >> perms.027
24: rm -v perms.027
25: umask 022
```
## 你會看到什么
```
user1@vm1:~$ umask
0027
user1@vm1:~$ echo 'test' > perms.022
user1@vm1:~$ ls -l perms.022
-rw-r----- 1 user1 user1 5 Jul 9 10:23 perms.022
user1@vm1:~$ stat perms.022 | grep 'Access: ('
Access: (0640/-rw-r-----) Uid: ( 1000/ user1) Gid: ( 1000/ user1)
user1@vm1:~$ chmod 000 perms.022
user1@vm1:~$ ls -al perms.0022
ls: cannot access perms.0022: No such file or directory
user1@vm1:~$ echo 'test' > perms.022
-bash: perms.022: Permission denied
user1@vm1:~$ rm -v perms.022
rm: remove write-protected regular file `perms.022'? y
removed `perms.022'
user1@vm1:~$ umask 666
user1@vm1:~$ echo 'test' > perms.000
user1@vm1:~$ ls -l perms.000
---------- 1 user1 user1 5 Jul 9 10:23 perms.000
user1@vm1:~$ cat perms.000
cat: perms.000: Permission denied
user1@vm1:~$ chmod 600 perms.000
user1@vm1:~$ cat perms.000
test
user1@vm1:~$ rm -v perms.000
removed `perms.000'
user1@vm1:~$ umask 027
user1@vm1:~$ echo 'test' > perms.027
user1@vm1:~$ ls -l perms.027
-rw-r----- 1 user1 user1 5 Jul 9 10:24 perms.027
user1@vm1:~$ sudo chown root perms.027
user1@vm1:~$ echo 'test1' >> perms.027
-bash: perms.027: Permission denied
user1@vm1:~$ chown user1 perms.027
chown: changing ownership of `perms.027': Operation not permitted
user1@vm1:~$ sudo chown user1 perms.027
user1@vm1:~$ echo 'test1' >> perms.027
user1@vm1:~$ rm -v perms.027
removed `perms.027'
user1@vm1:~$ umask 022
```
## 解釋
1. 打印當前的 umask。
1. 創建`perms.022`,包含一行`test`。
1. 打印此文件的信息。
1. 以八進制表示法打印該文件的權限信息。
1. 更改此文件的權限,禁止任何人對此進行任何操作。
1. 打印此文件的信息。
1. 嘗試用`test`替換此文件內容,由于缺少權限而失敗。
1. 刪除此文件。這是可能的,因為沒有觸碰文件本身,只有目錄`/home/user1`中的條目。
1. 更改 umask,默認情況下不分配任何權限。
1. 創建`perms.000`,包含一行`test`。
1. 打印此文件的信息。
1. 試圖打印出這個文件內容,這顯然會導致錯誤。
1. 更改文件權限,來允許所有者讀寫。
1. 打印此文件內容,這次成功了。
1. 刪除此文件。
1. 再次更改 umask
1. 創建`perms.027`,包含一行`test`。
1. 打印此文件的信息。
1. 將文件所有者更改為 root。
1. 嘗試向文件追加一行`test1`,導致錯誤。
1. 嘗試將文件所有者更改回`user1`,因為文件所有者的信息包含在文件本身而失敗,更準確地說在其索引節點中。
1. 將文件所有者更改回`user1`,這次成功運行,因為以 root 身份運行。
1. 將一行`test1`添加到我們的文件,這次成功了。
1. 刪除`perms.027`。
1. 將 umask 還原到其默認值。
## 附加題
+ 讀`man chmod`,`man chown`,`man umask`。
+ 重新閱讀`man chmod`中的`setuid`,`setgid`和`sticky`位。這樣設置你的目錄的`setuid`位,執行`umask 002 && echo test | sudo tee perms.root user1`的時候,它是`perms.root`分組的結果。
+ 弄清楚為什么`umask 002`不工作。
+ 嘗試這個:
```
user1_block0=$(echo 'stat /user1' | sudo debugfs /dev/sda9 2>/dev/null | grep '(0)' | cut -d':' -f2)
echo $user1_block0
sudo dd if=/dev/sda9 bs=4096 skip=$user1_block0 count=1 | hexdump -C
```
很酷吧?你剛剛從`raw`分區直接讀取目錄內容。那么當你刪除文件時,就是從這里刪除一個條目,你有權修改這個條目,因為這就是實際的目錄(一個特殊的文件)。
- 笨辦法學 Linux 中文版
- 練習 0:起步
- 練習 1:文本編輯器,vim
- 練習 2:文本瀏覽器,少即是多
- 練習 3:Bash:Shell、.profile、.bashrc、.bash_history
- 練習 4:Bash:處理文件,pwd,ls,cp,mv,rm,touch
- 練習 5:Bash:環境變量,env,set,export
- 練習 6:Bash:語言設置,LANG,locale,dpkg-reconfigure locales
- 練習 7:Bash:重定向,stdin,stdout,stderr,<,>,>>,|,tee,pv
- 練習 8:更多的重定向和過濾:head,tail,awk,grep,sed
- 練習 9:Bash:任務控制,jobs,fg
- 練習 10:Bash:程序退出代碼(返回狀態)
- 練習 11:總結
- 練習 12:文檔:man,info
- 練習 13:文檔:Google
- 練習 14:包管理:Debian 包管理工具aptitude
- 練習 15:系統啟動:運行級別,/etc/init.d,rcconf,update-rc.d
- 練習 16:處理進程,ps,kill
- 練習 17:任務調度:cron,at
- 練習 18:日志:/var/log,rsyslog,logger
- 練習 19:文件系統:掛載,mount,/etc/fstab
- 練習 20:文件系統:修改和創建文件系統,tune2fs,mkfs
- 練習 21:文件系統:修改根目錄,chroot
- 練習 22:文件系統:移動數據,tar,dd
- 練習 23:文件系統:權限,chown,chmod,umask
- 練習 24:接口配置,ifconfig,netstat,iproute2,ss,route
- 練習 25:網絡:配置文件,/etc/network/interfaces
- 練習 26:網絡:封包過濾配置,iptables
- 練習 27:安全 Shell,ssh,sshd,scp
- 練習 28:性能:獲取性能情況,uptime,free,top
- 練習 29:內核:內核消息,dmesg
- 練習 30:打磨、洗練、重復:總復習
- 下一步做什么
- Debian 手動安裝