Linux 文件访问权限

1 影响进程访问文件的几个因素

  • 进程的 有效用户ID
  • 进程的 有效用户组ID
  • 进程的 附加组ID
  • 进程的 保存的设置用户ID
  • 进程的 保存的设置用户组ID
  • 文件的 读写执行字段
  • 文件是否设置了 设置用户ID位(set user id bit)
  • 文件是否设置了 设置用户组ID位(set group id bit)
  • 文件的 拥有者
  • 文件的 所属组

其中,前五个是与进程相关,后面的几个是与文件相关。

2 文件的读写执行字段以及设置用户 ID 位和设置用户组 ID 位

详见 《Linux学习笔记(二)》

3 文件的拥有者和文件的所属组

详见 《Linux学习笔记(二)》

4 进程的几个相关 ID

一般情况下,打开 登录shell 或者 非登录shell 后,shell 进程的 实际用户ID 和 有效用户ID 为 登录用户ID,实际用户组ID 和 有效用户组ID 为登录用户的 主组ID,附加组ID 为 登录用户的 附加组ID,保存的设置用户ID 和 保存的设置用户组ID 也分别为 登录用户ID 和 登录用户的 主组ID。

可以通过如下命令查看 当前shell进程 的所有 ID: id

如果 实际用户ID 与 有效用户ID 相同,则仅显示 实际用户ID。如果 实际用户组ID 与 有效用户组ID 相同,则仅显示 实际用户组ID。

另外,fork 得到的子进程会继承父进程的所有 ID

4.1 进程的 实际用户ID 与进程的 实际用户组ID

当在某个子进程中用 exec 函数执行一个可执行文件时,这个执行后的子进程的 实际用户ID 以及实际用户组 ID 会分别 继承 执行前的子进程的 实际用户ID 以及 实际用户组ID。

对于普通用户,在进程的执行过程中一般不会变,即为登录用户 ID 以及对应的 主组ID。但对于 root 用户,在进程的执行过程中可以通过 setuid 函数以及 setgid 函数改变。

需要指出的是,进程访问文件时与进程的 有效用户ID,有效用户组ID,附加组ID 有关,与 实际用户ID,实际用户组ID 无关。

4.2 进程的 有效用户ID 与进程的 有效用户组ID

当在某个子进程中用 exec 函数执行一个可执行文件时,如果这个外部命令或者可执行文件没有设置 设置用户ID位(set user id bit),则这个执行后的子进程的 有效用户ID 以及有效用户组 ID 会分别 继承 执行前的子进程的 有效用户ID 以及 有效用户组ID。

但是,若设置了 设置用户ID位(set user id bit)时,当用 exec 函数执行这个可执行文件时,exec 函数会将建立的进程的 有效用户ID 变为这个文件的所有者。

同样,当一个文件设置了 设置用户组ID位(set group id bit),那么 exec 函数会将建立的进程的 有效用户组ID 变为这个文件的所属主组。

4.3 进程的 附加组ID

当用 exec 函数执行可执行文件时,执行后的子进程的 附加组ID 会 继承 执行前的子进程的 附加组ID。

4.4 进程的 保存的设置用户ID 与进程的 保存的设置用户组ID

用 exec 函数执行一个可执行文件时,当获得了 最终的 有效用户ID 和 有效用户组ID 后(也即在判定是否因设置了 set user id bit 和 set group id bit 而对 有效用户ID 和 有效用户组ID 做出改变之后),exec 函数会自动保存这个子进程的 有效用户ID 和 有效用户组ID,也即分别为 保存的设置用户ID保存的设置用户组ID

由于在进程执行期间,可能会因为某些需要,通过 setuid 函数或者 setgid 函数改变这个进程的 有效用户ID 或者 有效用户组ID。当完成了这些需求之后,需要将这个进程的 有效用户ID 或者 有效用户组ID 更改(仍然通过这两个函数)为改变之前的 有效用户ID 或者 有效用户组ID。这个时候,就需要用到 保存的设置用户ID 以及 保存的设置用户组ID 了。

5 改变这三个 用户ID 以及三个 用户组ID 的方法

当用 exec 函数建立进程的时候可能会改变 有效用户ID 或 有效用户组ID(根据 set user bit 和 set group bit 的设置情况)。而在进程执行中,可以通过 setuid 或者 setgid 来改变 实际用户ID,有效用户ID,保存的设置用户ID 或者 实际用户组ID,有效用户组ID,保存的设置用户组ID。

改变这三个 用户ID 的方法如下图所示: 改变用户ID.png-374.4kB

改变三个 用户组ID 的方法类似(用 exec 函数 和 setgid 函数)。

6 进程操作文件时的权限验证过程

  • 若进程的 有效用户ID 为 root,则表示拥有了所有权限,完全可以操作这个文件;
  • 否则。若进程的 有效用户ID 与所要操作的文件的拥有者相同,则进一步查看第一个读写执行字段中的相应位是否被设置。如果未被设置,则操作失败;
  • 若进程的 有效用户ID 与所要操作的文件的拥有者不同,那么检查这个进程的 有效用户组ID 或者 附加组ID 之一是否与文件的所属主组相同。若相同,则进一步查看第二个读写执行字段中的相应位是否被设置。若未被设置,则操作失败;
  • 若进程的 有效用户组ID 以及 附加组ID 均与文件的所属主组不同,那么该进程的 有效用户ID 就属于这个文件的其他用户了,检查这第三个读写执行字段中的相应位是否被设置。如果未被设置,则操作失败。

进程在用 exec 函数执行某个可执行文件时,也有同样的验证过程。

7 目录文件的权限

  • 如果要在目录中新建一个文件或者删除一个文件,则要求具有写权限。
  • 如果要列出该目录下的文件,则要求具有读权限。
  • 如果要通过路径搜索某个文件,而该目录位于这个路径之中,则要求这个目录具有执行权限。

Reference