Skip to content

Linux 权限管理

所有者

要修改文件或目录的所属组,使用 chgrp 命令:

chgrp [-R] 所属组 文件名/目录名 # -R选项用于递归更新目录中所有文件的所属组信息

而修改文件或目录的所属组,使用 chown 命令:

chown [-R] 所有者 文件名/目录名 
chown [-R] 所有者:所属组 文件名/目录名 # 可同时修改所有者和所属组

访问权限

Linux 系统中,每个文件都明确规定了不同身份用户的访问权限,使用 ls -l 命令可以看到。

$ ls -l ~
total 99
drwxrwxr-x  2 jiamin jiamin  4096 May 25 16:44 Download
-rwxrwxr-x  1 jiamin jiamin    79 Aug 22 18:42 connect.sh
-rw-r--r--  1 jiamin jiamin    79 Aug 22 20:11 test.txt
...

ls -l 命令输出内容的第一列即是各文件对不同用户设定的权限,一共有 11 位:

  • 第 1 位表示文件类型。- 表示普通文件,d 表示目录,l 表示连接文件,b 表示设备文件,等等。

  • 第 2~10 位为三种不同的用户身份设定权限,每三位为一组,三组分别代表所有者、所属组和其他人三种身份的权限。每组权限的三位分别规定了是否对文件有读(r)、写(w)、执行(x) 权限。除此之外,我们还可以在 x 权限的位置,看到 s 或者 t 权限。

    s 针对可执行文件或目录,使文件在执行阶段,临时拥有文件所有者的权限。t 针对目录,任何用户都可以在此目录中创建文件,但只能删除自己的文件

  • 第 11 位受 SELinux 的安全规则管理(不在此进行讨论)。

文件 目录
r 可读文件内容 可查看目录下文件/子目录列表
w 可更改文件内容 可新建/删除/移动该目录中文件/子目录,可对该目录下的文件/子目录做更名操作
x 可执行该文件 可进入该目录

例:若用户要执行 cp /dir1/file /dir2/ 命令,需要:

  • /dir1/ 拥有 x 权限
  • /dir1/file 拥有 r 权限
  • /dir2/ 拥有 w,x 权限

权限修改

可用 chmod 命令修改文件权限。

  1. 可用数字修改文件权限

    代表权限的 9 个字符,视为 3 个 3 位的二进制数,如 rwxrw-r-x 即视为 111 110 101 三个二进制数,用十进制表示即为 765,故可用 chmod 765 test_filetest_file 的权限改为 rwxrw-r-x

  2. 使用数字修改文件权限

    使用 ugo 分别代表所有者、所属组和其他人三种身份,也可使用 a 代表全部的身份。使用 rwx 分别代表读、写、执行权限。使用 + 添加权限、- 删除权限、= 设定权限。如:

    $ chmod u=rwx,go=rx .bashrc
    $ chmod a+x test.sh
    

默认权限

Linux 系统中,创建新的文件和目录时,通过使用 umask 默认权限来给所有新建的文件和目录赋予初始权限。

默认权限由 4 个八进制数组成,第一个数代表文件所具有的特殊权限(SetUID、SetGID、Sticky BIT),后三个数字分别代表创建的新文件/目录需要从最大默认权限中减去的数值。使用 umask 命令变可查看默认权限,默认 root 用户是 0022,而普通用户是 0002。

对文件来说,最大默认权限是 666,而目录最大权限是 777,因此,在不修改 umask 的情况下,root 用户创建的文件与目录权限分别为 644 和 755。

若要修改默认权限,使用 umask [mode] 修改,修改后只临时有效,若要永久设置,可写入 /etc/profile 文件中

ACL 访问控制权限

在实际使用时,光靠所有者、所属组和其他人三种身份,并不能完全满足更精细的权限管理,因此就需要使用 ACL 访问控制权限。ACL 全称是 Access Control List(访问控制列表),它可以对单一用户设定访问文件的权限。

要开启 ACL:

  1. 使用 mount -o remount,acl 分区 重新挂载需要开启 ACL 的分区,该方法临时生效
  2. 修改 /etc/fstab 文件,在需要开启 ACL 的分区的对应行的第 4 列挂载参数中添加 ,acl,以永久生效

若要设置 ACL 权限,使用 setfacl 命令,查看使用 getfacl 命令。

