このページでは、パートナーにとって重要である可能性のある 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
では、of_node_get()
とof_node_put()
の ref-counting は、noops
として実装されるため、実質的に無効となります。OF_DYNAMIC
を再び有効にすると、ドライバがstruct device_node
の ref-counting を誤って実装するため、問題が再び現れます。これにより、メモリ破損、解放後の使用、メモリリークなど、さまざまな種類のエラーが発生します。 - 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()
- 特定のループからのあらゆる種類の exit の後の
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
が再び有効になり、不具合のあるドライバが生じる可能性があります。
- 概要: