地址消毒器ASAN学习笔记

  • 地址消毒器ASAN学习笔记
    • 1. 概念
      • 获取消毒器
      • 使用地址消毒器
      • 关于调用栈
      • 关于编译选项
      • 关于运行时选项(环境变量)
      • 1. Use after free (dangling pointer dereference)
      • 2. Heap buffer overflow(堆缓冲区溢出)
      • 3. Stack buffer overflow(栈缓冲区溢出)
      • 4. Global buffer overflow(全局缓冲区溢出)
      • 5. Use after return(返回后使用)
      • 6. Use after scope(作用域后使用)
      • 7. Initialization order bugs(初始化顺序的Bug)
      • 8. Memory leaks(内存泄漏)
    • 参考资料

地址消毒器ASAN学习笔记

1. 概念

Asan(AddressSanitizer)字面意思为地址消毒器。是一个用于C/C++的内存错误检测工具。它非常快,只拖慢程序两倍左右。详细介绍见:https://github.com/google/sanitizers/wiki/AddressSanitizer
支持检测:

  1. Use after free (dangling pointer dereference)
  2. Heap buffer overflow(堆缓冲区溢出)
  3. Stack buffer overflow(栈缓冲区溢出)
  4. Global buffer overflow(全局缓冲区溢出)
  5. Use after return(返回后使用)
  6. Use after scope(作用域后使用)
  7. Initialization order bugs(初始化顺序的Bug)
  8. Memory leaks(内存泄漏)

该工具由一个编译器插入模块(目前是一个LLVM传递)和一个取代malloc函数的运行时库组成。
关于该工具支持的操作系统见下表。(未支持的说明还没有实现)

OS x86 x86_64 ARM ARM64 MIPS MIPS64 PowerPC PowerPC64
Linux yes yes yes yes yes yes
OS X yes yes
iOS Simulator yes yes
FreeBSD yes yes
Android yes yes yes yes

获取消毒器

AddressSanitizer地址消毒器,从LLVM 3.1开始、GCC 4.8开始就集成到编译器中了。到目前为止,官方仅仅在Linux Ubuntu 12.04,
64-bit操作系统上通过了测试。

使用地址消毒器

使用clang编译器,并用-fsanitize=address编译选项进行编译即可。可以使用-O1(或者更大,其中O是字母呕,不是零)
来获得合理的性能。也可以使用-fno-omit-frame-pointer编译选项以便在错误打印中获得更好的堆栈跟踪。

% tests/use-after-free.c
#include <stdlib.h>
int main() {char *x = (char*)malloc(10 * sizeof(char*));free(x);return x[5];
}
% clang -fsanitize=address -O1 -fno-omit-frame-pointer -g tests/use-after-free.c

运行编译出的可执行二进制文件,即可打印堆栈跟踪信息:

% ./a.out
==9901==ERROR: AddressSanitizer: heap-use-after-free on address 0x60700000dfb5 at pc 0x45917b bp 0x7fff4490c700 sp 0x7fff4490c6f8
READ of size 1 at 0x60700000dfb5 thread T0#0 0x45917a in main use-after-free.c:5#1 0x7fce9f25e76c in __libc_start_main /build/buildd/eglibc-2.15/csu/libc-start.c:226#2 0x459074 in _start (a.out+0x459074)
0x60700000dfb5 is located 5 bytes inside of 80-byte region [0x60700000dfb0,0x60700000e000)
freed by thread T0 here:#0 0x4441ee in __interceptor_free projects/compiler-rt/lib/asan/asan_malloc_linux.cc:64#1 0x45914a in main use-after-free.c:4#2 0x7fce9f25e76c in __libc_start_main /build/buildd/eglibc-2.15/csu/libc-start.c:226
previously allocated by thread T0 here:#0 0x44436e in __interceptor_malloc projects/compiler-rt/lib/asan/asan_malloc_linux.cc:74#1 0x45913f in main use-after-free.c:3#2 0x7fce9f25e76c in __libc_start_main /build/buildd/eglibc-2.15/csu/libc-start.c:226
SUMMARY: AddressSanitizer: heap-use-after-free use-after-free.c:5 main

关于调用栈

地址消毒器收集如下事件的调用栈:

  1. malloc and free
  2. thread creation
  3. failure

其中,malloc和free调用栈非常常见,如果你不在乎malloc/free,可以在ASAN_OPTIONS环境变量中使用malloc_context_size=0来关闭调用栈。
每个堆栈帧都需要symbolized(当然,如果二进制文件是带debug info的)。我们的目的是为了打印

