上文我们提到过, Linux操作系统会使用用户和用户组来关联登陆用户的信息, 因为Linux操作系统是多用户的系统, 因此进程的权限也非常重要, 本文将介绍, 操作系统是如何管理进程的权限的. 每个进程都关联着一组数值型的用户标识符和组标识符, 这里和文件是一样的,这些标识符有时也被称为进程凭证。具体包括:实际用户ID与实际组ID, 有效用户ID与有效组ID, 保存的设置用户ID与保存的设置组ID;实际用户ID(RUID)与实际组ID
实际用户ID与组ID用于标识进程所属的用户和组, 这是启动进程的用户ID。它标识了进程的真正所有者,通常不会改变. 实际用户ID用于记录谁启动了进程, 当后面进程修改了有效用户ID的时候, 也还有实际用户ID(RUID)记录了该进程的启动用户的相关信息.有效用户ID(EUID)与有效组ID
有效用户ID与有效组ID应用于内核检查文件/资源访问, 决定了进程尝试执行各种操作(即系统调用)时被授予的权限。若进程的有效用户ID为0(即root用户的ID),则拥有超级用户的所有权限。这样的进程被称为root进程。某些系统调用只能由root进程执行。通常情况下,有效用户ID和有效组ID与对应的实际ID值相同,但是也有方式可以修改有效用户ID. 为什么需要用到EUID, 而不是直接使用RUID来鉴权就可以了呢? 对于大部分的程序, RUID和EUID一样, 两者均为可执行文件的拥有者和执行者, 但是一些由于安全性需要保密的文件访问, 就需要跨越权限来进行操作了. 例如当需要修改用户的密码时, 对应存储密码文件的内容只有root用户可以访问. 对应于passwd程序, 其创建者是root, 但是所有的用户都可以执行该文件, 但是在需要以root权限执行某个系统调用的时候, passwd程序会在这个地方提升权限, 系统调用执行完毕之后, 再降低权限, 保证程序的正常执行.which passwd/usr/bin/passwdls -al /usr/bin/passwd-rwxr-xr-x 1 root wheel 172608 9 2 2023 /usr/bin/passwd
设置用户ID和设置用户组
设置用户ID程序允许进程通过将其有效用户ID设置为与可执行文件的用户ID(所有者)相同的值,从而获得其通常不具备的权限。设置用户组程序则为进程的有效组ID执行类似的功能(术语“set-user-ID 程序”和“set-group-ID 程序”有时缩写为 set-UID 程序和 set-GID 程序)。 与任何其他文件一样,可执行程序文件也有关联的用户ID和组ID,用于定义文件的所有权。此外,可执行文件还有两个特殊的权限位:set-user-ID 位和 set-group-ID 位。这两个权限位可以通过 chmod 命令进行设置。非root 用户可以为自己拥有的文件设置这些位,而root用户可以为任何文件设置这些位。 这里是不是有点混乱了? 上面只提到了有EUID, 怎么这里又多了一个set-UID呢? 注意, set-user-id是文件的一个属性,而EUID是进程的一个属性, set-user-id位只在执行时影响进程的EUID. 简单而言, 就是其是一个文件的属性, 设置与否会影响进程刚执行时候的EUID值, 就这么简单, 下面举例一个例子看下: 文件有如下的信息, 该可执行文件check_id的owner为root用户, 程序仅仅打印出RUID和EUID. 第一次执行的时候, EUID为501, 对应的就是用户yang. 下面使用chmod u+s命令打开文件的设置用户ID位, 再次以yang用户执行, 其EUID就变成了文件的所有者root了. 注意看下权限的第三位由x变成了s.#include "../tlpi.h"int main() { printf("UID = %d, GID = %d\n", getuid(), geteuid()); return 0;}yang@yangdeMacBook-Pro chap9 % ls -al check_id-rwxr-xr-x@ 1 root wheel 52680 1 25 13:26 check_idyang@yangdeMacBook-Pro chap9 % ./check_idUID = 501, GID = 501// 打开文件的设置用户ID位yang@yangdeMacBook-Pro chap9 % sudo chmod u+s check_idPassword:yang@yangdeMacBook-Pro chap9 % ls -al check_id-rwsr-xr-x@ 1 root wheel 52680 1 25 13:26 check_id./check_idUID = 501, GID = 0
这里就是为什么很多系统的软件owner是root用户, 但是普通用户执行, 也可以短暂执行root用户才能获取到的信息/执行的操作的秘密.保存的设置用户ID与保存的设置组ID
保存的设置用户ID和保存的设置组ID是为配合 set-user-ID 和 set-group-ID 程序而设计的。当执行一个程序时,会发生以下步骤: 如果可执行文件启用了 set-user-ID权限位,则进程的有效用户ID 将被设置为与可执行文件所有者相同。如果未设置 set-user-ID位,则进程的有效用户ID 保持不变。 保存的设置用户ID 和 保存的设置组ID 的值会从相应的有效ID中复制。无论被执行文件是否设置了 set-user-ID 或 set-group-ID 位,都会发生此复制操作。 多种系统调用允许一个 set-user-ID 程序在其实际用户ID 和 保存的设置用户ID 这两个值之间切换其有效用户ID。通过这种方式,程序可以临时放弃和重新获得与被执行文件的用户ID 相关联的任何root(换句话说,程序可以在“潜在拥有root”和“实际以root运行”这两种状态之间切换)。一个安全的编程实践是:当 set-user-ID 和 set-group-ID 程序实际上不需要执行任何与root(即保存的设置ID)相关联的操作时,应始终在非root(即实际)ID 下运行。 saved set-user-ID通常用于权限恢复, 它本身不会影响进程的权限, 在用户调用setuid设置了RUID之后, 可以通过此处的saved set-user-ID来进行权限的恢复.相对应的系统调用