Na tej stronie opisujemy ważne problemy i poprawki błędów znalezione w wersji android-mainline
, które mogą być istotne dla partnerów.
15 listopada 2024 r.
Clang został zaktualizowany do wersji 19.0.1 w przypadku
android-mainline
iandroid16-6.12
- Podsumowanie: nowa wersja Clang wprowadza ograniczenie zakresu dla tablic, w których rozmiar jest przechowywany w osobnej zmiennej połączonej z tablicą za pomocą atrybutu
__counted_by
. Jeśli rozmiar tablicy nie zostanie odpowiednio zaktualizowany, ta funkcja może spowodować panikę jądra. Komunikat o błędzie wygląda tak:
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 *[]')
Szczegóły: sprawdzanie granic jest niezbędne do ochrony integralności jądra przez wykrywanie dostępu poza granice. Gdy włączysz
CONFIG_UBSAN_TRAP
, sprawdzanie granic wywoła panikę jądra po znalezieniu dowolnego błędu.- Poprzednia wersja narzędzia do sprawdzania zakresów sprawdzała tylko tablice o stałym rozmiarze i nie sprawdzała tablic przydzielanych dynamicznie. Nowa wersja używa atrybutu
__counted_by
do określania zakresów tablicy w czasie wykonywania, co pozwala wykrywać więcej przypadków dostępu poza zakres. W niektórych przypadkach jednak dostęp do tablicy jest uzyskiwany przed ustawieniem zmiennej rozmiaru, co powoduje uruchomienie mechanizmu sprawdzania zakresu i wywołanie paniki jądra. Aby rozwiązać ten problem, ustaw rozmiar tablicy zaraz po przydzieleniu pamięci podstawowej, jak pokazano w aosp/3343204.
- Poprzednia wersja narzędzia do sprawdzania zakresów sprawdzała tylko tablice o stałym rozmiarze i nie sprawdzała tablic przydzielanych dynamicznie. Nowa wersja używa atrybutu
Informacje o opcji
CONFIG_UBSAN_SIGNED_WRAP
: nowa wersja Clanga sanitizes signed integer overflow and underflow pomimo opcji kompilatora-fwrapv
. Flaga-fwrapv
ma na celu traktowanie liczb całkowitych ze znakiem jako liczb całkowitych bez znaku z komplementem dwustronnym z zdefiniowanym zachowaniem przy przepełnieniu.- Sanityzacja przepełnienia podpisanego całkowitego w jądrze Linuksa może pomóc w identyfikacji błędów, ale są też przypadki, w których przepełnianie jest celowe, na przykład w przypadku funkcji
atomic_long_t
. W rezultacieCONFIG_UBSAN_SIGNED_WRAP
został wyłączony, aby UBSAN działał tylko jako narzędzie do sprawdzania zakresów.
- Sanityzacja przepełnienia podpisanego całkowitego w jądrze Linuksa może pomóc w identyfikacji błędów, ale są też przypadki, w których przepełnianie jest celowe, na przykład w przypadku funkcji
Informacje o
CONFIG_UBSAN_TRAP
: UBSAN jest skonfigurowany tak, aby wywoływać kernel panic, gdy wykryje problem, aby chronić integralność jądra. Jednak w okresie od 23 października do 12 listopada ta funkcja była wyłączona. Zrobiliśmy to, aby umożliwić aktualizację kompilatora, podczas gdy naprawialiśmy znane problemy.__counted_by
- Podsumowanie: nowa wersja Clang wprowadza ograniczenie zakresu dla tablic, w których rozmiar jest przechowywany w osobnej zmiennej połączonej z tablicą za pomocą atrybutu
1 listopada 2024 roku
- Linux 6.12-rc4
- Podsumowanie:
CONFIG_OF_DYNAMIC
może powodować poważne regresje w przypadku sterowników z błędami. - Szczegóły: podczas łączenia Linuksa
6.12-rc1
zandroid-mainline
zauważyliśmy problemy z wczytywaniem sterowników spoza drzewa. Zmiana, która spowodowała błędy sterownika, została zidentyfikowana jako commit274aff8711b2 ("clk: Add KUnit tests for clks registered with struct clk_parent_data")
i tymczasowo cofnięta w aosp/3287735. Zmiana wybieraCONFIG_OF_OVERLAY
, które z kolei wybieraCONFIG_OF_DYNAMIC
. W wersji!OF_DYNAMIC
zliczanie odwołań w funkcjachof_node_get()
iof_node_put()
jest w efekcie wyłączone, ponieważ są one implementowane jakonoops
. WłączenieOF_DYNAMIC
ponownie ujawnia problemy w sterownikach, które nieprawidłowo implementują zliczanie odwołań w przypadkustruct device_node
. Powoduje to różne typy błędów, takich jak uszkodzenie pamięci, use-after-free i wycieki pamięci. - Wszystkie przypadki użycia interfejsów API związanych z parsowaniem OF muszą zostać sprawdzone. Poniżej znajduje się częściowa lista, która zawiera przypadki, które obserwowaliśmy:
- Użycie po okresie próbnym:
- Ponowne użycie tego samego argumentu
device_node
: te funkcje wywołująof_node_put()
w danym węźle. Przed ich wywołaniem może być konieczne dodanie argumentuof_node_get()
(na przykład w przypadku wielokrotnego wywołania tej samej funkcji z tym samym węzłem jako argumentem):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()
- Użycie
device_node
po dowolnym wyjściu z pewnych pętli:for_each_available_child_of_node_scoped()
for_each_available_child_of_node()
for_each_child_of_node_scoped()
for_each_child_of_node()
- Przechowywanie bezpośrednich wskazówek do właściwości
char *
zdevice_node
, na przykład za pomocą:const char *foo = struct device_node::name
of_property_read_string()
of_property_read_string_array()
of_property_read_string_index()
of_get_property()
- Ponowne użycie tego samego argumentu
- Wycieki pamięci:
- Pobieranie
device_node
i zapominanie o odwoływaniu go (of_node_put()
). Węzły zwracane przez te elementy muszą zostać zwolnione w określonym momencie: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()
- Pobieranie
- Przechowywanie wartości
device_node
z itacji pętli. Jeśli wracasz do kodu lub przerywasz go w ramach tych elementów, musisz w pewnym momencie usunąć pozostałe odwołania:for_each_available_child_of_node()
for_each_child_of_node()
for_each_node_by_type()
for_each_compatible_node()
of_for_each_phandle()
- Użycie po okresie próbnym:
- Wspomniana wcześniej zmiana została przywrócona podczas uruchamiania Linuksa
6.12-rc4
(patrz aosp/3315251), co ponownie włączyłoCONFIG_OF_DYNAMIC
i potencjalnie spowodowało ujawnienie wadliwych sterowników.
- Podsumowanie: