2026-06-21 内核社区日报
MGLRU 曝出 stale aging batch 导致 memcg 离线时内核警告;debugobjects 修复与并发 OOM 禁用竞态;memblock 迭代清理冗余范围检查,cpuset attach 路径重构 mempolicy 绑定;BPF exceptions 迎来 RISC‑V 64 位支持。
🧠 重点 · 内存
1. MGLRU:stale aging batch 触发 lru_gen_exit_memcg 警告
发生了什么:
报告者在 syzkaller 环境下触发了一个 warning:当 memcg 被销毁时,MGLRU 的 lru_gen_exit_memcg() 检测到仍有遗留的 aging batch 未完成,从而输出 WARNING: ... lru_gen_exit_memcg。根因是 walk_mm() 中的 reset_batch_size() 在未持有 lruvec_lock 时积累 batch,而 lru_gen_reparent_memcg() 在 memcg 离线后清零 lrugen->nr_pages,两者存在竞争。stale batch 写回后导致 lru_gen_exit_memcg 的 VM_WARN_ON_ONCE 触发。报告附带了详细的 PoC、reproducer 脚本以及一个可能的修复方向(让 reset_batch_size() 跳过已离线的 memcg)。
为什么重要:
该 warning 暴露了 MGLRU 回收路径中 reset_batch_size() 与 memcg 离线时 lru_gen_reparent_memcg() 之间的竞争,可能触发不必要的 warning。报告提供了完整的根因分析和可重现的 PoC,并给出了修复方向,有助于后续补丁的落地。
2. debugobjects:修复与并发关闭调试对象池的竞态
发生了什么:
syzbot 报告了一个涉及 hrtimer 的调试对象 splat。根因是 debugobjects 在 debug_object_assert_init() 和 debug_object_activate() 中查找 shadow 对象时,与并发的内存分配失败(Out of Memory)导致调试对象池被释放、debug_objects_enabled 置为 false 的路径发生竞态。竞态导致 lookup 返回错误指针,但 fixup 回调被无条件调用,使 timer 失效。作者提交的修复在这两个函数中,在调用 debug_print_object() 和 fixup 之前增加对 debug_objects_enabled 的检查:若已为 false,则直接返回,避免访问已释放的 shadow 对象。
为什么重要:
debugobjects 是内核调试基础设施,该竞态可能导致其他子系统的调试信息错误或 panic。修复通过简单检查终止无效调用,提高了在高并发 OOM 场景下调试基础设施的稳定性,避免了虚假告警和潜在功能失效。
3. 移除 memblock 迭代中多余的范围有效性检查
发生了什么:
memblock 的 for_each_mem_range() 和 for_each_mem_pfn_range() 迭代器保证返回的范围内 start < end,但多个调用点仍保留了无效的范围检查。该系列共 6 个补丁(由 Sang-Heon Jeon 提交)分别移除了 arm64 kasan_init_shadow、LoongArch kasan_init、riscv init 和 kasan_init、mm early_calculate_totalpages 以及 mm/hugetlb 中的这些冗余检查。
为什么重要:
移除不可达的死代码使代码更清晰,减少不必要的逻辑干扰,属于代码清理改进。
4. cpuset:将 mpol_rebind_mm() 和 cpuset_migrate_mm() 移入 cpuset_attach_task()
发生了什么:
当前 cpuset 的 attach 操作(将任务迁移到不同 cpuset)中,mempolicy rebind 和页面迁移工作分散在 cpuset_attach() 和 cpuset_fork() 等多处。作者在该 v7 系列中整理逻辑,将 mpol_rebind_mm() 和 cpuset_migrate_mm() 统一封装进 cpuset_attach_task() 内调用,以正确处理 CLONE_INTO_CGROUP 等情况。主要改动:在 attach 的公共路径中统一执行 mempolicy rebind 和页面迁移,避免因遗漏导致新创建任务使用错误的 mempolicy。
为什么重要:
修复了从 clone3(CLONE_INTO_CGROUP) 创建任务时,cpuset 可能未正确应用新的 mempolicy 和页面布局的 bug。这对容器热迁移和 cpuset 分区管理场景有意义。
5. zswap:per-cgroup 主动写回设计发布 v4 系列
发生了什么:
Hao Jia 发布了 zswap per-cgroup 主动写回设计的 v4 系列。该系列在 memory.reclaim cgroup 接口中新增 “zswap_writeback_only” key,允许用户指定压缩大小的写回预算。v3→v4 主要变更包括:放弃 per-memcg cursor、保持 root cgroup cursor;写回预算改为使用压缩后大小;合并 shrink_worker() 和 shrink_memcg() 路径的逻辑,并在 shrink_worker() 中启用批量写回。系列包含 5 个补丁:扩展 shrink_memcg() 以支持基于压缩大小的批量写回、提取辅助函数、实现主动写回接口、添加 per-memcg 统计计数(zswpwb_proactive_b)、以及相应的 selftests。
为什么重要:
zswap 当前仅在被动的 shrinker 或 pool 满时触发写回,无法针对特定 memcg 精确控制写回量。该系列允许用户在系统相对空闲时主动刷出冷压缩数据到后端交换设备,为即将到来的内存密集型工作负载提前释放内存。
6. folio refcount 可扩展性优化 v4:AI review 指出潜在 ABA race
发生了什么:
该系列尝试优化 folio refcount 的可扩展性。AI review(Sashiko)指出了一个潜在的 ABA race:T1 将 refcount 降至 0 后被中断,T2 将同一 folio 的 refcount 从 0 增加再放回(触发析构函数),随后 T3 获取该 folio(类型 Y),使得 T1 恢复后错误调用类型 X 的析构函数。作者认为该 race 因完整分配器周期而不现实,但未能完全排除;Linus 则指出,按设计 refcount 到 0 并不会自动触发析构,唯一触发析构的是后续的“0→frozen”的 cmpxchg 成功者,因此该 race 可能不成立。
为什么重要:
讨论澄清了 folio refcount 冻结与析构函数调用的并发模型:refcount 降至 0 本身不触发析构,只有成功完成冻结的 cmpxchg 才触发。这一澄清消除了对该补丁中该 ABA race 的担忧,支持了补丁的后续推进。
7. libnvdimm/labels:修复整数溢出导致越界写入
发生了什么:
__nd_label_validate() 将 on‑media 的 nslot(u32)与 sizeof_namespace_label()(返回 unsigned)相乘,结果在 32 位下回绕,使边界检查失效。之后 nd_label_data_init() 的 memset() 写入超出 config_size 缓冲区,造成越界写入。Bryam Vargas 的补丁将乘积转换为 u64 确保边界检查精确。
为什么重要:
恶意构造的标签可触发越界写入,属于安全修复,应当合入 stable。
8. BPF exceptions 支持 RISC‑V 64 位
发生了什么: Varun R Mallya 提交补丁为 RISC‑V 实现 arch_bpf_stack_walk()(依赖 CONFIG_FRAME_POINTER),使 BPF 异常处理能正确展开栈帧至异常边界。同时移除 BPF selftests 的 RISC‑V 64 位 denylist 中的 exceptions 条目。Sashiko AI 审查指出,当前实现缺少 ftrace_graph_ret_addr() 解析,当 ftrace 函数图跟踪器启用时,BPF 异常展开会失效。
为什么重要: 该支持补齐了 RISC‑V 架构在 BPF 异常处理上的关键缺失,使 BPF 程序在 RISC‑V 64 位上能正确捕获并处理异常,但 ftrace_graph_ret_addr() 缺失问题需后续修复。
🔧 其它子系统
网络
-
*xfrm:
validate_xmit_xfrm()异步加密路径修复 v5
使validate_xmit_xfrm()在异步加密(-EINPROGRESS)时返回ERR_PTR(-EINPROGRESS)而非NULL,令__dev_queue_xmit()能区分丢包与异步窃取。新增补丁修复未更新链表头->prev导致的 use-after-free(异步加密窃取 GSO segment 后validate_xmit_skb_list()解引用旧指针)。来源 -
i40e:Flow Director ATR sample rate 从 per‑ring 移动至 PF 级,并统一初始化
将atr_sample_rate从i40e_ring结构体移至i40e_pf,在i40e_sw_init()中统一初始化一次,避免每个 TX ring 配置时重复赋值。i40e_atr()函数改为引用 PF 级字段,同时atr_count类型从u8扩展为u32以匹配采样率类型。此举将全局策略统一存储,减少冗余初始化,并使采样率判读更清晰。
来源 -
wwan/t7xx:CLDMA late init 失败时遗漏 DMA pool 清理
t7xx_cldma_late_init()创建 DMA pool 后,若 ring 初始化失败,错误路径释放了 ring 但未释放 pool,导致内存泄漏。修复:在失败路径中加入dma_pool_destroy()。
来源
eBPF
- BPF exceptions 支持 RISC‑V 64
Varun R Mallya 提交 3‑patch 系列,为 riscv64 实现arch_bpf_stack_walk()(基于 frame‑pointer unwinder),更新 BPF JIT 的 prologue/epilogue 以保存 callee‑saved 寄存器(s0‑s11、返回地址和 frame‑pointer),并令bpf_jit_supports_exceptions()返回真,使内核验证器不再拒绝含 BPF 异常的 riscv64 程序。同时该系列将 riscv64 从 BPF selftest denylist 中移除,测试表明除混合 bpf‑to‑bpf 调用与 tailcall 的用例外,其余异常测试均通过。
来源
内核调试基础设施
- KUnit 现在终于支持 JUnit 格式输出
KUnit 单元测试框架现在终于能够输出 JUnit 格式,以便与标准化该格式的其他 CI 系统等实现更好的互操作性。
来源
👀 值得追的讨论 / Patch
-
将 VM_FAULT_RETRY 拆分为两个标志的方案:Suren Baghdasaryan 在邮件中提及基于 LSFMM 讨论的方案,将 VM_FAULT_RETRY 拆分为两个标志——一个用于 per-VMA lock 重试,另一个用于回退到 mmap_lock。他询问 Barry Song 是否需要帮助,但当天无具体补丁或性能数据。
来源 -
Dynamic Kernel Stacks 系列:Thomas Gleixner 指出 PoC 的两个关键问题及对收益数据的要求
Thomas Gleixner 在回复中引用了“在 schedule() 中间需要内存通常是不可行的”这一观点,但承认两个方案都确实需要在 schedule() 期间分配内存。他重点指出该 PoC 系列的两个关键问题:1) 需要在几乎所有内核代码路径(而非仅 schedule())成功分配 12k 内存,而非仅仅是 schedule();2) #PF 可能发生在几乎任何地方,扩大了 x86 维护者的担忧范围。他还要求提供实际场景下的内存节省百分比与性能权衡数据,而非仅强调聚合的 PB 级节省。
来源 -
reserve_mem 的静态内存支持
RFC v2 尝试让 reserve_mem 支持跨启动持久的内存预留(用于 kdump 等),当前讨论集中在如何与内核热保留(KHO)接口协同。
来源
⚡ 一句话速览
-
DAMON 引入
damon_nr_accesses_mvsum()以逐步移除旧nr_accesses_bp机制:SeongJae Park 提交 v1.1 系列,新增damon_nr_accesses_mvsum()函数及其测试,并在__damos_valid_target()、DAMOS region 跟踪、sysfs-schemes 等路径中替换原nr_accesses_bp逻辑,最终移除damon_warn_fix_nr_accesses_corruption()、damon_verify_reset_aggregated()、damon_verify_merge_regions_of()等函数及damon_region->nr_accesses_bp字段,同时清理相关驱动测试和 selftest。
来源 -
alloc_tag IOCTL 增强:基于分配大小的过滤:Abhishek Bapat 的补丁扩展了 /proc/allocinfo 的 ioctl 接口,为过滤机制添加了 min_size 和 max_size 参数,允许用户根据总分配字节数筛选标签。
来源 -
mm/slab: Harry Yoo 的 kfree_rcu_nolock 系列在 bpf 列表被报告存在 NULL 解引用: 邮件指出
kfree_call_rcu_nolock()在传入大 kmalloc 对象(超过 KMALLOC_MAX_CACHE_SIZE,x86_64 上为 8 KB)时,virt_to_slab()返回 NULL,而后续slab->slab_cache解引用会导致确定性内核 NULL 指针崩溃;发件人 XIAO 在 QEMU 中复现了该崩溃并附上完整日志。来源 -
remove PageTransCompound() v2:Kefeng Wang 移除该宏的最后一个用户(KSM),完成清理,获 NVIDIA Ack。
来源 -
swap tiers for cgroup v9:Youngjun Park 发布第 9 版,引入 swap tier 基础设施,包括与 memcg 关联的 swap 设备分级、memcg 接口用于 tier 选择,以及基于 memcg tier mask 的 swap 分配过滤。
来源 -
eventpoll: 修复 clear_tfile_check_list 中的 UAF:Deepanshu Kartikey 提交 v3,修复 epoll 路径在
ep_insert()失败后clear_tfile_check_list()读取已释放 file 的 race。
来源 -
hfsplus: 修复恶意镜像导致的 bnode 重复创建:syzbot 报告 hfsplus 镜像可触发
hfs_bnode_create()中重复 bnode 的 WARN,补丁在创建前校验 bno 是否已存在。
来源 -
rust/drm: 修复 ioctl 处理参数中的无界 lifetime:Danilo Krummrich 的 v4 补丁系列(共16个补丁)修复 DRM ioctl 处理参数中的无界 lifetime 问题。
来源 -
rust/samples: 新增 QEMU EDU PCI 驱动样例:Maurice Hieronymus 添加了 Rust 编写的 sample PCI driver,展示 Rust 绑定用法。
来源 -
Linux 7.2 合并窗口为 NVIDIA Blackwell‑Next 做准备:VFIO 补丁首次提及“Blackwell‑Next”代号,为未来 GPU 直通做基础设施预留。
来源 -
Qualcomm 为 HP EliteBook X G2q 笔记本提交 Linux 支持补丁。
来源