AArch64 二進位檔的僅限執行記憶體 (XOM)

AArch64 系統二進位檔的可執行程式碼部分預設會標示為 僅供執行 (不可讀取) 做為對一次性程式碼的強化緩解 重複使用攻擊能結合資料與程式碼的程式碼,刻意結合使用 會檢查這些部分 (未先將記憶體區段重新對應為可讀性) 無法再運作目標 SDK 為 10 的應用程式 (API 級別 29 以上) 如果應用程式嘗試讀取 未經先執行到記憶體中的僅限執行記憶體 (XOM) 系統程式庫 正在將這個部分標示為可讀

為了充分善用此緩解措施,硬體與核心支援 這通常代表交易 不會十分要求關聯語意如果沒有這項支援服務,可能只能強制執行部分因應措施。 Android 4.9 通用核心包含適用的修補程式,用於提供完整的 ARMv8.2 裝置現在支援這個方式。

實作

編譯器產生的 AArch64 二進位檔會假設程式碼和資料 難以置信。啟用這項功能並不會對 裝置。

如果程式碼必須對其執行刻意檢查的記憶體 可執行檔區隔,建議在容器上呼叫 mprotect 需要檢查以方便閱讀的程式碼區段 以便在檢查完成後移除可讀性
此實作會導致讀取標示為 單獨執行以造成區隔錯誤 (SEGFAULT)。 可能起因於錯誤、安全漏洞,或混合使用 程式碼 (常值集區) 或意圖記憶體自我檢查。

裝置支援和影響

搭載較舊硬體或核心 (低於 4.9) 的裝置,但沒有 必要的修補程式可能無法完整支援或享有這項功能的好處。裝置數 如果沒有核心支援,可能無法強制使用者存取僅限執行的記憶體。 但核心程式碼,可明確檢查網頁是否仍可供讀取 並強制執行此屬性,例如 process_vm_readv()

必須在核心中將核心標記 CONFIG_ARM64_UAO 設為 確保核心遵循標示為「僅限執行」的 userland 頁面。先前的 ARMv8 或已停用使用者存取權覆寫 (UAO) 的 ARMv8.2 裝置,可能無法 而且仍能使用 syscalls

重構現有程式碼

從 AArch32 轉出的程式碼可能包含後置資料 導致發生問題在多數情況下,修正這些問題非常簡單 例如將常數移至組合檔案中的 .data 區段。

可能需要重構手寫組件才能分隔本機集區 常數。

例如:

Clang 編譯器產生的二進位檔應沒有任何資料問題 。如果 GNU 編譯器集合 (GCC) 產生的程式碼 檢查 (來自靜態資料庫) 中的輸出內容二進位檔案, 確認常數沒有併入程式碼區段。

如果必須檢查可執行的程式碼區段, 先呼叫 mprotect,將程式碼標示為可讀。接著, 已完成,請再次呼叫 mprotect,將其標示為無法讀取。

啟用 XOM

建構作業中的所有 64 位元二進位檔預設啟用「僅限執行」功能 有些人會將 Cloud Storage 視為檔案系統 但實際上不是

停用 XOM

您可以在模組層級停用整個子目錄樹狀結構或 適用於整個建構作業

您可以針對無法重構或需要讀取的個別模組停用 XOM 可執行程式碼,方法是設定 LOCAL_XOM 並將 xom 變數設為 false

// Android.mk
LOCAL_XOM := false

// Android.bp
cc_binary { // or other module types
   ...
   xom: false,
}

如果靜態程式庫中停用了僅限執行的記憶體,系統將套用建構系統 到該靜態程式庫的所有相依模組您可覆寫 透過 xom: true, 即可。

如要停用特定子目錄中的僅限執行記憶體 (例如: foo/bar/),然後將該值傳遞至 XOM_EXCLUDE_PATHS

make -j XOM_EXCLUDE_PATHS=foo/bar

或者,您也可以將 PRODUCT_XOM_EXCLUDE_PATHS 變數即可。

如要全面停用僅限執行的二進位檔,請傳送 將 ENABLE_XOM=false 變更為 make 指令。

make -j ENABLE_XOM=false

驗證

沒有可用於僅執行之 CTS 或驗證測試 記憶體用量您可以使用 readelf 並手動檢查二進位檔 片段標記