我們寫程式總免不了會有 bugs, 其中 Memory 相關的 bugs 佔了一大部份, 有工具可以幫我們檢查嗎?
有的, 最常見的是 Valgrind, 除此之外還有 Pin、Dr.Memory、Sanitizer ...
| AddressSanitizer | Valgrind (Memcheck) | Valgrind (SGCheck) | |
|---|---|---|---|
| technology | CTI | DBI | DBI |
| ARCH | x86, x86_64, ARM, PPC, ... | x86, x86_64, ARM, PPC, ... | x86, x86_64, ARM, PPC, ... |
| OS | Linux, FreeBSD, Android, Mac, Windows, ... | Linux, FreeBSD, Android, Mac, ... | Linux, FreeBSD, Android, Mac, ... |
| Slowdown | 2x | 20x | |
| Detects: | |||
| Heap OOB | O | O | X |
| Stack OOB | O | X | O |
| Global OOB | O | X | O |
| UAF | O | O | X |
| UAR | O | X* | X |
| UMR | X | O | X |
| Leaks | O | O | X |
* : 可能會變成 UAF 被偵測到
| 縮寫 | 全名 |
|---|---|
| CTI | Compile-Time Instrumentation |
| DBI | Dynamic Binary Instrumentation |
| UMR | Uninitialized Memory Reads |
| UAF | Use-After-Free (aka dangling pointer) |
| UAR | Use-After-Return |
| OOB | Out-Of-Bounds |
沒在上面 table !?
int *x = malloc(sizeof(int));
free(x);
free(x);int *x = malloc(sizeof(int));
free(x);
*x = 42;char *x = malloc(sizeof(char) * 3);
x[42] = 'C';char x[3];
x[42] = 'C';char x[3];
x[42] = 'C';int* f() {
int a = 0;
return &a;
}
void g() {
int* x = f();
*x = 42;
}int x;
if (x > 0)
return 1;- Valgrind
- LLVM Sanitizer
Wrapper for Activity Manager
setprop wrap.$PACKAGE "logwrapper /data/local/Inst/bin/start_valgrind.sh"script 1 : start_valgrind.sh
#!/system/bin/sh
PACKAGE="com.android.browser"
export TMPDIR=/data/data/$PACKAGE
VGPARAMS="--log-file=$TMPDIR/valgrind.log.%p --error-limit=no --trace-children=yes"
# Memcheck tool
VGPLUGIN="--tool=memcheck --leak-check=full --show-reachable=yes"
echo "valgrind args: $*"
exec /data/local/Inst/bin/valgrind $VGPARAMS $VGPLUGIN $*stcript 2 : bootstrap_valgrind.sh
#!/usr/bin/env sh
PACKAGE="com.android.browser"
ACTIVITY=".BrowserActivity"
adb push start_valgrind.sh /data/local/Inst/bin/
adb shell chmod 777 /data/local/Inst/bin/start_valgrind.sh
adb root
adb shell setprop wrap.$PACKAGE "logwrapper /data/local/Inst/bin/start_valgrind.sh"
echo "wrap.$PACKAGE: $(adb shell getprop wrap.$PACKAGE)"
# -S: force stop the target app before starting the activity
# -D: enable debugging
# -a: <ACTION> Specify the intent action, such as "android.intent.action.VIEW". You can declare this only once.
# -n: <COMPONENT> Specify the component name with package name prefix to create an explicit intent, such as "com.example.app/.ExampleActivity".
adb shell am start -S -a android.intent.action.MAIN -n $PACKAGE/$ACTIVITY
adb logcat -c # -c: clears (flushes) the entire log and exits.
adb logcatvalgrind first revision : https://github.com/svn2github/valgrind-master-mirror/commit/de4a1d01951937632098a6cda45859afa587a06f
- Android : https://github.com/google/sanitizers/wiki/AddressSanitizerOnAndroid
- http://lists.llvm.org/pipermail/llvm-dev/2013-June/063073.html
及早除蟲,避免腐爛
Table of Contents
系統程式
timeline
Valgrind ----->
Sanitizer ------------>
code coverage
其中 Memory 相關的問題佔了很大一部份,
Therac-25 是由 AECL 生產的輻射治療機器, 但是因為軟體的問題造成六起醫療事故, 使患者死亡或者受到嚴重的輻射灼傷。
Therac-25 使用 PDP-11 進行機器控制, 沿用原先有硬體保護機制的 Therac-20 的軟體, 操作過快時會造成 race conditions, 產生嚴重的後果。 但是原先的 Therac-20 有硬體保護, 所以先前都沒有出問題, 後來 Therac-25 完全由軟體控制, 問題因此顯現。
歐洲太空總署耗費 10 年打造無人駕駛的 Ariane 5 火箭, 於 1996 年 6 月 4 日進行發射, 但是因為軟體錯誤, 造成升空後 37 秒就爆炸, 損失約 3.7 億美元。
此軟體 bug 為 64-bit 浮點數和 16-bit 整數的轉換, 整套系統承襲自 Ariane 4, 但是 Ariane 5 的運算能力比 Ariane 5 高, 原先不會發生的問題就此產生, 造成 overflow, 產生 hardware exception, 最後使整個系統失效, 造成火箭發射失敗。
- 靜態
- 動態
- 搭配 Test Case
- 搭配 Fuzz Testing
| 優點 | 缺點 | |
|---|---|---|
| 靜態 | 執行前找出問題 | 有些問題無法找到 |
| 動態 | 可找出更多種類的問題 |
|
- Coverity
- Valgrind
- LLVM Sanitizer
Valgrind 是一個 Dynamic Binary Instrumentation Framework, 可以在已經編完的 Binary 程式裡插入檢查的 code。 內部使用 VEX IR 作為中間層, 任何平台的 Binary (x86/MIPS/ARM/...) 只要接上 frontend 轉成 VEX IR, 就可以接上已經寫好的 Plugin, JIT 地轉換成新的 Binary 後執行。
可以解決 Ariane 5 的問題
- no false positive
- need good multithread test
- data race
- thread leak
- deadlocks
- incorrect uses of mutexes
- malloc calls in signal handlers
- ...
- natively understands atomic operations (can find bugs in lock-free algorithms)
市面上常見的分析工具大多先針對 x86 平台, 然而現今 ARM 的設備已經相當普遍, 這些工具在 ARM 上又是否能使用呢?
仍然缺乏
zygote with sanitizer
http://lists.llvm.org/pipermail/llvm-dev/2013-June/063101.html http://address-sanitizer.googlecode.com/svn-history/r1624/wiki/Android.wiki https://github.com/google/sanitizers/wiki/AddressSanitizer https://github.com/google/sanitizers/wiki/AddressSanitizerOnAndroid
Android NDK supports AddressSanitizer on arm, armv7 and x86 ABIs starting with version r10d (2014-12).
AddressSanitizer on Android requires a rooted device (either -eng or -userdebug build, or any other setup that allows editing the contents of the /system partition).
!!! http://swsys.ru/index.php?page=article&id=3593&lang=en
Combining compile-time and run-time instrumentation for testing tools 昨天晚上找到的 還沒空讀完 裡面提到 DRASan 是要結合 Dynamo 和 AddressSanitizer (有看到裡面在討論混合式的 Instrumentation)
http://blog.chromium.org/2012/04/fuzzing-for-security.html
Static binary instrumentation
https://www.chromium.org/developers/how-tos/using-drmemory https://en.wikipedia.org/wiki/DynamoRIO#cite_note-9
dr memory vs valgrind
http://seclab.cs.sunysb.edu/seclab/pubs/vee14.pdf
Still working on it ...
- Wikipedia - List of software bugs
- Wikipedia - Software bug
- Wikipedia - Therac-25
- Wikipedia - Cluster (spacecraft)
- Wikipedia - Heartbleed
- Wikipedia - AddressSanitizer
- GCC Undefined Behavior Sanitizer – ubsan
- Coverity - Software Testing and Static Analysis Tools
- How to Prevent the next Heartbleed
- ThreadSanitizer: Slaughtering Data Races