代码 bug 嗅探器:Sanitizer

Android native开发严重问题总结 本文用于总结开发过程中遇到的重要问题分析原因及其解决方案 1、libnativeloader.so" is not accessible for the namespace “classloader-namespace” 原因:安卓高版本中将会限制三方APP访问非NDK公开so库,即不能访问system/lib/lib64下面的私有so库。 两种情况的解决方案: 第一:若是系统system app,该问题的产生原因是app是通过install的,这样不可行,必须将该模块在编译产品后的system/app路径 阅读详情

代码 bug 总在不经意间出现,导演了一出出 crash 的悲剧。为了扼杀 bug 于襁褓之中,本文介绍的主角 Sanitize 挺身而出,致力于解决内存泄露、缓冲区溢出和未定义行为。

本文将从原理来探索 Sanitize 的相关能力实现,介绍 ASan、MSan、UBSan、TSan,而关于如何使用,在官方教程都有,不会过多介绍。

AddressSanitizer (ASan)

ASan 是用来检测 释放后使用(use-after-free)、多次释放(double-free)、缓冲区溢出(buffer overflows)和下溢(underflows) 的内存问题。

该工具包含有编译器插桩模块(a compiler instrumentation module,现在是一个 LLVM 的 pass 了),还有一个运行时的库用来替换 malloc 函数。

插桩模块主要用在栈内存上,而运行时库主要用在堆内存上。

run-time library

ASan 的运行时库会使用 __asan_malloc 来替换掉所有对 malloc 的调用。

在 malloc 函数所分配的字节周围,插入雷区,对于 free 释放掉的内存进行投毒,从而跟踪 malloc / free 行为。

void *__asan_malloc(size_t sz) {
    void *rz = malloc(RED_SZ);  // 上接雷区
    Poison(rz, RED_SZ);
    void *addr = malloc(sz);    // 真正分配的内存
    UnPoison(addr, sz);
    rz = malloc(RED_SZ);        // 下接雷区
    Poison(rz, RED_SZ);
    return addr;                // 返回分配的内存首地址
}

Instrumentation

ASan 的编译器插桩模块,会对每一个 store 和 load 的内存读写指令,进行编译时的插桩。

可以在上图的代码部分看到,ASan 在使用的内存周围,插入了 instrumented code。

在 x86_64 平台上,其插桩后的指令如下:

# long load8(long *a) { return *a; }                 # 原函数实现
0000000000000030 <load8>:
  30:   48 89 f8                mov    %rdi,%rax               # 读取参数
  33:   48 c1 e8 03             shr    $0x3,%rax               # 右移 3 位,获取影子内存的操作
  37:   80 b8 00 80 ff 7f 00    cmpb   $0x0,0x7fff8000(%rax)   # 对对应的影子内存判断值是否异常
  3e:   75 04                   jne    44 <load8+0x14>         # 如果不正常则跳到第 9 行,0x44
  40:   48 8b 07                mov    (%rdi),%rax   <<<<<< original load 原本的操作
  43:   c3                      retq   
  44:   52                      push   %rdx
  45:   e8 00 00 00 00          callq  __asan_report_load8      # 报错

Mapping

虚拟内存空间会被划分为以下两个类别:

  • Main application memory 主应用程序内存:即应用程序代码所使用的内存。
  • Shadow memory 影子内存:即包含有影子数据的内存。与主应用程序内存相关,对主存的一个字节投毒,意味着在对应影子内存中写入特殊数据。
shadow_address = MemToShadow(address);
if (ShadowIsPoisoned(shadow_address)) {
  ReportError(address, kAccessSize, kIsWrite);
}

ASan 会把 8 字节的程序内存映射为 1 字节的影子内存。

这 1 字节会保存一个值,来表示程序内存的状态(对齐状态下):

  • 0,表示整个 8 字节内存都正常
  • 负数,表示整个 8 字节内存都被投毒了
  • k,表示头 k 个字节正常、后 8-k 个字节被投毒了

对于不对齐的内存读取,需要采用特殊处理。以下是越界读取(out-of-bound,OOB)的案例:

