CVE-2026-31431 漏洞修复说明

最近更新时间:2026-05-04 10:35:57

我的收藏

CVE-2026-31431 漏洞修复说明

背景

CVE-2026-31431(又称 Copy Fail)是 Linux 内核 crypto 子系统中的一个高危本地提权漏洞,问题位于 algif_aead 模块,即内核 userspace crypto API 的 AEAD socket 接口(AF_ALG)。该漏洞可通过 AF_ALG + splice() 影响内核 page cache,攻击者在已能于节点上执行用户态代码的前提下,可能进一步提权至节点 root,或产生跨容器影响(同一宿主机上的进程共享内核 page cache)。Linux kernel 社区对该漏洞的修复描述为:crypto: algif_aead - Revert to operating out-of-place。具体信息详见【安全通告】Linux Kernel 本地权限提升漏洞风险通告(CVE-2026-31431)

影响范围

受影响版本:
Linux 内核:包含 CONFIG_CRYPTO_USER_API_AEAD=m=y 编译配置、且尚未应用 CVE-2026-31431 修复补丁的版本。
TKE 节点:运行上述受影响内核版本的普通节点原生节点超级节点
注册节点:操作系统由用户自行控制,需用户自行评估内核版本及风险。
说明:
若内核编译时 CONFIG_CRYPTO_USER_API_AEAD=n(未编译该模块),则天然免疫,无需操作。
攻击条件:
攻击者需已能够在目标节点的容器或用户态进程中执行代码(如通过容器逃逸、exec 权限、恶意镜像等方式获得节点执行能力),方可尝试利用此漏洞进行本地提权。该漏洞不可远程直接利用,但在多租户集群、CI/CD Runner 集群、开放 exec/debug 权限的集群中风险更高。
以下集群需要重点关注:
集群类型
风险说明
多租户集群
不可信用户可提交 Pod,风险高
CI/CD Runner 集群
构建任务通常执行不可信代码,风险高
在线业务混部集群
单业务容器被攻破后可能影响整节点
开放 exec / debug 权限的集群
攻击者更容易获得容器内代码执行能力
运行高权限 Pod 的集群
漏洞利用后横向风险更大
GPU / MaaS 推理集群
通常承载第三方模型、代码、插件或用户任务,需要重点评估

修复建议

一、彻底修复(推荐)

不同节点类型的根治方案不同:
普通节点的操作系统由 CVM 镜像提供。请关注 CVM 公共镜像更新记录,在包含 CVE-2026-31431 修复补丁的镜像版本发布后
新建节点默认使用修复版本,天然不受此漏洞影响。
存量节点可通过置换节点完成根治:先对节点执行驱逐(drain)将业务 Pod 迁移至其他节点,再将旧节点移出集群,最后新建节点加入集群(新节点默认使用修复版本镜像)。
原生节点的操作系统由 TKE 统一管控。请关注 TKE 后续公告更新,在 TKE 发布包含修复补丁的节点镜像后
新建节点默认使用修复版本,天然不受此漏洞影响。
存量节点可通过置换节点完成根治:先对节点执行驱逐(drain)将业务 Pod 迁移至其他节点,再将旧节点移出集群,最后新建节点加入集群(新节点默认使用修复版本镜像)。
超级节点的底层节点资源由 TKE 统一管控。请关注 TKE 后续公告更新,在 TKE 发布修复后
新建 Pod 默认运行在修复版本的节点上,天然不受此漏洞影响。
存量 Pod 可通过重建 Pod(删除后由控制器重新调度)使其重建完成根治。

二、临时缓解(内核升级前)

