每个进程都有一组关联的ID:
Real user id and group id
Effective user id and group id
saved set-user-id and saved set-group-id
filesystem user id and group id
supplementary group IDs
表明了进程所属的用户和组。比如登录过程中,登录shell从/etc/passwd获取用户uid和组gid。这个ID是从父亲继承过来的。
effective user id 和 effective group id决定了进程的权限,通常euid和uid相同的,但是euid可以修改成不同。
euid为0的进程具有所有的权限。
Linux中的文件有两个特殊属性,set-user-id和set-group-id属性。通过
chmod u+s <file>
chmod g+s <file>
来设置这两个属性。
当执行具有set-user-id属性的可执行文件时,新创建进程的effective user id是文件owner的用户id。effective group id是文件owner的组id。
这提供了一种让普通用户运行root权限进程的方法。
当进程初始创建时,saved set-user-id等于effective user id,但是通过修改id的接口,后续可能不同。saved set-user-id存储了一个之前的user id,unprivileged用户,只能切换到real user id和saved set-user-id。
总结:
fork的时候,real user id,effective user id和saved set-user-id继承自父进程。execv的时候如果没有有set-user-id属性,则UID和EUID不变。如果有,则EUID等于文件owner的UID。execv之后saved set-user-id始终等于EUID。
访问文件时基于fsuid检查的,但是通常情况下fsuid等于euid,除非调用setfsuid来显式的修改fsuid。
进程可以属于多个组,具有所有这些组的访问权限。补充组ID可以读取和添加。
相关接口如下
getuid() getgid() | 读取real user/group id |
geteuid() getegid() | 读取effective user/group id |
setuid() setgid() | unprivileged user:修改effective user/group id,且只能改为ruid/euid/suid中的一个,修改为其它的uid,将报EPERM错误。 privileged user:可以改为任何值,且会同时修改ruid/euid/suid为设置的id。 |
seteuid() setegid() | 和setuid相同,不过不会修改ruid和suid。 |
setreuid(ruid, euid) setregid() | 如果指定-1,则不修改。 对于unprivileged user: ruid只能修改为之前的ruid和euid。 euid只能修改为之前的ruid/euid/suid。 如果下列情况之一发生,suid修改成和新的euid相同: ruid不是-1。 euid修改成不是之前的ruid的值。 |
setresuid(ruid, euid, suid) setresgid() | 修改ruid/euid/suid |
getresuid() getresgid() | 读取ruid/euid/suid |
setfsuid() setfsgid() | 修改fsuid |
getgroups(size, groups) | 读取补充组id |
setgroups() initgroups() | 前者设置补充组id 后者从/etc/groups设置补充组id |