#0xabcdf function_name file_name.cc:1234

关于编译选项

编译选项 说明
-fsanitize=address 启用地址消毒器
-fno-omit-frame-pointer Leave frame pointers. Allows the fast unwinder to function properly.
-fsanitize-blacklist=path 传递黑名单文件
-fno-common 不要将C中的全局变量视为公共变量(允许ASan检测它们)

关于运行时选项(环境变量)

大多数运行时选项通过ASAN_OPTIONS环境变量传递:

ASAN_OPTIONS=verbosity=1:malloc_context_size=20 ./a.out

也可以通过实现__asan_default_options函数在源代码中嵌入默认标志:

const char *__asan_default_options() {return "verbosity=1:malloc_context_size=20";
}

如下是常用环境变量的列表:

环境变量 默认值 说明
detect_stack_use_after_return false 启用stack-use-after-return运行时检查
halt_on_error true 打印第一个错误报告后崩溃程序。仅当代码是使用-fsanitize-recover=address 编译选项编译时,该标志才有效。
log_path stderr 将日志写入log_path.pid,特殊取值为stdout和stderr
sleep_before_dying 0 打印错误报告和终止程序之间的睡眠秒数。用于调试目的(例如,当需要附加gdb时)。

1. Use after free (dangling pointer dereference)

int main(int argc, char **argv) {int *array = new int[100];delete [] array;return array[argc];  // array已经被释放了
}

2. Heap buffer overflow(堆缓冲区溢出)

int main(int argc, char **argv) {int *array = new int[100];array[0] = 0;int res = array[argc + 100];  // 堆溢出delete [] array;return res;
}

3. Stack buffer overflow(栈缓冲区溢出)

int main(int argc, char **argv) {int stack_array[100];stack_array[1] = 0;return stack_array[argc + 100];  // 栈溢出
}

4. Global buffer overflow(全局缓冲区溢出)

int global_array[100] = {-1};
int main(int argc, char **argv) {return global_array[argc + 100];  // 全局缓冲区溢出
}

5. Use after return(返回后使用)

// 一般情况下不会检测,需要导入环境变量 ASAN_OPTIONS=detect_stack_use_after_return=1
int *ptr;
__attribute__((noinline))
void FunctionThatEscapesLocalObject() {int local[100];ptr = &local[0];
}int main(int argc, char **argv) {FunctionThatEscapesLocalObject();return ptr[argc];
}

6. Use after scope(作用域后使用)

// 编译选项:-fsanitize=address -fsanitize-address-use-after-scope
// 禁用方式:ASAN_OPTIONS=detect_stack_use_after_scope=0 /tmp/use-after-scopevolatile int *p = 0;int main() {{int x = 0;p = &x;}*p = 5;return 0;
}

7. Initialization order bugs(初始化顺序的Bug)

$ 文件a.c
#include <stdio.h>
extern int extern_global;
int __attribute__((noinline)) read_extern_global() {return extern_global;
}
int x = read_extern_global() + 1;
int main() {printf("%d\n", x);return 0;
}$ 文件b.c
int foo() { return 42; }
int extern_global = foo();

8. Memory leaks(内存泄漏)

$ memory-leak.c
#include <stdlib.h>
void *p;
int main() {p = malloc(7);p = 0; // The memory is leaked here.return 0;
}=================================================================
==7829==ERROR: LeakSanitizer: detected memory leaksDirect leak of 7 byte(s) in 1 object(s) allocated from:#0 0x42c0c5 in __interceptor_malloc /usr/home/hacker/llvm/projects/compiler-rt/lib/asan/asan_malloc_linux.cc:74#1 0x43ef81 in main /usr/home/hacker/memory-leak.c:6#2 0x7fef044b876c in __libc_start_main /build/buildd/eglibc-2.15/csu/libc-start.c:226SUMMARY: AddressSanitizer: 7 byte(s) leaked in 1 allocation(s).

参考资料

https://github.com/google/sanitizers/wiki/AddressSanitizer
https://llvm.org/ (LLVM编译器基础架构)
https://gcc.gnu.org/ (GCC,GNU编译器集合)

