我不知道issetugid()
,但我可以通过阅读 BSD 或 Solaris 手册页来学习。该函数来自 OpenBSD。
1) OpenBSD 的issetugid(2)手册说:“如果进程是 setuid 或 setgid 作为最后一次或其他先前 execve() 系统调用的结果,则 issetugid() 函数返回 1。否则返回 0。” 然后它建议使用 issetugid() 检查环境变量中命名的文件是否可以安全打开。
2) 不,您的 Linux 和 Solaris 代码不等效。运行 setuid 的进程可能会将其真实 uid 设置为其有效 uid,而无需清理其环境变量。例如,uid_t uid = geteuid(); setresuid(uid, uid, uid);
将真实 uid 和保存的 uid 都设置为有效 uid。然后你的 Linux issetugid() 将返回 0,但 Solaris issetugid() 将返回 1。
SolarisSUGID
在执行时检查进程标志。Illumos 是 Solaris 的免费分支,在执行文件时会在src/uts/common/os/exec.c中设置 SUGID。OpenBSD 也有类似的逻辑。OpenBSD 的手册说,
如果子进程执行一个新的可执行文件,将确定一个新的 issetugid 状态。此状态基于现有进程的 uid、euid、gid 和 egid 权限以及可执行文件的模式。如果新的可执行文件模式是 setuid 或 setgid,或者如果现有进程正在使用 uid != euid 或 gid != egid 执行新映像,则新进程将被视为 issetugid。
Solaris 和 OpenBSD 在执行时比较 id。您的 Linux 代码将比较延迟到调用 issetugid() 之前,因此它是不等价的。
3) geteuid()
andgetegid()
函数似乎在任何地方都做同样的事情;他们只是返回有效的用户 id 和有效的组 id。
4)保存的ID无关紧要。该进程可能在未清理其环境变量的情况下更改了这些 ID。没有一个真实的、有效的或保存的 id 告诉我们谁为当前进程设置了环境变量。
5) 至少在 OpenBSD 和 Solaris 上,临时删除 root 的进程不会被污染。OpenBSD 的手册页说,
issetugid() 系统调用的结果不受对 setuid()、setgid() 或其他此类调用的调用的影响。在 fork() 的情况下,子进程继承相同的状态。
issetugid() 的状态仅受 execve() 影响。
当进程使用 setuid() 或 seteuid() 临时删除 root 时,它不会执行文件,因此它的 issetugid() 值不会改变。
但 FreeBSD、DragonFly BSD 和 NetBSD 对 issetugid() 的定义更为严格。FreeBSD 的issetugid(2)手册说,
如果一个进程是由于 execve(2) 系统调用的结果而创建的,该系统调用设置了 setuid 或 setgid 位(并因此获得了额外的特权),或者如果它更改了任何真实有效的进程,则该进程被污染或保存的用户或组 ID,因为它开始执行。
在这些系统中,删除根的进程确实会强制其 issetugid() 值为 1。
6) 不,等于保存的 id 的有效 id 不会污染进程。如果是这样,那么每个进程都会受到污染,因为每个进程在执行时都将其保存的 id 设置为其有效 id。