写点什么

【网易云信】Sanitizers 系列之 Sanitizers 概述

作者:网易智企
  • 2022-10-27
    浙江
  • 本文字数:2408 字

    阅读完需:约 8 分钟

【网易云信】Sanitizers 系列之 Sanitizers 概述

Challenge

C/C++ 提供了直接操作内存的强大能力,然而使用不当也会招致许多问题,下面是 Google chromium 团队的一组统计数据: 

"Around 70% of our high severity security bugs are memory unsafety problems (that is, mistakes with C/C++ pointers). Half of those are use-after-free bugs."

与内存相关的问题往往排查难度较大,耗时较多。网易云信的 IM、RTC 等 SDK 都是使用 C/C++ 来进行开发的,作为软件供应商,网易云信面临的挑战更大:

  • 需要支持更多的操作系统;

  • 需要支持更多的开发框架。

上述挑战促使我们使用更强大、更通用的 Sanitizer 工具来帮助工程师快速排查与定位内存问题,提高生产力,本系列文章共四篇,旨在向读者介绍网易云信的工程实践,本文为第一篇。


Sanitizers 简介

Sanitizers 是由 Google 研发团队提出的用于检测 C/C++ 程序常见内存错误的工具集,Google 工程师公开了它们的源代码和算法:

https://github.com/google/sanitizers

并在 LLVM clang 上实现,它们已经被用于多个工程中。比如 Chromium、Firefox 等知名项目中。

下表汇总整理了 Sanitizers 的各个工具和它们的作用:



从表格的内容可以看出,Sanitizers 除了能够检测内存错误外,还能够检测一些其它常见的错误。后面笔者将分章节介绍上述几种 Sanitizer 的用法与原理。


 Sanitizers 的优势 

当前市面上存在着多种用于检测内存错误的工具,在投入生产使用之前,可以从如下维度来评估: 



在后续介绍各种 Sanitizer 工具时,会从上述几个维度进行介绍。Sanitizer 并不是第一个被发明出来用于检测内存错误的工具,在它之前,同类的工具已经非常多了,Sanitizer 其实是在前人的成果上改进加创新而来,因此它在上述几个方面比起同类工具有着优势。


Sanitizers 具备如下优势

  • 与 Compiler 集成,主流 IDE 都提供了不同程度的集成,因此使用起来相对简单;

  • 目前主流 OS 的 Compiler 都能够不同程度上支持 Sanitizer,其通用性更强,因此对于需要跨平台的项目而言,它具备很大的优势;

  • 相比同类工具,可用性更强,成本更低;

  • 能力更强,能够检测的错误类型较多,诊断信息非常准确,能够帮助快速定位问题。

主流编译器对 Sanitizers 的支持情况 

目前主流编译器都在一定程度上支持 Sanitizers,本节整理了 clang、GCC、MSVC 这三款主流编译器对 Sanitizers 的支持情况。

  • LLVM clang

    Google 工程师最初在 LLVM clang 上实现了 Sanitizers,LLVM clang 对各种 Sanitizer 支持非常全面,具体可以参见 LLVM clang 的官方文档:


  • Apple clang

需要注意的是,Apple clang 是基于 LLVM clang 但是不是完全照搬 LLVM clang,两者是存在区别的。目前 Apple clang 不支持 lsan,支持其它几种 Sanitizer,macOS 的 Instruments 工具提供了检测 Memory leakage 的能力。

  • MSVC

目前 MSVC 仅支持 asan,不支持检测 use-after-return 类错误,从实践来看,MSVC 在开启 asan 后,在一些特定情况下会出现比较奇怪的问题,用户可以考虑设计编译器版本。

更多内容参见:

https://github.com/google/sanitizers/wiki/AddressSanitizerWindowsPort

  • GCC

从实践和 GCC 支持的编译选项来看,GCC 不支持 msan,支持其它几种 Sanitizer。

更多内容参见:

https://gcc.gnu.org/onlinedocs/gcc/Instrumentation-Options.html


What every programer should know about memory 

在介绍正式的内容之前,我们一起回顾一下关于 Memory 的知识。


Virtual memory 

当今 OS 普遍采用 Virtual memory 技术,下图形象地展示了 Virtual memory。



上图源自:

https://en.wikipedia.org/wiki/File:Paging.svg


Process memory address space 

下图展示进程的地址空间布局:



上图源自:

https://en.wikipedia.org/wiki/File:Program_memory_layout.pdf


Memory error 分类 

Memory error 的分类有多种,下表是根据 Sanitizer 工具的能力划分的一种分类方式:



在后面的章节中,对每一类错误都会进行详细介绍,并提供具体的例子。


更多关于 Memory 的知识,参见:

  • https://en.wikipedia.org/wiki/Memory_address

  • https://en.wikipedia.org/wiki/Virtual_address_space

  • https://people.freebsd.org/~lstewart/articles/cpumemory.pdf


C++ 语言标准对 Memory 的抽象

C++ 作为一门能够直接操作内存的语言,它的标准在语言层面对 Memory 进行抽象,概括的说,每个 C++ object 会占用一片内存区域,根据 C++ object 所处的内存位置对 object 的分类如下:



上面表格中使用的“storage”术语其实是 C++ 语言标准使用的,读者可以参见: 

https://en.cppreference.com/w/cpp/language/storage_duration

这个术语所表达的其实是 object 所占用的内存。本系列后续的文章将会对 heap objectstack objectglobal object 的不同类型的内存错误进行介绍。

C++ 语言标准对 object lifetime 进行了规范,概括地说,一个 C++object lifetime 如下:



C++ 标准明确指出“access outside of object lifetime”是错误的读者可以参见:

https://en.cppreference.com/w/cpp/language/lifetime#Access_outside_of_lifetime

由于每个 C++ object 对应一片内存区域,这提示我们可以从 object lifetime 的角度来分析 Memory error,在这里可以提前告诉读者,后面即将介绍的很多内存错误都可以归入“access outside of lifetime”范畴。

后续将继续推出 Sanitizers 系列文章之 Address Sanitizer 用法篇、Address Sanitizer 原理篇、Leak Sanitizer 介绍等相关文章,请大家持续关注。


参考资料 

  • Memory safety: https://www.chromium.org/Home/chromium-security/memory-safety/

  • Introduction to Memory Unsafety for VPs of Engineering: https://alexgaynor.net/2019/aug/12/introduction-to-memory-unsafety-for-vps-of-engineering/

  • AddressSanitizerComparisonOfMemoryTools: https://github.com/google/sanitizers/wiki/AddressSanitizerComparisonOfMemoryTools

  • https://en.cppreference.com/w/cpp/language/lifetime

发布于: 2022-10-27阅读数: 3
用户头像

网易智企

关注

网易智企是网易旗下一站式企业服务提供商。 2022-05-09 加入

网易智企是网易旗下一站式企业服务提供商,包含网易易盾、网易云信、网易云商三大业务板块。

评论

发布
暂无评论
【网易云信】Sanitizers 系列之 Sanitizers 概述_运维_网易智企_InfoQ写作社区