Le GPU d’Apple et le Bug Improbable

En fin 2020, Apple lançait le M1 avec l’architecture GPU AGX, supposée dérivée de la série PowerVR d’Imagination. Depuis, chez Asahi Linux, nous avons entrepris de rétro-ingénier AGX et de construire des pilotes graphiques open source.

En janvier dernier, j’ai réussi à dessiner un triangle avec mon propre code, mais un bogue récalcitrant est apparu :

Le pilote ne parvient pas à rendre de grandes quantités de géométrie.

Un cube en rotation fonctionne sans problème, une géométrie faible en polygones aussi, mais les modèles détaillés ne sont pas affichés correctement.

La commande GPU ne rend qu’une partie du modèle avant de faire défaut.

Problèmes de Détails et Hypothèses Déconcertantes

Il est difficile de déterminer combien de détails peuvent être rendus sans erreurs. Ce n’est pas juste la complexité géométrique qui compte.

La même géométrie peut être affichée avec des shaders simples mais échouer avec des shaders complexes. Cela suggère que le rendu détaillé avec un shader complexe « prend trop de temps », et le GPU dépasse un délai.

Mais cette explication ne cadre pas avec l’architecture matérielle existante.

Pour tester cette hypothèse, nous pouvons ajuster le temps de traitement avec un shader spécialement conçu pour durer autant que nous le souhaitons :

for (int i = 0; i < LARGE_NUMBER; ++i) { 
    /* du travail pour empêcher l'optimiseur de supprimer la boucle */ 
}

Les essais montrent que :

  1. Si les shaders ont une limite de temps pour se protéger contre les boucles infinies, cette limite est astronomiquement haute, notre lapin ne l'atteint jamais.
  2. Les symptômes d'un dépassement de délai sont différents de ceux de notre rendu du pilote.

Cette théorie étant exclue, nous avons expérimenté plus avant. En modifiant le shader et observant où il échoue, seul un facteur contribuait au bogue : la quantité de données interpolées par sommet.

Les API graphiques modernes permettent de spécifier des données "varying" pour chaque sommet, telles que la couleur ou la normale de surface, lesquelles sont ensuite interpolées pour obtenir des entrées lisses dans le shader fragment, permettant des techniques courantes comme l'ombrage Blinn-Phong.

Une Révision de l'Architecture GPU

Si l'on considère les architectures GPU courantes, les rendus en mode immédiat directement dans le tampon de trame nécessitent des accès mémoire constants, tandis que les rendus différés en mode tuile divisent le rendu en deux passes pour minimiser le trafic mémoire.

Les GPU AGX d'Apple, dérivés de la technologie de rendu tuile des PowerVR, nécessitent un tampon pour l’ensemble des données de sommets.

Nous confrontons une situation où, avec trop de données de sommets, le tampon se remplit trop vite et cause un défaut.

Sur certains rendus différés, le pilote espace utilisateur calcule et alloue la taille du tampon des "varyings".

Un examen du comportement du pilote Metal d'Apple révèle qu'augmenter la quantité de géométrie n'augmente pas la taille des tampons alloués, ce qui suggère que le tampon en question est alloué par le noyau ou le micrologiciel.

La documentation publique évoque que le "Tampon de Sommet Tuile" peut entraîner un rendu partiel si rempli. En traçant les allocations mémoire GPU, nous identifions deux compteurs pertinents : le nombre de rendus partiels et les octets utilisés du tampon de paramètres.

Le guide d'optimisation PowerVR confirme que ce tampon de paramètres, stockant les sommets transformés, cause un rendu partiel si saturé. Dans notre cas, cette mécanique semble défaillante sur le M1.

Une vérification montre que nous ne spécifions aucun programme pour ce chargement de tampon partiel.

En suivant le modèle de Metal et en ajustant notre propre code, nous fournissons un programme pour recharger le tampon après un rendu partiel.

Le résultat ? Les défauts disparaissent mais le rendu reste incorrect pour quelques images, le système répondant à l'overflow en ajustant dynamiquement la taille du tampon de paramètres, réduisant les rendus partiels coûteux.

Après inspections et optimisations, nous constatons enfin que le bug repose non seulement sur la gestion du tampon couleur, mais également sur le tampon de profondeur, crucial pour la gestion correcte des pixels occlus, expliquant la défaillance initiale du test de profondeur.

Avec les ajustements finaux, notre lapin Phong ombré s'affiche correctement.

En conclusion, comprendre et corriger ce bug improbable a nécessité une analyse approfondie et des tests rigoureux pour révéler les subtilités de l'architecture GPU AGX d'Apple.

Cela illustre une fois de plus l'importance de la ténacité et de l'expertise technique pour surmonter les défis complexes en cybersécurité et informatique.

Un Risque Caché par le Bug

Le problème identifié avec le pilote et le rendu incorrect des modèles graphiques révèle un risque en cybersécurité potentiellement significatif.

En effet, toute vulnérabilité dans le fonctionnement du matériel ou des pilotes GPU pourrait être exploitée par des acteurs malveillants pour exécuter du code non autorisé à travers des shaders compromis ou des tampons mémoire mal gérés.

Pour une entreprise, cela pourrait signifier des portes dérobées permettant des accès non souhaités à des systèmes critiques, posant un sérieux risque pour la sécurité des données sensibles et des opérations quotidiennes.

Consolider la Sécurité GPU

Pour atténuer ce risque, il est primordial d'assurer une mise à jour régulière des pilotes graphiques et de surveiller les correctifs publiés par les constructeurs.

Les entreprises doivent implémenter des mécanismes de détection d'intrusion pour identifier rapidement des comportements GPU inhabituels.

De plus, l'adoption d'une approche de principe de moindre privilège en limitant les accès aux ressources GPU et en segmentant les réseaux peut réduire les surfaces d'attaque et protéger les systèmes contre des exploitations potentielles.