当前位置: 首页 > news >正文

Linus 震怒!内核整数溢出“安全”之争:从华为案例看 Linux Kernel 的硬核防御演进

前言

在 C 语言的世界里,整数溢出就像一个潜伏在暗处的幽灵。你以为 $2^{31}-1 + 1$ 会变成一个巨大的正数,结果它却变成了一个负数。这种“数学奇点”在内核空间往往意味着系统权限的彻底丧失。

最近,内核社区围绕“陷阱整数”展开了一场长达一年的技术博弈。Linus Torvalds 的亲自下场开喷,让原本枯燥的补丁讨论变成了关于“什么才是真正的安全”的哲学思辨。


一、 深度复盘:华为 HSO 驱动漏洞(CVE-2021-39290)

作为 Linux 内核的重要贡献者,华为在追求极致性能的同时,也时刻在与底层的算术错误作斗争。这个著名的漏洞生动地展示了一个简单的加法是如何毁掉整个系统防御的

1. 漏洞成因:消失的边界检查

在华为维护的hso网络驱动中,处理数据包(skb)时需要计算缓冲区的总长度。

// 简化后的逻辑 int len = header_len + payload_len; if (len > MAX_BUFFER_SIZE) { return -EINVAL; } unsigned char *buf = kmalloc(len, GFP_KERNEL);

致命点:攻击者可以从用户态构造一个极大的payload_len(例如0xFFFFFFF0)。当它与header_len相加时,结果发生了整数回绕,变成了一个极小的正数(如15)。这个小数字顺利通过了MAX_BUFFER_SIZE的检查,导致kmalloc只分配了一个极小的内存块。

2. 连锁反应:堆溢出与 Panic

接下来的memcpycopy_from_user依然会按照原始巨大的payload_len进行拷贝。结果就是:小小的缓冲区被瞬间撑破,相邻的内核对象被恶意覆盖。攻击者借此可以篡改函数指针,甚至直接获取 Root 权限。

3. 华为的解决方案

华为工程师与社区协作,迅速推动了补丁。核心逻辑是引入了内核安全算术库:

  • 强制校验:严禁直接使用+*计算内存大小。

  • 引入check_add_overflow使用编译器内置的溢出检测机制,在加法发生的瞬间捕捉异常。

  • 代码审计:华为内部以此为契机,对网络协议栈中所有涉及size计算的逻辑进行了地毯式扫描。


二、 举一反三:这些整数风险你避开了吗?

除了华为遇到的缓冲区分配问题,整数溢出在内核中还有以下变种:

  1. 参考计数溢出(Reference Count Overflow):

    当一个内核对象的引用计数(refcount)被非法增加到溢出并回绕至 0 时,内核会误认为该对象已不再使用并将其释放(Free)。然而,系统中可能仍有指针指向它,这就造成了Use-After-Free (UAF)漏洞,这是目前内核中最易被利用的漏洞类型。

  2. 循环计数器陷阱:

    for (i = 0; i < count; i++) { ... }

    如果count来自用户态且由于溢出变成了一个负数(对于有符号整型),循环可能完全不执行;或者如果i溢出导致条件永远为真,则会引发内核死循环,导致 CPU 100% 占用,系统瞬间宕机。

  3. 数组索引越界:

    计算数组下标时发生溢出,可能导致指针访问到数组边界之外的地址。即便溢出后的偏移量很小,也可能修改到内核的关键全局变量。


三、 社区大地震:Kees Cook 与 Linus 的“生死战”

面对这些层出不穷的漏洞,安全专家 Kees Cook 提出了他的“终极武器”:属性标注系统

  • __ob_wrap:官方认证的“回绕”。告诉工具:我知道这里会溢出,我是故意的(比如哈希算法)。

  • __ob_trap:一旦溢出,直接让 CPU 报错,停止运行。

Linus 的怒火:死掉的机器不是安全的

Linus Torvalds 对此大发雷霆。他的观点非常务实:“一个直接崩溃(Oops)的系统,对用户来说和被黑了同样糟糕。”

