このページでは、android-mainline
で確認された、パートナーにとって重要な問題とバグ修正について説明します。
2024 年 11 月 15 日
android-mainline
とandroid16-6.12
の Clang が 19.0.1 に更新- 概要: 新しいバージョンの 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
フラグは、符号付き整数を定義されたオーバーフロー動作を持つ 2 の補数の符号なし整数として扱うように設計されています。- Linux カーネルで符号付き整数オーバーフローをサニタイズするとバグの特定に役立ちますが、
atomic_long_t
など、オーバーフローが意図的に発生することもあります。そのため、UBSAN が境界サニタライザーとしてのみ機能するように、CONFIG_UBSAN_SIGNED_WRAP
は無効にされています。
- Linux カーネルで符号付き整数オーバーフローをサニタイズするとバグの特定に役立ちますが、
CONFIG_UBSAN_TRAP
について: UBSAN は、問題を検出するとカーネル パニックをトリガーしてカーネルの整合性を保護するように構成されています。ただし、10 月 23 日から 11 月 12 日まで、この動作は無効になりました。これは、既知の__counted_by
の問題を修正しながら、コンパイラ アップデートのブロックを解除するために行いました。
- 概要: 新しいバージョンの Clang では、配列の境界サニタイザーが導入されています。このサニタイザーでは、配列のサイズが
2024 年 11 月 1 日
- Linux 6.12-rc4 のリリース
- 概要:
CONFIG_OF_DYNAMIC
により、欠陥のあるドライバで深刻なリグレッションが発生する可能性があります。 - 詳細: Linux
6.12-rc1
をandroid-mainline
に統合する際に、ツリー外のドライバが読み込まれないという問題が発生しました。ドライバのバグを公開した変更は commit274aff8711b2 ("clk: Add KUnit tests for clks registered with struct clk_parent_data")
として特定され、aosp/3287735 で一時的に元に戻されました。この変更により、CONFIG_OF_OVERLAY
が選択され、CONFIG_OF_DYNAMIC
が選択されます。!OF_DYNAMIC
では、noops
として実装されているため、of_node_get()
とof_node_put()
のリファレンス カウントは実質的に無効になります。OF_DYNAMIC
を有効にすると、struct device_node
のリファレンス カウントを誤って実装しているドライバの問題が再び発生します。これにより、メモリ破損、use-after-free、メモリリークなどのさまざまなタイプのエラーが発生します。 - 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_node
のchar *
プロパティへの直接ポインタを保持する(例: 以下を使用)。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()
- 解放後の使用(UAF):
- 前述の変更は、Linux
6.12-rc4
のリリース中に復元されました(aosp/3315251 を参照)。これによりCONFIG_OF_DYNAMIC
が再度有効になり、欠陥のあるドライバが公開される可能性があります。
- 概要: