第19章:特殊权限与 ACL

第十九章:特殊权限与 ACL

恭喜你!如果你能坚持到这里,说明你对Linux权限已经有相当的了解了。

但Linux的权限系统还有"隐藏关卡"——特殊权限ACL(访问控制列表)

普通权限只能控制"所有者、所属组、其他人"三类人,但如果我想让张三有读写权限,李四只有读权限,王五完全没权限呢?普通权限做不到,这就需要ACL出场了。

而特殊权限——SUID、SGID、Sticky Bit——则是一些"魔法权限",能让普通用户干一些平时干不了的事。

这一章,让我们一起揭开这些"隐藏技能"!


19.1 SUID 特殊权限(4):让普通用户执行 root 权限

SUID的全称是Set User ID,也叫Set-UID。

它的作用是什么?

当一个可执行文件设置了SUID权限后,任何运行这个程序的用户,都会以该文件所有者的身份运行它

这听起来有点绕,让我举个例子:

1
2
3
4
5
6
7
8
9
# /usr/bin/passwd 命令的所有者是root
# 而且它设置了SUID权限

# 意味着:
# 普通用户longx运行passwd时
# 不是以longx的身份运行
# 而是以root的身份运行!

# 这样longx才能修改/etc/shadow(这个文件只有root能写)

19.1.1 典型例子:/usr/bin/passwd

1
2
3
4
5
6
7
# 查看passwd命令的权限
ls -l /usr/bin/passwd

# 输出:
# -rwsr-xr-x 1 root root ... /usr/bin/passwd
#       ^
#       注意这个s!这就是SUID的标志

正常情况下,普通用户不能修改/etc/shadow(因为只有root能写)。但passwd命令需要让普通用户能够修改自己的密码,怎么办?给它设置SUID!

设置了SUID后,运行passwd的任何人,都会暂时"变成"root,当然就能修改shadow文件了。

19.1.2 设置:chmod 4755 文件

1
2
3
4
5
6
7
8
9
# 设置SUID
# 4 = SUID
# 755 = rwxr-xr-x(普通权限)
# 所以4755 = SUID + rwxr-xr-x

chmod 4755 /path/to/file

# 或者用符号方式:
chmod u+s /path/to/file
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# 查看SUID是否设置
ls -l /path/to/file

# 如果有SUID:
# -rwsr-xr-x  ... file
#    ^
#    s 表示SUID+执行权限

# 如果没有执行权限但有SUID:
# -rwSr-xr-x  ... file
#    ^
#    S 表示SUID但没有执行权限(无效状态)

SUID的注意事项

1
2
3
4
5
6
7
8
9
# 危险的SUID示例:
chmod 4755 /bin/bash
# 这会让任何人运行bash都以root身份运行!
# 相当于给所有人开了个root后门!
# 绝对不要这么做!

# 正确的做法:
# SUID只应该用于确实需要的程序(如passwd)
# 不应该用于shell、编辑器等
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# 查看系统里所有设置了SUID的文件
sudo find / -perm -4000 -type f 2>/dev/null

# 输出大概是:
# -rwsr-xr-x 1 root root /usr/bin/passwd
# -rwsr-xr-x 1 root root /usr/bin/sudo
# -rwsr-xr-x 1 root root /usr/bin/newgrp
# -rwsr-xr-x 1 root root /usr/bin/gpasswd
# -rwsr-xr-x 1 root root /usr/bin/mount
# -rwsr-xr-x 1 root root /usr/bin/umount

19.2 SGID 特殊权限(2):目录内文件继承组

SGID的全称是Set Group ID,也叫Set-GID。

它的作用是什么?

SGID对文件和目录有不同的效果:

  • 对文件:类似SUID,但以文件所属组的身份运行
  • 对目录:在该目录内创建的文件,会自动继承该目录的所属组

19.2.1 典型例子:/usr/bin/mlocate

1
2
3
4
5
6
7
# mlocate数据库查询工具
ls -l /usr/bin/mlocate

# 输出:
# -r-xr-s 1 root mlocate ... /usr/bin/mlocate
#        ^
#        s 表示SGID

19.2.2 目录继承组:协作目录的最佳实践

SGID在目录上非常有用!假设一个团队在共享目录里工作:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
# 场景:公司有一个共享项目目录/workspace
# 所有开发人员都属于developers组
# 团队希望所有新创建的文件都自动属于developers组

