写点什么

谷歌将空间内存安全功能“改造”到 C++ 上

  • 2025-01-26
    北京
  • 本文字数:2782 字

    阅读完需:约 9 分钟

大小:1.34M时长:07:49
谷歌将空间内存安全功能“改造”到C++上

本文最初发布于 THENEWSTACK。



在分析了从 2014 年 7 月 15 日到 2023 年 12 月 14 日近 10 年的 CVE 后,谷歌研究人员计算得出,在 C++中,至少 40%的安全漏洞空间内存漏洞(如越界写入内存)有关。



 (查看大图)

 

不过,谷歌正在努力解决这一问题,同时为这个充满不安全遗留代码的世界树立榜样。

 

谷歌研究人员表示,他们能够将空间安全 “加装 ”到 C++ 代码库中,而且对性能的影响非常非常小。网上有一篇关于他们研究成果的博文,引发了更为广泛的讨论,其中不乏一些有趣的跟帖,有人甚至大声质疑,这种低影响是否意味着 C++代码可以默认包含空间内存安全特性。

 

该文还提出了一种可能性,即一些已经存在很长时间的假设可能会随着时间的推移而受到挑战——当面临的问题比较严重时,或许可以尝试引入新技术。

改进安全设计

这一切都源于一篇博文,该文描述了谷歌如何通过在 C++代码中添加边界检查来保护其服务器端生产系统,从而提高 Gmail、YouTube、谷歌地图甚至谷歌搜索引擎的安全性。谷歌是内存安全语言和其他安全编码实践的早期采用者,但全面过渡往往需要数年时间。也就是说,他们还需要额外做一些工作: “尽可能地在现有 C++代码库中改用安全设计原则"。

 

该博文由资深软件工程师Alex RebertKinuko Yasuda(与谷歌的Max Shavrick合作,后者也是安全基础团队的成员)撰写。该文首先指出,C++标准库的 LLVM 实现中包括几种用于发现未定义行为的加固模式,从而可以对 C++代码进行边界检查

 

该文解释说:”[我们]现在已将其作为服务器端生产系统的默认设置,同时密切监控上线情况。“

 

结果如何?

  • 该团队发现了 1000 多个 Bug。(据谷歌估计,平均每年发现的 Bug 可增加到 1000 至 2000 个)。

  • 谷歌 “整个生产环境的基线分段故障率降低了 30%”。在博文中,他们将此归功于更好的代码可靠性和质量: “除了崩溃之外,检查还发现了一些错误。这些错误可能会表现为不可预测的行为或损坏数据"。

  • 最终,它还帮助谷歌 “发现并修复了多个在代码中潜伏了十多年的 Bug”。经过加固的 C++检查 “将许多难以诊断的内存损坏转化为即时且易于调试的错误”。

  • 它甚至还瓦解了内部的一次红队演习,“证明了它在挫败漏洞利用方面的有效性”。



 (查看大图)

 

“我错了”

其中有一项结果最引人关注。谷歌的博文称,加固libc++“对我们的服务平均造成了 0.30%的性能影响”。

C++中的边界检查:有人问,0.3%的开销是否属实?这不仅仅是一个基准测试结果,我们是通过 Google-Wide profiling 得到的这个结果,我们通过它获得了来自 DC 的实时洞察。这也让我们大吃一惊,因为那比我们预想的要少得多。

https://t.co/zBUvoYzGi1 https://t.co/7NAWBuxdtP

— Kinuko Yasuda (@kinu) 2024年11月16日

 

谷歌杰出工程师Chandler Carruth回应了他们的博文。他也是新兴编程语言Carbon的创始人和联合牵头人。Carruth 撰写了一篇博文,其中第一节的标题就是 "边界检查的开销:我错了"。

 

“其他人关于成本的一些历史报告,再加上我自己的一些简单实验,让我坚定地认为,边界检查的成本不可能低到可以默认启用的程度。然而,到目前为止,它们看起来确实非常低。“

 

