cozystack/copy-fail-blocker

GitHub: cozystack/copy-fail-blocker

一个基于 BPF-LSM 的 Kubernetes DaemonSet,通过拦截 AF_ALG 套接字创建来即时缓解 CVE-2026-31431 提权漏洞,无需重启节点。

Stars: 17 | Forks: 2

# copy-fail-blocker 针对 [CVE-2026-31431](https://copy.fail/)(“Copy Fail”)以及依赖于用户空间访问 Linux 内核 crypto API(`AF_ALG` / `algif_*`)的类似提权漏洞的 BPF-LSM 缓解方案。 一个小型 DaemonSet 在每个节点上附加了一个 BPF-LSM 程序到 `socket_create` 钩子。该程序对所有 `socket(AF_ALG, ...)` 调用返回 `-EPERM`,无论其进程 capabilities、namespace 或 seccomp profile 如何。 已在 Talos Linux 上测试(自 v1.10 起,默认附带 `CONFIG_BPF_LSM=y` 且 LSM 栈中包含 `bpf`),适用于任何具有相同内核配置的发行版。 ## 为什么需要它 CVE-2026-31431 是 `algif_aead` 中的一个逻辑缺陷,它允许无特权的本地用户对任何 setuid 二进制文件执行 4 字节的页缓存写入,只需一个 732 字节的 Python 脚本即可获得 root 权限。该漏洞利用仅需要 `AF_ALG` + `splice()`,而在默认情况下,任何无特权的进程都可以访问它们。 正确的修复方法是打内核补丁(主线 `a664bf3d603d`)。在您的发行版包含该补丁之前,可以通过阻止用户空间打开 `AF_ALG` 套接字来消除攻击面。与其他替代方案相比: | 缓解措施 | 覆盖范围 | 需要重启? | 持久性? | | ------------------------------------------- | ----------------------- | --------- | --------------- | | `module_blacklist=algif_aead` (内核参数) | 全主机 | 是 | 是 | | 不包含 `CRYPTO_USER_API_AEAD` 的自定义内核 | 全主机 | 是 | 是 | | 按 pod 自定义的 seccomp profile | 仅带标签的工作负载 | 否 | 是 | | **copy-fail-blocker (本项目)** | **全主机** | **否** | DaemonSet 运行期间 | 本项目提供的是无需重启的选项。在整个集群中运行它,然后按照您正常的补丁更新计划安排永久的内核修复。 ## 工作原理 `bpf/blocker.c` 是一个 15 行的 BPF-LSM 程序: ``` SEC("lsm/socket_create") int BPF_PROG(block_af_alg, int family, int type, int protocol, int kern, int ret) { if (ret) return ret; if (family == AF_ALG) // 38 return -EPERM; return 0; } ``` Go 加载器(`main.go`,约 40 行)加载该程序并通过 `bpf(BPF_LINK_CREATE)` 进行附加。在 pod 的整个生命周期内,该链接会一直保持。在收到 `SIGTERM` 时,链接将关闭,钩子随之分离。 这要求内核在编译时启用了 `CONFIG_BPF_LSM=y`,并且活动的 LSM 栈中包含 `bpf`(在内核命令行中设置为 `lsm=...,bpf`)。Talos Linux 自 v1.10 起默认启用了这两项。 ## 安装 ### kubectl ``` kubectl apply -f https://raw.githubusercontent.com/cozystack/copy-fail-blocker/v0.2.1/manifests/copy-fail-blocker.yaml ``` 获取 `main` 分支上的最新提交(可能包含未发布的更改): ``` kubectl apply -f https://raw.githubusercontent.com/cozystack/copy-fail-blocker/main/manifests/copy-fail-blocker.yaml ``` ### Helm 该 chart 未作为 OCI 构件发布(其注册表路径与容器镜像共享)。请从带有 tag 的检出中进行安装: ``` git clone --branch v0.2.1 https://github.com/cozystack/copy-fail-blocker cd copy-fail-blocker helm upgrade --install copy-fail-blocker charts/copy-fail-blocker \ --namespace kube-system ``` 或者通过 Makefile 快捷方式: ``` make apply # helm upgrade --install into kube-system make diff # preview changes against the cluster make delete # uninstall make manifest # regenerate manifests/copy-fail-blocker.yaml ``` 该 DaemonSet 必须以特权模式运行(它会加载 BPF 程序并写入 bpffs)。请将其放置在具有 privileged Pod Security Standard 的命名空间中,或放置在默认具有特权的 `kube-system` 中。 ## 验证 从受覆盖节点上的任意 pod 中执行: ``` python3 -c ' import socket try: socket.socket(socket.AF_ALG, socket.SOCK_SEQPACKET, 0) print("FAIL: AF_ALG socket created") except OSError as e: print("OK:", e)' ``` 预期输出: ``` OK: [Errno 1] Operation not permitted ``` ## 构建 ``` make image # docker buildx build + push make image REGISTRY=ghcr.io/myorg TAG=v0.2.1 # custom tag make image PUSH=0 LOAD=1 # build locally without pushing ``` `make image` 会使用解析出的镜像摘要来更新 `charts/copy-fail-blocker/values.yaml`,以便 chart 始终通过摘要进行固定。 构建依赖项位于 Containerfile 中(clang、libbpf-dev、Go)。本地主机只需要 `docker buildx`、`helm`、`yq` (mikefarah)、`kubectl` 和 `helm-diff`。 ## 配置 `charts/copy-fail-blocker/values.yaml`: | 键 | 默认值 | 备注 | | --------------------- | ------------------------------------ | -------------------------------------- | | `image.repository` | `ghcr.io/cozystack/copy-fail-blocker`| 由 `make image` 自动更新 | | `image.tag` | `v0.1.0@sha256:...` | 通过摘要固定 | | `priorityClassName` | `system-node-critical` | 确保 daemon 在驱逐中存活 | | `tolerations` | `[{operator: Exists}]` | 在每个节点上运行,包括受污染的节点 | | `resources.requests` | `5m CPU / 16Mi memory` | 附加后的空闲资源消耗 | ## 限制 - **钩子仅在 pod 运行时存在。** 在 pod 重启时,会有一个短暂的窗口期(几秒钟),在此期间 `AF_ALG` 会再次变得可访问。对于大多数威胁模型来说,这是可以接受的;如果不行,请考虑将 BPF 链接固定到 bpffs(此处未实现——参见 [issues](https://github.com/cozystack/copy-fail-blocker/issues))。 - **主机上拥有 `CAP_BPF` 和 `CAP_SYS_ADMIN` 的任何人**都可以分离该钩子。这不能替代集群范围的特权限制。 - **不会阻止 `algif_skcipher` / `algif_hash` / 等。** 该程序拒绝了整个 `AF_ALG` 系列,但目前仅已知 `algif_aead` 是可被利用的。如果未来的 CVE 需要更精细的过滤(例如,挂钩 `bind()` 并检查 `salg_type`),可以很直接地添加。 - **对已经持有打开的 `AF_ALG` 套接字的进程没有影响。** 现有套接字在关闭前将继续工作。 ## 许可证 Apache License 2.0 — 参见 [LICENSE](LICENSE)。
标签:AF_ALG, BPF-LSM, CVE-2026-31431, DaemonSet, K8s安全, Linux内核安全, LSM, setuid, Talos Linux, Web截图, Web报告查看器, 内核加密API, 内核漏洞, 子域名突变, 安全策略, 安全缓解, 容器安全, 提权防御, 提示词设计, 无重启缓解, 日志审计, 本地提权, 漏洞防御, 特权升级, 系统调用拦截, 网络安全, 请求拦截, 阻止漏洞利用, 隐私保护, 页面缓存写入