int *x = new int[2]; // 8 bytes: [0,7].
int *u = (int*)((char*)x + 6);
*u = 1;  // Access to range [6-9]

不对齐的内存读取,其开销是很大的,所以编译器和运行时内存分配器一般会优化代码,来使大多数的内存读取是对齐的。

对比

ASan 性能影响大概 ~2x,内存影响大概 ~2x。

MemorySanitizer (MSan)

ASan 无法覆盖到未初始化的内存,对于未初始化的内存,进行读取的行为同样危险,这时候就需要 MSan 出马了。

MSan 实现的是一个 bit to bit 的影子内存,每一比特都有映射,所以在计算影子内存的位置时,十分高效。

0 代表已初始化过的,1 代表未初始化的,所以开始时,影子内存填满了 0xFF。

MSan 的性能开销大概 ~3x,内存开销大概 ~2x。

Shadow propagation

大多数编译器,是允许加载未初始化 int 或 float 值,来达到期望的效果的。

而且在类或结构体中,对其中内存对齐的部分的加载,也应该是合乎逻辑的。

所以 MSan 允许对未初始化内存的复制、以及一些安全的操作的。为了能达到这一目的,MSan 实现了 shadow propagation。

对于未初始化内存的读取结果是 undefined value(未定义值),它会被临时赋值给一个 shadow value(影子值) 来管理,然后当 application value(程序里的变量值) 被保存时,把这个 shadow value 存到对应的影子内存中。

某一些对 application value 的操作,需要是已初始化的,包括 conditional branch(有状态跳转)、system call(系统调用)、pointer dereference(解指针)。

instrumentation 主要就是对这些操作,进行封装插桩。

MSan 还能开启溯源操作,将源头的 shadow value 传播出去。

run-time library

除了插桩指令以外,MSan 同样需要运行时库的支持,用来在启动时,将低地址内存设置为不可读,然后映射为影子内存。

被 malloc 返回的内存、以及被 dealloc 的内存、局部的栈对象都会被标记为未初始化的。

UndefinedBehaviorSanitizer (UBSan)

UBSan 主要就是检查未定义行为(undefined behavior),包括有符号整型溢出、空指针的使用、除 0 操作、越界读取等。

UBSan 在编译时对可疑操作进行插桩,以捕获程序运行时的未定义行为,如果检查到是 UB 行为,则会调用 __ubsan_handle_ 函数进行处理,输出报错信息。

UBSan 会有 ~1.25x 的性能开销,不会有内存开销。

ThreadSanitizer (TSan)

TSan 用来检查数据争用(data race)、死锁(deadlock) 的。

当多个线程同时操作同一个变量的时候,而至少一个的操作是写操作时,就会发生数据争用。

当多个线程因争夺资源而造成的一种互相等待的想象,若无外力介入,它们都无法继续推进,就是死锁。

TSan 需要所有代码都以 -fsanitize=thread 编译参数进行编译,不然某些代码可能会导致误判。

TSan 会有 2x~20x 的性能开销,有 5x~10x 的内存开销。

state machine

TSan 的运行时主要是维护了状态机的使用,对 libc/pthread 的大部分函数也进行了拦截操作。

程序执行可以看作是一连串的事件:

  • 内存存取事件:读、写
  • 同步事件:锁、happen-before(signal & wait)

TSan 包含有全局的和 内存 ID (per-ID,a unique ID of a memory location) 的状态。全局状态是关于同步事件的信息,而 per-ID 状态是内存地址的信息。

下图中的 SS 代表 set of segment,segment 表示一个线程上包含的一连串的内存存取事件,比如对于一个内存 ID 而言,SSWr 表示对某个内存 ID 进行读操作的事件的集合。

判断是否存在数据争用,其主要逻辑是:对同一内存 ID 进行操作时,却没有进行相同的锁来限制。

还有很多的状态机算法,就不过多介绍了,在文末论文链接可以查看。

Instrumentation

在编译时,TSan 会在每一个内存存取操作、函数的调用、函数的 entry 和 exit 进行插桩。

同样,TSan 会采用影子内存来存取相关的信息。

参考

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

