地址消毒器ASAN学习笔记
地址消毒器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
支持检测:
- Use after free (dangling pointer dereference)
- Heap buffer overflow(堆缓冲区溢出)
- Stack buffer overflow(栈缓冲区溢出)
- Global buffer overflow(全局缓冲区溢出)
- Use after return(返回后使用)
- Use after scope(作用域后使用)
- Initialization order bugs(初始化顺序的Bug)
- 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
关于调用栈
地址消毒器收集如下事件的调用栈:
- malloc and free
- thread creation
- 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学习笔记相关推荐
- cma linux 起始地址,CMA模块学习笔记
CMA模块学习笔记 作者:linuxer 发布于:2017-6-28 18:29 分类:内存管理 前言 本文是近期学习CMA模块的一个学习笔记,方便日后遗忘的时候,回来查询以便迅速恢复上下文. 学习的 ...
- IP地址转化(学习笔记)
1.什么是ip地址 IP地址是一种Internet上的主机编址方式,也称为网际协议地址. IP地址是任意一台主机在网络中的唯一标识 2. IP地址的分类 1.ipv4,占32位 ...
- IPy-IPv4和IPv6地址处理模块学习笔记
在日常网络规划中,会有很多关于IP地址的分配规划问题,如果是手动分配,在量很大的情况下,容易出错.而利用IPy这个python模块,可以很容易实现对iP地址的分配等操作. 以下是对IPy模块学习的一个 ...
- [转载]dorado学习笔记(二)
原文地址:dorado学习笔记(二)作者:傻掛 ·isFirst, isLast在什么情况下使用?在遍历dataset的时候会用到 ·dorado执行的顺序,首先由jsp发送请求,调用相关的ViewM ...
- opencv学习笔记02
原创博文地址:opencv学习笔记02 OpenCV-Python教程:11.图片阈值 https://www.jianshu.com/p/267a32ad0a23 cv2阈值处理:https://b ...
- opencv学习笔记01
原创博文地址:opencv学习笔记01 学习目标 1,opencv能做什么,不能做什么 2,阅读代码,知道某种func后图片怎么样了 3,在图片相关机器学习算法预处理阶段,希望通过对图片的简单处理,达 ...
- django学习笔记03
原创博客地址:django学习笔记03 第一章,模型层 查询集API 一.QuerySet何时被提交 迭代 QuerySet是可迭代的,在首次迭代查询集时执行实际的数据库查询 切片:如果使用切片的&q ...
- 视觉slam学习笔记以及课后习题《第五讲特征点法视觉里程计》
这篇博客主要记录了我在深蓝学院视觉slam课程中的课后习题,因为是为了统计知识点来方便自己以后查阅,所以有部分知识可能不太严谨,如果给大家造成了困扰请见谅,大家发现了问题也可以私信或者评论给我及时改正 ...
- jqGrid学习笔记(一)
原文地址为: jqGrid学习笔记(一) jqGrid 是一个用来显示网格数据的jQuery插件,通过使用jqGrid可以轻松实现前端页面与后台数据的ajax异步通信.文档比较全面,其官方网址为: h ...
- RT-Thread 入门学习笔记 - 解决RT_ASSERT失效的问题
RT-Thread 入门学习笔记 - menuconfig Kconfig的使用 RT-Thread 入门学习笔记 - 熟悉动态内存申请与释放 RT-Thread 入门学习笔记 - 查看线程栈的地址 ...
最新文章
- MySQL 触发器错误
- mysqlevent每天,附答案
- 浅谈主流内存发展历史
- 经典C语言程序100例之八八
- 基于xml进行bean装配
- python 子图大小_Python | 图的大小
- ausam3x 嵌入式linux,ATSAM3X8EA-AU - 微控制器, 32位, SAM3X系列, ARM 皮质-M3, 84nb
- Nagios Plugin for Cacti (npc插件) Download 下载
- 为何大佬都愿意为“996”站台?中国的程序员活该加班?
- Android学习笔记(十八)——使用意图筛选器和实现浏览网页(附源代码)
- java 反射覆盖方法,java – 确定一个方法是否覆盖使用反射的另一个?
- 32个设计非常精美的国外网站作品范例(下篇)
- 深入浅出MFC 6大关键技术之仿真 mfc程序初始化过程
- talib python文档_GitHub - HuaRongSAO/talib-document: talib学习 talib中文翻译 talib中文文档...
- ROS导航仿真操作(3)
- Python3-word文档操作(七):提取word文档中的图片方式一-利用word文档的压缩文件属性
- 2019中南大学计算机考研分数线,中南大学2019考研分数线已公布
- JMS Message消息头、消息体、消息属性
- Unity多人游戏集合
- OKR如何与绩效考核并行?