MemTagSanitizer¶
簡介¶
注意: 本頁面描述的是一個仍在開發中的工具。部分功能已規劃但尚未實作。截至 2019 年 10 月,尚不存在能夠運行 MemTagSanitizer 的硬體。
MemTagSanitizer 是一個快速的記憶體錯誤偵測器和程式碼強化工具,基於 Armv8.5-A 記憶體標記擴展。它偵測到的錯誤類型與 AddressSanitizer 或 HardwareAssistedAddressSanitizer 類似,但具有更低的效能負擔。
MemTagSanitizer 的效能負擔預計在個位數百分比的低範圍內,包括 CPU 和記憶體。有計劃推出偵錯模式,該模式具有稍高的記憶體負擔和更好的診斷功能。MemTagSanitizer 的主要用例是在生產環境二進位檔案中進行程式碼強化,預計它將成為堆疊和堆積記憶體錯誤的強大緩解措施。
用法¶
使用 -fsanitize=memtag
標 flag 編譯和連結您的程式。這僅在以具有記憶體標記擴展的 AArch64 Android 為目標時有效。一種可能的方法是在您的編譯 flag 中加入 --target=aarch64-linux-android -march=armv8+memtag
。
請注意,這樣做會覆蓋相同類型的現有 flag。假設您已經以 AArch64 Android 為目標,另一種方法是在您的編譯 flag 中加入 -Xclang -target-feature -Xclang +mte
。這會加入記憶體標記功能,而不會更改任何其他內容。
實作¶
有關基於標記的記憶體安全通用概述,請參閱 HardwareAssistedAddressSanitizer。MemTagSanitizer 遵循類似的實作策略,但標記儲存(陰影)由硬體提供。
MTE 硬體功能的快速概述
每 16 個對齊的記憶體位元組都可以分配一個 4 位元的配置標記。
每個指標都可以有一個 4 位元的位址標記,位於其最高有效位元組中。
如果位址標記 != 配置標記,則大多數記憶體存取指令都會產生例外。
提供特殊指令以進行快速標記操作。
堆疊檢測¶
堆疊記憶體錯誤的偵測方法是:在每個區域變數生命週期的開始時,將其配置標記更新為隨機值,並在其生命週期結束時將其重設為堆疊指標的位址標記。未配置的堆疊空間預期與 SP 的位址標記相符;這允許在可以靜態證明記憶體安全性的情況下,跳過任何變數的標記。
在大型函式中為每個堆疊變數分配一個真正的隨機標記可能會導致顯著的程式碼大小負擔,因為這意味著每個變數的位址都是一個獨立的、不可重新具體化的值;因此,具有 N 個區域變數的函式將有額外的 N 個活動值需要在其大部分生命週期內保留。
因此,MemTagSanitizer 每個函式最多產生一個隨機標記,稱為「基礎標記」。其他堆疊變數(如果有的話)會被分配與基礎標記有固定偏移量的標記。
有關堆疊檢測的更多詳細資訊,請參閱 此文件。
堆積標記¶
注意: 截至 2019 年 10 月,此部分尚未實作。
MemTagSanitizer 將使用 Scudo 強化的分配器,並加入額外程式碼以在以下情況更新記憶體標記:
從系統取得新的記憶體。
釋放分配的記憶體。
只要傳回具有相符位址標記的指標,就無需更改 malloc() 中已分配記憶體主體的配置標記。