Linux 文件权限主要有以下几个:
ugo 基本权限
acl 权限
suid,sgid,sticky 高级权限
selinux
ugo 基本权限
一个文件对应三种权限对象, 分别文件的所有者 user, 所属组 group 和其他人 other
每个权限对象对应三种权限, 分别是读 r, 写 w 和执行 x
权限数字对应关系
权限名称 | 十进制 | 二进制 |
---|---|---|
r | 4 | 0100 |
w | 2 | 0010 |
x | 1 | 0001 |
这么设计的目的是 rwx 任意组合不会互相影响
相关操作举例
- $ touch file1
- $ ls -l file1
- -rw-r--r-- 1 root root 0 Jul 14 15:15 file1
- $ mkdir dir1
- drwxr-xr-x 1 root root 4096 Jul 14 15:15 dir1
默认的文件权限为 0644
默认的目录权限为 0755
之所以默认权限为这些, 是因为 umask 的值
$ umask 0022
umask 默认值为 0022, 则目录默认权限为 0777-0022=0755
而默认的文件权限在此基础上减去执行权限变为 0644
至于 0644,0755 前面的 0 是什么, 我们在高级权限中再介绍
umask 命令只能临时生效, 退出再登录后就又还原成默认的了, 如果想要永远生效, 可以更改 / etc/profile 或~/.bash_profile(没有则添加, 有则修改)
而 r,w,x 三种权限对于目录和文件所表示的意义也不同, 如下表
权限名称 | 文件 | 目录 |
---|---|---|
r | 可查看文件内容,如 cat file1 | 可列出目录内容,如 ls dir1 |
w | 可更改文件内容,如 echo 1 >> file1 | 可创建或删除目录中的文件 (对于无 x 权限的目录,w 权限无效) |
x | 可作为命令被执行 | 可进入目录,如 cd dir1; 可访问目录中的文件 (当然也要看文件的权限) |
权限更改
格式 1 chmod {权限对象}{赋值符号}{权限} {文件名}
其中 {权限对象} 可以是 u,g,o,a 中的一种, 分别代表所有者 user, 所属组 group, 其他人 other, 所有人 all
格式 2 chmod {权限数字} {文件名}
- $ chmod u+x file1
- $ chmod g+w,o-r,u=wrx file1
- $ chmod 755 file1
小思考:
对于 / root 目录中一个其他人有读取权限的文件, 新建一个用户, 能否查看该文件?
修改根目录权限为 777, 新建一个用户, 能否删除 / etc 目录?
acl 权限
上面的文件 file1,root 用户有 rw 权限, root 组用户和其他人有 r 权限, 此时, 我想让 tom 用户拥有 x 权限, 怎么办? 单凭 ugo 基本权限, 貌似不能实现这种操作, 这就要用到我们现在要说的 acl 权限了
acl 权限是对 ugo 基本权限的扩展, 用来实现对文件权限更精细的操控
查看 acl 权限
- $ getfacl file1
- # file: file1
- # owner: root
- # group: root
- user::rw-
- group::r--
- other::r--
此时没有 acl 权限
添加 acl 权限
- $ setfacl -m u:tom:x file1
- $ ls -l file1
- -rw-r-xr--+ 1 root root 0 Oct 12 23:10 file1
- $ getfacl file1
- # file: file1
- # owner: root
- # group: root
- user::rw-
- user:tom:--x
- group::r--
- mask::r-x
- other::r--
添加完 acl 权限后发现, ls -l 的结果有了变化:
其中所属组的权限变成了 rx, 而原来是 r, 权限 -rw-r-xr-- 后面多了个 +
先说 +, 表示该文件有 acl 扩展权限
此时 getfacl 查看 acl 权限发现, 较最初无 acl 权限时多了两行
- user:tom:--x
- mask::r-x
此时 ls -l 所展示的所属组处的 r-x 其实不是所属组的权限, 而是 mask 权限, 而什么又是 mask 权限呢?
mask 权限会随着新设置的 acl 的权限的变化而变化, 它是该文件所有 acl 权限和 group 权限的并集, 即此时 mask 的权限为 user:tom:--x 和 group::r-- 权限的并集 r-x; 如果再添加一条 acl 权限, 使 tony 组的用户有写入权限 setfacl -m g:jack:w, 则此时 mask 的权限为 rwx
mask 权限的作用是为了临时限制 acl 权限, 举例说明, 此时 file1 的详细权限为
- user::rw-
- user:tom:--x
- group::r--
- mask::r-x
- other::r--
假设此时不只有 tom 有 acl 权限, jack,andy 等人也有好多 acl 权限, 此时要临时降低他们的权限, 如何操作? 难道用 setfacl -b file1 命令删除所有 acl 权限, 如果用户多的话, 删完再一个个地添加, 这得多么麻烦呀! 此时只需要临时禁止 mask 权限便可
- $ setfacl -m m::- file1
- $ getfacl file1
- # file: file1
- # owner: root
- # group: root
- user::rw-
- user:tom:--x #effective:---
- group::r-- #effective:---
- mask::---
- other::r--
此时 tom 的有效权限是 '---', 因为 mask 权限掩盖了所有 acl 权限
但实际真这样么, 其实这里有个小问题, tom 用户对 file1 是有读权限的, 因为 mask 禁用所有权限后, tom 用户便重新属于了 other, 而 other 对 file1 是有读权限的
suid,sgid,sticky 高级权限
现在来说一说前面的权限数字, 0755,0664 中的 0 是什么意思; 这一位代表的便高级权限的数字, 0 表示没有高级权限, 1 代表 sticky(粘滞位),2 代表 sgid,4 代表 suid
suid
suid 只能作用于可执行的二进制文件上, 为什么?
suid 的作用是使执行该二进制程序的人拥有二进制文件所有者的权限
所以 suid 只能作用于可执行的文件
看例子:
- #### 当前为 root 账号
- $ ll file2
- -rw-r----- 1 root root 0 Oct 12 01:37 /root/file2
- #### 切换为 tom 账号
- $ cat file2
- cat: file2: Permission denied
- #### 查看 / etc/shadow 文件, 该文件用于存储用户密码
- $ ll /etc/shadow
- ---------- 1 root root 685 Oct 12 01:42 /etc/shadow
- #### 当前为 tom 用户, 修改密码操作
- $ passwd
- #### ...
- #### 最后发现在 tom 用户通过 passwd 密令更改了 / etc/shadow 文件
- #### 为什么 tom 能通过 passwd 命令修改对于 tom 没有 w 权限 / etc/shadow 文件
- #### 而 tom 不能通过 cat 命令查看对于 tom 没有 r 权限的 file2 文件
- $ ll /usr/bin/cat
- -rwxr-xr-x. 1 root root 54080 Nov 6 2016 /usr/bin/cat
- $ ll /usr/bin/passwd
- -rwsr-xr-x. 1 root root 27832 Jun 10 2014 /usr/bin/passwd
通过例子可以看出, passwd 命令与 cat 命令的区别在于 passwd 的权限是'-rwsr-xr-x', 而 cat 命令的权限是'-rwxr-xr-x', 这里 passwd 权限中原来所有者的 x 权限处变成了 s, 所以 tom 在通过 passwd 命令修改没有 w 权限的 / etc/shadow 时, 会自动拥有 / etc/shadow 文件所有者 root 的权限(虽然文件对于 root 也没有 w 权限, 但 root 用户有一切权限, 即使文件对 root 没有权限也无所谓)
guid
关于 sgid, 它有两个作用. 一个是同 suid 类似, 当 sgid 加在一个可执行的二进制文件时, 使执行该文件的用户拥有它的所属组的所有权限; 再一个就是, 如果 sgid 加在一个目录上, 则在该目录下创建的文件或目录的所属组和该目录一样, 且创建的目录也会自动加上 sgid
- $ ll dir2 -d
- drwx--s--- 4 root tom 32 Oct 15 22:16 dir2
- # dir2 权限为 2710, 即 0710 又加了个 sgid
- # 此时 umask 为 022, 默认值
- $ touch dir2/file1
- $ ll dir2
- -rw-r--r-- 1 root tom 0 Oct 15 22:20 file1
- $ mkdir dir2/dir21
- drwxr-sr-x 2 root tom 6 Oct 15 22:14 dir21
- # dir21 目录继承了 dir2 的 sgid 和所属组 tom
- $ umask 777
- $ mkdir dir2/dir22
- d-----S--- 2 root tom 17 Oct 15 22:16 dir22
- # dir22 目录继承了 dir2 的 sgid, 但由于 dir22 对于所属组没有 x 权限,
- # 所以代表 sgid 的 s 变成了大写的, 大写的 S 代表无效,
- # 另外, suid 加在对于所属主没有 x 权限的文件上也是大写的 S
- sticky
我们知道,/tmp 目录对于任何人都是可读可写可进入的, 根据前面 ugo 权限可知, 当一个目录对用户可写时, 用户可以随意删除移动目录内的文件
- $ ll /tmp/xxx.log
- -rw-r--r-- 1 root root 122 Sep 9 16:02 /tmp/xxx.log
- $ su - tom
- $ rm -f /tmp/xxx.log
- rm: cannot remove '/tmp/xxx.log': Operation not permitted
为什么 tom 不能删除对于 tom 可写的 / tmp 目录下的 xxx.log 文件呢?
- $ ll -d /tmp
- drwxrwxrwt. 33 root root 8192 Oct 15 22:46 /tmp/
可以看到 / tmp 的权限多了个 t, 这便是 sticky
sticky 的目的是让用户只能删除移动自己的文件, 对于不属于自己的文件, 没权限删除或移动
对于 sticky, 目录必须对 other 有 x 权限, 否则 t 变成大写, 无效, why?
想想也容易理解, 如果目录没有 x 权限, 那么就不能进入目录, 就更别提删除移动目录内的文件了, 此时要 sticky 权限又有何用
说明: 当使用 chmod 为文件或目录添加 suid 或 sgid 时, 只能是'chomd u+s/g+s file', 而不能是'chmod o+s file',o+s 加也加不上; 而给目录加 sticky 时, 也只能是'chmod o+t dir'; 给目录加 suid 和给文件加 sticky 都能加上, 但又有什么用呢? 没啥用
SELinux
selinux 是对标准 Linux 权限的增强
所有操作系统的访问控制都是以关联的客体和主体的某种类型的访问控制属性为基础的.
怎么理解这句话?
操作系统: 当然是 Linux 等操作系统
访问控制: 前面说的权限都可以说是访问控制
客体(object): 主要是指文件, 目录, 端口等
主体(subject): 主要是指进程
访问控制属性: 对应标准 Linux 权限的读写执行等权限, 而对应 selinux 则叫做安全上下文(Security Context)
举例来说, 主体进程 httpd 要访问一个客体网页文件 a.html 时, 在没有 selinux 的情况下, 需要看 a.HTML 的访问控制属性 (即读取执行权限) 是否对主体 httpd 进程开放
再看 selinux 的安全上下文是什么
- # 查看文件的安全上下文
- $ ll -Z /var/www/HTML
- -rw-r--r--. root root unconfined_u:object_r:admin_home_t:s0 a.HTML
- -rw-r--r--. root root unconfined_u:object_r:httpd_sys_content_t:s0 index.HTML
- # 查看进程的安全上下文
- $ ps -ZC httpd
- LABEL PID TTY TIME CMD
- system_u:system_r:httpd_t:s0 8083 ? 00:00:01 httpd
- system_u:system_r:httpd_t:s0 8094 ? 00:00:00 httpd
- # 查看端口安全上下文
- $ semanage port -l | egrep '\<80\>'
- http_port_t tcp 80, 81, 443, 488, 8008, 8009, 8443, 9000
这里主要说的是文件权限, 对于进程和端口安全上下文先不做说明
在开启 selinux 的前提下, httpd 服务器可以访问到 index.HTML, 而不能访问到 a.HTML(会报 403 错误). 为什么呢? 原因就在于其安全上下文上
a.HTML 的安全上下文: unconfined_u:object_r:admin_home_t:s0
index.HTML 的安全上下文: unconfined_u:object_r:httpd_sys_content_t:s0
以分号分隔的几种安全上下文分别代表: USER:ROLE:TYPE[LEVEL[:CATEGORY]]
在默认安全策略 targeted 中, USER 和 ROLE 对于文件几乎没什么影响, 主要是 TYPE, 这里 httpd 不能访问 a.HTML 的原因也是由于两个文件的 TYPE 不同
selinux 中有两种安全策略, targeted(常见的网络服务 httpd,vsftpde 受 selinux 控制)和 strict(每个进程都受 selinux 的控制, 这里主要说下 targeteda, 这也是默认的安全策略
修改文件安全上下文
- $ chcon -t httpd_sys_content_t /var/www/HTML/a.HTML
- $ ll -Z /var/www/HTML/a.HTML
- -rw-r--r--. root root unconfined_u:object_r:httpd_sys_content_t:s0 /var/www/HTML/a.HTML
selinux 安全上下文规则
- # 查看规则
- $ semanage fcontext -l | grep "/var/www/html"
- ...
- /var/www/HTML(/.*)? all files system_u:object_r:httpd_sys_content_t:s0
- ...
- # 添加规则(/var/www/HTML 目录的所有 PHP 文件安全上下文标签为 admin_home_t)
- $ semanage fcontext -a -t admin_home_t "/var/www/html/(.*\.php)"
- $ touch /var/www/HTML/1.PHP && ll -Z /var/www/HTML/1.PHP
- -rw-r--r--. root root unconfined_u:object_r:httpd_sys_content_t:s0 /var/www/HTML/1.PHP
- # 为什么新建的文件没有按照规则来生成 admin_home_t 标签的文件? 因为文件生成是是根据父目录来的
- # 如何让文件按照规则来改变安全上下文标签呢? 需要用到下面的命令: restorecon
- # 重置规则
- $ restorecon -RFv /var/www/HTML # 将该目录按照该目录内的所有规则重置安全上下文标签
- restorecon reset /var/www/HTML/1.PHP context unconfined_u:object_r:httpd_sys_content_t:s0->system_u:object_r:admin_home_t:s0
关于文件权限的 selinux, 就说到这里, selinux 还包括除文件外的其它内容, 如端口, 进程等, 以及其它细节方面的东西, 我自己也还有好多不明白的,
来源: https://www.cnblogs.com/MessiXiaoMo3334/p/11353565.html