GKI 16-6.12 android-mainline errata

本頁說明 android-mainline 發現的重要問題和錯誤修正,這些資訊對合作夥伴可能相當重要。

2024 年 11 月 15 日

  • Clang 已更新為 19.0.1,適用於 android-mainlineandroid16-6.12

    • 摘要:新版 Clang 導入陣列的界限清除器,陣列大小會儲存在與陣列連結的個別變數中,並使用 __counted_by 屬性。如果陣列大小未正確更新,這項功能可能會導致核心恐慌。錯誤訊息如下所示:
    UBSAN: array-index-out-of-bounds in common/net/wireless/nl80211.c
    index 0 is out of range for type 'struct ieee80211_channel *[] __counted_by(n_channels)' (aka 'struct ieee80211_channel *[]')
    
    • 詳細資料:邊界清除工具可偵測越界存取,保護核心完整性,因此至關重要。啟用後,邊界清理程式會在發現任何問題時觸發核心恐慌。CONFIG_UBSAN_TRAP

      • 舊版邊界清除器只會檢查固定大小的陣列,無法檢查動態分配的陣列。新版本會使用 __counted_by 屬性在執行階段判斷陣列界限,並偵測更多超出界限的存取案例。不過,在某些情況下,系統會在設定大小變數前存取陣列,觸發邊界清除器並導致核心恐慌。如要解決這個問題,請在分配基礎記憶體後立即設定陣列大小,如 aosp/3343204 所示。
    • 關於 CONFIG_UBSAN_SIGNED_WRAP:新版 Clang 會清除帶正負號的整數溢位和下溢,即使有 -fwrapv 編譯器旗標也一樣。-fwrapv 標記的設計目的是將正負號整數視為兩個互補的無正負號整數,並定義溢位行為。

      • 雖然在 Linux 核心中清除帶正負號的整數溢位有助於找出錯誤,但有時溢位是刻意為之,例如使用 atomic_long_t 時。因此,CONFIG_UBSAN_SIGNED_WRAP 已停用,UBSAN 只能做為界限清除器運作。
    • 關於 CONFIG_UBSAN_TRAP:UBSAN 會在偵測到問題時觸發核心恐慌,以保護核心的完整性。不過,我們已在 10 月 23 日11 月 12 日期間停用這項功能。我們這麼做是為了在修正已知問題時,解除編譯器更新的封鎖狀態。__counted_by

2024 年 11 月 1 日

  • Linux 6.12-rc4 登陸
    • 摘要:CONFIG_OF_DYNAMIC 可能會導致有問題的驅動程式發生嚴重回歸。
    • 詳細資料:將 Linux 6.12-rc1 合併至 android-mainline 時,我們發現樹狀結構外的驅動程式無法載入。我們已將導致驅動程式錯誤的變更識別為提交 274aff8711b2 ("clk: Add KUnit tests for clks registered with struct clk_parent_data"),並在 aosp/3287735 中暫時還原該變更。這項變更會選取 CONFIG_OF_OVERLAY,而 CONFIG_OF_OVERLAY 會選取 CONFIG_OF_DYNAMIC。 使用 !OF_DYNAMIC 時,系統會有效停用 of_node_get()of_node_put() 的參照計數,因為這些項目是以 noops 實作。再次啟用 OF_DYNAMIC 會導致驅動程式中錯誤實作的參照計數問題曝光。struct device_node這會導致各種錯誤,例如記憶體損毀、使用已釋放記憶體和記憶體流失。
    • 所有使用 OF 剖析相關 API 的情況都必須接受檢查。以下列出部分案例,但並非詳盡無遺:
      • 釋放後使用 (UAF):
        • 重複使用相同的 device_node 引數:這些函式會對指定節點呼叫 of_node_put(),可能需要在呼叫前新增 of_node_get() (例如,使用相同節點做為引數重複呼叫時):
          • of_find_compatible_node()
          • of_find_node_by_name()
          • of_find_node_by_path()
          • of_find_node_by_type()
          • of_get_next_cpu_node()
          • of_get_next_parent()
          • of_get_next_child()
          • of_get_next_available_child()
          • of_get_next_reserved_child()
          • of_find_node_with_property()
          • of_find_matching_node_and_match()
        • 在從特定迴圈結束後使用 device_node
          • for_each_available_child_of_node_scoped()
          • for_each_available_child_of_node()
          • for_each_child_of_node_scoped()
          • for_each_child_of_node()
        • 保留來自 device_nodechar * 屬性直接指標,例如使用:
          • const char *foo = struct device_node::name
          • of_property_read_string()
          • of_property_read_string_array()
          • of_property_read_string_index()
          • of_get_property()
      • 記憶體流失:
        • 取得 device_node 並忘記取消參照 (of_node_put())。 從這些項目傳回的節點必須在某個時間點釋放:
          • of_find_compatible_node()
          • of_find_node_by_name()
          • of_find_node_by_path()
          • of_find_node_by_type()
          • of_find_node_by_phandle()
          • of_parse_phandle()
          • of_find_node_opts_by_path()
          • of_get_next_cpu_node()
          • of_get_compatible_child()
          • of_get_child_by_name()
          • of_get_parent()
          • of_get_next_parent()
          • of_get_next_child()
          • of_get_next_available_child()
          • of_get_next_reserved_child()
          • of_find_node_with_property()
          • of_find_matching_node_and_match()
      • 從迴圈疊代保留 device_node。如果您要從下列項目中傳回或中斷,必須在某個時間點捨棄其餘參照:
        • for_each_available_child_of_node()
        • for_each_child_of_node()
        • for_each_node_by_type()
        • for_each_compatible_node()
        • of_for_each_phandle()
    • 在登陸 Linux 6.12-rc4 時,系統還原了先前提及的變更 (請參閱 aosp/3315251),再次啟用 CONFIG_OF_DYNAMIC,可能導致驅動程式故障。