原文:Exercise 23. Filesystems: security permissions, chown, chmod, umask

译者:飞龙

协议:CC BY-NC-SA 4.0

自豪地采用谷歌翻译

现在是时候了解 Linux 文件系统的安全模型了。我们首先引用维基百科的权限文章:

大多数当前文件系统拥有方法,来管理特定用户和用户组的权限或访问权的。这些系统控制用户查看或更改文件系统内容的能力。

类 Unix 系统的权限在三个不同的类中进行管理。这些类称为用户, 组和其他。实际上,Unix 权限是访问控制列表(ACL)的简化形式。

当在类 Unix 系统上创建新文件时,其权限将从创建它的进程的 umask 确定。

对于 Linux 中的每个文件,都有三个权限类。对于每个权限类,有三个权限。

这是权限类:

描述
用户 文件的拥有者。
分组 同组用户
其它人 任何其他用户或组

这是每个类可分配的权限:

权限 符号 描述
r-- 读取文件的能力
-w- 写入文件的能力
执行 --x 将文件作为程序执行的能力,例如 ShellScript 应该设置这个

这两个表格应该总结一下:

所有者 同组 其它人
r w x r w x r w x

这些权限表示为数字。考虑下面的输出:

  1. user1@vm1:~$ ls -al tmp.img
  2. -rw-r--r-- 1 root root 252706816 Jul 6 07:54 tmp.img
  3. user1@vm1:~$ stat tmp.img
  4. File: 'tmp.img'
  5. Size: 252706816 Blocks: 494064 IO Block: 4096 regular file
  6. Device: 809h/2057d Inode: 88534 Links: 1
  7. Access: (0644/-rw-r--r--) Uid: ( 0/ root) Gid: ( 0/ root)
  8. Access: 2012-07-06 07:56:58.000000000 -0400
  9. Modify: 2012-07-06 07:54:54.000000000 -0400
  10. Change: 2012-07-06 07:54:54.000000000 -0400
  11. user1@vm1:~$

这里我们能够看到,tmp.img由用户root,分组root拥有,并且拥有权限-rw-r–r–。让我们试着阅读他们。

  1. -rw # 所有者可以读取和写入文件
  2. r-- # 同组用户只能读取文件
  3. r-- # 其它人只能读取文件
  4. 1 #
  5. root # 所有者是 root
  6. root # 分组是 root(但不要和 root 用户搞混了)
  7. 252706816 #
  8. Jul #
  9. 6 #
  10. 07:54 #
  11. tmp.img #

这里是八进制表示法的相同权限:

  1. Access:
  2. (
  3. 0
  4. 6 -rw
  5. 4 r--
  6. 4 ---
  7. )
  8. Uid: ( 0/ root)
  9. 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,SGID 和粘连位的东西。我不会详细介绍,但我会给你一个额外的附加题和翻译表。

特殊位:

