Cette page décrit les problèmes importants et les corrections de bugs trouvés sur android-mainline
qui peuvent être importants pour les partenaires.
15 novembre 2024
Mise à jour de Clang vers la version 19.0.1 pour
android-mainline
etandroid16-6.12
- Résumé : La nouvelle version de Clang introduit un outil de vérification des limites pour les tableaux, où la taille du tableau est stockée dans une variable distincte liée au tableau à l'aide de l'attribut
__counted_by
. Cette fonctionnalité peut entraîner une panique du noyau si la taille du tableau n'est pas mise à jour correctement. Le message d'erreur ressemble à ceci :
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 *[]')
Détails : Le module de désinfection des limites est essentiel pour protéger l'intégrité du noyau en détectant les accès hors limites. Avec
CONFIG_UBSAN_TRAP
activé, le vérificateur de limites déclenche un kernel panic pour chaque problème détecté.- La version précédente du module de désinfection des limites ne vérifiait que les tableaux de taille fixe et ne pouvait pas vérifier les tableaux alloués de manière dynamique. La nouvelle version utilise l'attribut
__counted_by
pour déterminer les limites du tableau au moment de l'exécution et détecter davantage de cas d'accès hors limites. Toutefois, dans certains cas, le tableau est consulté avant que la variable de taille ne soit définie, ce qui déclenche le module de désinfection des limites et provoque un plantage du noyau. Pour résoudre ce problème, définissez la taille du tableau immédiatement après avoir alloué la mémoire sous-jacente, comme illustré dans aosp/3343204.
- La version précédente du module de désinfection des limites ne vérifiait que les tableaux de taille fixe et ne pouvait pas vérifier les tableaux alloués de manière dynamique. La nouvelle version utilise l'attribut
À propos de
CONFIG_UBSAN_SIGNED_WRAP
: la nouvelle version de Clang assainit les dépassements de capacité et les dépassements négatifs d'entiers signés malgré l'indicateur de compilation-fwrapv
. L'indicateur-fwrapv
est conçu pour traiter les entiers signés comme des entiers non signés en complément à deux avec un comportement de dépassement de capacité défini.- Bien que la désinfection du dépassement de capacité des entiers signés dans le noyau Linux puisse aider à identifier les bugs, il existe des cas où le dépassement de capacité est intentionnel, par exemple avec
atomic_long_t
. Par conséquent,CONFIG_UBSAN_SIGNED_WRAP
a été désactivé pour permettre à UBSAN de fonctionner uniquement en tant que vérificateur de limites.
- Bien que la désinfection du dépassement de capacité des entiers signés dans le noyau Linux puisse aider à identifier les bugs, il existe des cas où le dépassement de capacité est intentionnel, par exemple avec
À propos de
CONFIG_UBSAN_TRAP
: UBSAN est configuré pour déclencher une panique du noyau lorsqu'il détecte un problème afin de protéger l'intégrité du noyau. Toutefois, nous avons désactivé ce comportement du 23 octobre au 12 novembre. Nous avons fait cela pour débloquer la mise à jour du compilateur pendant que nous résolvions les problèmes__counted_by
connus.
- Résumé : La nouvelle version de Clang introduit un outil de vérification des limites pour les tableaux, où la taille du tableau est stockée dans une variable distincte liée au tableau à l'aide de l'attribut
1er novembre 2024
- Lancement de Linux 6.12-rc4
- Résumé :
CONFIG_OF_DYNAMIC
peut entraîner de graves régressions pour les pilotes défectueux. - Détails : lors de la fusion de Linux
6.12-rc1
dansandroid-mainline
, nous avons constaté des problèmes de chargement des pilotes hors arbre. La modification qui a révélé les bugs du pilote a été identifiée comme le commit274aff8711b2 ("clk: Add KUnit tests for clks registered with struct clk_parent_data")
. Nous l'avons temporairement annulée dans aosp/3287735. La modification sélectionneCONFIG_OF_OVERLAY
, qui sélectionneCONFIG_OF_DYNAMIC
. Avec!OF_DYNAMIC
, le décompte des références surof_node_get()
etof_node_put()
est effectivement désactivé, car ils sont implémentés en tant quenoops
. L'activation deOF_DYNAMIC
révèle à nouveau des problèmes dans les pilotes qui implémentent de manière incorrecte le comptage des références pourstruct device_node
. Cela entraîne différents types d'erreurs, comme la corruption de la mémoire, l'utilisation après libération et les fuites de mémoire. - Toutes les utilisations des API liées à l'analyse OF doivent être inspectées. La liste suivante est partielle, mais contient des cas que nous avons observés :
- Utilisation après libération de la mémoire (UAF) :
- Réutilisation du même argument
device_node
: ces fonctions appellentof_node_put()
sur le nœud donné. Il peut être nécessaire d'ajouter unof_node_get()
avant de les appeler (par exemple, lors d'appels répétés avec le même nœud comme argument) :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()
- Utilisation de
device_node
après tout type de sortie de certaines boucles :for_each_available_child_of_node_scoped()
for_each_available_child_of_node()
for_each_child_of_node_scoped()
for_each_child_of_node()
- Conserver des pointeurs directs vers les propriétés
char *
dedevice_node
, par exemple en utilisant :const char *foo = struct device_node::name
of_property_read_string()
of_property_read_string_array()
of_property_read_string_index()
of_get_property()
- Réutilisation du même argument
- Fuites de mémoire :
- Obtenir un
device_node
et oublier de le libérer (of_node_put()
). Les nœuds renvoyés par ceux-ci doivent être libérés à un moment donné :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()
- Obtenir un
- Conserver un
device_node
à partir d'une itération de boucle. Si vous renvoyez ou sortez d'un des éléments suivants, vous devez supprimer la référence restante à un moment donné :for_each_available_child_of_node()
for_each_child_of_node()
for_each_node_by_type()
for_each_compatible_node()
of_for_each_phandle()
- Utilisation après libération de la mémoire (UAF) :
- La modification mentionnée précédemment a été restaurée lors de l'atterrissage de Linux
6.12-rc4
(voir aosp/3315251), ce qui a permis de réactiverCONFIG_OF_DYNAMIC
et d'exposer potentiellement des pilotes défectueux.
- Résumé :