liunx 用户 ID
组 ID 同 用户 ID,不多赘述。
实际用户 ID(real user ID)
当前用户登录 shell 时所使用的的用户 ID。
有效用户 ID(effective user ID)
有效用户 ID 用于一些系统调用权限的判断,比如,文件读/写。(在 linux 上文件打开权限另外算的,要判断文件系统用户 ID)
- 一般情形:
用户启动进程,自动设置有效用户 ID = 实际用户 ID
- 可执行文件设置了 set-user-ID 位:
可执行文件指 linux 下为
ELF
格式的可执行文件,不含类似 bash 可执行文件,可以使用file filename
查看文件的类型。$ file shell_test/test shell_test/test: Bourne-Again shell script, ASCII text executable $ file /usr/bin/passwd /usr/bin/passwd: setuid ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=191e5ed22855b6344cf01659f8ae7b7cf4767798, for GNU/Linux 3.2.0, stripped
set-user-ID 位可使用
chmod
命令设置,设置之后,启动该可执行文件,有效用户 ID 为该文件的属主,比如:文件A属于用户甲,设置了 set-user-ID 位,用户乙执行文件A,对应进程的有效用户 ID 是乙。# 设置 set-user-ID 位前观察 $ ls -l copy -rwxrwxr-x 1 XXX XXX 28200 Jun 4 19:46 copy # 设置 set-user-ID 位 $ chmod u+s copy # 设置 set-user-ID 位后观察 # 用户的可执行权限位,由 x 变为 s $ ls -l copy -rwsrwxr-x 1 XXX XXX 28200 Jun 4 19:46 copy
- tlpi 的 9.7 节介绍的系统调用可以改变有效用户 ID。
保存的 set-user-ID(saved set-user-ID)
最开始有效用户 ID 的副本。进程开始执行会先根据,set-user-ID 位确认有效用户 ID,再将之保存为 saved set-user-ID
。进程执行过程中,有效用户 ID 可能改变(前面有提及),saved set-user-ID
不会变。
文件系统用户 ID(file-system user ID)
区别于有效用户 ID,文件系统用户 ID 用于判断是否有文件打开、修改文件属主、改变文件权限位的权限。
- 一般情形:文件系统用户 ID 跟随文件有效用户 ID 变化。
- 历史遗留:特权进程想显示调用 setfsuid() 修改文件系统用户 ID。
文件系统用户 ID 历史遗留问题的再说明
需要文件系统用户 ID 的特殊场景描述:甲进程向乙进程发送信号;丙进程是一个特权进程;丙需要修改自己的用户 ID 用于查看进程乙对应可执行文件的信息,但又不希望收到甲进程发送给乙进程的信号。
根据 kill(2)
的 man page 描述,整理不同 linux 版本的判断信号是否可发送的依据(描述的是一般进程):
- 1.0 - 1.2.2:发送方的有效用户 ID = 接收方有效用户 ID;或者发送方的实际用户 ID = 接收方实际用户 ID。
- 1.2.3 - 1.3.77:发送方的有效用户 ID = 接收方有效用户 ID或实际用户 ID。
- 1.3.78 - 至今:发送方的有效用户 ID 或实际用户 ID = 接收方保存的设置用户 ID(saved set-user-ID)或实际用户 ID
即,对于 1.3.78 版本之前的 linux 内核,为了符合前面描述的特殊场景(丙进程需要查看乙进程对应文件的属主信息,又不想受到发送给乙的信号),linux 设计了文件系统用户 ID,把部分文件权限独立出来。
对于 1.3.78 及以后版本的 linux 内核,只需要将丙进程的有效用户 ID 设置为乙进程的有效用户 ID,就可以实现既能查看其对应文件的属主信息,又收不到多余的信号,也就不用设置文件系统用户 ID ,所以说文件系统用户 ID 就成了一个系统遗留问题,但为了兼容以前的代码,现在的文件系统用户 ID 跟随有效用户 ID 变化。
tlpi 9.5 节中也举了一个类似甲给乙发送信号的例子,但我认为它的例子中的描述实际上跟它前面的定义是自相矛盾的。我举的例子是从 setfsuid(2) man page 中找到的,我认为比较准确描述了对应的情形。
参考
- linux/unix 系统编程手册(tlpi) 第9章及第20章第5节:https://book.douban.com/subje...
- setfsuid(2):https://man7.org/linux/man-pa...
- kill(2):https://man7.org/linux/man-pa...
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。