Skip to content

权限与归属 ​

Permission denied 几乎是新人第一周必遇到的错误。这一节把 ls -l 那串字符彻底拆开,再讲三个特殊位和 ACL。

一、读懂 ls -l ​

bash
ls -l /opt/app
text
-rwxr-x--- 1 app  app  20480 Oct 27 21:20 start.sh
drwxr-xr-x 2 app  app   4096 Oct 27 20:02 config
-rw-r--r-- 1 root root  1280 Oct 27 18:00 README.md
lrwxrwxrwx 1 app  app     12 Oct 27 19:00 logs -> /data/app/logs

逐位拆:

text
-  rwx  r-x  ---   1  app  app
│   │    │    │    │   │    │
│   │    │    │    │   │    └─ 所属组
│   │    │    │    │   └────── 属主
│   │    │    │    └────────── 硬链接数(目录表示子目录数+2)
│   │    │    └─────────────── 其他人 (other) 权限
│   │    └──────────────────── 所属组 (group) 权限
│   └───────────────────────── 属主 (user) 权限
└───────────────────────────── 类型:- 文件, d 目录, l 软链, s socket, p 管道, b/c 设备

权限位含义:

位文件目录
r读内容列出里面有哪些文件(ls)
w改内容在里面新建/删除/重命名文件
x执行进入目录(cd)、访问里面的文件

目录没有 x 就什么都做不了

只有 r 没有 x 的目录:能 ls 看到文件名,但读不了文件内容、也 cd 不进去。这是"权限看起来给了却还是打不开"的常见原因。

二、chmod ​

数字法:

text
r = 4    w = 2    x = 1
bash
chmod 644 app.conf      # rw-r--r--   普通文件
chmod 755 start.sh      # rwxr-xr-x   可执行文件/目录
chmod 600 id_rsa        # rw-------   私钥
chmod 640 app.env       # rw-r-----   配置(组内可读)

符号法:

bash
chmod u+x start.sh          # 属主加执行
chmod g-w,o-rwx secret      # 组去写、其他人全去
chmod a+r README.md         # 所有人可读
chmod -R g+r /data/shared   # 递归
chmod u=rwx,g=rx,o= dir     # 精确设置

X(大写)只给目录或已有执行位的文件加 x,适合递归:

bash
chmod -R a+rX /var/www       # 文件保持原样,目录都加 x

不要 chmod -R 777

777 意味着任何用户都能改、能删。把 web 目录设成 777,等于把上传目录变成提权入口(攻击者放一个 .php 进去直接执行)。

遇到权限问题正确的做法是:明确进程以哪个用户运行,然后只把该用户需要的权限给它。

三、chown ​

bash
chown app:app /opt/app -R
chown -R 10001:10001 /data/app
chgrp www-data /var/www

chown user 只改属主,chown user:group 同时改。chown :group 只改组。

容器场景经常用 UID:

bash
docker run --rm myapp:1.0.0 id
text
uid=10001(app) gid=10001(app) groups=10001(app)
bash
chown -R 10001:10001 /data/app/data

四、umask:新文件的默认权限 ​

bash
umask
text
0022

规则:文件默认 666 减 umask,目录默认 777 减 umask。

umask新文件新目录
022644755
002664775
077600700

002 适合团队共享目录(同组可写),077 适合私密目录。

bash
# 临时
umask 002

# 永久(当前用户)
echo 'umask 002' >> ~/.bashrc

五、三个特殊位 ​

SUID(4) ​

bash
ls -l /usr/bin/passwd
text
-rwsr-xr-x 1 root root 32688 ... /usr/bin/passwd

属主的 x 变成 s:任何用户执行它时,临时获得属主(root)的权限。passwd 靠这个改 /etc/shadow。

bash
chmod 4755 /path/to/binary     # 加 SUID
chmod u-s /path/to/binary      # 去 SUID

SUID 是提权面

给自定义脚本/程序加 SUID 前先想清楚:一旦程序有漏洞,攻击者直接拿到 root。查找系统里所有 SUID 文件:

bash
find / -perm -4000 -type f 2>/dev/null

SGID(2) ​

对文件:执行时临时获得属组权限(很少用)。 对目录:在目录里新建的文件,属组自动继承目录的组。

bash
chmod 2775 /data/shared
ls -ld /data/shared
text
drwxrwsr-x 2 root devteam 4096 Oct 27 21:24 /data/shared

团队共享目录的标准配置:chgrp devteam /data/shared && chmod 2775 /data/shared。

Sticky(1) ​

只对目录有效:目录里的文件只有属主(或 root)能删,即使其他人对该目录有写权限。

bash
ls -ld /tmp
text
drwxrwxrwt 15 root root 4096 Oct 27 21:25 /tmp

最后的 t 就是 sticky。/tmp 是 1777,人人都能建文件,但删不了别人的。

六、ACL:给单个用户开小灶 ​

普通权限只有"属主/组/其他"三档。要给某个特定用户单独开权限,用 ACL。

bash
getfacl /data/report
setfacl -m u:zhangsan:rx /data/report
setfacl -m g:analysts:r /data/report/*
text
# file: data/report
# owner: root
# group: root
user::rwx
user:zhangsan:r-x
group::r-x
group:analysts:r--
mask::r-x
other::r-x

递归与默认 ACL:

bash
# 递归加(目录也要 x)
setfacl -R -m u:zhangsan:rX /data/report

# 默认 ACL:以后在这个目录里新建的文件自动带这些权限
setfacl -d -m u:zhangsan:rw /data/report

# 删除某条
setfacl -x u:zhangsan /data/report

# 删除全部 ACL
setfacl -b /data/report

getfacl 输出里如果有个 +(ls -l 的权限串末尾),说明该文件有 ACL:

text
drwxr-x---+ 2 root root 4096 Oct 27 21:28 report

备份恢复会丢 ACL

cp -a / tar 默认不带 ACL。要保留:

bash
cp -a --preserve=all src dst
tar --acls --xattrs -czf backup.tar.gz dir/
getfacl -R /data > acl-backup.txt   # 单独备份 ACL
setfacl --restore=acl-backup.txt

七、常见目录该给什么权限 ​

场景目录文件
Web 静态资源755644
上传目录(进程可写)755 属主为应用用户进程创建的文件 644
团队共享(同组可写)2775 + 属组664
临时交换目录1777—
私钥、密钥文件700(目录)600
配置文件含密码750640

八、踩过的坑 ​

现象根因处置
Permission denied 但权限看着是 r父目录缺 x给路径上每级目录补 x
sudo 能跑、普通用户不行文件属主/组不对chown 成运行用户
新文件组不对缺 SGIDchmod 2775 目录
别人能删我的文件目录是 777 无 stickychmod 1777
容器写不了挂载目录容器 UID 与宿主不匹配chown 成容器内 UID
chmod -R 777 后漏洞被利用过度授权收敛到最小权限
ACL 生效了但 cp 后丢了cp 不带 ACLcp -a --preserve=all
SELinux 下仍报权限安全上下文不对ls -Z、restorecon、挂载加 :z