Be Wise, Sanitize - Keeping Your C++ Code Free From Bugs:https://m-peko.github.io/craft-cpp/posts/be-wise-sanitize-keeping-your-cpp-code-free-from-bugs/

AddressSanitizer:https://clang.llvm.org/docs/AddressSanitizer.html

AddressSanitizer - wiki:https://github.com/google/sanitizers/wiki/AddressSanitizer

Automated Test-Case Generation:Address Sanitizer:https://ece.uwaterloo.ca/~agurfink/stqam.w20/assets/pdf/W04-ASan.pdf

《MemorySanitizer: fast detector of uninitialized memory use in C++》:https://static.googleusercontent.com/media/research.google.com/en//pubs/archive/43308.pdf

UBSan: run-time undefined behavior sanity checker:https://lwn.net/Articles/617364/

《ThreadSanitizer – data race detection in practice》:https://static.googleusercontent.com/media/research.google.com/zh-TW//pubs/archive/35604.pdf

Finding races and memory errorswith LLVM instrumentation:https://llvm.org/devmtg/2011-11/Serebryany_FindingRacesMemoryErrors.pdf

ThreadSanitizer, MemorySanitizer:https://llvm.org/devmtg/2012-11

理解ASAN的shadow memory和读懂报错信息 什么是ASAN ASAN(Address Sanitizer)是一个内存检测工具。gcc4.8版本及以上自带。支持多平台(x86, ARM, MIPS (both 32- and 64-bit versions of all architectures), PowerPC64)、多操作系统(Linux, Darwin (OS X and iOS Simulator), FreeBSD, Android)。 ASAN主要由两部分构成:instrumentation module和run-time librar 阅读详情

相关推荐

tinyalsa tinyplay播放音频报错

tinyplay 使用usb声卡设备播放音频文件时候报错,这个文件用aplay播放是正常的。原因是音频文件格式和声卡支持的格式不一致。这里只需要把wav文件格式改为 48k 双通道,就行了。

JCYAO_的博客 1720

ASAN报错汇总

启动错误:Shadow memory range interleaves with an existing memory mapping. ASan cannot proceed correctly. ABORTING ASan shadow was supposed to be located in the [0x1ffff000-0x3fffffff] range. 地址消毒使用影子内存判断读...

qq_23350817的博客 5334

别再羡慕专业版!用这个批处理脚本,一键给Win11家庭版装上官方沙盒

本文详细介绍了如何通过批处理脚本在Windows 11家庭版上安装官方Windows沙盒(Windows Sandbox),无需复杂操作即可享受专业版功能。脚本自动激活系统内置组件,提供安全隔离的虚拟化环境,适用于软件测试、安全浏览等场景。

weixin_26757925的博客 497

程序分析-klee查找bug过程

klee查找bug的过程

qq_44370676的博客 1666

基于Meteoinfo与TrajStat的后向轨迹聚类分析实战:从数据准备到可视化制图

本文详细介绍了基于Meteoinfo与TrajStat进行后向轨迹聚类分析的完整实战流程。从Java环境配置、Meteoinfo软件与TrajStat插件安装,到精准获取NOAA气象数据、设置参数进行批量轨迹计算,再到利用聚类分析提炼主要气流路径,并最终完成专业地图可视化与制图。文章旨在帮助环境与气象研究者快速掌握从数据准备到成果输出的全链路操作。

p4q5r6s7t的博客 804

关于爱思唯尔官方Latex模版参考文献不是按照引用顺序编号,乱序问题

接下来使用工具打开cas-model2-names.bst文件,全词匹配搜索。其他期刊的模版也是一样的操作,把规定序号的规则的。爱思唯尔给的Latex模版大概文件结构如此。发现是按照第一作者的姓氏的大写字母排序。命令行给注释掉,小写的sort可别注释。

weixin_42748439的博客 5112

面向开发的内存调试神器,如何使用ASAN检测内存泄漏、堆栈溢出等问题

