09.01 Linux 进程凭证(Credentials)
Linux 进程凭证
进程凭证包括以下内容:
- 实际用户 ID(real user ID)和实际组 ID(real group ID)。
- 有效用户 ID(effective user ID)和有效组 ID(effective group ID)。
- 保存的 set-user-ID(saved set-user-ID)和保存的 set-group-ID(saved set-group-ID)。
- 文件系统用户 ID(file-system user ID)和文件系统组 ID(file-system group ID)(Linux 专有)。
- 辅助组 ID。
保存的设置用户/组 ID
文件系统中每个非目录文件有设置用户/组 ID 位,启动这样的文件会使得有效用户/组 ID 按照文件的所有者来设置。出于安全考虑,在 Linux 中可执行文件的设置用户/组 ID 权限对于 shell 脚本无效。
设计保存的设置用户 ID(保存的设置组 ID 同,为了表述方便略去)是为了让程序的有效用户 ID 能够在实际用户 ID 和保存的设置用户 ID 之间切换。这样程序在不需要使用其他用户(尤其是 root)的权限时可以将有效用户 ID 转回实际用户 ID,需要权限时再转回来。程序启动时,保存的设置用户 ID 从有效用户 ID 复制过来。
文件系统用户/组 ID
文件系统用户/组 ID 管辖和文件系统操作相关的权限问题,是由 Linux 专有的。一般情况下它们和有效用户/组 ID 相同,除非调用了 setfsuid
/ setfsgid
。
文件系统 ID 始见于 Linux 1.2 版本。在该版本的内核中,如果进程某甲的有效用户 ID 等同于进程某乙的实际用户 ID 或者有效用户 ID,那么发送者(某甲)就可以向目标进程(某乙)发送信号。这在当时影响到了不少程序,比如 Linux NFS(网络文件系统)服务器程序,在访问文件时就好像拥有着相应客户进程的有效 ID。然而,如果 NFS 服务器真的修改了自身的有效用户 ID,面对非特权用户进程的信号攻击,又将不堪一击。为了防范这一风险,文件系统用户 ID 和组 ID 应运而生。NFS 服务器将有效 ID 保持不变,而是通过修改文件系统 ID 伪装成另一用户,这样既达到了访问文件的目的,又避免了遭受信号攻击。
自内核 2.0 起,Linux 开始在信号发送权限方面遵循 SUSv3 所强制规定的规则,这些规则和目标进程的有效用户 ID 无关,但是文件系统用户 ID 因为兼容性原因被保留了下来。
辅助组 ID
英文是 supplementary group ID。
特权级进程可以通过系统调用 setgroups
和 initgroups
设置自己(以及将来的子进程)的辅助组 ID。
initgroups
的签名如下:
int initgroups(const char *user, gid_t group);
首先是扫描 /etc/group 文件,找到 user
所在的所有组,这些组将加入到辅助组列表中。然后将参数 group 指定的组追加到进程辅助组 ID 的列表中。一般 login(1) 等创建登录会话的程序会使用这个系统调用,在实际调用时,参数 group 一般是 /etc/passwd 文件中指定的 gid(含义为登录 shell 初始的实际组 ID、有效组 ID 和保存的 set-group-ID)。