Linus 认为,安全不应该以“自杀”为代价。他提出,如果发生了溢出,系统应该优雅地跳出当前逻辑,清理现场,然后报错返回,而不是简单粗暴地让整个内核崩掉。


四、 最终共识:带标签的跳转机制

在 Linus 的坚持下,社区达成了一个折中且精妙的方案:“溢出标签跳转”

int __overflow_label(out_of_bounds) process_data(u32 a, u32 b) { // 标注 count 为“陷阱类型” u32 __attribute__((overflow_behavior(trap))) count; // 执行逻辑 count = a + b; // 如果这里溢出,自动跳转到 out_of_bounds return 0; out_of_bounds: // 优雅清理资源并报错,Linus 觉得这很 Cool pr_err("Detect integer overflow! Recovering...\n"); return -ERANGE; }

五、 结语

从华为的补丁实战到内核社区的架构之争,我们看到 Linux 内核正在从“防御 Bug”向“改变语言规范”演进。

作为内核开发者或底层驱动开发者,我们要记住:数学不会骗人,但 C 语言会。永远不要相信用户输入的长度,永远优先使用check_add_overflowarray_size等安全宏。

http://www.jsqmd.com/news/753817/

相关文章:

  • 【电力系统】基于Matlab的中压电缆的局部放电传输模型
  • 终极鸣潮工具箱:解锁120帧+画质优化+抽卡分析完整指南
  • 丁于洲博士应邀出席北京大学人工智能与中药大健康产业高级研修班
  • ImageGlass:重新定义Windows图片浏览体验的轻量级利器
  • 效率提升:基于快马平台快速生成2026精准资料管理系统前端
  • 避坑指南:nRF52832 SAADC配置中的那些‘坑’——增益、参考电压与EasyDMA缓冲区设置详解
  • 华为麒麟电脑福音:Crossover 完美安装 Office 2016 教程及避坑指南
  • 立创EDA专业版 vs 标准版:焊接辅助工具等生产功能深度对比,教你按需选择
  • Gemini3.1Pro:零基础生成SQL搞定办公数据分析
  • AI 导致消费降级?从身边真实案例看职场人的破局之道
  • AI智能体开发实战:基于agent-recipes构建可复现的智能体配方
  • 手把手教你写LSF esub脚本:从自动补全项目名到拦截危险作业,5个实战案例一次搞定
  • 别再只用if-else了!用状态机优化你的STM32循迹小车代码,让逻辑更清晰
  • League Akari:英雄联盟玩家的本地化智能助手完全指南
  • Redis分布式锁进阶第十二篇
  • java微服务项目的架构和链路串联
  • RetinaNet之后,One-Stage检测器如何卷出新高度?YOLOv5/v7、FCOS对比分析
  • 别再只盯着总大小了!深度解读Oracle SYSAUX表空间的‘住户’清单:V$SYSAUX_OCCUPANTS视图实战解析
  • Claude Opus 4.6技术深度拆解:百万上下文、Agent Teams与自适应思考
  • 学期学习记录6
  • DINOv2与SiT-B/2结合的图像生成优化技术
  • 终极指南:3步让Hyper-V虚拟机性能飙升200%的免费神器
  • 如何快速掌握TQVaultAE:终极泰坦之旅装备管理完整指南
  • 如何在 Node.js 项目中正确配置 babel 支持 async await 语法
  • 告别代码内耗:2026“科技+商科”复合背景高薪突围策略
  • 改进YOLOv10:基于动态正负样本均衡策略解决类别不平衡问题
  • 10分钟打造专属文件共享中心:彩虹外链网盘实战指南
  • 【紧急预警】DOTS 2.0正式版中已被移除的API兼容层正在 silently 拖垮你的构建速度:3类高危Deprecated调用检测脚本(附自动化修复工具)
  • 如何快速搭建一个免费的问卷、考试、刷题系统?Windows 解压双击就能用
  • 静态反射不再纸上谈兵,C++27元数据驱动开发全链路解析,含AST遍历、属性注入与SFINAE-Free约束推导