• 日期:2026-09-13
  • 项目:codex(本机 Codex CLI,Ubuntu 24.04.5 云主机)
  • 涉及组件:bubblewrap 0.9.0(系统版 + Codex 自带 codex-resources/bwrap)、AppArmor 4.0.1、Codex CLI 0.154.0
  • 状态:已修复并验证

现象

Codex 所有需要在沙箱内执行的操作全部失败,报同一条错误:

bwrap: loopback: Failed RTM_NEWADDR: Operation not permitted

具体表现:

  • apply_patch 无法写入文件,报 fs sandbox helper failed with status exit status: 1: bwrap: loopback: ...;
  • 工具内的普通命令(exec_command)必须提权到沙箱外执行才能跑通;
  • 手工执行 codex sandbox -- uname -a 同样报错。

排查过程

  1. 直接复现,排除 Codex 自身因素:

    bwrap --unshare-net --dev-bind / / /bin/true
    # bwrap: loopback: Failed RTM_NEWADDR: Operation not permitted

    Codex 自带的 ~/.codex/packages/standalone/releases/0.154.0-x86_64-unknown-linux-musl/codex-resources/bwrap 用同样参数也报同一错误 —— 说明与 Codex 无关,是 bubblewrap 在本机起不来。

  2. 查环境与内核加固状态:

    Ubuntu 24.04.5 LTS(KVM 云主机,Alibaba Cloud ECS),内核 6.8.0-63-generic
    kernel.apparmor_restrict_unprivileged_userns = 1
    kernel.unprivileged_userns_clone = 1,user.max_user_namespaces = 6177
    AppArmor:enforcing;/etc/apparmor.d/ 下没有任何 bwrap 相关配置

    另外确认本机 uid 1000 有免密 sudo,可在本机直接修复。

根因

Ubuntu 24.04 默认开启 kernel.apparmor_restrict_unprivileged_userns=1,限制非特权用户命名空间。本机又没有给 bwrap 配 AppArmor 放行,于是 bubblewrap 创建新用户命名空间后,为其中的 loopback 接口配置地址的 netlink 调用被 AppArmor 拒绝并返回 EPERM,对应到 bwrap 的输出就是 loopback: Failed RTM_NEWADDR: Operation not permitted。沙箱进程起不来,上层 apply_patch、命令执行等一律失败。

注意事项

  • AppArmor 配置文件不支持 profile bwrap /路径A /路径B { ... } 这种多路径写法,本机 apparmor_parser 4.0.1 会报 syntax error, unexpected TOK_ID, expecting TOK_OPEN;要用花括号写法 /{路径A,路径B}。
  • 另一种修法是 sudo sysctl -w kernel.apparmor_restrict_unprivileged_userns=0,但那会放松整机策略(且默认不持久),本次没有采用。
  • Codex 自带 bwrap 的路径包含版本号(standalone/releases/<版本>/codex-resources/bwrap),配置里用 standalone/releases/*/ 通配,避免升级后失效。
  • 修复前本次会话的临时绕行方式是用带提权的脚本直接写文件,相关记录见 meta/2026-08-29-notes-conventions.md 末尾;沙箱恢复后已改回 apply_patch。

修复

新建 /etc/apparmor.d/bwrap,写法与系统内同类配置(如 QtWebEngineProcess)一致,只给 bwrap 放行 userns,并同时覆盖系统版和 Codex 自带版本:

abi <abi/4.0>,
include <tunables/global>

profile bwrap /{usr/bin/bwrap,home/admin/.codex/packages/standalone/releases/*/codex-resources/bwrap} flags=(unconfined) {
  userns,

  include if exists <local/bwrap>
}

加载配置:

sudo apparmor_parser -r -W /etc/apparmor.d/bwrap

apparmor 服务本身是 enabled + active,该文件在重启后会自动加载,无需额外操作。回滚方式:

sudo apparmor_parser -R /etc/apparmor.d/bwrap && sudo rm /etc/apparmor.d/bwrap

验证方法

/usr/bin/bwrap --unshare-net --dev-bind / / /bin/true                      # 通过
~/.codex/packages/standalone/releases/*/codex-resources/bwrap --unshare-net --dev-bind / / /bin/true   # 通过
codex sandbox -- uname -a                                                   # 正常输出内核信息
sudo cat /sys/kernel/security/apparmor/profiles | grep bwrap                # bwrap (unconfined)

另外确认沙箱策略仍然生效,而不是被绕过:沙箱内 curl -s -m 6 https://example.com 仍以 Couldn't resolve host(exit 6)失败,说明网络限制照常生效;apply_patch 在 /tmp 与 ~/.codex 下新建、删除文件均正常。

标签: codex, bubblewrap, apparmor, ubuntu, sandbox

添加新评论