Hotdry.
security

结合 seccomp、用户命名空间、cgroups v2 和挂载命名空间的多层沙箱隔离

在代理式环境中,结合 seccomp 过滤器、用户命名空间、cgroups v2 和挂载命名空间,实现鲁棒的多层沙箱隔离,提供具体配置参数、实现清单与监控要点。

在代理式(agentic)环境中,AI 代理生成并执行未经验证的代码已成为常态,如强化学习管道或多租户脚本平台。这种场景下,单一隔离机制远不足以抵御内核漏洞或特权提升攻击。多层沙箱隔离通过叠加 Linux 原语 ——seccomp 过滤器、用户命名空间、cgroups v2 和挂载命名空间 —— 构建防御纵深,每层针对不同攻击向量,提供从资源限制到 syscall 过滤的全面防护。这种组合在共享内核上实现强隔离,适用于执行 AI 生成代码的场景,而无需引入 gVisor 或 microVM 的性能开销。

各层隔离机制解析

挂载命名空间(Mount Namespace):隔离文件系统视图,进程只能访问自身挂载点下的文件系统,防止通过路径遍历访问宿主机敏感路径。攻击者即使获得 fd 泄漏,也无法逃逸到宿主机根目录。例如,在 CVE-2024-21626 中,runc fd 未关闭导致容器访问宿主机文件系统,但严格的挂载命名空间可将 blast radius 限制在沙箱内。

用户命名空间(User Namespace):映射内部 root 到外部 nobody(UID 65534),剥离特权能力。即使沙箱内代码以 root 运行,也无宿主机 CAP_SYS_ADMIN 等能力,避免嵌套特权提升。结合 PR_SET_NO_NEW_PRIVS,子进程无法获得新特权。

cgroups v2:统一资源控制组,精确限额 CPU、内存、I/O 和进程数,防范 DoS 攻击。不同于 v1 的多层级,v2 采用单层委托模型,便于动态调整。例如,设置 cpu.max=100ms 1000ms 限制突发 CPU 为 10%,memory.max=512M 防止 OOM killer 波及宿主。

seccomp 过滤器(Seccomp-BPF):在内核入口过滤 syscall,只允许白名单操作,如 read/write/openat2,阻塞 ptrace、clone3(防嵌套 ns)、io_uring(防异步逃逸)。默认 Docker profile 阻挡 40+ syscall,进一步缩小攻击面至~300 个。

这些原语共享同一内核,但层层递进:挂载 ns 挡住 fs 逃逸,用户 ns 挡住 priv esc,cgroups 挡住资源耗尽,seccomp 挡住 syscall 滥用。如 Shayon Mukherjee 指出,“命名空间是可见性墙,而非安全边界”,但叠加 seccomp 后,攻击需同时绕过多层。

可落地实现:自定义沙箱脚本

使用 unshare(利用 clone (2) 创建 ns)+ newuidmap(用户 ns 映射)+ systemd-cgtop(cgroups v2)+ seccomp json profile 构建纯原语沙箱。以下 bash 脚本示例执行任意命令(如 python script.py),适用于 agentic 工作负载:

#!/bin/bash
# sandbox.sh <cmd>...

SANDBOX_UID=65534  # nobody
CGROUP_PATH="/sandbox/$(date +%s)"  # 唯一 cgroup
SECCOMP_PROFILE="seccomp.json"  # 白名单 profile,见下

# 1. 创建 cgroups v2
mkdir -p /sys/fs/cgroup/sandbox
echo "+cpu +memory +io +pids" > /sys/fs/cgroup/sandbox/cgroup.subtree_control
mkdir -p $CGROUP_PATH
echo "100000 1000000" > $CGROUP_PATH/cpu.max  # 10% CPU
echo "512M" > $CGROUP_PATH/memory.max
echo "100M" > $CGROUP_PATH/io.max  # I/O 限额
echo "100" > $CGROUP_PATH/pids.max