地址消毒器ASAN学习笔记相关推荐

  1. cma linux 起始地址,CMA模块学习笔记

    CMA模块学习笔记 作者:linuxer 发布于:2017-6-28 18:29 分类:内存管理 前言 本文是近期学习CMA模块的一个学习笔记,方便日后遗忘的时候,回来查询以便迅速恢复上下文. 学习的 ...

  2. IP地址转化(学习笔记)

    1.什么是ip地址 IP地址是一种Internet上的主机编址方式,也称为网际协议地址.  IP地址是任意一台主机在网络中的唯一标识 2. IP地址的分类 1.ipv4,占32位           ...

  3. IPy-IPv4和IPv6地址处理模块学习笔记

    在日常网络规划中,会有很多关于IP地址的分配规划问题,如果是手动分配,在量很大的情况下,容易出错.而利用IPy这个python模块,可以很容易实现对iP地址的分配等操作. 以下是对IPy模块学习的一个 ...

  4. [转载]dorado学习笔记(二)

    原文地址:dorado学习笔记(二)作者:傻掛 ·isFirst, isLast在什么情况下使用?在遍历dataset的时候会用到 ·dorado执行的顺序,首先由jsp发送请求,调用相关的ViewM ...

  5. opencv学习笔记02

    原创博文地址:opencv学习笔记02 OpenCV-Python教程:11.图片阈值 https://www.jianshu.com/p/267a32ad0a23 cv2阈值处理:https://b ...

  6. opencv学习笔记01

    原创博文地址:opencv学习笔记01 学习目标 1,opencv能做什么,不能做什么 2,阅读代码,知道某种func后图片怎么样了 3,在图片相关机器学习算法预处理阶段,希望通过对图片的简单处理,达 ...

  7. django学习笔记03

    原创博客地址:django学习笔记03 第一章,模型层 查询集API 一.QuerySet何时被提交 迭代 QuerySet是可迭代的,在首次迭代查询集时执行实际的数据库查询 切片:如果使用切片的&q ...

  8. 视觉slam学习笔记以及课后习题《第五讲特征点法视觉里程计》

    这篇博客主要记录了我在深蓝学院视觉slam课程中的课后习题,因为是为了统计知识点来方便自己以后查阅,所以有部分知识可能不太严谨,如果给大家造成了困扰请见谅,大家发现了问题也可以私信或者评论给我及时改正 ...

  9. jqGrid学习笔记(一)

    原文地址为: jqGrid学习笔记(一) jqGrid 是一个用来显示网格数据的jQuery插件,通过使用jqGrid可以轻松实现前端页面与后台数据的ajax异步通信.文档比较全面,其官方网址为: h ...

  10. RT-Thread 入门学习笔记 - 解决RT_ASSERT失效的问题

    RT-Thread 入门学习笔记 - menuconfig Kconfig的使用 RT-Thread 入门学习笔记 - 熟悉动态内存申请与释放 RT-Thread 入门学习笔记 - 查看线程栈的地址 ...

最新文章

  1. MySQL 触发器错误
  2. mysqlevent每天,附答案
  3. 浅谈主流内存发展历史
  4. 经典C语言程序100例之八八
  5. 基于xml进行bean装配
  6. python 子图大小_Python | 图的大小
  7. ausam3x 嵌入式linux,ATSAM3X8EA-AU - 微控制器, 32位, SAM3X系列, ARM 皮质-M3, 84nb
  8. Nagios Plugin for Cacti (npc插件) Download 下载
  9. 为何大佬都愿意为“996”站台?中国的程序员活该加班?
  10. Android学习笔记(十八)——使用意图筛选器和实现浏览网页(附源代码)
  11. java 反射覆盖方法,java – 确定一个方法是否覆盖使用反射的另一个?
  12. 32个设计非常精美的国外网站作品范例(下篇)
  13. 深入浅出MFC 6大关键技术之仿真 mfc程序初始化过程
  14. talib python文档_GitHub - HuaRongSAO/talib-document: talib学习 talib中文翻译 talib中文文档...
  15. ROS导航仿真操作(3)
  16. Python3-word文档操作(七):提取word文档中的图片方式一-利用word文档的压缩文件属性
  17. 2019中南大学计算机考研分数线,中南大学2019考研分数线已公布
  18. JMS Message消息头、消息体、消息属性
  19. Unity多人游戏集合
  20. OKR如何与绩效考核并行?

热门文章

  1. java面试题全覆盖
  2. 浙商经久不衰的五条规矩
  3. python与药学的联系_你如何理解BE与药学研究的内在联系呢?
  4. 工作笔记--五--@PostConstruct和@Bean注解
  5. 自由职业者如何快速提升自己的能力?
  6. Ubuntu系统安装chrony时间同步服务(局域网集群内同步)
  7. springBoot 安全
  8. 学习uni-app的心得体会
  9. 强势品牌是如何塑造出来的
  10. idea 开发ionic配置