遗憾的是,这种普遍的看法使得高质量的动态安全检查没有出现在 libc++及其他 C++库中,最初也没有出现在 LLVM 中。

C 的加固之路

但 Carruth 看到,Microsoft Visual C++引入了基于编译器的检查,而 “在这里,苹果公司所有推动在C++中实现安全缓冲区的人都做了一项了不起的工作,让 LLVM 生态系统(包括 Clang 和 libc++)最终在这一领域拥有了一个可靠的工具”。Carruth 认为,另一个因素是内存安全语言开发人员为 LLVM 做出了更多的贡献(因为更多的非 C/C++语言开始使用 LLVM),从而带来了 “一系列稳定而系统化的改进”。

 

回首过去,Carruth 认为,虽然 LLVM 经过了多年的改进,但"我们并没有真正注意到什么时候已经达到了一个临界点。在那一刻,所有改进一起从根本上降低了此类检查的实际成本,使其在默认情况下就普遍适用。“

 

“这种水平的可用性改变了安全游戏的规则,因为我们不用再在性能或安全性之间做出痛苦的权衡取舍,我们可以两者兼得。“

 

Carruth 用粗体字写道:"我认为,通过努力,借助编译器对内存安全检查的持续支持,我们确实有机会默认实现空间内存安全,即使是在 C 和 C++中,即使是在性能最受限制的环境中。”

 

这就提出了一个问题:现在是否应该考虑下参考计数等其他安全检查——即使我们认为这些检查会带来令人望而却步的性能影响。

 

“我认为,有足够的证明表明,对于比较小的系统(手机、笔记本电脑、其他用电池的东西),缓存流量和潜在同步开销的成本即使再大也微不足道。我认为,Swift 已经提供了强有力的证据,只要在优化基础设施上投入一些资金并认真实施,参考计数就能够在这些处理器上实现极高的效率。”

 

当然,谷歌的博文也在 LinkedIn 上引发了不少讨论:



 (查看大图)

 


 (查看大图)

 

是否需要优化?

Carruth 还回顾了为了“让 LLVM 在优化加固方面做得更好”所作出的努力。他认为,性能敏感型工作负载得益于配置文件引导优化(或 PGO),以及“人们系统性地构建优化基础设施......将代码的热门路径与安全检查的开销隔离开来,并释放了 LLVM 围绕它们所开发的所有其他优化技术,最大限度地降低了它们的成本”。

 

至于谷歌,他们的博文确实承认了这一点以及其他提高性能的技巧,但也补充说:"即使没有这些先进技术,边界检查的开销仍然微乎其微。(谷歌的博文将这种低影响归因于加固后的libc++的高效设计,以及编译器在优化过程中消除冗余检查的方式)。

 

不过,当发现 LLVM 在执行一项不必要的检查(并且对性能有很大影响)时,他们编写了一个修复程序,并将其贡献给了 LLVM 项目,“以便与广大的 C++社区分享这项改进带来的好处”。

各方反应

谷歌的博文在网络上引发了一些积极的反响。在 Hacker News 上,WebAssembly 联合创始人Ben Titzer对此作出了回应,他还记得 20 年前关于 C++中边界检查必要性的争论。”程序中存在边界检查能捕捉到的 Bug。将其作为一种内置特性,编译器就会对其进行专门针对边界检查的优化,这样可以消除许多 Bug,并大大降低动态成本。“

 

“仅仅在库中打开安全检查并不一定能实现所有的编译器优化,但这只是一个开始。安全检查应该真正地内置于语言中"。

 

另一个回应来自Walter Bright,他创建了另一种编译器 Zortech C++。Bright 也是系统编程语言 D 的创建者。他描述了 20 年前 D 引入数组边界检查后发生的事情: “这是一个巨大的胜利“。在另一条评论中,Bright回忆了如何使边界检查成为 D 语言的默认选项。

 

“事实证明,这是正确的选择。”

 

Rust 基金会杰出顾问Shane Miller发表在 LinkedIn 上的回应可能是最积极的,“很高兴你们没有止步于通过这一举措获得安全方面的胜利。“

 

