MemTagSanitizer

簡介

**注意:**本頁描述了一個正在開發中的工具。部分功能已規劃但尚未實作。截至 2019 年 10 月,尚不存在能夠執行 MemTagSanitizer 的硬體。

MemTagSanitizer 是一款快速的記憶體錯誤偵測器和**程式碼強化工具**,基於 Armv8.5-A 記憶體標記擴充功能。它偵測的錯誤類型與 AddressSanitizerHardwareAssistedAddressSanitizer 類似,但**開銷低得多**。

MemTagSanitizer 的 CPU 和記憶體開銷預計都在個位數以內。目前有計劃推出除錯模式,該模式具有略高的記憶體開銷和更好的診斷功能。MemTagSanitizer 的主要用例是在生產二進制檔案中進行程式碼強化,預計它可以有效地減輕基於堆疊和堆積的記憶體錯誤。

用法

使用 -fsanitize=memtag 旗標編譯和連結您的程式。這僅在使用 MemTag 擴充功能的 AArch64 目標平台上有效。一種可能的方法是在編譯旗標中加入 -target aarch64-linux -march=armv8+memtag

實作

有關基於標記的記憶體安全方法的概述,請參閱 HardwareAssistedAddressSanitizer。MemTagSanitizer 採用類似的實作策略,但標記儲存區(陰影)由硬體提供。

MTE 硬體功能快速概覽

  • 每 16 個對齊的記憶體位元組可以分配一個 4 位元的配置標記。

  • 每個指標都可以有一個 4 位元的地址標記,位於其最高有效位元組中。

  • 如果地址標記 != 配置標記,大多數記憶體存取指令都會產生例外狀況。

  • 提供了特殊的指令,用於快速操作標記。

堆疊插樁

透過在每個區域變數生命週期開始時將其配置標記更新為隨機值,並在其生命週期結束時將其重設為堆疊指標地址標記,即可偵測基於堆疊的記憶體錯誤。未配置的堆疊空間預計會與 SP 的地址標記相符;這允許在靜態證明記憶體安全性的情況下跳過任何變數的標記。

為大型函數中的每個堆疊變數分配一個真正的隨機標記可能會導致程式碼大小顯著增加,因為這意味著每個變數的地址都是一個獨立的、不可重複使用的值;因此,具有 N 個區域變數的函數在其大部分生命週期中都需要額外保留 N 個活動值。

因此,MemTagSanitizer 在每個函式中最多只會產生一個隨機標籤,稱為「基礎標籤」。其他堆疊變數(如果有的話)會被分配從基礎標籤開始固定偏移量的標籤。

如需堆疊程式碼插裝的詳細資訊,請參閱此文件

堆積標記

注意:此部分截至 2019 年 10 月尚未實作。

MemTagSanitizer 將使用Scudo 強化配置器,並搭配額外的程式碼在以下情況下更新記憶體標籤:

  • 從系統取得新的記憶體時。

  • 釋放配置的記憶體時。

只要傳回具有相符地址標籤的指標,就無需變更 malloc() 中大部分已配置記憶體的配置標籤。

更多資訊