我正在通过seccomp模式为自定义字节码解释器实现Linux安全沙箱。为了尽可能减少攻击面,我想在一个完全干净的虚拟地址空间中运行它。我只需要代码和数据段以及可用的堆栈,但我不需要vsyscall,vdso和vvar。
有没有办法禁止为给定进程分配此页面?
答案 0 :(得分:1)
基本上,不,如果您希望映射本身不可用,则必须全局禁用vsyscall / vDSO。如果您只希望程序无法调用vsyscall / vDSO系统调用,则seccomp将能够执行此操作。但有些警告:
请参阅https://www.kernel.org/doc/Documentation/prctl/seccomp_filter.txt
在x86-64上,默认启用vsyscall仿真。 (vsyscalls是 vDSO调用上的遗留变种。)目前,模拟的vsyscalls将尊重seccomp,但有一些奇怪之处:</ p>
SECCOMP_RET_TRAP的返回值将设置指向的si_call_addr 给定调用的vsyscall条目,而不是后面的地址 &#39;系统调用&#39;指令。任何想要重启呼叫的代码 应该知道(a)已经模拟了一个ret指令,并且(b) 尝试恢复系统调用将再次触发标准vsyscall 仿真安全检查,主要是恢复系统调用 没有意义的。
SECCOMP_RET_TRACE的返回值将像往常一样发出跟踪信号, 但系统调用可能无法使用更改为另一个系统调用 orig_rax注册。它可能只会更改为-1以跳过 目前正在模拟通话。任何其他更改都可以终止该过程。 跟踪器看到的rip值将是系统调用条目地址; 这与正常行为不同。跟踪器不得修改 rip或rsp。 (不要依赖于终止该过程的其他更改。 他们可能会工作。例如,在某些内核上,选择一个系统调用 只存在于未来的内核中将被正确模拟(通过 返回-ENOSYS)。
要检测这种古怪的行为,请检查地址和数据。 ~0x0C00 == 0xFFFFFFFFFF600000。 (对于SECCOMP_RET_TRACE,请使用rip SECCOMP_RET_TRAP,使用siginfo-&gt; si_call_addr。)不要检查任何其他 条件:未来的内核可以改善vsyscall仿真和当前 vsyscall = native模式中的内核将表现不同,但是 0xF ... F600 {0,4,8,C} 00处的指令不会是这些中的系统调用 例。
请注意,现代系统根本不可能使用vsyscalls - 它们 是遗留功能,它们比标准速度慢得多 系统调用。新代码将使用vDSO和vDSO发出的系统调用 与正常的系统调用无法区分。
因此,模拟的vsyscalls可以被seccomp限制,而vDSO同样受到seccomp的限制。如果禁用gettimeofday()
,则受限程序将无法通过模拟的vsyscall,vDSO或常规系统调用来调用该系统调用。如果你用seccomp这样限制它们,你就不必担心它们创建的攻击面。
如果您担心攻击者利用vDSO映射本身(不需要调用系统调用),那么我不相信有一种方法可以在每个进程上禁用它基础可靠。您可以阻止它被链接,但是很难防止受损的字节码解释器分配内存并将其放回。您可以使用vdso=0
内核参数进行引导,这将在全局禁用它,因此将其链接将无效。