# 1. 创建共享目录
sudo mkdir /workspace

# 2. 设置目录所属组为developers
sudo chown :developers /workspace

# 3. 设置SGID,这样目录下创建的文件都自动属于developers组
sudo chmod 2775 /workspace
#       ^^
#       2 = SGID

# 4. 给开发者们设置权限
sudo chmod 770 /workspace
# 或者让所有developers组的人都能访问
sudo chmod 770 /workspace
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
# 现在验证一下SGID的效果
cd /workspace

# longx创建一个文件
touch project.txt

# 查看文件权限
ls -l project.txt

# 输出:
# -rw-r--r-- 1 longx developers ... project.txt
#              ^^^^^^^^^^
#              自动继承了目录的组!
1
2
3
# 设置SGID的命令
chmod 2775 /directory    # 2 = SGID
chmod g+s /directory      # 符号方式
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# 查看SGID
ls -ld /directory

# 如果有SGID:
# drwxrwsr-x ... directory
#      ^
#      s 表示SGID+执行权限

# 如果有执行权限但没s(无效):
# drwxr-Sr-x ... directory

19.3 Sticky Bit 粘滞位(1):只能删除自己的文件

Sticky Bit,也叫粘滞位。

它的作用是什么?

设置了Sticky Bit的目录,在该目录里,只有文件所有者才能删除自己的文件

这听起来有点绕?为什么需要这个?

19.3.1 典型例子:/tmp

1
2
3
4
5
6
7
# /tmp目录大家都能用,但谁也不能删别人的文件
ls -ld /tmp

# 输出:
# drwxrwxrwt 8 root root ... /tmp
#        ^
#        t 就是Sticky Bit的标志

/tmp目录是公共目录,所有人都在里面创建文件。如果不设置Sticky Bit:

  • 假设我是张三,我创建了/tmp/zhangsan.txt
  • 李四跑过来一看不顺眼,给我删了

这多可怕!设置Sticky Bit后:

  • 只能删除自己的文件
  • 别人的文件?对不起,删不了

19.3.2 设置:chmod 1777 目录

1
2
3
4
5
6
7
# 设置Sticky Bit
chmod 1777 /public_directory
#     ^
#     1 = Sticky Bit

# 或者用符号方式:
chmod +t /public_directory
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# 查看Sticky Bit
ls -ld /public_directory

# 如果有Sticky Bit:
# drwxrwxrwt ... /public_directory
#        ^
#        t 表示Sticky Bit+执行权限

# 如果有执行权限但没t(无效):
# drwxrwxr-T ... /public_directory

📊 三种特殊权限对比

graph LR
    A["特殊权限"] --> B["SUID (4)<br/>以所有者身份运行"]
    A --> C["SGID (2)<br/>以所属组身份运行<br/>或目录内文件继承组"]
    A --> D["Sticky Bit (1)<br/>目录内只能删自己的文件"]
    
    B --> E["典型例子<br/>/usr/bin/passwd"]
    C --> F["典型例子<br/>/workspace共享目录"]
    D --> G["典型例子<br/>/tmp"]
    
    style B fill:#ff6b6b
    style C fill:#ffd93d
    style D fill:#51cf66

19.4 查看特殊权限:ls -l 第四位字符

ls -l查看文件权限时,特殊权限会显示在第四位:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
# 普通权限
ls -l file.txt
# -rw-r--r-- ... file.txt

# SUID(所有者执行位变s)
ls -l /usr/bin/passwd
# -rwsr-xr-x ... /usr/bin/passwd
#    ^

# SGID(所属组执行位变s)
ls -ld /workspace
# drwxrwsr-x ... /workspace
#     ^

# Sticky Bit(其他人执行位变t)
ls -ld /tmp
# drwxrwxrwt ... /tmp
#       ^
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# 权限位对照表:
#          SUID    SGID    Sticky
# 文件:  -rwSrwSrwx  (无效状态,有SUID/SGID但没有执行位)
#        -rwsr-xr-x    (SUID有效)
#        -rwxr-sr-x    (SGID有效)
#        -rwsr-xr-t    (SUID+Sticky有效)
#
# 目录:  drwxr-Sr-x    (无效状态)
#        drwxrwsr-x     (SGID有效)
#        drwxrwxrwt     (Sticky有效)
#        drwxrwsrwt     (SGID+Sticky有效)