临时缓解不能替代内核升级,请尽快完成彻底修复。
在完成节点 OS 升级前,可采用临时缓解措施降低攻击面。普通节点 / 原生节点 / 超级节点默认不加载 algif_aead,整体风险较低。临时缓解通过 DaemonSet 写入 /etc/modprobe.d 黑名单并卸载模块。该 DaemonSet 须使用高权限(hostPID/hostNetwork/privileged),属于节点级高危变更,必须先 canary 后全量
Step 1:选择 1~3 台低风险节点预检并打标:
单节点预检命令:可以先在少量节点上执行。
uname -r
lsmod | grep '^algif_aead' || echo "algif_aead not loaded"
modinfo algif_aead 2>/dev/null || echo "algif_aead module not found or built-in"
test -f /etc/modprobe.d/blacklist-algif_aead.conf && \\
cat /etc/modprobe.d/blacklist-algif_aead.conf || \\
echo "blacklist config not found"
检查结果
结论
lsmod 能看到 algif_aead
当前运行态存在风险,需要卸载
配置文件不存在
重启后仍可能被自动加载,需要修复
只有 blacklist algif_aead
建议增强为 install algif_aead /bin/false
modinfo 查不到,但功能仍存在
可能是 built-in 或路径差异,需要进一步确认
模块正在被使用,无法卸载
需结合业务评估,可能要通过节点重启生效
预检完成后,对节点打上标签:
kubectl label node <node-1> algif-aead-fix=canary
kubectl label node <node-2> algif-aead-fix=canary
Step 2:保存为 disable-algif-aead-canary.yaml 并部署 Canary DaemonSet:
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: disable-algif-aead
namespace: kube-system
labels:
app: disable-algif-aead
spec:
selector:
matchLabels:
app: disable-algif-aead
updateStrategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 1
template:
metadata:
labels:
app: disable-algif-aead
spec:
hostPID: true
hostNetwork: true
tolerations:
- operator: Exists
nodeSelector:
algif-aead-fix: canary
restartPolicy: Always
containers:
- name: disable-algif-aead
image: busybox:1.36
imagePullPolicy: IfNotPresent
securityContext:
privileged: true
volumeMounts:
- name: host-root
mountPath: /host
readOnly: false
command:
- /bin/sh
- -c
- |
set -eu

MODULE="algif_aead"
CONF="/host/etc/modprobe.d/blacklist-algif_aead.conf"
STATE_DIR="/host/var/lib/cve-2026-3143"
STATE_FILE="${STATE_DIR}/pre-fix-state.json"
ROLLBACK_DONE="${STATE_DIR}/rollback-done"

echo "[INFO] node=$(hostname) start precheck"

mkdir -p /host/etc/modprobe.d
mkdir -p "${STATE_DIR}"

# ========== 清理上一次回滚标记(支持反复 disable/rollback) ==========
if [ -f "${ROLLBACK_DONE}" ]; then
echo "[FIX] clearing previous rollback marker"
rm -f "${ROLLBACK_DONE}"
fi

# ========== 记录禁用前状态(用于回滚) ==========
MODULE_LOADED="false"
MODULE_LINE=""
if grep -q "^${MODULE} " /proc/modules; then
MODULE_LOADED="true"
MODULE_LINE=$(grep "^${MODULE} " /proc/modules)
fi

CONF_EXISTED="false"
CONF_BACKUP=""
if [ -f "${CONF}" ]; then
CONF_EXISTED="true"
CONF_BACKUP=$(cat "${CONF}" 2>/dev/null || echo "")
fi

# 仅首次执行时写入状态文件,避免重复运行覆盖原始状态
if [ ! -f "${STATE_FILE}" ]; then
cat > "${STATE_FILE}" <<SNAP
{
"timestamp": "$(date -u '+%Y-%m-%dT%H:%M:%SZ')",
"hostname": "$(hostname)",
"kernel": "$(uname -r)",
"module_was_loaded": ${MODULE_LOADED},
"module_proc_line": "${MODULE_LINE}",
"blacklist_conf_existed": ${CONF_EXISTED},
"blacklist_conf_backup": "${CONF_BACKUP}",
"cve": "CVE-2026-3143"
}
SNAP
chmod 0644 "${STATE_FILE}"
echo "[STATE] pre-fix state saved to ${STATE_FILE}"
else
echo "[STATE] state file already exists, skip (idempotent)"
fi

echo "[STATE] recorded state:"
cat "${STATE_FILE}"

# ========== Precheck ==========
if [ "${MODULE_LOADED}" = "true" ]; then
echo "[PRECHECK] ${MODULE} is loaded: ${MODULE_LINE}"
else
echo "[PRECHECK] ${MODULE} is not loaded"
fi

if [ "${CONF_EXISTED}" = "true" ]; then
echo "[PRECHECK] existing config:"
echo "${CONF_BACKUP}"
else
echo "[PRECHECK] config not found"
fi

# ========== Fix ==========
echo "[FIX] writing blacklist config"
cat > "${CONF}" <<EOF
# Managed by TKE DaemonSet disable-algif-aead
# CVE: CVE-2026-3143
blacklist algif_aead
install algif_aead /bin/false
EOF

