Docker Copy Fail 漏洞修复指南:CVE-2026-31431 内核升级与容器加固
更新日期:2026-08-30
Copy Fail(CVE-2026-31431)是一项 Linux kernel 本地提权漏洞,根因位于 AF_ALG crypto subsystem 的 algif_aead 模块。它并不是 Docker 基础设施被攻破,也不是 docker cp 命令复制文件失败。Docker 之所以受到关注,是因为旧版默认安全 profile 允许普通容器进程触达该内核攻击面。
Docker Engine 29.4.2 曾尝试通过 seccomp 缓解,但会破坏部分 i386、32 位 Go、SteamCMD 和 Wine workload,而且兼容模式仍可能绕过。Docker 随后在 29.4.3 修正方案。真正的根因修复仍然是安装 Linux 发行版提供的安全内核并重启宿主机。
先说结论
- Copy Fail 是 Linux kernel algif_aead 的 CVE-2026-31431,Ubuntu 将其评为 High、CVSS 3.1 为 7.8。
- 攻击通常要求攻击者已能以非特权用户或容器进程执行代码;漏洞可把能力提升到 root,并可能影响共享同一 page cache 的宿主机和其他容器。
- Docker 官方判断:运行 patched host kernel,或者 Docker Engine 29.4.3+ 的默认缓解,可阻断其描述的 Docker 默认容器路径。
- Docker Engine 缓解不能修复内核,也不覆盖本地用户、其他 runtime、privileged/unconfined 或不使用默认 profile 的所有场景。优先更新 kernel。
- Docker 29.4.2 不是推荐目标;存在 32 位兼容回归。应使用发行渠道当前受支持版本,且不得低于 29.4.3。
- 不要用 --security-opt seccomp=unconfined、关闭 AppArmor/SELinux 或 privileged container 来解决兼容问题。
Copy Fail 到底能做什么
Linux 通过 AF_ALG socket 向 userspace 暴露部分内核密码学能力。Copy Fail 出现在 AEAD 操作的 in-place 处理路径:已有本地执行能力的攻击者可对 page cache 进行受控写入。
page cache 并不是某一个容器私有的数据副本。宿主进程和多个容器可能映射相同文件或共享 image layer,因此攻击影响可能跨越原容器边界。Docker 官方举出的直接路径是临时篡改可读的 setuid binary,从容器内非特权用户提升为 root;更一般的风险是其他读取相同缓存页的 workload 看到被修改内容。
这不等于互联网上的匿名请求可以无条件直接获得宿主 root。攻击者首先需要在宿主或容器中执行代码,例如通过应用 RCE、恶意 CI job、不可信插件或多租户 workload。安全评估要把 Copy Fail 与最初代码执行入口串起来,但不能因为需要前置条件就忽略它。
为什么默认 Docker 容器也可能受影响
利用链需要创建 AF_ALG socket。Docker Engine 29.4.3 之前的默认 security profile 允许普通容器进程这样做,不要求额外 Linux capability。容器没有 --privileged 并不能自动免疫。
风险组合可以这样判断:
| Host kernel | Docker/profile | 判断 |
|---|---|---|
| 已安装并运行 vendor patched kernel | 任意 Docker 版本仍需做常规升级 | Copy Fail 根因已修复 |
| 未修复 kernel | Docker Engine 29.4.3+ 且默认 AppArmor/SELinux/seccomp 缓解生效 | 官方默认容器路径得到缓解,仍应安排 kernel patch |
| 未修复 kernel | Docker 29.4.2 或更早 | 暴露,优先处置 |
| 未修复 kernel | custom profile、unconfined、privileged 或其他 runtime | 不应假设 Docker 默认缓解覆盖 |
rootless container 也不应被直接标记为安全。漏洞发生在共享 host kernel,判断依据仍是运行中的 kernel 与实际 security profile。
不要与 docker cp 的其他漏洞混淆
“Copy Fail”这个名字描述的是 page cache 写入能力,不是 Docker CLI 的 docker cp 子命令。
Docker Engine 29.5.1 还修复了 CVE-2026-41567、CVE-2026-41568 和 CVE-2026-42306 等 docker cp 问题。它们有不同根因、触发条件与公告。资产系统应分别记录,不能因为已经处理 docker cp CVE 就关闭 CVE-2026-31431,也不能拿 Copy Fail 的 kernel patch 代替 Engine 自身其他安全更新。
第一步:盘点运行中的真实状态
在每个 Linux container host 上记录:
cat /etc/os-release
uname -r
docker version --format 'client={{.Client.Version}} server={{.Server.Version}}'
docker info --format '{{json .SecurityOptions}}'
关注 server version,不要只看本地 Docker CLI。远程 context、CI runner 和管理节点可能连接另一台 daemon。
再检查运行容器是否绕过默认隔离:
docker ps -q | xargs -r docker inspect \
--format '{{.Name}} privileged={{.HostConfig.Privileged}} security={{json .HostConfig.SecurityOpt}}'
同时搜索 Compose、systemd 和编排配置中的:
- privileged: true
- seccomp=unconfined
- apparmor=unconfined
- 自定义 security_opt
- Docker socket 或 host filesystem mount
这些配置不一定都是 Copy Fail 的直接必要条件,但会改变默认缓解是否生效,并放大容器被攻破后的影响。
第二步:由发行版确认内核是否已修复
不要仅用上游 kernel 主版本比较。Linux 发行版会把安全修复 backport 到原有 ABI,同一个 6.8 字样可能包含或不包含补丁;generic、HWE、cloud 与厂商 kernel 的包版本也不同。
以 Ubuntu 为例,官方 CVE tracker 在 2026 年 8 月已经把维护中的 24.04、22.04、25.10 等主要 kernel package 标记为 fixed,并列出每个 flavor 的准确包版本。五月份“Ubuntu 尚未提供修复”的旧文章已经过时。
Ubuntu/Debian 可以先查看可用更新与 reboot 状态:
sudo apt update
apt list --upgradable 2>/dev/null | grep -E '^linux-(image|headers|generic|virtual|aws|azure|gcp)'
test -f /var/run/reboot-required && cat /var/run/reboot-required.pkgs
然后按照当前发行版安全公告升级实际安装的 kernel flavor。RHEL、SUSE、云厂商优化内核也应使用各自 security advisory 和受支持 repository,不要下载一个上游 .deb/.rpm 强行覆盖。
完成后需要 reboot 才会切换运行内核:
uname -r
sudo reboot
uname -r 应在重启前后都记录,重启后再与 vendor tracker 的 fixed package 对照。只看到新 kernel 文件已经安装,却仍运行旧 kernel,不能算修复完成。
第三步:升级 Docker Engine 到 29.4.3 或更高
Docker Engine 29.4.2 在 default seccomp profile 中同时阻止 socket(AF_ALG) 和 socketcall(2)。问题是旧 glibc i386、GOARCH=386、SteamCMD 和 Wine 等依赖 socketcall,导致容器网络等功能中断;amd64 进程还可能切到 ia32 compatibility path 绕过直接 socket 参数过滤。
29.4.3 改用组合防线:
- seccomp 继续阻止直接 socket(AF_ALG)。
- AppArmor 用 deny network alg 覆盖 socket 与 socketcall 路径。
- SELinux 使用 alg_socket 规则,但要求 daemon 显式启用 SELinux integration。
- 修复 daemon restart 后默认 AppArmor profile 没有正确更新的问题。
截至 2026 年 8 月,Docker 官方 29.x release notes 最新条目为 29.7.2。生产目标应是当前发行渠道支持的安全版本,最低不低于 29.4.3;不要为了“只改一个 CVE”锁死到已经落后的 29.4.3。
如果使用 Docker 官方 apt repository,可先检查 candidate,再在维护窗口升级:
apt-cache policy docker-ce docker-ce-cli containerd.io
sudo apt-get install --only-upgrade \
docker-ce docker-ce-cli containerd.io \
docker-buildx-plugin docker-compose-plugin
docker version --format 'server={{.Server.Version}}'
发行版自带 docker.io、Mirantis、云厂商或企业镜像应使用对应渠道的 backport/advisory,不能假定 package version 与 Docker CE 完全相同。
第四步:让新的默认 profile 真正生效
Docker 官方说明升级到 29.4.3+ 后,restart daemon 足以加载更新后的 Docker 默认缓解,不需要为了 Engine 配置本身 reboot:
sudo systemctl restart docker
sudo systemctl --no-pager --full status docker
docker info --format '{{json .SecurityOptions}}'
daemon restart 可能影响没有启用 live-restore、重启策略不完整或依赖控制面的容器。必须在维护窗口确认 workload 状态,而不是在高峰直接执行。
AppArmor 主机检查:
sudo aa-status
SELinux 主机检查:
getenforce
docker info --format '{{json .SecurityOptions}}'
Docker release notes 明确指出 SELinux mitigation 需要 daemon 配置 selinux-enabled: true 或使用 --selinux-enabled。系统安装了 SELinux package、但 Docker integration 未启用,不代表规则已经作用于容器。
custom seccomp/AppArmor profile 不会自动神奇继承所有新版 default 规则。需要把它们与当前 Docker default profile 做差异审查,并在兼容测试后发布。不要复制来源不明的 JSON profile。
29.4.2 的 32 位回归应该怎样处理
Docker 29.4.2 的已知问题可能表现为 i386 image、32 位 Go、SteamCMD、Wine 等网络失败。正确方向是升级到 29.4.3 或更高,并测试 Docker 新的 AppArmor/SELinux 方案。
不要使用:
--security-opt seccomp=unconfined
seccomp/v0.2.0
privileged: true
Docker 文档曾为特定场景提供 seccomp/v0.2.1 compatibility profile,但同时明确警告:使用该 profile 的容器仍可能通过 socketcall 触达 CVE-2026-31431。只有 host kernel 已修复且 workload 确实需要时才评估这种兼容配置,不能把它当安全修复。
临时 mitigation 只用于无法及时更新的主机
Docker 官方给出的临时方向包括 blacklist af_alg 与 algif_aead modules,或使用正确的 custom seccomp profile 阻止 AF_ALG。
模块 blacklist 仅在相关功能编译为 loadable module 时有效;若内核把它编译为 built-in,则不会生效。可以检查当前 kernel config:
grep -E 'CONFIG_CRYPTO_USER_API|CONFIG_CRYPTO_USER_API_AEAD' \
"/boot/config-$(uname -r)"
不要在不了解依赖的情况下在线 modprobe -r:正在使用 AF_ALG 的应用可能中断。blacklist 也通常要结合 initramfs、reboot 和发行版方式处理。临时 mitigation 应有到期时间,并在 kernel patch 后移除或重新评估。
Kubernetes、containerd 与 Docker Desktop 怎么看
Kubernetes 节点如果直接使用 containerd/CRI-O,升级 Docker Engine 不会改变它的 runtime profile。必须优先修复 host kernel,并核对 Kubernetes Pod Security、seccomp、AppArmor/SELinux 配置。
Docker Desktop 的 Linux container 运行在受控 VM 中,Engine 与 kernel 更新由 Desktop release 一起交付。不要只升级宿主 macOS/Windows Docker CLI;应安装 Docker Desktop 官方当前安全版本并确认内部 Engine 已更新。
多租户 CI、在线代码执行、构建平台和允许用户上传插件的服务优先级最高,因为它们更容易满足“容器内已有不可信代码执行”这一前置条件。
验证修复不要运行公开 exploit
生产验收不需要执行 Copy Fail PoC。足够的证据包括:
- Vendor tracker 将当前安装并运行的 kernel package 标记为 fixed。
- Reboot 后 uname -r 与安全包版本一致。
- Docker server version 达到当前受支持版本且不低于 29.4.3。
- Docker daemon restart 完成,AppArmor/SELinux/seccomp 状态符合设计。
- 没有未经审批的 privileged/unconfined/custom profile 绕过。
- 32 位、SteamCMD、Wine 和关键网络 workload 回归通过。
- 容器、节点、日志、监控与编排控制面恢复正常。
漏洞扫描器可能只根据版本字符串判断,遇到发行版 backport 时会误报或漏报。应把 vendor advisory、已安装 package、运行 kernel 和 daemon profile 证据一起保留。
灰度、回滚与应急
先在同 kernel flavor、同 LSM 与同 32 位 workload 的 canary node 升级,再 drain/替换生产节点。Kubernetes 环境应遵循 PodDisruptionBudget 与容量计划;单机 Docker 要验证 restart policy、volume 与外部队列。
如果新 kernel 引发硬件或驱动回归,可以启动另一个同样包含 CVE 修复的受支持 kernel,而不是永久退回已知 vulnerable kernel。若 Docker 新版出现应用兼容问题,应回滚业务配置或切换另一个包含 29.4.3+ mitigation 的受支持 Engine 版本,不能退回 29.4.2 并关闭 seccomp。
发现疑似利用迹象时,不要只 patch 后继续运行:隔离节点、保全日志和内存/磁盘证据、轮换宿主与 workload credentials、重建受影响 node,并检查共享 image layer 和其他 container workload。
完成检查清单
- 每个节点的发行版、kernel package、运行 kernel 和 Docker server version 已盘点。
- Vendor tracker 确认当前运行 kernel 已修复 CVE-2026-31431。
- Kernel 更新后已 reboot,并核对 uname -r。
- Docker Engine 使用当前支持版本且不低于 29.4.3。
- Docker daemon 已 restart,AppArmor/SELinux/seccomp 状态符合设计。
- custom profile、privileged、unconfined 与其他 runtime 已独立审查。
- 29.4.2 的 32 位回归没有通过降低隔离强度解决。
- 32 位、SteamCMD、Wine、网络和关键业务回归通过。
- 多租户与运行不可信代码的节点已优先完成轮换。
- 回滚目标仍包含 kernel fix 与 Docker mitigation。
