Linux 权限检查不看“人”,看“进程”。
内核不认识屏幕前的你,只认运行中的进程手里拿的“身份证”。
理解权限的关键,在于搞懂这张“身份证”如何在进程间传递,以及接受检查的是哪个进程。
1. 进程的身份证
进程必须持有身份标识,内核才允许它访问资源。这张身份证包含:
- • 有效用户 ID (Effective UID):权限检查的核心依据。它代表进程当前是以“谁”的名义在干活。
2. 身份由父进程向子进程传递
进程的身份不是凭空产生的,而是通过父进程传给子进程的。
你登录的 Shell 是谁,通常由它启动的程序也是谁。
默认原则:复制
在 Linux 中,启动一个新程序(如 reader)包含两个动作:
- 1. 复制:当前的 Shell 进程(父进程)复制出一个完全一样的自己(子进程)。此时,子进程手里拿的身份证与父进程完全一致。
- 2. 替换:子进程加载
reader 程序的代码,开始运行。
例外:SUID
如果程序文件本身设置了 SUID 位,传递规则会改变。在“替换”代码阶段,内核会强制将子进程的 Effective UID 修改为程序文件所有者的 ID。这相当于临时借用了特权(例如 passwd 命令)。
3. 内核检查进程的权限
当你执行用程序文件 ./reader 读取数据文件 data.txt 时,并不是同一个进程在闯关。实际上,这是两个不同的进程先后接受了两次检查。
第一道关卡:Shell 进程受检
- • 负责进程:Shell 进程(你的命令行终端)。
- • 动作:Shell 拿着你的身份证,问内核:“我有权执行 (x) 这个程序吗?”
- • 失败:Shell 直接报错(Permission denied)。新进程根本不会诞生。
第二道关卡:新进程受检
- • 负责进程:新启动的 reader 进程(子进程)。
- • 动作:程序启动后,问内核:“我有权读取 (r) 这个文件吗?”
通过区分负责检查的进程,能清楚分辨两种失败情况:
情况一:连工具都拿不起来
- • 实质:Shell 进程(父进程)手中的身份证没有该程序的执行权。倒在第一关,子进程从未存在。
情况二:拿起了工具,但看不了数据
- • 实质:Shell 进程 成功把身份证复印给了 新进程(子进程),但这份身份证的权限不足以读取数据。倒在第二关。
附录