对Linux的进程权限进行了一些总结。
本文是Linux系统下讨论。注意,Linux和Unix有很多不同的地方,并且各个不同的Unix系统也有很多不同。
本文讨论对象:
- ruid: real user id,即实际用户,也即当前登录的用户
- euid: effective user id, 即有效用户,也即以哪个用户身份来执行脚本
- suid: saved user id, 保存用户
- fuid: file system user id, 即文件系统用户
- s权限位: 即 set user ID bit,即除了rwx之外的那个s标志位
查看这几个uid有2种方式:
-
使用ps命令:
ps -ax -o ruid -o euid -o suid -o fuid -o pid -o fname
-
查看进程的status文件:
cat /proc/{pid}/status | grep Uid
另:
查看用户的uid、gid等,可以使用命令 id
普通场景下的uid情况
实验1:
首先,a.out程序属于用户test1和组test.
然后,su test1,作为test1用户。
然后,执行a.out程序。
此时,使用方法1观察,可见4个uid(ruid, euid, suid, fuid)全部为test1.
然后,su test2,作为test2用户。
再执行a.out程序。
再用方法1观察,可见4个uid全部都变成了test2.
结论1
在常见情况下,这4个uid等同于执行用户的uid,而和文件的owner无关。
关于权限出让的情况
实验2-1:出让权限给其他用户
注意:只有root用户才能出让权限给其他用户。
首先,a.out程序属于用户test1和组test;
但是,在a.out程序中,使用系统调用setuid()将uid设置为test2的uid.
然后,让root用户来执行此程序;
使用方法1观察,会发现4个uid都是 test2 的 uid
实验2-2:
和实验2-1基本一致,不同点在于,在a.out程序中,使用seteuid()系统调用将euid设置为test2的euid.
此时,用方法1观察,会发现:
ruid=root,euid=test2,suid=root,fuid=test2
结论2
- setuid和seteuid是有区别的:
setuid是永久放弃了root用户权限,转让给非root用户后,无法再收回;
seteuid只是临时放弃root用户权限,将来可通过seteuid(0)再回到root权限; - seteuid会同时改变euid和fuid都为所设置的euid的值;
- 只有root用户才能出让权限,即只有root用户才能调用setuid.
权限出让的常见场景,比如apache和mysql,启动的时候使用root用户启动,设置一些root用户才能操作的系统配置,而在创建子进程时通过setuid降级为nobody用户。
s权限位对进程权限的影响
实验3:
首先,a.out属于test1用户和test用户组;
然后,以test1用户的身份来运行 chmod u+s a.out
最后,使用root用户来运行a.out
使用方法1 ps命令来查看进程情况,会发现:
ruid=root,euid=suid=fuid=test1
s权限位最经典的案例是passwd命令:
-rwsr-xr-x 1 root root 45396 may 25 2012 /usr/bin/passwd
- 由上可见,user2有权限执行passwd
- 执行时,ruid仍是user2,而euid是root. 注意,ruid总是实际执行者的uid,而目前这个case下,euid是文件所有者的uid.
- user2之所以能够改变他自己的密码,是因为passwd内部会检查ruid是否是root,若不是,则其行为会局限于修改ruid的密码
- 让euid变成root是必须的,因为密码的改变必然要求写 /etc/shadow 文件,而该文件权限位是 640,即只有root能写,所以euid必须是root.
结论3
euid和ruid什么时候不一样呢?
只有一种情况:可执行文件设置了suid位,然后由非owner用户来执行;此时,ruid为执行者,而euid为owner.
对用户文件权限的影响
实验4:
在程序中 setfsuid({test2_uid}) , 然后调用fopen(“some file”, “a+”);
该程序执行结束后,使用 ls -l 会发现文件已经变成了属于test2的文件。
结论4
- 影响用户文件权限的是fuid,不是euid.
- fuid是Linux特有的属性,Unix系统是靠euid来判定用户权限。
进程权限的继承
结论5
- 当使用fork子进程的时候,子进程全部继承父进程4个uid
- 当使用exec系列函数时候,会把suid置为euid
参考文献
- http://blog.chinaunix.net/uid-27105712-id-3349522.html
- http://blog.csdn.net/nirendao/article/details/55549515