跳至内容

本文档中所有示例均使用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(读) 表示可以读取该文件。可以使用catheadmorelesstail等命令。
2 w(写) 表示可以修改该文件。可以使用vim等命令。
1 x(执行) 可执行文件的权限(如脚本或二进制文件)。

对于目录

数字表示 权限 描述
4 r(读) 表示可以列出目录的内容,例如ls -l
2 w(写) 表示可以在此目录中创建、删除和重命名文件,例如mkdirtouchrm等命令。
1 x(执行) 表示可以进入该目录,例如cd命令。

信息

对于目录,rx权限通常同时出现。

特殊权限

在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命令为例

SetUID1

可以看到,普通用户只有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

SUID2

警告

由于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命令时,其所属组会切换为slocateslocate/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]。

  • "+"表示增加权限;
  • "-"表示减少权限;
  • "="表示等于某个权限。

最常用的权限(也称为属性)是ai

属性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