Questa pagina descrive problemi importanti e correzioni di bug trovati su android-mainline
che potrebbero essere significativi per i partner.
15 novembre 2024
Clang è stato aggiornato alla versione 19.0.1 per
android-mainline
eandroid16-6.12
- Riepilogo: la nuova versione di Clang introduce un bounds sanitizer per gli array,
in cui la dimensione dell'array è memorizzata in una variabile separata collegata all'array
utilizzando l'attributo
__counted_by
. Questa funzionalità potrebbe causare un kernel panic se le dimensioni dell'array non vengono aggiornate correttamente. Il messaggio di errore ha il seguente aspetto:
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 *[]')
Dettagli: il sanificatore dei limiti è essenziale per proteggere l'integrità del kernel rilevando l'accesso fuori dai limiti. Se
CONFIG_UBSAN_TRAP
è abilitato, Bounds Sanitizer attiva un kernel panic per ogni risultato.- La versione precedente del sanitizer dei limiti controllava solo gli array di dimensioni fisse
e non poteva controllare gli array allocati dinamicamente. La nuova versione utilizza l'attributo
__counted_by
per determinare i limiti dell'array in fase di runtime e rilevare più casi di accesso fuori dai limiti. Tuttavia, in alcuni casi, si accede all'array prima che venga impostata la variabile di dimensione, attivando il sanitizer dei limiti e causando un kernel panic. Per risolvere il problema, imposta le dimensioni dell'array subito dopo l'allocazione della memoria sottostante, come illustrato in aosp/3343204.
- La versione precedente del sanitizer dei limiti controllava solo gli array di dimensioni fisse
e non poteva controllare gli array allocati dinamicamente. La nuova versione utilizza l'attributo
Informazioni su
CONFIG_UBSAN_SIGNED_WRAP
: la nuova versione di Clang esegue la sanificazione dell'overflow e dell'underflow di interi con segno nonostante il flag del compilatore-fwrapv
. Il flag-fwrapv
è progettato per trattare gli interi con segno come interi senza segno in complemento a due con comportamento di overflow definito.- Sebbene la sanificazione dell'overflow di interi con segno nel kernel Linux possa aiutare
a identificare i bug, ci sono casi in cui l'overflow è intenzionale, ad esempio con
atomic_long_t
. Di conseguenza,CONFIG_UBSAN_SIGNED_WRAP
è stato disattivato per consentire a UBSAN di funzionare esclusivamente come strumento di sanificazione dei limiti.
- Sebbene la sanificazione dell'overflow di interi con segno nel kernel Linux possa aiutare
a identificare i bug, ci sono casi in cui l'overflow è intenzionale, ad esempio con
Informazioni su
CONFIG_UBSAN_TRAP
: UBSAN è configurato per attivare un kernel panic quando rileva un problema per proteggere l'integrità del kernel. Tuttavia, abbiamo disattivato questo comportamento dal 23 ottobre al 12 novembre. Abbiamo eseguito questa operazione per sbloccare l'aggiornamento del compilatore mentre risolvevamo i problemi__counted_by
noti.
- Riepilogo: la nuova versione di Clang introduce un bounds sanitizer per gli array,
in cui la dimensione dell'array è memorizzata in una variabile separata collegata all'array
utilizzando l'attributo
1° novembre 2024
- Linux 6.12-rc4 landing
- Riepilogo:
CONFIG_OF_DYNAMIC
potrebbe causare gravi regressioni per driver difettosi. - Dettagli: durante l'unione di Linux
6.12-rc1
inandroid-mainline
abbiamo notato problemi con il caricamento dei driver out-of-tree. La modifica che ha esposto i bug del driver è stata identificata come commit274aff8711b2 ("clk: Add KUnit tests for clks registered with struct clk_parent_data")
e l'abbiamo temporaneamente ripristinata in aosp/3287735. La modifica selezionaCONFIG_OF_OVERLAY
, che selezionaCONFIG_OF_DYNAMIC
. Con!OF_DYNAMIC
, il conteggio dei riferimenti suof_node_get()
eof_node_put()
è effettivamente disattivato perché sono implementati comenoops
. L'abilitazione diOF_DYNAMIC
espone nuovamente problemi nei driver che implementano in modo errato il conteggio dei riferimenti perstruct device_node
. Ciò causa vari tipi di errori come la corruzione della memoria, l'utilizzo dopo la liberazione e le perdite di memoria. - Tutti gli utilizzi delle API correlate all'analisi OF devono essere esaminati. Il seguente elenco è
parziale, ma contiene i casi che abbiamo osservato:
- Use-after-free (UAF):
- Riutilizzo dello stesso argomento
device_node
: queste funzioni chiamano <x0A>of_node_put()
sul nodo specificato, potenzialmente devono aggiungere un <x0A>of_node_get()
prima di chiamarle (ad esempio, quando si chiama <x0A>ripetutamente con lo stesso nodo come argomento): <x0A>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()
- Utilizzo di
device_node
dopo qualsiasi tipo di uscita da determinati loop:for_each_available_child_of_node_scoped()
for_each_available_child_of_node()
for_each_child_of_node_scoped()
for_each_child_of_node()
- Mantenere puntatori diretti alle proprietà
char *
dadevice_node
circa, ad esempio utilizzando:const char *foo = struct device_node::name
of_property_read_string()
of_property_read_string_array()
of_property_read_string_index()
of_get_property()
- Riutilizzo dello stesso argomento
- Perdite di memoria:
- Ottenere un
device_node
e dimenticarsi di annullare il riferimento (of_node_put()
). I nodi restituiti da questi devono essere liberati a un certo punto: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()
- Ottenere un
- Mantenere un
device_node
da un'iterazione del ciclo. Se stai tornando o interrompendo una delle seguenti operazioni, devi eliminare il riferimento rimanente a un certo punto:for_each_available_child_of_node()
for_each_child_of_node()
for_each_node_by_type()
for_each_compatible_node()
of_for_each_phandle()
- Use-after-free (UAF):
- La modifica menzionata in precedenza è stata ripristinata durante l'approdo di Linux
6.12-rc4
(vedi aosp/3315251) riattivandoCONFIG_OF_DYNAMIC
ed esponendo potenzialmente driver difettosi.
- Riepilogo: