0/849 已展开

LLM 分析

Linux 5.15 stable:5.15.212-rc1 超大规模修复审查

系列概况

  • 标题[PATCH 5.15 000/843] 5.15.212-rc1 review
  • 作者:稳定版系列由 Greg Kroah-Hartman 发布;补丁来自多个上游作者,并由稳定版维护者回移。
  • 版本:Linux 5.15.212-rc1。
  • 规模:843 个正式补丁,加 1 封封面邮件和 5 封回复,共 849 封邮件。
  • 修改文件:跨越 NVMe、NFS、F2FS、网络、调度器、KVM、BPF、USB、PCI、perf、ALSA、IIO、加密、文件系统及大量设备驱动。输入未提供完整汇总文件清单。
  • 代码统计:封面邮件称提供了 diffstat,但输入中的封面正文在 shortlog 中途截断,无法可靠给出全系列增删行总数。部分补丁各自带有局部统计。
  • Message-ID20260721152405.946368001@linuxfoundation.org
  • 完整性:补丁编号 000/843843/843 均出现,编号层面完整;但大量邮件正文为空,若只依赖本次输入,不能逐项核验这些补丁的 commit message、diff 和依赖关系。

尽管来源频道标为 sched,这不是单独的 scheduler 系列,而是一次覆盖整个 Linux 5.15 稳定树的发布候选审查。

补丁目的

该系列准备 Linux 5.15.212 稳定版,目标是把已经进入上游或其他稳定树的修复安全地回移到 5.15.y,并在正式发布前收集构建、启动和运行回归报告。

整体重点包括:

  1. 修复 use-after-free、越界访问、整数溢出、空指针和信息泄漏。
  2. 修复锁顺序、引用计数、资源释放及设备移除竞态。
  3. 加强文件系统、网络协议、固件和设备返回数据的边界检查。
  4. 修正 scheduler、RT mutex、CPU hotplug、cpufreq 和 perf 等核心路径。
  5. 为 5.15 的旧 API 和旧数据结构进行上下文适配。

旧流程的问题

多个补丁反映了相似的旧流程缺陷:

  • 外部长度、索引或状态值未经验证便参与数组访问、位移或长度计算。
  • 对象已经进入销毁阶段,异步工作、socket 回调或错误路径仍可能再次操作它。
  • 数据结构被移动或拆分时,配套的所有权位图、引用计数或状态位没有同步移动。
  • 错误路径直接释放已发布对象,没有先从 IDR、RCU 列表或注册表中摘除。
  • 旧稳定树直接接受较新内核 API 的调用,可能缺少函数、类型或结构成员。
  • 部分调度决策统计了任务不允许运行的 CPU,或者为非 PREEMPT_RT 配置启用了代价较高的 RT push IPI。

新流程

新流程普遍采用“先验证、再变更;先阻止新使用者、再释放”的顺序:

Upstream fixes
      |
      v
5.15 backport and context adaptation
      |
      v
843-patch stable review ---> build and runtime testers
      |                              |
      |                              v
      +---------------------- regression reports
                                     |
                                     v
                           fix, dependency, or drop

典型防护逻辑可以概括为:

if (!entry_is_valid(entry))
	return -EINVAL;

lock_object_state();
if (object_is_tearing_down())
	return -ESHUTDOWN;

update_state_and_ownership_together();

对于无锁页表重检,则只在条目确实为 present PTE 时解释写权限位,避免把 swap 或 migration entry 的 offset 位误当成权限位。

Patch 概览

范围或补丁作用
001串行化 NVMe/TCP ICReq 完成与 queue teardown,防止重复释放
003–015修复 NFSD stateid 生命周期并整理 recovery 数据所有权
005userfaultfd 只对 present PTE 检查 write bit
016KVM ioeventfd 使用 get_unaligned(),移除 guest 可触发的 BUG_ON()
018修复 nftables 删除 set 失败后的事务回滚
019–020sk_msg.sg.copy 攓为位图,并在 SG 变换中保持同步
021–023修复 AppArmor 引用竞态、netns 权限检查和 Fast Open connect 绕过
024–033F2FS 元 inode、损坏镜像、zone capacity、xattr 与 GC 死锁修复
044–045修正 rtmutex waiter 删除对象及未入队 waiter 处理
117非 PREEMPT_RT 配置默认关闭 RT_PUSH_IPI
199fair scheduler 选择目标组时只统计任务允许的 CPU
405–440集中修复 perf 工具的空文件、长度、格式化和边界问题
620修复 MIPS scheduler 在 CPUMASK_OFFSTACK 下的内存破坏
765–770PCI Resizable BAR 失败回滚、资源树恢复及代码整理
843修复 ALSA sequencer 事件复制中的未初始化堆数据泄漏

关键实现

1. NVMe/TCP queue teardown 状态机

nvmet_tcp_handle_icreq() 原来可能在 teardown 已把队列设为 DISCONNECTING 后,又写回 LIVE 或失败状态,导致后续 socket 状态变化再次进入释放路径并执行第二次 kref_put()

补丁在发送 ICResp 后使用 state_lock 检查状态;若 teardown 已开始,返回内部哨兵 -ESHUTDOWN。接收状态仍保持 NVMET_TCP_RECV_ERR,防止旧 ICReq 被再次解析。

ICReq consumed             socket closes
      |                          |
      v                          v
   io_work                 DISCONNECTING
      |                          |
      +------ state_lock --------+
                    |
             already tearing down?
               /            \
             yes             no
              |               |
        -ESHUTDOWN          set LIVE

2. F2FS 的边界与死锁修复

F2FS 补丁形成一个相对完整的防护组:

  • 拒绝损坏目录项把普通 inode 指向内部 meta inode。
  • 只在 compress_cache 启用时把压缩缓存 inode 视为内部 inode。
  • 校验 orphan block 的 entry_count,防止越过 ino[]
  • 无论 inode 是否带 inline-xattr 标志,都限制磁盘提供的最大 inline xattr size。
  • 使用 zone capacity 而不是物理 section 大小计算有效块。
  • pinned file 的 fallocate 起点向 section 边界下取整。
  • foreground GC 前提交缓存的 OPU/IPU DATA bio,避免 GC 与 writeback 围绕同一 folio 互相等待。

3. sk_msg.sg.copy 所有权同步

sg.copy 表示对应 scatterlist entry 是否来自不能向 BPF 暴露为可写内存的外部页。

旧代码移动 sg.data[] 时没有移动该位,可能把 page-cache 页移动到一个 copy 位为 0 的槽中,使 BPF 获得错误的可写视图。019 先把单个 unsigned long 改为可扩展位图,020 再覆盖 pull、push、pop、shift、xfer 和 TLS split 等变换路径。

4. scheduler 与锁路径

  • sched/fair 选择 destination group 时只更新任务 cpumask 允许 CPU 的统计,避免不可达 CPU 扭曲负载均衡结果。
  • sched/rt 对普通非 PREEMPT_RT 内核默认关闭 RT_PUSH_IPI,减少不必要的跨 CPU push 中断行为。
  • rtmutex 补丁使用 waiter->task 而不是假定 current,且 waiter 未实际入队时不再调用删除逻辑。
  • MIPS scheduler 修复动态 cpumask 存储使用错误导致的内存破坏。

5. 审查中发现的 perf 构建回归

Florian Fainelli 报告 5.15.212-rc1 的 perf 构建失败,错误指向:

  • perf_env__get_cpu_topology() 在 5.15 工具代码中没有声明;
  • (struct perf_cpu){ al->cpu } 与该树的数据结构不匹配。

这与补丁 406 perf tools: Use perf_env__get_cpu_topology() in machine__resolve() 高度相关,说明回移时可能遗漏前置 API 或结构体转换。它是本线程中最明确的 RC 阻塞项,不能仅凭内核本体构建成功而忽略。

类比

这次 stable review 像一次大型旧楼翻修:843 个补丁分别加固电线、消防门、电梯和水管。很多修复本身来自新楼的成熟方案,但 5.15 是旧楼,接口尺寸和管线位置不同,不能把新零件原样塞进去。

sk_msg.sg.copy 类似货箱上的“不可拆封”标签:搬动货箱时必须连标签一起搬。只移动箱子、不移动标签,就可能让下一位工人误把外部所有的货物当成可修改物品。

perf 回归则像消防系统改造完成后,发现维护人员的检测仪插头与旧楼插座不兼容:修复意图正确,但回移缺少配套接口,发布前仍必须修正。

Highlight:风险与注意点

  • 明确构建阻塞:perf 的 perf_env__get_cpu_topology() 缺失或 API 不匹配需要在发布前解决。
  • 系列过大:843 个补丁横跨全树,单一 RC 中的交互风险和二分成本都很高。
  • 输入内容不完整:大量邮件正文为空,无法从本次材料审计每个补丁的实际 diff、签名链和依赖。
  • 回移语义风险:多个补丁明确进行了 5.15 专用改写,不能仅依据上游测试结果确认正确性。
  • 调度语义变化RT_PUSH_IPI 默认值和 allowed-CPU 统计会改变特定负载下的迁移行为,需要 RT、cpuset、CPU hotplug 和 NUMA 场景测试。
  • 安全修复密集:系列包含大量 UAF、OOB、权限绕过和信息泄漏修复,应避免因普通硬件测试通过而低估其重要性。
  • 依赖顺序重要:019→020、026→027、031→032、765→770 等补丁需要按系列顺序应用。

版本变化

本线程只提供 5.15.212-rc1,没有 v2 或 rc2。

不过可见多处上游到 5.15 的适配:

  • NVMe/TCP 删除了 5.15 尚不存在的 NVMET_TCP_Q_FAILED 相关 hunk。
  • userfaultfd 将新树的 marker/return 风格改写为 5.15 原有函数结构。
  • KVM 使用旧树的 <asm/unaligned.h>
  • AppArmor 展开了 5.15 中不存在的 sk_is_tcp()
  • NFSD 因 5.15 没有 ls_fence_work,删除了对应初始化 hunk。

一句话总结

5.15.212-rc1 是一组以安全性、并发正确性和边界校验为主的超大稳定版回移,但当前已出现明确的 perf 旧树 API 构建回归,修复并完成跨架构验证后才适合发布。