setfacl 命令使用基本格式为 setfacl 参数 file,其常用参数为:

功能 参数 例子
设定 ACL 权限 -m u/g:用户/组名:权限 setfacl -m u:user0:rx test/
设定目录中新建文件的默认权限 -m d:u/g:用户/组名:权限 setfacl -m d:u:user0:rx test/
删除指定用户/组的 ACL 权限 -x u/g:用户名 setfacl -x u:user0 test/
删除所有 ACL 权限 -b setfacl -b test/

设置 ACL 权限后,使用 ls -l 查看文件时,便会发现对应条目的第一列的第 11 个字符变为了 +,可通过 getfacl 文件名/目录名 来查看 ACL 权限细节。

可以看到, getfacl 的输出中还有 mask 这一项。设定的 ACL 权限还需与 mask 按位与,才是最终权限,其作用即规定了 ACL 最大能设定的权限。mask 权限可通过 setfact -m m:权限 目录/文件 来修改。

Linux 文件特殊权限

SetUID(SUID)

前面提到过,在所有者执行(x)权限的位置,有时候还能看到 s 权限,这种权限针对可执行文件,使文件在执行阶段,临时拥有文件所有者的权限。这种权限通常称为 SetUID,或 SUID 特殊权限。

$ which passwd
/usr/bin/passwd
$ ls -l /usr/bin/passwd
-rwsr-xr-x 1 root root 68208 Mar 14  2022 /usr/bin/passwd

在 Linux 系统中,用户的密码数据记录在 /etc/shadow 整个文件中

$ ls -l /etc/shadow
-rw-r----- 1 root shadow 1551 Apr 20 13:09 /etc/shadow

但可以看到,除 root 外其他用户对该文件没有写权限,那么 Linux 如何让普通用户修改自己的密码呢?答案就在 passwd 命令的 SetUID 权限上了,普通用户在使用 passwd 命令修改自己密码时,会临时拥有所有者 root 的权限来执行这个命令,从而修改 /etc/shadow 文件,命令执行完毕,普通用户所拥有的 root 身份也会失效。

SUID 作用于可执行文件,要求执行命令的用户对文件拥有 x 权限,这样 SUID 才会生效。使用 chmod u+s 文件名 可为文件设置 SUID 权限。

SetGID(SGID)

当 s 权限在所属组的 x 权限位上时,此时的权限称为 SetGID,或 SGID 特殊权限。同 SUID 权限,SGID 会使得执行该文件的用户的组身份临时变为文件所属者。

$ ls -l /usr/bin/plocate
-rwxr-sr-x 1 root plocate 313904 Feb 17  2022 /usr/bin/plocate

plocate 命令在执行过程中,用户会临时获得 plocate 这个组的权限,从而可以在 /var/lib/plocate/plocate.db 这个数据库中查看信息。

$ ls -l /var/lib/plocate/plocate.db
-rw-r----- 1 root plocate 30541707 Sep  3 17:04 /var/lib/plocate/plocate.db

SGID 也可作用于目录,作用于目录时,用户要对该目录拥有 rwx 权限,SGID 命令才能生效,这样若其他用户在设置了 SGID 的目录下新建文件,新文件所属组为父目录所属组,而所有者还是该用户。

# su - user0
$ ls -ld /tmp/dtest/
drwxr-srwx 2 root root 4096 Sep  3 17:33 /tmp/dtest/
$ touch /tmp/dtest/testfile
$ ls -l /tmp/dtest/
total 0
-rw-rw-r-- 1 user0 root 0 Sep  3 17:41 testfile

Stick BIT(SBIT)

Stick BIT,即 SBIT 特殊权限。SBIT 权限仅对目录有效,一旦目录设定了 SBIT,那么用户在此目录下创建的文件或目录,就只有用户自己和 root 拥有修改以及删除权限。如 Linux 系统中的 /tmp 目录就设定了 SBIT 权限:

$ ls -ld /tmp
drwxrwxrwt 25 root root 36864 Sep  3 17:23 /tmp

所有用户都可以在 /tmp 文件夹中新建文件/目录,一旦创建,就只有该用户以及 root 可以修改或删除,而除此之外的其他用户就只有读权限。

特殊权限的设置

我们知道,使用 chmod 命令可以设置文件的权限,777 是 rwxrwxrwx755rwxr-xr-x,那么特殊权限 SUID、SGID、SBIT 应该如何设置呢?