GreatSQL社区原创内容未经授权不得随意使用,转载请联系小编并注明来源。 [toc] 介绍 首先,先介绍一下 Sanitizer 项目,该项目是谷歌出品的一个开源项目,该项目包含了 ASAN、LSAN、MSAN、TSAN等内存、线程错误的检测工具,这里简单介绍一下这几个工具的作用: ASAN: 内存错误检测工具,在编译命令中添加-fsanitize=address启用 LSAN: 内存泄漏检测工具,已经集成到 ASAN 中,可以通过设置环境变量ASAN_OPTIONS=detect_leaks=.

GreatSQL2021的博客 7046

VSCode+Keil高效开发STM32:Keil Assistant插件配置全攻略

本文详细介绍了如何通过VSCode的Keil Assistant插件,将Keil MDK的编译调试能力与VSCode的现代编辑体验相结合,打造高效的STM32开发环境。文章涵盖了从环境配置、工程导入、智能提示设置到与STM32CubeMX协同工作的全流程攻略,旨在解决Keil编辑器效率低下的痛点,大幅提升嵌入式开发的编码与项目管理效率。

gold的博客 508

Sanitizer-代码问题嗅探器介绍

本文主要从Sanitizer相关的实现探索其使用的场景,ASan,MSan,UBSan,TSan;介绍其如何解决内存泄漏,缓存区溢出和未定义行为的bug问题

u010830462的博客 1811

EDSR图像超分辨程序复现(踩坑及解决记录)

EDSR图像超分辨程序复现(踩坑及解决记录)

Sunny_Coder的博客 3642

052、联发科Imagiq HyperEngine架构适配:天玑9000/9200的ISP多核并行调度与Tuning Toolkit调优案例

摘要: 项目组在适配联发科天玑9200的Imagiq 890 ISP架构时,遇到多摄预览功耗过高、帧率不稳等问题。通过分析多核调度机制,调整辅核QoS通道、优化AI-ISP协同模式(采用FREERUN+运动补偿),并利用Tuning Toolkit的Pipeline Viewer动态分配负载,最终降低功耗30mA、提升画质。关键经验包括:避免多核带宽冲突、合理配置动态时钟策略,以及统一校准参数版本管理。天玑9000/9200的HyperEngine架构需优先理解多核协同逻辑,再针对性调优,否则易引发场景兼容

zzfmlxs的博客 38

AddressSanitizer 和 valgrind 和mprotect+libseg。。。

1)./configure --prefix=/home/xiaoming/valgirnd-install/ --enable-only32bit \ //linux32 ./configure //若有configure关于glibc版本问题可以修改configure中版本检测:加上本地glibc的版本支持 make make install //测试后因为程序有大数组,错误: val...

makeiteasier的博客 1162

第十届MathorCup高校数学建模挑战赛-B题:养老服务床位需求预测与运营模式研究

当养老床位数增加时存在的商机,提出了相应的养老服务床位的运营商业模式。就业的可能性,建立多目标规划模型,尽可能同时满足三方面的要求。务床位的需求、制定合理的养老服务床位发展规划,是构建和谐社会、幸福社会。问题一的床位需求与市场类型的分类结果,查找关于国内养老院的相关数据,探。求,又能持续发展养老事业,同时还能促进社会就业的养老服务床位运营的商业。养老服务床位数的增加能够带来的就业方面因素的影响,并对这些因素进行一个。你们的模型及其结论为科学依据,对政府管理部门针对养老床位规划提出合理的。

getusushu的博客 1139

iOS7.1以及iOS9.2与之前的不同

先说下要适配iOS9要做的事: 1.更改http为https  两种方案: 一.公司后台服务器更改; 二.作为开发者,可在Xcode暂时退回到http协议.  开发者更改方法如下: 1.在Info.plist中添加App Transport Security Settings (或NSAppTransportSecurity), 类型Dictionary。 2.在A

ZZ825194632的博客 2200

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

非法检测之UBSAN

UBSAN:全称Undefined Behavior Sanitizer,用于运行时检测一些未定义行为。未定义,是一个统称,并非是代码中的变量等没有定义,如果是此类错误,编译就会进行拦截。此含义就可以理解为一个非法行为的检测,比如定义的变量超过范围,数组使用不正确的下标,左右移不符合规范,或者超过变量的范围,对齐不匹配等等。

