Hotdry.
security

浏览器沙箱的系统调用过滤机制与工程实践

深入解析 Chrome 如何通过 seccomp-bpf 实现系统调用白名单,结合 namespace 隔离构建多层防御的浏览器沙箱安全模型。

现代浏览器的安全模型已经从简单的权限隔离演进到对操作系统接口的深度控制。在 Linux 平台上,Chrome 通过 seccomp-bpf 过滤器在系统调用层面构建了一道关键防线,将渲染进程能够执行的操作系统操作限制在严格的白名单范围内。这种设计不仅限制了恶意代码的破坏能力,更重要的是从根本上削减了内核攻击面,使得即便渲染进程被攻破,攻击者也难以利用丰富的系统调用接口实施进一步渗透。

Chrome 在 Linux 上采用多层沙箱机制的组合策略。根据 Chromium 官方文档的描述,系统会根据内核功能特性选择性地启用 setuid 辅助程序、命名空间隔离、seccomp-bpf 过滤以及新兴的 landlock 机制。在现代 Linux 内核环境下,Chrome 会同时启用 setuid 沙箱、命名空间以及 seccomp-bpf 三层防御。这些机制并非孤立运作,而是相互叠加、层层设限:setuid 程序负责创建空的 PID 和网络命名空间,将渲染进程与宿主系统进程树和网络栈隔离;chroot 操作将进程限制在只读的伪根文件系统中;而 seccomp-bpf 则在这一基础上进一步限制进程能够发起的系统调用种类。

seccomp-bpf 的核心价值在于其能够在系统调用的入口处进行早期评估。当沙箱中的进程尝试执行任何系统调用时,内核会先运行 Chrome 预先注入的 BPF 程序,该程序根据预定义的策略决定放行还是终止该请求。Chrome 的 seccomp 策略采用白名单机制,只有那些在设计时就被认定为安全且必要的系统调用才会被允许通过。这意味着渲染进程无法随意打开文件、创建进程、建立网络连接,或者执行其他可能危及系统安全的操作。这种 "最小权限" 的设计哲学贯穿于整个沙箱架构之中。

工程实践中维护 syscall 白名单是一项极具挑战性的任务。开发团队必须穷举沙箱代码可能触发的所有系统调用路径,包括自有代码和第三方依赖产生的调用。任何遗漏都可能成为安全漏洞,而任何过度限制又可能导致功能异常。Chrome 的应对策略是建立完善的测试覆盖体系,确保所有代码路径都在沙箱环境下运行并暴露其使用的系统调用。测试覆盖的完整性直接决定了白名单策略的安全边界是否可靠。这一要求也使得沙箱代码的演进变得格外谨慎,新增系统调用支持往往需要经过严格的安全审计。

ChromeOS 的安全文档提出了一个 "禁止交集" 的概念模型来描述多层沙箱的协同效应。该模型指出,同时满足以 root 身份运行、处于 init 命名空间、且缺乏 seccomp 或 landlock 策略约束这三种条件时,系统处于最危险的状态。有效的沙箱设计必须打破这一交集,例如通过以普通用户身份运行、使用非 init 命名空间、并强制启用 seccomp 过滤来实现纵深防御。这种设计理念确保了即使某一层防御被绕过,其他层仍能提供保护。

从部署路径来看,Chrome 的 setuid 辅助程序通常安装在 /opt/google/chrome/chrome-sandbox,在浏览器启动时由父进程调用执行。该程序完成命名空间创建、chroot 切换和能力降权后,会主动放弃 root 权限并将控制权交还给主进程。这种设计既利用了 root 权限创建隔离环境,又在初始化完成后以普通用户身份运行,将权限暴露的时间窗口压缩到最短。对于需要禁用沙箱进行开发的场景,Chrome 提供了 --disable-setuid-sandbox 启动参数,但这一选项仅应用于受信任的调试环境。

资料来源:Chromium Sandbox 官方文档(chromium.googlesource.com/chromium/src)

查看归档