本文档中所有示例均使用root操作,普通用户的操作单独注释。在markdown代码块中,命令说明会在前一行用#表示。
复习基本权限¶
众所周知,GNU/Linux的基本权限可以通过ls -l
来查看
Shell > ls -l
- rwx r-x r-x 1 root root 1358 Dec 31 14:50 anaconda-ks.cfg
↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓
1 2 3 4 5 6 7 8 9 10
它们的含义如下
部分 | 描述 |
---|---|
1 | 文件类型。- 表示这是一个普通文件。七种文件类型后面会介绍。 |
2 | 文件所有者用户的权限,rwx的含义分别表示:读、写、执行。 |
3 | 文件所有者所属用户组的权限。 |
4 | 其他用户的权限。 |
5 | 子目录数量(包含. 和.. )。对于文件,它表示硬链接的数量,1表示它本身。 |
6 | 文件所有者用户的名称。 |
7 | 文件所有者所属用户组的名称。 |
8 | 对于文件,显示文件的大小。对于目录,显示文件命名所占用的固定值4096字节。要计算目录的总大小,请使用du -sh |
9 | 最后修改日期。 |
10 | 文件(或目录)的名称。 |
七种文件类型¶
文件类型 | 描述 |
---|---|
- | 表示普通文件。包括纯文本文件(ASCII);二进制文件(binary);数据格式文件(data);各种压缩文件。 |
d | 表示目录文件。每个目录默认包含. 和.. 。 |
b | 块设备文件。包括各种硬盘、U盘等。 |
c | 字符设备文件。串口的接口设备,如鼠标、键盘等。 |
s | 套接字文件。是专门用于网络通信的文件。 |
p | 管道文件。是一种特殊的文件类型,主要目的是解决多个程序同时访问一个文件所带来的错误。FIFO是先进先出(first-in-first-out)的缩写。 |
l | 软链接文件,也叫符号链接文件,类似于Windows下的快捷方式。硬链接文件,也叫物理链接文件。 |
基本权限的含义¶
对于文件
数字表示 | 权限 | 描述 |
---|---|---|
4 | r(读) | 表示可以读取该文件。可以使用cat 、head 、more 、less 、tail 等命令。 |
2 | w(写) | 表示可以修改该文件。可以使用vim 等命令。 |
1 | x(执行) | 可执行文件的权限(如脚本或二进制文件)。 |
对于目录
数字表示 | 权限 | 描述 |
---|---|---|
4 | r(读) | 表示可以列出目录的内容,例如ls -l 。 |
2 | w(写) | 表示可以在此目录中创建、删除和重命名文件,例如mkdir 、touch 、rm 等命令。 |
1 | x(执行) | 表示可以进入该目录,例如cd 命令。 |
信息
对于目录,r和x权限通常同时出现。
特殊权限¶
在GNU/Linux中,除了上述基本权限外,还有一些特殊权限,我们将逐一介绍。
ACL权限¶
什么是ACL?ACL(Access Control List),其目的是解决Linux下三种身份无法满足资源权限分配需求的问题。
例如,老师给学生上课,老师在OS的根目录下创建一个目录。只允许本班学生上传下载,其他人不允许。此时,目录的权限是770。有一天,一个外校的学生来听课,如何分配权限?如果将该学生放入所有者组,他将拥有与本班学生相同的权限——rwx。如果将该学生放入其他用户,他将没有任何权限。此时,基本权限分配无法满足要求,需要使用ACL。
Windows操作系统也有类似的功能。例如,要为用户分配文件权限,对于用户自定义目录/文件,右键单击--->属性--->安全--->编辑--->添加--->高级--->立即查找,找到相应的用户/组--->分配特定权限--->应用,完成。
GNU/Linux也一样:将指定用户/组添加到文件/目录并授予适当的权限,以完成ACL权限分配。
如何启用ACL?你需要找到挂载点的设备文件名及其分区号。例如,在我的机器上,你可以这样做
Shell > df -hT
Filesystem Type Size Used Avail Use% Mounted on
devtmpfs devtmpfs 3.8G 0 3.8G 0% /dev
tmpfs tmpfs 3.8G 0 3.8G 0% /dev/shm
tmpfs tmpfs 3.8G 8.9M 3.8G 1% /run
tmpfs tmpfs 3.8G 0 3.8G 0% /sys/fs/cgroup
/dev/nvme0n1p2 ext4 47G 11G 35G 24% /
/dev/nvme0n1p1 xfs 1014M 187M 828M 19% /boot
tmpfs tmpfs 774M 0 774M 0% /run/user/0
Shell > dumpe2fs /dev/nvme0n1p2 | head -n 10
dumpe2fs 1.45.6 (20-Mar-2020)
Filesystem volume name: <none>
Last mounted on: /
Filesystem UUID: c8e6206d-2892-4c22-a10b-b87d2447a885
Filesystem magic number: 0xEF53
Filesystem revision #: 1 (dynamic)
Filesystem features: has_journal ext_attr resize_inode dir_index filetype needs_recovery extent 64bit flex_bg sparse_super large_file huge_file dir_nlink extra_isize metadata_csum
Filesystem flags: signed_directory_hash
Default mount options: user_xattr acl
Filesystem state: clean
Errors behavior: Continue
当你看到“Default mount options: user_xattr acl”这行时,表示ACL已启用。如果未启用,也可以暂时启用——mount -o remount,acl /
。也可以永久启用
Shell > vim /etc/fstab
UUID=c8e6206d-2892-4c22-a10b-b87d2447a885 / ext4 defaults,acl 1 1
Shell > mount -o remount /
# or
Shell > reboot
ACL的查看与设置¶
要查看ACL,需要使用getfacl
命令——getfacl FILE_NAME
如果要设置ACL权限,需要使用setfacl
命令。
Shell > setfacl <option> <FILE_NAME>
选项 | 描述 |
---|---|
-m | 修改文件的当前ACL |
-x | 从文件的ACL中删除条目 |
-b | 删除所有扩展ACL条目 |
-d | 操作应用于默认ACL |
-k | 删除默认ACL |
-R | 递归到子目录 |
使用文章开头提到的老师的例子来说明ACL的使用。
# The teacher is the root user
Shell > groupadd class1
Shell > mkdir /project
Shell > chown root:class1 /project
Shell > chmod 770 /project
Shell > ls -ld /project/
drwxrwx--- 2 root class1 4096 Jan 12 12:58 /project/
# Put the students in the class into the class1 group
Shell > useradd frank
Shell > passwd frank
Shell > useradd aron
Shell > passwd aron
Shell > gpasswd -a frank class1
Shell > gpasswd -a aron class1
# A student from another school came to listen to the teacher
Shell > useradd tom
Shell > passwd tom
# If it is a group, "u" here should be replaced by "g"
Shell > setfacle -m u:tom:rx /project
# "+" sign is added in the output message
Shell > ls -ld /project/
drwxrwx---+ 2 root class1 4096 Jan 12 12:58 /project/
Shell > getfacl -p /project/
# file: /project/
# owner: root
# group: class1
user::rwx
user:tom:r-x
group::rwx
mask::rwx
other::---
ACL的最大有效权限¶
当使用getfacl
命令时,“mask:: rwx”在输出信息中是什么意思?mask用于指定最大有效权限。授予用户的权限并非真实权限,真实权限需要通过用户权限与mask权限进行“逻辑与”运算才能获得。
信息
“逻辑与”的意思是:如果都为真,结果为真;有一个为假,结果为假。
用户设置的权限 | Mask权限 | 结果 |
---|---|---|
r | r | r |
r | - | - |
- | r | - |
- | - | - |
信息
因为默认mask为rwx,所以对于任何用户的ACL权限,结果都是其自身的权限。
也可以调整mask权限
Shell > setfacl -m u:tom:rwx /project
Shell > setfacl -m m:rx /project
Shell > getfacl -p /project/
# file: project/
# owner: root
# group: class1
user::rwx
user:tom:rwx #effective:r-x
group::rwx #effective:r-x
mask::r-x
other::---
删除ACL权限¶
# Delete the ACL permissions of user/group in the specified directory
Shell > setfacl -x u:USER_NAME FILE_NAME
Shell > setfacl -x g:GROUP_NAME FILE_NAME
# Removes all ACL permissions for the specified directory
Shell > setfacl -b FILE_NAME
ACL权限的默认与递归¶
ACL权限的递归是什么意思?对于ACL权限,这意味着当父目录设置了ACL权限后,所有的子目录和子文件都会继承相同的ACL权限。
信息
递归适用于目录中已有的文件/目录。
看下面的例子
Shell > setfacl -m m:rwx /project
Shell > setfacl -m u:tom:rx /project
Shell > cd /project
Shell > touch file1 file2
# Because there is no recursion, the file here does not have ACL permission.
Shell > ls -l
-rw-r--r-- 1 root root 0 Jan 12 14:35 file1
-rw-r--r-- 1 root root 0 Jan 12 14:35 file2
Shell > setfacl -m u:tom:rx -R /project
Shell > ls -l /project
-rw-r-xr--+ 1 root root 0 Jan 12 14:35 file1
-rw-r-xr--+ 1 root root 0 Jan 12 14:35 file2
现在有一个问题:如果我在这个目录中创建一个新文件,它是否具有ACL权限?答案是否定的,因为新创建的文件是在执行setfacl -m u:tom:rx -R /project
命令之后。
Shell > touch /project/file3
Shell > ls -l /project/file3
-rw-r--r-- 1 root root 0 Jan 12 14:52 /project/file3
如果你希望新创建的目录/文件也具有ACL权限,则需要使用默认ACL权限。
Shell > setfacl -m d:u:tom:rx /project
Shell > cd /project && touch file4 && ls -l
-rw-r-xr--+ 1 root root 0 Jan 12 14:35 file1
-rw-r-xr--+ 1 root root 0 Jan 12 14:35 file2
-rw-r--r-- 1 root root 0 Jan 12 14:52 file3
-rw-rw----+ 1 root root 0 Jan 12 14:59 file4
Shell > getfacl -p /project
# file: /project
# owner: root
# group: class1
user::rwx
user:tom:r-x
group::rwx
mask::rwx
other::---
default:user::rwx
default:user:tom:r-x
default:group::rwx
default:mask::rwx
default:other::---
信息
使用ACL权限的默认和递归要求命令的操作对象为目录!如果操作对象为文件,会报错提示。
SetUID¶
“SetUID”的作用
- 只有可执行的二进制文件才能设置SUID权限。
- 命令的执行者对程序本身拥有x权限。
- 命令的执行者在执行该程序时,获得该程序文件所有者的身份。
- 身份的改变仅在执行期间有效,一旦二进制程序执行完毕,执行者的身份将恢复为原来的身份。
为什么GNU/Linux需要这种特殊的权限?以最常见的passwd
命令为例
可以看到,普通用户只有r和x权限,但所有者的x变成了s,证明passwd
命令具有SUID权限。
众所周知,普通用户(uid>=1000)可以修改自己的密码。真正的密码存储在/etc/shadow文件中,但shadow文件的权限是000,普通用户没有任何权限。
Shell > ls -l /etc/shadow
---------- 1 root root 874 Jan 12 13:42 /etc/shadow
既然普通用户可以修改自己的密码,那么他一定将密码写进了/etc/shadow文件。当普通用户执行passwd
命令时,它会临时变成文件所有者——root。对于shadow文件,root不受权限限制。这就是为什么passwd
命令需要SUID权限。
前面提到,基本权限可以用数字表示,例如755、644等。SUID用4表示。对于可执行的二进制文件,可以这样设置权限——4755。
# Set SUID permissions
Shell > chmod 4755 FILE_NAME
# or
Shell > chmod u+s FILE_NAME
# Remove SUID permission
Shell > chmod 755 FILE_NAME
# or
Shell > chmod u-s FILE_NAME
警告
当一个可执行二进制文件/程序的所有者没有x权限时,使用大写S表示该文件无法正确使用SUID权限。
# Suppose this is an executable binary file
Shell > vim suid.sh
#!/bin/bash
cd /etc && ls
Shell > chmod 4644 suid.sh
警告
由于SUID可以暂时将普通用户提升为root,所以在维护服务器时,需要特别注意带有此权限的文件。可以使用以下命令查找带有SUID权限的文件
Shell > find / -perm -4000 -a -type f -exec ls -l {} \;
SetGID¶
“SetGID”的作用
- 只有可执行的二进制文件才能设置SGID权限。
- 命令的执行者对程序本身拥有x权限。
- 命令的执行者在执行该程序时,获得该程序文件所有者组的身份。
- 身份的改变仅在执行期间有效,一旦二进制程序执行完毕,执行者的身份将恢复为原来的身份。
以locate
命令为例
Shell > rpm -ql mlocate
/usr/bin/locate
...
/var/lib/mlocate/mlocate.db
Shell > ls -l /var/lib/mlocate/mlocate.db
-rw-r----- 1 root slocate 4151779 1月 14 11:43 /var/lib/mlocate/mlocate.db
Shell > ll /usr/bin/locate
-rwx--s--x. 1 root slocate 42248 4月 12 2021 /usr/bin/locate
locate
命令使用mlocate.db数据库文件来快速查找文件。
由于locate
命令具有SGID权限,当执行者(普通用户)执行locate
命令时,其所属组会切换为slocate。slocate对/var/lib/mlocate/mlocate.db文件具有r权限。
SGID用数字2表示,因此locate
命令具有2711权限。
# Set SGID permissions
Shell > chmod 2711 FILE_NAME
# or
Shell > chmod g+s FILE_NAME
# Remove SGID permission
Shell > chmod 711 FILE_NAME
# or
Shell > chmod g-s FILE_NAME
警告
当一个可执行二进制文件/程序的所有者组没有x权限时,使用大写S表示该文件无法正确使用SGID权限。
# Suppose this is an executable binary file
Shell > touch sgid
Shell > chmod 2741 sgid
Shell > ls -l sgid
-rwxr-S--x 1 root root 0 Jan 14 12:11 sgid
SGID不仅可以用于可执行的二进制文件/程序,也可以用于目录,但很少使用。
- 普通用户对此目录必须拥有rwx权限。
- 普通用户在此目录中创建的文件,其所属组默认为该目录的所属组。
例如
Shell > mkdir /SGID_dir
Shell > chmod 2777 /SGID_dir
Shell > ls -ld /SGID_dir
drwxrwsrwx 2 root root 4096 Jan 14 12:17 SGID_dir
Shell > su - tom
Shell(tom) > cd /SGID_dir && touch tom_file && ls -l
-rw-rw-r-- 1 tom root 0 Jan 14 12:26 tom_file
警告
由于SGID可以暂时将普通用户的所属组切换为root,所以在维护服务器时,需要特别注意带有此权限的文件。可以通过以下命令查找带有SGID权限的文件
Shell > find / -perm -2000 -a -type f -exec ls -l {} \;
Sticky BIT¶
“Sticky BIT”的作用
- 仅对目录有效。
- 普通用户对该目录拥有w和x权限。
- 如果没有Sticky Bit,拥有w权限的普通用户可以删除该目录下的所有文件(包括其他用户创建的文件)。一旦给目录添加了SBIT权限,只有root用户才能删除所有文件。即使普通用户拥有w权限,他们也只能删除自己创建的文件(不能删除其他用户创建的文件)。
SBIT用数字1表示。
文件或目录可以拥有7755权限吗?不可以,它们针对的对象不同。SUID用于可执行的二进制文件;SGID用于可执行二进制文件和目录;SBIT仅用于目录。也就是说,你需要根据不同的对象来设置这些特殊权限。
目录/tmp具有SBIT权限。以下是一个例子
# The permissions of the /tmp directory are 1777
Shell > ls -ld /tmp
drwxrwxrwt. 8 root root 4096 Jan 14 12:50 /tmp
Shell > su - tom
Shell > cd /tmp && touch tom_file1
Shell > exit
Shell > su - jack
Shell(jack) > cd /tmp && rm -rf tom_file1
rm: cannot remove 'tom_file1': Operation not permitted
Shell(jack) > exit
# The file has been deleted
Shell > su - tom
Shell(tom) > rm -rf /tmp/tom_file1
信息
root(uid=0)用户不受SUID、SGID和SBIT权限的限制。
chattr¶
chattr权限的功能:用于保护系统中重要文件或目录不被误操作删除。
chattr
命令的用法——chattr [ -RVf ] [ -v version ] [ -p project ] [ mode ] files...
符号模式的格式为+-=[aAcCdDeFijPsStTu]。
- "+"表示增加权限;
- "-"表示减少权限;
- "="表示等于某个权限。
最常用的权限(也称为属性)是a和i。
属性i说明¶
删除 | 自由修改 | 追加文件内容 | 查看 | 创建文件 | |
---|---|---|---|---|---|
文件 | × | × | × | √ | - |
目录 | x (目录及其下的文件) |
√ (目录中的文件) |
√ (目录中的文件) |
√ (目录中的文件) |
x |
文件示例
Shell > touch /tmp/filei
Shell > vim /tmp/filei
123
Shell > chattr +i /tmp/filei
Shell > lsattr -a /tmp/filei
----i---------e----- /tmp/filei
Shell > rm -rf /tmp/filei
rm: cannot remove '/tmp/filei': Operation not permitted
# Cannot be modified freely
Shell > vim /tmp/file1
Shell > echo "adcd" >> /tmp/filei
-bash: /tmp/filei: Operation not permitted
Shell > cat /tmp/filei
123
目录示例
Shell > mkdir /tmp/diri
Shell > cd /tmp/diri && echo "qwer" > f1
Shell > chattr +i /tmp/diri
Shell > lsattr -ad /tmp/diri
----i---------e----- /tmp/diri
Shell > rm -rf /tmp/diri
rm: cannot remove '/tmp/diri/f1': Operation not permitted
# Allow modification
Shell > vim /tmp/diri/f1
qwer-tom
Shell > echo "jim" >> /tmp/diri/f1
Shell > cat /tmp/diri/f1
qwer-tom
jim
Shell > touch /tmp/diri/file2
touch: settng time of '/tmp/diri/file2': No such file or directory
移除上述示例中的i属性
Shell > chattr -i /tmp/filei /tmp/diri
属性a说明¶
删除 | 自由修改 | 追加文件内容 | 查看 | 创建文件 | |
---|---|---|---|---|---|
文件 | × | × | √ | √ | - |
目录 | x (目录及其下的文件) |
x (目录中的文件) |
√ (目录中的文件) |
√ (目录中的文件) |
√ |
文件示例
Shell > touch /etc/tmpfile1
Shell > echo "zxcv" > /etc/tmpfile1
Shell > chattr +a /etc/tmpfile1
Shell > lsattr -a /etc/tmpfile1
-----a--------e----- /etc/tmpfile1
Shell > rm -rf /etc/tmpfile1
rm: cannot remove '/etc/tmpfile1': Operation not permitted
# Cannot be modified freely
Shell > vim /etc/tmpfile1
Shell > echo "new line" >> /etc/tmpfile1
Shell > cat /etc/tmpfile1
zxcv
new line
目录示例
Shell > mkdir /etc/dira
Shell > cd /etc/dira && echo "asdf" > afile
Shell > chattr +a /etc/dira
Shell > lsattr -ad /etc/dira
-----a--------e----- /etc/dira/
Shell > rm -rf /etc/dira
rm: cannot remove '/etc/dira/afile': Operation not permitted
# Free modification is not allowed
Shell > vim /etc/dira/afile
asdf
Shell > echo "new line" >> /etc/dira/afile
Shell > cat /etc/dira/afile
asdf
new line
# Allow creation of new files
Shell > touch /etc/dira/newfile
移除上述示例中的a属性
Shell > chattr -a /etc/tmpfile1 /etc/dira/
问题
如果我对一个文件设置了ai属性会怎么样?除了查看,你对该文件做什么都无法进行。
对于目录呢?允许:自由修改、追加文件内容、查看。不允许:删除和创建文件。
sudo¶
“sudo”的作用
- 通过root用户,将只有root用户(uid=0)才能执行的命令,分配给普通用户来执行。
- “sudo”的操作对象是系统命令。
我们知道,在GNU/Linux目录下,只有管理员root才有权限使用/sbin/和/usr/sbin/下的命令。一般情况下,一个公司会有一个团队来维护一套服务器。这套服务器可以指一个地理位置的单台计算机机房,也可以指多个地理位置的机房。团队负责人拥有root用户的权限,其他团队成员可能只是普通用户的权限。由于负责人工作繁忙,没有时间维护服务器的日常工作,大部分工作需要普通用户来维护。但是,普通用户在命令使用上有很多限制,此时就需要使用sudo权限。
为了给普通用户授权,必须使用root用户(uid=0)。
你可以通过visudo
命令来赋予普通用户权限,你实际修改的是/etc/sudoers文件。
Shell > visudo
...
88 Defaults secure_path = /sbin:/bin:/usr/sbin:/usr/bin
89
90 ## Next comes the main part: which users can run what software on
91 ## which machines (the sudoers file can be shared between multiple
92 ## systems).
93 ## Syntax:
94 ##
95 ## user MACHINE=COMMANDS
96 ##
97 ## The COMMANDS section may have other options added to it.
98 ##
99 ## Allow root to run any commands anywhere
100 root ALL=(ALL) ALL
↓ ↓ ↓ ↓
1 2 3 4
...
部分 | 描述 |
---|---|
1 | 用户名或所属组名。指给哪个用户/组授予权限。如果是所属组,需要加上“%”号,如%root。 |
2 | 允许执行命令的主机。可以是一个单独的IP地址、一个网段,或者是ALL。 |
3 | 表示可以切换成哪种身份。 |
4 | 授权的命令,需要使用绝对路径表示。 |
例如
Shell > visudo
...
101 tom ALL=/sbin/shutdown -r now
...
# You can use the "-c" option to check for errors in /etc/sudoers writing.
Shell > visudo -c
Shell > su - tom
# View the available sudo commands.
Shell(tom) > sudo -l
# To use the available sudo command, ordinary users need to add sudo before the command.
Shell(tom) > sudo /sbin/shutdown -r now
如果你的授权命令是/sbin/shutdown
,那么就意味着被授权用户可以使用该命令的任何选项。
警告
由于sudo是“越权”操作,在处理/etc/sudoers文件时一定要小心!
作者:李天赐
贡献者:Serge, Ganna Zhyrnova