fangjun791350的博客 5670

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

Sanitizers 系列之 address sanitizer 原理篇

本文主要介绍asan的算法,asan的各种优势本质上是源自于它的算法,本节的内容主要基于 asan 的论文 《AddressSanitizer: A Fast Address Sanity Checker 》。

netease_im的博客 1258

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

20190ctf ageis

Analysis checksec franex@franex-virtual-machine:~/桌面/babyaegis$ checksec aegis [*] '/home/franex/\xe6\xa1\x8c\xe9\x9d\xa2/babyaegis/aegis' Arch: amd64-64-little RELRO: Full RELRO Stack: Canary found NX: NX enabled PIE:

qq_46441427的博客 1103

Asan检测原理(AddressSanitizerAlgorithm chatgpt翻译记录)

这是由malloc返回8字节对齐的内存块所保证的。唯一的情况是对齐的qword的不同字节具有不同的状态,是malloc分配的区域的尾部。例如,如果我们调用malloc(13),我们将有一个完整的未污染的qword和一个有5个未污染字节的qword。free将整个区域的阴影值标记为污染,并将内存块放入隔离队列中(这样在某段时间内,malloc不会再次返回该块)。相应于红区的阴影值被标记为污染,主内存区域的阴影值被清除。AddressSanitizer将应用程序内存的8个字节映射为影子内存的1个字节。

qq_33243369的博客 1117

FAQ for ASAN on Android10/Android11/Android12/8155/8295

FAQ for ASAN on Android10/Android11/Android12/8155/8295

漂流瓶の海岸 3400

GCC软件内存使用问题定位方法

GCC软件内存使用问题定位@TOC AddressSanitizer介绍 AddressSanitizer is a fast memory error detector. It consists of a compiler instrumentation module and a run-time library. The tool can detect the following types of bugs: Out-of-bounds accesses to heap, stack and glob

StarEmbedded的博客 781

AddressSanitizer 内存检测工具

还有另一个内存检查工具valgrind 转自:https://code.google.com/p/address-sanitizer/ AddressSanitizer: a fast memory error detector Updated Apr 22, 2014 by konstant...@gmail.com IntroductionGet

haima1998的专栏 1万+

Linux中的常用内存问题检测工具

C/C++等底层语言在提供强大功能及性能的同时,其灵活的内存访问也带来了各种纠结的问题。如果crash的地方正是内存使用错误的地方,说明你人品好。如果crash的地方内存明显不是consistent的,或者内存管理信息都已被破坏,并且还是随机出现的,那就比较麻烦了。当然,祼看code打log是一个办法,但其效率不是太高,尤其是在运行成本高或重现概率低的情况下。另外,静态检查也是一类方法,有很多工具(lint, cpp

世事难料,保持低调 4万+

异常处理与MiniDump详解(4) MiniDump

在此我非常感谢博客版主 九天雁翎(JTianLing) 先生/女士 做出的辛苦劳动,写了这么好的文章,本人受益匪浅,特此感谢!原文地址:http://blog.youkuaiyun.com/vagrxie/archive/2009/07/31/4398721.aspx 异常处理与MiniDump详解(4) MiniDumpwrite by 九天雁翎(JTianLing) -- blog.csd

1827

通过asan和tsan对内存越界、内存泄露、死锁等进行检测

ASan/TSan的性能开销通常比Valgrind/Helgrind低,ASan/TSan是通过编译时插入的代码来检测内存错误,因此在运行时的性能开销相对较小。注意:tsan的死锁检测是基于运行态(data race也一样),只有当thread2_main函数被执行到时,死锁问题才能被发现,所以需要完备的测试用例覆盖尽可能多的分支。AddressSanitizer(ASan)是一种内存错误检测工具,可以帮助我们发现C/C++程序中的内存错误,如缓冲区溢出、使用已释放的内存、内存泄露等。

qq_37174816的博客 2483
上一篇: 跨语言调 C 库:DragonFFI
下一篇: 【译】LLVM 类型相等判断
流左沙
博客等级 码龄11年 46粉丝 55原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值