19.5 设置特殊权限:chmod 4755

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
# 完整格式:特殊权限 + 普通权限
# chmod [特殊权限][所有者][所属组][其他人] 文件

# SUID (4) + rwxr-xr-x (755) = 4755
chmod 4755 myapp

# SGID (2) + rwxrwxr-x (775) = 2775
chmod 2775 shared_dir

# Sticky Bit (1) + rwxrwxrwx (777) = 1777
chmod 1777 /tmp

# 组合:SGID + Sticky Bit + rwxrwxr-x = 3775
chmod 3775 shared_dir
1
2
3
4
5
6
7
8
# 也可以分开设置
chmod u+s file    # 添加SUID
chmod g+s dir     # 添加SGID
chmod +t dir      # 添加Sticky Bit

chmod u-s file    # 移除SUID
chmod g-s dir     # 移除SGID
chmod -t dir      # 移除Sticky Bit

19.6 ACL 访问控制列表:更细粒度的权限

ACL(Access Control List)可以给文件设置"例外权限"——除了所有者、所属组、其他人之外,还能单独给某个特定用户或组设置权限。

为什么需要ACL?

普通权限只能控制三类人,但现实更复杂:

1
2
3
4
5
6
7
# 场景:
# 文件属于root:root,权限是640(root读写,组只读,其他人无权限)

# 但是!张三需要读写这个文件
# 普通权限做不到!

# 解决方案:ACL!

19.6.1 getfacl 文件:查看 ACL

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# 查看文件的ACL
getfacl myfile.txt

# 输出大概是:
# # file: myfile.txt
# # owner: root
# # group: root
# user::rw-
# group::r--
# other::---

这就是默认的ACL(没有额外设置)。现在给张三添加读写权限:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
# 1. 给用户zhangsan添加读写权限
setfacl -m u:zhangsan:rw myfile.txt

# 2. 再查看ACL
getfacl myfile.txt

# 输出:
# # file: myfile.txt
# # owner: root
# # group: root
# user::rw-
# user:zhangsan:rw-         # 新增的!
# group::r--
# mask::rw-                  # ACL掩码
# other::---

19.6.2 setfacl -m u:用户:权限 文件

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# 格式:setfacl -m [u:用户:g:组]:权限 文件

# 给用户设置权限
setfacl -m u:username:rwx file

# 给组设置权限
setfacl -m g:groupname:rx file

# 同时设置多个ACL规则
setfacl -m u:zhangsan:rw,g:developers:r,o::- file
#           用户      组           其他
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 实战例子
# 文件属于root:root,权限644
# 现在需要:
# - zhangsan:读写
# - lisi:只读
# - developers组:读写

sudo setfacl -m u:zhangsan:rw /shared.txt
sudo setfacl -m u:lisi:r /shared.txt
sudo setfacl -m g:developers:rw /shared.txt

# 验证
getfacl /shared.txt

# 输出:
# # file: shared.txt
# # owner: root
# # group: root
# user::rw-
# user:zhangsan:rw-
# user:lisi:r--
# group::r--
# group:developers:rw-
# mask::rw-
# other::---
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
# 设置目录的默认ACL(该目录内新建的文件自动继承这个ACL)
setfacl -m d:u:zhangsan:rw /workspace

# 查看带默认ACL的目录
getfacl /workspace

# 输出:
# # file: workspace
# user::rwx
# group::r-x
# other::r-x
# default:user::rwx
# default:user:zhangsan:rw-
# default:group::r-x
# default:mask::rwx
# default:other::r-x

ACL权限的删除

1
2
3
4
5
6
7
8
# 删除某个用户的ACL
setfacl -x u:zhangsan /shared.txt

# 删除某个组的ACL
setfacl -x g:developers /shared.txt

# 删除所有ACL
setfacl -b /shared.txt

ACL掩码(mask)

1
2
3
4
5
6
7
# ACL有一个"掩码",会限制所有ACL条目的最大权限
# 查看掩码
getfacl file | grep mask

# 设置掩码
setfacl -m m::rx file
# 这会把所有用户和组的ACL权限限制在r-x范围内

19.7 lsattr 查看文件属性

lsattr可以查看文件的特殊属性(不是权限!是属性!)。

1
2
3
4
5
# 查看文件的属性
lsattr myfile.txt

