# 练习 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 手动安装