💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
# 练习 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`分区直接读取目录内容。那么当你删除文件时,就是从这里删除一个条目,你有权修改这个条目,因为这就是实际的目录(一个特殊的文件)。