2013-05-18 64 views
1

根据issetugid的手册页,呼叫应该是(1)警告uid/gid变化;或(2)警告可能受污染的环境。函数名称提示了第三个目的。issetugid的用途?

第一个问题:它的目的是什么?

当我看到可用的实现(例如,Linux系统作为一个库,因为Linux内核不提供API上),我发现了以下内容:

if (getuid() != geteuid()) return 1; 
if (getgid() != getegid()) return 1; 
return 0; 

在Solaris上,它看起来如下:

return ((curproc->p_flag & SUGID) != 0); 

我有点怀疑,但是这部分是因为它很难明白什么样的跨平台geteuidgetegid回报功能 - 例如,BSD,Linux,Unix和Solaris操作系统。

第二个问题:Linux代码在语义上是否等同于Solaris代码?

第三个问题:是否geteuidgetegid跨平台实现?对于拥有三位身份证明系统的系统如何 - 真实,有效并保存?

第四个问题:在这里唯一的id是否是有效的id?

如果一个进程以UID = 0开始,并暂时放弃权限,那么saved就会发挥作用。暂时丢弃root的进程不需要exec,并且不应该被污染。

第五个问题:是否会暂时丢弃根感染的进程?

第六个问题:如果一个进程的有效id是被保存的id被认为是有问题的?

+0

所陈述的主要理由骂issetugid-在setuid或setgid程序或程序 ,一个成功的高管后,有更多的权限运行时,以保证安全 行为。你可能会使它比实际更复杂。 –

+0

谢谢吉姆。我处于困境 - 我正在审核一些使用该函数的代码。在Linux上,该库提供API,因为它不是。但我不知道它应该做的(因为它的非标),或者如果它有效地做这件事([设置uid揭秘](http://www.cs.berkeley.edu/~daw/papers/setuid- usenix02.pdf))。 – jww

回答

4

六个问题有点多,以设计为一个回答的问题,特别是如果没有一个人知道答案,所有六个,但我会尽力的系统回答...

1)目的issetugid()的目的是让图书馆知道它们是否被用于一个以提升特权运行的程序中,以便它们可以避免诸如信任LD_LIBRARY_PATH,NLSPATH等的风险行为。环境变量会让调用者加载可能会滥用提升特权。你可以看到它的一些历史讨论,如ncurses 4.1 security bug thread

2)该代码似乎不如BSD & Solaris版本安全,因为它没有考虑保存的setid位。

3)它们在不同的内核上可能有不同的实现 - 查看平台源代码以找出答案。

4)5)& 6)不,是的,是的 - 一个可以将其euid或egid更改回更高级别的进程仍然不相信导致它加载用户提供的代码来利用它们的环境变量。

+0

〜alanc - “六个问题有点多,以设计为一个问题的系统回答......”是的,同意。这是一个职位与多个问题,或多个职位(与大量复制/粘贴)与一个问题之间的权衡。 – jww

+0

感谢您回答问题2和4.我有同样的感受。另外,你看到的比赛是一个问题(这是因为Linux(和其它操作系统一个不太重要的问题)是全种族的)。 – jww

+0

如果代码是多线程的,那么,检查的getuid/geteuid /等等的当前结果。如#2所示可以与setuid/seteuid /等竞争。根据谁赢得比赛,调用并返回不同的答案。 – alanc

2

我不知道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);会将真实用户和保存的用户界面设置为有效的用户界面。然后,您的Linux issetugid()将返回0,但Solaris issetugid()将返回1.

Solaris在执行时检查SUGID进程标志。 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()getegid()函数似乎在任何地方都是这样做的;他们只需返回有效的用户标识和有效的组标识。

4)保存的id不重要。该过程可能在不清除其环境变量的情况下更改了这些ID。真实的,有效的或保存的id没有告诉我们是谁为当前进程设置了环境变量。

5)至少在OpenBSD和Solaris上,暂时丢弃root的进程不会被污染。 OpenBSD的手册页说,

issetugid()系统调用的结果不受对setuid(),setgid()或其他此类调用的调用的影响。在fork()的情况下,子进程继承相同的状态。

issetugid()的状态只受execve()的影响。

当进程临时将setuid()或seteuid()放在根上时,它不会执行文件,因此其issetugid()值不会更改。

但FreeBSD,DragonFly BSD和NetBSD更严格地定义了issetugid()。 FreeBSD的手册issetugid(2)说,如果它被作为execve的(2)系统调用其具有任一组的setuid或setgid位(和额外的特权的结果创建的给予结果

的方法受到了污染),或者自从它开始执行以来它已经更改了任何真实的,有效的或保存的用户或组ID。

使用这些系统,删除根的进程确实将其issetugid()值强制为1。

6)否,有效的ID等于保存的ID不玷污的处理。如果是这样,那么每个进程都会受到污染,因为每个进程都会在执行时将其保存的id设置为其有效标识。