题干与适用场景
一个命令行工具需要读取少量输入文件、写入指定输出目录,并执行不可信插件。部署环境不允许授予额外特权,但内核可能只支持较早的 Landlock ABI。你会如何设计沙箱,验证规则确实生效,并避免把“限制更严格”误当成“安全已经足够”?
这道题适合 Linux、安全工程、构建系统和多租户执行平台岗位。重点是理解 Landlock 作为可叠加的进程自我约束机制,而不是背诵某个 C 结构体。
面试官考察点
- 是否能区分规则域、规则类型、访问权限位和进程作用域。
- 是否会先探测内核 ABI,再按支持的权限集合构建规则。
- 是否理解沙箱生效后已打开的文件描述符不受同样限制。
- 是否能设计继承、exec、子进程和线程的边界。
- 是否把失败模式、审计、回退和测试纳入上线方案。
回答前需要澄清的问题
- 工具需要哪些路径的读取、创建、删除、执行和网络能力?
- 插件是否会 fork、exec、创建线程或把文件描述符交给子进程?
- 最低支持的内核版本和可接受的安全降级是什么?
- 进程启动前是否已经打开日志、输入文件、套接字或设备?
- 是阻断高风险操作,还是还需要 seccomp、容器或 MAC 提供额外边界?
30 秒回答框架
“我会让进程先探测 Landlock ABI,再创建规则域,只授予输入目录的读取权限和输出目录的创建、写入权限,随后通过 restrict_self 让当前线程及其后代继承限制。规则生效前打开的文件描述符需要单独审计,因为它们可能继续可用。对不支持的权限位采用最小共同集合;如果核心隔离无法建立,就拒绝运行或进入明确记录的低风险只读模式,不静默当作安全沙箱。”
分步骤深入解答
第一步:定义威胁和最小权限
先列出插件可能做的动作:读取宿主机文件、覆盖输出、执行其他程序、删除目录、访问网络或利用继承的描述符。将每个动作映射到 Landlock 支持的文件层级权限,只允许输入目录的必要读取权限和输出目录的必要写入权限。未授予的权限保持拒绝,避免先开放整个根目录再试图收紧。
第二步:按 ABI 探测能力
Landlock 的接口按 ABI 逐步增加权限位。启动时读取当前 ABI 版本,把期望权限拆成“必须”和“可选”两组;对可选位只在内核支持时加入。规则中不能使用当前内核不认识的权限位,否则创建规则可能失败。把探测结果、规则版本和实际授予集合写入结构化日志,便于复现。
第三步:建立规则域并绑定路径
创建规则域后,为每个允许的文件层级打开目录文件描述符,并用路径规则把权限位绑定到这些目录。目录描述符应使用受信任的启动阶段打开方式,避免规则配置阶段被插件替换路径。规则组合完成后调用限制当前进程的接口;线程和后续 exec 的继承关系要在测试中确认。
第四步:审计已打开资源和继承链
Landlock 约束的是后续访问请求,沙箱建立前已经打开的文件描述符可能仍然可读写。因此在建立规则前关闭不需要的描述符,或把它们标记为受控资源并限制传递。检查标准输入输出、日志、套接字、目录句柄和插件传入的描述符。对 fork、exec、线程和子进程分别验证继承结果。
第五步:设计失败与组合防线
Landlock 不能替代所有安全机制,也不会自动限制网络、系统调用或已经拥有的能力。若工具需要更强边界,可组合 seccomp、容器、用户命名空间或系统级 MAC。核心规则域创建失败时,根据威胁模型选择拒绝启动、只读模式或人工批准;任何降级都要告警并带上原因,不能无提示继续执行不可信插件。
第六步:验证、观测与回滚
在 CI 中用测试目录覆盖允许和拒绝矩阵:读取输入成功、写入输出成功、读取其他路径失败、删除和执行按预期失败,子进程也重复验证。记录 ABI、规则哈希、拒绝计数和退出原因。灰度期间比较误拒绝率;发现插件需要额外权限时更新权限清单和测试,而不是直接开放父目录。回滚可关闭插件或恢复旧执行器,但应保留沙箱失败告警。
高质量示范回答
我会先把插件的文件、执行和继承需求列成权限清单,再探测目标内核的 Landlock ABI。规则域只允许输入目录的读取和输出目录的创建、写入,所有可选权限按 ABI 逐位启用;不支持的必要能力直接判定为不可运行。建立规则前关闭不需要的文件描述符,审计标准输入输出、日志和套接字,确认 fork、exec、线程和子进程的继承行为。
调用限制当前进程的接口后,我会用允许/拒绝矩阵和真实插件测试规则,记录 ABI、规则版本、拒绝操作和降级原因。Landlock 是进程自我约束且可叠加的文件访问边界,不能替代 seccomp、容器或 MAC;如果核心规则无法建立,就拒绝运行或进入明确告警的只读模式,绝不静默绕过。
常见错误
- 把 Landlock 当成特权隔离 → 它主要约束进程后续的受控访问 → 按威胁模型组合其他机制。
- 忽略 ABI 差异 → 新权限位可能在旧内核上无法识别 → 探测并构建最小共同权限集合。
- 沙箱前打开全部文件 → 既有描述符可能继续可用 → 启动前关闭、审计并禁止无关描述符继承。
- 授予父目录再靠应用逻辑限制 → 插件可遍历并访问更多路径 → 按目录和权限位给最小授权。
- 失败后静默裸奔 → 操作者无法知道隔离缺失 → 拒绝、只读降级或人工批准,并记录告警。
- 只测主进程 → fork、exec 和线程会改变边界 → 对每种继承路径做拒绝矩阵。
追问及应对
Landlock 能否限制已经打开的文件?
不能把它当作自动关闭机制。沙箱建立前已打开的文件描述符可能继续使用,因此应在建立规则前关闭不需要的描述符,限制描述符传递,并把遗留句柄纳入审计和测试。
ABI 不支持某个权限位时应该怎样做?
把权限分为必须和可选。启动时探测 ABI,仅加入受支持的可选位;若必须能力缺失则拒绝启动或切换到明确告警的安全模式。不能忽略创建规则失败,也不能把未知位强行写入规则。
为什么还需要 seccomp 或容器?
Landlock 的核心价值是文件层级的、非特权的自我约束;它不覆盖全部系统调用、网络或宿主机策略。seccomp、用户命名空间、容器和 MAC 可以分别补足调用、身份和系统级边界,组合时仍要验证继承和失败路径。