练习 23:文件系统:权限,`chown`,`chmod`,`umask`
现在是时候了解 Linux 文件系统的安全模型了。我们首先引用维基百科的权限文章:
大多数当前文件系统拥有方法,来管理特定用户和用户组的权限或访问权的。这些系统控制用户查看或更改文件系统内容的能力。
类 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,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: 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
解释
- 打印当前的 umask。
- 创建
perms.022
,包含一行test
。 - 打印此文件的信息。
- 以八进制表示法打印该文件的权限信息。
- 更改此文件的权限,禁止任何人对此进行任何操作。
- 打印此文件的信息。
- 尝试用
test
替换此文件内容,由于缺少权限而失败。 - 删除此文件。这是可能的,因为没有触碰文件本身,只有目录
/home/user1
中的条目。 - 更改 umask,默认情况下不分配任何权限。
- 创建
perms.000
,包含一行test
。 - 打印此文件的信息。
- 试图打印出这个文件内容,这显然会导致错误。
- 更改文件权限,来允许所有者读写。
- 打印此文件内容,这次成功了。
- 删除此文件。
- 再次更改 umask
- 创建
perms.027
,包含一行test
。 - 打印此文件的信息。
- 将文件所有者更改为 root。
- 尝试向文件追加一行
test1
,导致错误。 - 尝试将文件所有者更改回
user1
,因为文件所有者的信息包含在文件本身而失败,更准确地说在其索引节点中。 - 将文件所有者更改回
user1
,这次成功运行,因为以 root 身份运行。 - 将一行
test1
添加到我们的文件,这次成功了。 - 删除
perms.027
。 - 将 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
分区直接读取目录内容。那么当你删除文件时,就是从这里删除一个条目,你有权修改这个条目,因为这就是实际的目录(一个特殊的文件)。