chmod 0644 "${CONF}"
sync

echo "[FIX] try to unload ${MODULE}"
if grep -q "^${MODULE} " /proc/modules; then
if chroot /host /sbin/modprobe -r "${MODULE}" 2>/tmp/modprobe-r.err; then
echo "[FIX] modprobe -r ${MODULE} succeeded"
else
echo "[WARN] modprobe -r failed:"
cat /tmp/modprobe-r.err || true

if chroot /host /sbin/rmmod "${MODULE}" 2>/tmp/rmmod.err; then
echo "[FIX] rmmod ${MODULE} succeeded"
else
echo "[ERROR] failed to unload ${MODULE}:"
cat /tmp/rmmod.err || true
fi
fi
else
echo "[FIX] ${MODULE} is not loaded, skip unload"
fi

# ========== Postcheck ==========
echo "[POSTCHECK] config:"
cat "${CONF}"

if grep -q "^${MODULE} " /proc/modules; then
echo "[POSTCHECK][FAIL] ${MODULE} is still loaded"
else
echo "[POSTCHECK][OK] ${MODULE} is not loaded"
fi

while true; do
sleep 3600
done
volumes:
- name: host-root
hostPath:
path: /
type: Directory
kubectl apply -f disable-algif-aead-canary.yaml

# 观察(成功标准:日志出现 [POSTCHECK][OK] algif_aead is not loaded)
kubectl -n kube-system get pod -l app=disable-algif-aead -o wide
kubectl -n kube-system logs -l app=disable-algif-aead --tail=50
Step 3:Canary 通过后,删除 YAML 中的 nodeSelector 段,全量 apply:
kubectl apply -f disable-algif-aead.yaml
kubectl -n kube-system rollout status ds/disable-algif-aead --timeout=10m
kubectl -n kube-system get ds disable-algif-aead
修复后检查
# DaemonSet 状态(期望 DESIRED = READY)
kubectl -n kube-system get ds disable-algif-aead

# 日志检查(成功标准: [POSTCHECK][OK] algif_aead is not loaded)
kubectl -n kube-system logs -l app=disable-algif-aead --tail=300 | grep -E "POSTCHECK|ERROR|WARN|FAIL|OK"

# 抽样检查宿主机配置
POD=$(kubectl -n kube-system get pod -l app=disable-algif-aead -o jsonpath='{.items[0].metadata.name}')
kubectl -n kube-system exec "$POD" -- cat /host/etc/modprobe.d/blacklist-algif_aead.conf
kubectl -n kube-system exec "$POD" -- grep '^algif_aead ' /proc/modules || echo "not loaded - OK"

# 节点与业务状态
kubectl get nodes
kubectl get events -A --sort-by='.lastTimestamp' | tail -100
重点确认没有新增:NodeNotReady / MemoryPressure / DiskPressure / PIDPressure / NetworkUnavailable / FailedCreatePodSandBox / FailedMount,以及业务层面的 Pod 重启、错误率、CNI/DNS 连通性、存储挂载、GPU 调度(含 NVIDIA device plugin)是否正常;若有自研加密组件、IPsec 或依赖内核 crypto API 的场景,需额外确认。

异常处理与回滚