在 Linux 中 SUID、SGID、SBIT 分别使用 4、2、1 来指示,在原先三位权限的前面添加特殊权限对应的数字之和便能使用 chmod 权限 文件名 来设置特殊权限了。

# su - user0
$ cd /tmp
$ mkdir test
$ ll -d test
drwxrwxr-x 2 user0 user0 4096  9月  3 18:09 test/
$ chmod 5755 test
$ ll -d test
drwsr-xr-t 2 user0 user0 4096  9月  3 18:09 test/

也可通过 u+s g+s o+t 的方式分别赋予文件特殊权限。

若对没有 x 权限的权限的文件设置 SUID、SGID 或 SBIT 权限,权限将不会生效,并且,使用 ls -l 命令查看的时候,对应位将显示为大写的 ST

$ touch test2
$ chmod 7666 test2
$ ll -d test2
-rwSrwSrwT 1 user0 user0 0  9月  3 18:14 test2

隐藏属性

除普通权限和特殊权限外,Linux 系统中还有一些隐藏权限,隐藏权限通过 chattr 命令进行修改,基本格式为:

chattr [+-=] [属性] 文件或目录名

下表列出常用属性,及其功能

属性 功能
i 不可做任何修改(即使是 root):
1. 拥有 i 属性的普通文件,不可删除、改名、修改内容、添加内容;
2. 拥有 i 属性的目录,内部不可建立、删除、重命名文件
a 仅可以 append 模式打开:
1. 拥有 a 属性的普通文件,只能在文件中增加内容,而不可删除文件、改名、修改内容
2. 拥有 a 属性的目录,只能在内部新建文件,不能删除、更名内部文件
s 拥有 s 属性的目录或普通文件,删除时,会彻底删除,用 0 填充所占区域

使用 lsattr 命令查看文件隐藏属性,常用选项有 -a -d -R 选项,这些选项功能和 ls 命令的相同。

sudo 命令

通过 sudo 命令,用户可以使用其他用户的身份去执行命令。该命令基本格式为:

sudo [参数] command

常用参数为:

  • -u user :欲使用用户的用户名或 ID,若不指定,默认使用 root 用户
  • -l:显示出自己的权限
  • -k:强制使用者在下一次执行 sudo 时询问密码(默认 5 分钟不使用 sudo 会再次询问密码)

为普通用户添加 sudo 权限

sudo 命令运行时,系统会先通过 /etc/sudoers 文件验证用户是否有 sudo 命令的权限,如果有,用户需输入自己的密码进行确认,密码正确后才会以指定的身份执行 sudo 后的命令。默认情况下,系统只有 root 用户拥有 sudo 命令的权限。要让普通用户获得 sudo 权限,一种方法是直接修改 /etc/sudoers 文件,另一种方法后文会介绍。

我们通常会使用 visudo 命令修改 /etc/sudoers 文件,这是因为 visudo 会自行检测 /etc/sudoers 文件的语法。大多 Linux 系统默认使用 vi 编辑器(Ubuntu 默认使用的是 nano,若要修改默认编辑器,使用 update-alternatives --config editor 命令)。可以看到,/etc/sudoers 文件中包含有如下的内容(在 Ubuntu 系统中是 sudo 组,在 CentOS 系统中是 wheel 组):

root     ALL=(ALL:ALL) ALL
%sudo    ALL=(ALL:ALL) ALL
  • 每行开头使用 username 或者 %groupname 指定这行规则所适用的用户或用户组;
  • 其后的第一个 ALL 意味着这条规则适用于所有 host;
  • 括号内的两个 ALL 指示了适用于这条规则的用户使用 sudo 命令时,可以使用所有的用户(user)以及所有的用户组(group)身份;
  • 最后一个 ALL 表明适用于这条规则的用户可以用 sudo 执行所有的命令。

因此要给某一用户,如 user0,添加 sudo 命令的权限,有两种方法:

  1. (不推荐)修改 /etc/sudoers 文件,在其中添加:

    user0    ALL=(ALL:ALL) ALL
    
  2. user0 用户加入 sudo 组(或 wheel 组)

    • 修改 /etc/groups 文件,找到 sudo 组所在的行,在最后添加 user0(若要添加多个用户,使用 , 分隔):
    sudo:x:27:user0
    
    • 或者直接执行如下命令:
    usermod -aG sudo user0