模式 符号 描述
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创建了一个文件,它将具有哪些权限?事实证明,你可以使用文件模式创建掩码(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. 1: umask
  2. 2: echo 'test' > perms.022
  3. 3: ls -l perms.022
  4. 4: stat perms.022 | grep 'Access: ('
  5. 5: chmod 000 perms.022
  6. 6: ls -al perms.0022
  7. 7: echo 'test' > perms.022
  8. 8: rm -v perms.022

记得上个练习的附加题中的问题吗?你现在处于类似的情况,因为你不能对此文件执行任何操作。但是为什么允许你删除它?这是因为当删除文件时,实际上是从目录中删除此文件的信息,对文件本身不做任何事情。我在这个话题上有很多的附加题。

  1. 9: umask 666
  2. 10: echo 'test' > perms.000
  3. 11: ls -l perms.000
  4. 12: cat perms.000
  5. 13: chmod 600 perms.000
  6. 14: cat perms.000
  7. 15: rm -v perms.000
  8. 16: umask 027
  9. 17: echo 'test' > perms.027
  10. 18: ls -l perms.027
  11. 19: sudo chown root perms.027
  12. 20: echo 'test1' >> perms.027
  13. 21: chown user1 perms.027
  14. 22: sudo chown user1 perms.027
  15. 23: echo 'test1' >> perms.027
  16. 24: rm -v perms.027
  17. 25: umask 022

你会看到什么

  1. user1@vm1:~$ umask
  2. 0027
  3. user1@vm1:~$ echo 'test' > perms.022
  4. user1@vm1:~$ ls -l perms.022
  5. -rw-r----- 1 user1 user1 5 Jul 9 10:23 perms.022
  6. user1@vm1:~$ stat perms.022 | grep 'Access: ('
  7. Access: (0640/-rw-r-----) Uid: ( 1000/ user1) Gid: ( 1000/ user1)
  8. user1@vm1:~$ chmod 000 perms.022
  9. user1@vm1:~$ ls -al perms.0022
  10. ls: cannot access perms.0022: No such file or directory
  11. user1@vm1:~$ echo 'test' > perms.022
  12. -bash: perms.022: Permission denied
  13. user1@vm1:~$ rm -v perms.022
  14. rm: remove write-protected regular file `perms.022'? y
  15. removed `perms.022'
  16. user1@vm1:~$ umask 666
  17. user1@vm1:~$ echo 'test' > perms.000
  18. user1@vm1:~$ ls -l perms.000
  19. ---------- 1 user1 user1 5 Jul 9 10:23 perms.000
  20. user1@vm1:~$ cat perms.000
  21. cat: perms.000: Permission denied
  22. user1@vm1:~$ chmod 600 perms.000
  23. user1@vm1:~$ cat perms.000
  24. test
  25. user1@vm1:~$ rm -v perms.000
  26. removed `perms.000'
  27. user1@vm1:~$ umask 027
  28. user1@vm1:~$ echo 'test' > perms.027
  29. user1@vm1:~$ ls -l perms.027
  30. -rw-r----- 1 user1 user1 5 Jul 9 10:24 perms.027
  31. user1@vm1:~$ sudo chown root perms.027
  32. user1@vm1:~$ echo 'test1' >> perms.027
  33. -bash: perms.027: Permission denied
  34. user1@vm1:~$ chown user1 perms.027
  35. chown: changing ownership of `perms.027': Operation not permitted
  36. user1@vm1:~$ sudo chown user1 perms.027
  37. user1@vm1:~$ echo 'test1' >> perms.027
  38. user1@vm1:~$ rm -v perms.027
  39. removed `perms.027'
  40. user1@vm1:~$ umask 022

解释

  1. 打印当前的 umask。
  2. 创建perms.022,包含一行test
  3. 打印此文件的信息。
  4. 以八进制表示法打印该文件的权限信息。
  5. 更改此文件的权限,禁止任何人对此进行任何操作。
  6. 打印此文件的信息。
  7. 尝试用test替换此文件内容,由于缺少权限而失败。
  8. 删除此文件。这是可能的,因为没有触碰文件本身,只有目录/home/user1中的条目。
  9. 更改 umask,默认情况下不分配任何权限。
  10. 创建perms.000,包含一行test
  11. 打印此文件的信息。
  12. 试图打印出这个文件内容,这显然会导致错误。
  13. 更改文件权限,来允许所有者读写。
  14. 打印此文件内容,这次成功了。
  15. 删除此文件。
  16. 再次更改 umask
  17. 创建perms.027,包含一行test
  18. 打印此文件的信息。
  19. 将文件所有者更改为 root。
  20. 尝试向文件追加一行test1,导致错误。
  21. 尝试将文件所有者更改回user1,因为文件所有者的信息包含在文件本身而失败,更准确地说在其索引节点中。
  22. 将文件所有者更改回user1,这次成功运行,因为以 root 身份运行。
  23. 将一行test1添加到我们的文件,这次成功了。
  24. 删除perms.027
  25. 将 umask 还原到其默认值。

附加题

  • man chmodman chownman umask
  • 重新阅读man chmod中的setuidsetgidsticky位。这样设置你的目录的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分区直接读取目录内容。那么当你删除文件时,就是从这里删除一个条目,你有权修改这个条目,因为这就是实际的目录(一个特殊的文件)。