若模块卸载失败(rmmod: ERROR: Module algif_aead is in use),不要强制破坏业务进程,确认配置文件已写入后记录该节点为"已配置未卸载",业务低峰重启或替换节点。若日志出现 [POSTCHECK][FAIL] algif_aead is still loaded,说明配置已落盘但运行态卸载失败,常见原因包括:模块正在被使用、模块为 built-in、节点缺少 modprobe/rmmod、安全策略阻止卸载。
若 DaemonSet Pod 无法启动,常见原因为 PSP / OPA / Gatekeeper 策略阻止特权容器,需临时为 kube-system 命名空间放开 k8sPSPPrivilegedContainerk8sPSPHostNamespacek8sPSPHostNetworkingPorts 限制,修复完成后恢复。
若节点出现异常,先诊断,如节点承载关键业务则立即驱逐后回滚或替换节点:
kubectl describe node <node-name>
kubectl get events -A --sort-by='.lastTimestamp' | tail -200
# 关键业务节点:先驱逐
kubectl cordon <node-name>
kubectl drain <node-name> --ignore-daemonsets --delete-emptydir-data
若业务出现异常(加密、网络、安全组件等),立即停止扩大范围,执行:
kubectl -n kube-system delete ds disable-algif-aead
然后执行下方回滚 DaemonSet 恢复配置。回滚动作包括:删除宿主机黑名单配置、可选重新加载 algif_aead、检查业务恢复情况。注意删除 DaemonSet 只会删除 Pod,不会自动删除宿主机上的配置文件,需通过以下回滚 DaemonSet 清理。
保存为 rollback-algif-aead.yaml 并执行:
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: rollback-algif-aead
namespace: kube-system
labels:
app: rollback-algif-aead
spec:
selector:
matchLabels:
app: rollback-algif-aead
updateStrategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 1
template:
metadata:
labels:
app: rollback-algif-aead
spec:
hostPID: true
hostNetwork: true
tolerations:
- operator: Exists
restartPolicy: Always
containers:
- name: rollback-algif-aead
image: busybox:1.36
imagePullPolicy: IfNotPresent
securityContext:
privileged: true
volumeMounts:
- name: host-root
mountPath: /host
readOnly: false
command:
- /bin/sh
- -c
- |
set -eu

MODULE="algif_aead"
CONF="/host/etc/modprobe.d/blacklist-algif_aead.conf"

echo "[ROLLBACK] node=$(hostname) start rollback"

if [ -f "${CONF}" ]; then
echo "[ROLLBACK] remove ${CONF}"
rm -f "${CONF}"
sync
else
echo "[ROLLBACK] config not found, skip"
fi

echo "[ROLLBACK] try to reload ${MODULE}, optional"
if grep -q "^${MODULE} " /proc/modules; then
echo "[ROLLBACK] ${MODULE} already loaded"
else
if chroot /host /sbin/modprobe "${MODULE}" 2>/tmp/modprobe.err; then
echo "[ROLLBACK] modprobe ${MODULE} succeeded"
else
echo "[WARN] modprobe ${MODULE} failed; module may be unavailable or not required"
cat /tmp/modprobe.err || true
fi
fi

if [ -f "${CONF}" ]; then
echo "[POSTCHECK][FAIL] config still exists"
else
echo "[POSTCHECK][OK] config removed"
fi

if grep -q "^${MODULE} " /proc/modules; then
echo "[POSTCHECK] ${MODULE} is loaded"
else
echo "[POSTCHECK] ${MODULE} is not loaded"
fi

while true; do
sleep 3600
done
volumes:
- name: host-root
hostPath:
path: /
type: Directory
kubectl apply -f rollback-algif-aead.yaml

# 观察
kubectl -n kube-system get pod -l app=rollback-algif-aead -o wide
kubectl -n kube-system logs -l app=rollback-algif-aead --tail=200
# 成功后清理
kubectl -n kube-system delete ds rollback-algif-aead

常见问题

TKE 普通 / 原生 / 超级节点默认有风险吗?

默认情况下,这三种节点的操作系统由 TKE 管控,均不会开启 algif_aead 模块,整体风险较低。注册节点需用户自行评估。

禁用 algif_aead 是否会影响 HTTPS、SSH、普通 TLS?

通常不会。普通 TLS/SSH/OpenSSL 使用用户态 crypto 库,不依赖 algif_aead。如有自研内核加密组件或 IPsec 场景,需先灰度验证。

DaemonSet 临时修复后是否还需要升级内核?

需要。DaemonSet 仅是临时缓解,根治需升级到含 CVE-2026-31431 修复补丁的内核或节点镜像。

为什么要写 install algif_aead /bin/false,而不是只写 blacklist

blacklist 主要阻止自动加载,install algif_aead /bin/false 进一步阻止手动 modprobe,两者同时配置安全加固效果更强。

DaemonSet 为什么需要 privileged 权限?

需要修改宿主机 /etc/modprobe.d 并执行内核模块卸载,没有 privileged 和宿主机根目录挂载无法完成操作。

集群开了 PSP 怎么办?

若开启了 k8sPSPPrivilegedContainerk8sPSPHostNamespacek8sPSPHostNetworkingPorts 且未豁免 kube-system,需先临时放开 kube-system 命名空间,修复完成后恢复。超级节点方案不受此限制影响。

如果修复后有业务异常怎么办?

立即停止扩大范围,参见上方 异常处理与回滚 章节执行回滚。