# 输出:
# -------------e-- myfile.txt

属性位说明:

属性含义
a只能追加(append only),只能写入,不能删除或覆盖
A不更新访问时间(atime)
c自动压缩后存储
i不可修改(immutable),不能删除、不能重命名、不能修改
j数据写入前先记录到日志(ext3/4)
s安全删除(文件删除时,内容被零填充)

19.8 chattr 修改文件属性

chattr用来修改文件的特殊属性。

19.8.1 chattr +i 文件:不可修改

1
2
3
4
5
6
7
8
9
# 设置i属性:文件不可修改(连root都不能删改)
sudo chattr +i /etc/passwd

# 尝试删除或修改
rm /etc/passwd
# rm: cannot remove '/etc/passwd': Operation not permitted

# 移除i属性
sudo chattr -i /etc/passwd

19.8.2 chattr +a 文件:只能追加

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# 设置a属性:只能追加,不能覆盖或删除
sudo chattr +a /var/log/mylog.log

# 可以追加内容
echo "new log entry" >> /var/log/mylog.log

# 但不能覆盖
echo "overwrite" > /var/log/mylog.log
# bash: /var/log/mylog.log: Operation not permitted

# 移除a属性
sudo chattr -a /var/log/mylog.log

常用场景

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
# 1. 保护系统配置文件
sudo chattr +i /etc/passwd
sudo chattr +i /etc/shadow
sudo chattr +i /etc/group

# 2. 日志文件只允许追加(防止被篡改)
sudo chattr +a /var/log/auth.log

# 3. 保护重要的日志文件(即使root也删不了)
sudo chattr +i /var/log/syslog

# 4. 查看所有设置了i属性的文件
sudo find / -attr +i 2>/dev/null
1
2
3
4
5
# chattr的属性对照表
chattr +i file    # 不可删除、不可修改(完全锁死)
chattr +a file    # 只能追加、不能覆盖
chattr +s file    # 安全删除(删除时内容清零)
chattr +u file    # 恢复删除(如果文件系统支持)

📊 特殊权限与 ACL 速查表

graph TD
    A["特殊权限"] --> B["SUID (4)<br/>chmod 4755<br/>运行时效仿所有者"]
    A --> C["SGID (2)<br/>chmod 2775<br/>运行时效仿所属组<br/>目录内文件继承组"]
    A --> D["Sticky Bit (1)<br/>chmod 1777<br/>目录内只能删自己的"]
    
    E["ACL"] --> F["getfacl<br/>查看ACL"]
    E --> G["setfacl -m<br/>设置ACL"]
    E --> H["setfacl -x<br/>删除ACL"]
    
    I["文件属性"] --> J["chattr +i<br/>不可修改"]
    I --> K["chattr +a<br/>只能追加"]
    
    style B fill:#ff6b6b
    style C fill:#ffd93d
    style D fill:#51cf66
    style E fill:#74b9ff

本章小结

本章我们学习了Linux的特殊权限和ACL:

🔑 核心知识点

  1. SUID(Set User ID)

    • 数值:4
    • 作用:任何用户运行该程序,都以文件所有者的身份运行
    • 典型例子:/usr/bin/passwd
    • 设置:chmod 4755 file
  2. SGID(Set Group ID)

    • 数值:2
    • 作用:对文件是以所属组身份运行,对目录是新建文件继承目录组
    • 设置:chmod 2775 directory
  3. Sticky Bit(粘滞位)

    • 数值:1
    • 作用:目录内每个用户只能删除自己的文件
    • 典型例子:/tmp
    • 设置:chmod 1777 directory
  4. ACL(访问控制列表)

    • 作用:给特定用户或组设置"例外权限"
    • getfacl file:查看ACL
    • setfacl -m u:user:rw file:添加用户ACL
    • setfacl -x u:user file:删除用户ACL
  5. 文件属性(chattr)

    • chattr +i:不可修改(连root也挡不住)
    • chattr +a:只能追加

💡 记住这个原则

特殊权限是双刃剑——用得好是神器,用不好是灾难。SUID/SGID不要滥用,Sticky Bit是共享目录的好帮手,ACL是细粒度权限的终极解决方案。


当前时间:2026年3月23日 20:42:03 已完成"第十九章"!🎉

最后修改 March 24, 2026: 新增JavaScript教程 (37305c4)