跳至内容

本文档中的所有示例都使用 root 权限操作,普通用户操作另行注释。在 Markdown 代码块中,命令描述将在前一行使用 # 表示。

回顾基本权限

众所周知,可以使用 ls -l 查看 GNU/Linux 的基本权限

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);二进制文件(二进制);数据格式文件(数据);各种压缩文件。
d表示目录文件。默认情况下,每个目录中都包含一个 ...
b块设备文件。包括各种硬盘驱动器、USB 驱动器等等。
c字符设备文件。串行端口的接口设备,例如鼠标、键盘等。
s套接字文件。它是一种专门用于网络通信的文件。
p管道文件。它是一种特殊的文件类型,主要目的是解决多个程序同时访问一个文件时出现的错误。FIFO 是 first-in-first-out 的缩写。
l软链接文件,也称为符号链接文件,类似于 Windows 中的快捷方式。硬链接文件,也称为物理链接文件。

基本权限的含义

对于文件

数字表示权限描述
4r(读)表示您可以读取此文件。您可以使用 catheadmorelesstail 等命令。
2w(写)表示可以修改文件。可以使用 vim 等命令。
1x(执行)可执行文件(例如脚本或二进制文件)的权限。

对于目录

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

信息

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

特殊权限

在 GNU/Linux 中,除了上面提到的基本权限外,还有一些特殊权限,我们将一一介绍。

ACL 权限

什么是 ACL?ACL(访问控制列表),目的是解决 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,您需要使用 getfacle 命令 -- getfacle FILE_NAME

如果您要设置 ACL 权限,则需要使用 setfacl 命令。

Shell > setfacl <option> <FILE_NAME>
选项描述
-m修改文件(s)的当前 ACL(s)
-x从文件(s)的 ACL(s) 中删除条目
-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" 意味着什么?**掩码** 用于指定最大有效权限。授予用户的权限不是实际权限,实际权限只能通过使用用户权限和掩码权限的“逻辑与”来获得。

信息

“逻辑与”的意思是:如果所有条件都为真,则结果为真;如果有一个条件为假,则结果为假。

用户设置的权限掩码权限结果
rrr
r--
-r-
---

信息

因为默认掩码为 rwx,所以对于任何用户的 ACL 权限,结果都是他们自己的权限。

您也可以调整掩码权限

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 命令时,所有者组将切换到 **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  {} \;

粘滞位

"粘滞位" 的作用

  • 仅对目录有效。
  • 普通用户对该目录具有 w 和 x 权限。
  • 如果没有粘滞位,具有 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 ** 文件时需要格外小心!

作者: tianci li

贡献者: Serge, Ganna Zhyrnova