# 2. 创建用户 ns 映射 /etc/subuid
echo "$(id -u):100000:1" >> /etc/subuid  # 映射 100000 -> nobody

# 3. unshare 多 ns + exec
unshare -U -m -p -n -i --propagation private \
  newuidmap $$ 0 $SANDBOX_UID 1 \
  newgidmap $$ 0 65534 1 \
  sh -c "
    # 挂载 tmpfs 私有 fs
    mount -t tmpfs -o mode=755 tmpfs /work
    mount --make-rprivate /
    mount --make-rslave /proc /sys /dev

    # Seccomp load + priv drop
    seccomp-load $SECCOMP_PROFILE
    prctl PR_SET_NO_NEW_PRIVS 1
    setuid $SANDBOX_UID

    # 进入 cgroup
    echo \$\$ > $CGROUP_PATH/cgroup.procs

    # 执行命令
    exec $@ --workdir=/work
  "

seccomp.json 示例(最小白名单,JSON BPF):

{
  "defaultAction": "ERRNO",
  "architectures": ["X86_64"],
  "syscalls": [
    {"names": ["read", "write", "openat", "close", "mmap", "munmap", "exit"], "action": "SCMP_ACT_ALLOW"},
    {"names": ["clone"], "args": [{"index": 0, "op": "SCMP_CMP_EQ", "datatype": "SCMP_A0", "arg1": "CLONE_VFORK"}], "action": "SCMP_ACT_ALLOW"},
    {"names": ["execve"], "action": "SCMP_ACT_ALLOW"}
  ]
}

编译:gcc -o seccomp-load seccomp-load.c(使用 libseccomp)。

此脚本启动 <1ms,冷启动快,内存开销 <10MB。测试:./sandbox.sh python -c 'import os; os.system("id")' 应失败于特权 syscall。

工程化参数与阈值

  • cgroups v2

    资源 参数 推荐值(短任务) 监控阈值
    CPU cpu.max 50000 500000 (10%) >80% 告警
    Mem memory.max 256M-2G OOM 事件
    I/O io.max 50M read/write 吞吐 > 限额
    PIDs pids.max 50-200 爆表杀进程
  • seccomp:阻挡 top 50 危险 syscall(ptrace, kmod, perf_event_open)。允许率 <5%,日志审计违规。

  • ns 配置:--propagation private 防共享挂载传播;user ns 映射 1:1,避免子 UID 溢出。

监控与回滚策略

  • 指标:cgroupfs events(memory.pressure, cpu.stat),seccomp_ret=ERRNO 计数(/sys/kernel/debug/tracing)。
  • 告警:Prometheus cgroup exporter + Grafana,阈值:CPU>90%、违规 syscall >10/min。
  • 审计:auditd 捕获 ns 进入 / 退出,falco seccomp 违反。
  • 回滚:原子 umount /work + rmdir cgroup(echo 0 > memory.high 软限先),O (1) 清理。

风险:fd 泄漏(用 closefrom (2)),mount race(lockfd),配置错(如无 PR_SET_NO_NEW_PRIVS)。测试用 syzkaller fuzzing。

实施清单

  1. 启用 kernel.unprivileged_userns=1, user.max_user_namespaces=15000。
  2. 安装 libseccomp-tools, systemd-cgtop。
  3. 生成 sub {u,g} id(useradd --no-create-home sandbox)。
  4. 基准:iperf3 测试 I/O,stress-ng CPU。
  5. 集成 agent:Python subprocess.call (sandbox.sh, shell=False)。
  6. CI/CD:GitHub Actions 用此沙箱跑 untrusted tests。

此多层方案在 agentic 环境中平衡安全与性能,escape 难度指数级提升。资料来源:[1] Shayon Mukherjee, "Let's discuss sandbox isolation", https://www.shayon.dev/post/2026/52/lets-discuss-sandbox-isolation/ (讨论 namespaces/seccomp 在沙箱光谱中的作用)。

查看归档