“你们在识别 Bug 和提高可靠性方面所掌握的数据是一个很好的参考"。

 

声明:本文为 InfoQ 翻译,未经许可禁止转载。

 

原文链接:https://thenewstack.io/google-retrofits-spatial-memory-safety-onto-c/

2025-01-26 11:3211271

评论 1 条评论

发布
用户头像
最好集成到语法里
2025-01-28 10:50 · 北京
回复
没有更多了

Flutter-从入门到项目 07: 微信项目-发现页面

iOSer

flutter ios 小程序flutter, 跨平台

python精度控制

里昂

Python 数据结构

添加小助理vx:mxzFAFAFA即可!!

比伯

Java 编程 架构 面试 计算机

3分钟学会如何上手supervisor看门狗

happlyfox

Linux centos7 28天写作 2月春节不断更

优化软件测试成本的7个步骤

程序员阿沐

软件测试 自动化测试 测试工程师 黑盒测试 白盒测试

翻译:《实用的Python编程》02_06_List_comprehension

codists

Python

到底什么是敏捷

Teobler

敏捷 敏捷开发 敏捷精髓 敏捷书籍

Serverless 2.0,鸡蛋还是银弹?

Serverless Devs

腾讯云 阿里云 Serverless 运维 大前端

架构设计篇之微服务实战笔记(六)

小诚信驿站

架构师 刘晓成 小诚信驿站 28天写作 架构师成长笔记

为语音社交平台加一个防护罩,即构上线实时语音安全方案

ZEGO即构

诊所数字化:连锁型诊所应用远程会诊做分级诊疗

boshi

数字化医疗 七日更 28天写作

Git教程--git merge命令

生之欢愉,时间同行

git 程序员 git merge

国产芯片WiFi物联网智能插座—项目简介

不脱发的程序猿

物联网 28天写作 二月春节不断更 WiFi物联网插座 智能插座

研发效能的历史和未来

李小腾

研发效能 数据驱动

「超全!」谷歌大神LeetCode刷题笔记PDF分享

C语言与CPP编程

c++ 程序员 算法 LeetCode 编程、

2021金三银四涨薪季,这些面试题都掌握了嘛?

ios 面试

简述:一款优秀的缺陷管理系统有哪些功能特点!

优秀

缺陷管理系统

运维工程师小张的日记

XSKY星辰天合

图解定时任务线程池

叫练

面试 定时任务 线程池 Timer 线程池工作原理

第一篇文章

棉花糖

安卓软件开发教程!全世界都在问Android开发凉了吗?offer拿到手软

欢喜学安卓

android 程序员 面试 移动开发

魔改出一个 Encoder | Rust 学习笔记(一)

李大狗

区块链 rust 入门

技术干货 | 中间件技术在百度云原生测试中的应用实践

百度开发者中心

底层技术 #技术干货#

DCache 分布式存储系统|K-K-Row 缓存模块的创建与使用

TARS基金会

MySQL 数据库 nosql 分布式存储 TARS

国产芯片WiFi物联网智能插座—电源功能设计

不脱发的程序猿

28天写作 二月春节不断更 智能插座 WiFi物联网智能插座 电源设计

话题讨论 | 英语对IT从业人员重要吗?

happlyfox

IT 话题讨论 28天写作 2月春节不断更 话题王者

大牛荐书 | 百度技术大牛都在读的7本书!

百度Geek说

技术 技术人 书籍推荐 技术书籍

常见的初级排序算法,这次全搞懂

Silently9527

Java 排序算法

安卓天气app开发!2021年Android开发者跳槽指南,社招面试心得

欢喜学安卓

android 程序员 面试 移动开发

日记 2021年2月25日(周四)

Changing Lin

2月春节不断更

2021版面试必问178条性能优化建议!(Java+JVM+Redis+MySQL等)

Java架构追梦

Java 架构 面试 性能优化 金三银四跳槽

谷歌将空间内存安全功能“改造”到C++上_编程语言_David Cassel_InfoQ精选文章