Linux沙箱(2): seccomp sandbox
Seccomp(secure computing)是Linux kernel (自从2.6.23版本之后)所支持的一种简洁的sandboxing机制。它能使一个进程进入到一种“安全”运行模式,该模式下的进程只能调用4种系统调用(system calls),即read(), write(), exit()和sigreturn(),否则进程便会被终止。
Seccomp是Andrea Arcangeli在2005年设计的,其目的是解决grid computing中的安全问题,比如你打算出租你的CPU资源,但又担心不可信的代码会破坏你的系统。那么,Seccomp则可以为“不可信的纯计算型代码”提供一个“安全(SAFE, not SECURE)”的运行环境,以保护你的系统和应用程序的正常运行不受不可信代码的干扰。
据说Google Chrome浏览器的开发人员曾经考虑过使用Seccomp来建立Chrome Sandbox,但考虑到Seccomp的一些不足而“另辟蹊径”—— Native Client 。『据了解,Google Chrome 4 在今年 CanSecWest Applied Security 大会上是唯一没有被当场攻破的浏览器,而IE8 on Windows7/Vista/XP, Mozilla Firefox 3 和 Apple Safari 4 都相继被攻破。』
简洁、优美是Seccomp的优点,但只能支持“纯计算型”代码却使得其应用受到很大限制。比如,Seccomp模式的进程不能动态分配内存、不能与其它进程使用共享内存、不能使用新的文件描述符、等等。如果要支持具有丰富功能的应用程序,则需要另外的方法来截获并处理其它系统调用。
有人提议对seccomp进行改进使其支持对系统调用提供更细粒度的控制。比如,对seccomp增加一个新的mode,使用一个bitmap来精确描述哪些系统调用是可以被访问的,而哪些是被禁止的。而进程自己还可以丢弃(但不能重新获取)它所具有的访问哪些系统调用的能力(这种工作方法有点像Linux capability安全机制,尽管这两者是完全正交的)。但是到今天为止,还没有看到相关的进展,据说是因为ftrace也支持类似的功能,如何裁定还需要进一步讨论。
通过截获系统调用来实现sandbox是一贯的做法,它假设Kernel是好人,而User不一定是好人。在现代操作系统中,User和Kernel的空间是隔离的,一个进程只能通过系统调用才能从user空间进入kernel空间。如果一个进程不需要执行系统调用(即不需要kernel提供的丰富功能),那么我们的系统被攻击的风险就小。当然假设进程不使用系统调用是不切实际的,但对今天的多数系统来说,为用户程序提供的丰富功能是以牺牲安全性为代价的。但是,“仅仅通过截获并处理系统调用的方法去实现sandbox”是否是正确的技术方向呢?我们知道,当系统调用的参数保存在用户空间的时候,要想验证该参数是否“安全”是非常困难的,比如TOC2TOU问题便是一个挑战:一个恶意进程可能会在“参数被安全检查”之后、而在“实际使用参数”之前将该参数换掉,这便使截获系统调用时所做的参数检查变得没有意义。要解决这个问题,我们也许不应当只将目光锁定在系统调用的入口处。
sandboxing一直以来都是一个大难题,对于今天的COTS OS来说还不存在一个通用的安全方案。如何去做满足自己需要的sandbox,则需要量体裁衣。