首頁 > 軟體

Kasan - Linux 核心的記憶體檢測工具

2020-06-16 17:25:22

Kernel address sanitizer (Kasan) 是一款隨 Linux 核心程式碼一同發布和維護的記憶體檢測工具,由核心社群維護和發展。本文簡要介紹 Kasan 的原理及使用方法。

引言

Kasan 是 Kernel Address Sanitizer 的縮寫,它是一個動態檢測記憶體錯誤的工具,主要功能是檢查記憶體越界存取和使用已釋放的記憶體等問題。Kasan 整合在 Linux 核心中,隨 Linux 核心程式碼一起發布,並由核心社群維護和發展。

背景

Kasan 可以追溯到 LLVM 的 sanitizers 專案(https://github.com/google/sanitizers),這個專案包含了 AddressSanitizer,MemorySanitizer,ThreadSanitizer 和 LeakSanitizer 等工具。但這些工具只能檢測使用者空間的記憶體問題。通過在編譯時加入指定的選項,就可以給使用者程式加入 Address Sanitizer 功能。

清單 1. 使用者空間記憶體錯誤程式碼範例
 // To compile: g++ -O -g -fsanitize=address use-after-free.c 
 int main(int argc, char **argv) { 
  int *array = new int[10]; 
  delete [] array; 
  return array[argc];  // BOOM 
 }

當執行以上有記憶體使用錯誤的程式時,加入 Address Sanitizer 功能的的版本會報告如下的錯誤資訊,而沒有任何選項的版本則會正常結束程式。

清單 2. Address Sanitizer 執行結果
 tengrui@virtualbox:~/workspace/cc$ g++ -O -g -fsanitize=address use-after-free.cc 
 tengrui@virtualbox:~/workspace/cc$ ./a.out 
 ================================================================= 
 ==4206==ERROR: AddressSanitizer: heap-use-after-free on address 
 0x60400000dfd4 at pc 0x0000004007d4 bp 0x7ffdfdd414f0 sp 0x7ffdfdd414e0 
 READ of size 4 at 0x60400000dfd4 thread T0 
    #0 0x4007d3 in main /home/tengrui/workspace/cc/use-after-free.cc:4 
    #1 0x7f8aa150882f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f) 
    #2 0x4006b8 in _start (/home/tengrui/workspace/cc/a.out+0x4006b8) 

 0x60400000dfd4 is located 4 bytes inside of 40-byte region 
 [0x60400000dfd0,0x60400000dff8) 
 freed by thread T0 here: 
    #0 0x7f8aa194abca in operator delete[](void*) 
     (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x99bca) 
    #1 0x4007a7 in main /home/tengrui/workspace/cc/use-after-free.cc:3 

 previously allocated by thread T0 here: 
    #0 0x7f8aa194a5d2 in operator new[](unsigned long) 
     (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x995d2) 
    #1 0x400797 in main /home/tengrui/workspace/cc/use-after-free.cc:2 

 SUMMARY: AddressSanitizer: 
 heap-use-after-free /home/tengrui/workspace/cc/use-after-free.cc:4 main 
 Shadow bytes around the buggy address: 
  0x0c087fff9ba0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 
  0x0c087fff9bb0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 
  0x0c087fff9bc0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 
  0x0c087fff9bd0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 
  0x0c087fff9be0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 
 =>0x0c087fff9bf0: fa fa fa fa fa fa fa fa fa fa[fd]fd fd fd fd fa 
  0x0c087fff9c00: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 
  0x0c087fff9c10: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 
  0x0c087fff9c20: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 
  0x0c087fff9c30: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 
  0x0c087fff9c40: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 
 Shadow byte legend (one shadow byte represents 8 application bytes): 
  Addressable:           00 
  Partially addressable: 01 02 03 04 05 06 07 
  Heap left redzone:       fa 
  Heap right redzone:      fb 
  Freed heap region:       fd 
  Stack left redzone:      f1 
  Stack mid redzone:       f2 
  Stack right redzone:     f3 
  Stack partial redzone:   f4 
  Stack after return:      f5 
  Stack use after scope:   f8 
  Global redzone:          f9 
  Global init order:       f6 
  Poisoned by user:        f7 
  Container overflow:      fc 
  Array cookie:            ac 
  Intra object redzone:    bb 
  ASan internal:           fe 
 ==4206==ABORTING

Andrey Ryabinin 借鑑了 AddressSanitizer 的思想,並在 Linux 核心中實現了 Kernel Address Sanitizer。所以 Kasan 也可以看成是用於核心空間的 Address Sanitizer。

原理

Kasan 的原理是利用“額外”的記憶體來標記那些可以被使用的記憶體的狀態。這些做標記的區域被稱為影子區域(shadow region)。了解 Linux 記憶體管理的讀者知道,記憶體中的每個物理頁在記憶體中都會有一個 struct page 這樣的結構體來表示,即每 4KB 的頁需要 40B 的結構體,大約 1% 的記憶體用來表示記憶體本身。Kasan 與其類似但“浪費”更為嚴重,影子區域的比例是 1:8,即總記憶體的九分之一會被“浪費”。用官方文件中的例子,如果有 128TB 的可用記憶體,需要有額外 16TB 的記憶體用來做標記。

做標記的方法比較簡單,將可用記憶體按照 8 子節的大小分組,如果每組中所有 8 個位元組都可以存取,則影子記憶體中相應的地方用全零(0x00)表示;如果可用記憶體的前 N(1 到 7 範圍之間)個位元組可用,則影子記憶體中響應的位置用 N 表示;其它情況影子記憶體用負數表示該記憶體不可用。

圖 1. Kasan 記憶體布局原理

使用

Kasan 是核心的一部分,使用時需要重新設定、編譯並安裝核心。Kasan 在 Linux 核心 4.0 版本時被引入核心,所以選擇的核心程式碼需要高於 4.0 版本。另外,最基本的 Kasan 功能需要 GCC4.9.2 支援,更多的支援則需要 GCC5.0 及以上版本。

首先是設定和編譯核心。

執行如下命令啟動圖形設定介面:

清單 3. Linux 圖形設定命令
 make menuconfig
圖 2. Kasan 核心選項設定介面

圖 3. Kasan 模式選項

然後重新編譯並安裝核心即可,除了通用的編譯和安裝命令,在 Fedora 這種發行版本中,還需要更新 grub。

清單 4. Linux 核心編譯、安裝命令
 make menuconfig 
 make 
 sudo make modules_install 
 sudo make install
清單 5. Grub 設定命令
 sudo grub2mkconfig – o /boot/grub/grub.cfg

其它發行版本請參考相關文件。

更多詳情見請繼續閱讀下一頁的精彩內容http://www.linuxidc.com/Linux/2016-12/138712p2.htm


IT145.com E-mail:sddin#qq.com