[LINUX] Le désinfectant d'adresses du noyau (KASAN) (2/2)

À l'origine, il fait partie du code source du noyau Linux, il sera donc traité comme GPLv2 (reconnaissance qu'il devrait l'être).

https://www.kernel.org/doc/html/latest/index.html

Licensing documentation

The following describes the license of the Linux kernel source code (GPLv2), how to properly mark the license of individual files in the source tree, as well as links to the full license text.

https://www.kernel.org/doc/html/latest/process/license-rules.html#kernel-licensing

https://www.kernel.org/doc/html/latest/dev-tools/kasan.html


Docs » Development tools for the kernel » The Kernel Address Sanitizer (KASAN)

The Kernel Address Sanitizer (KASAN)

Implementation details

Generic KASAN

From a high level, our approach to memory error detection is similar to that of kmemcheck: use shadow memory to record whether each byte of memory is safe to access, and use compile-time instrumentation to insert checks of shadow memory on each memory access.

D'un niveau élevé, notre approche de la détection des erreurs de mémoire est similaire à kmemcheck. Utilisez la mémoire fantôme pour enregistrer si l'accès est sécurisé dans chaque octet de mémoire et insérez une vérification de la mémoire fantôme à chaque accès mémoire au moment de la compilation.

Generic KASAN dedicates 1/8th of kernel memory to its shadow memory (e.g. 16TB to cover 128TB on x86_64) and uses direct mapping with a scale and offset to translate a memory address to its corresponding shadow address.

Le KASAN générique alloue 1/8 de la mémoire du noyau à la mémoire fantôme (par exemple, 16 To pour couvrir 128 To pour x86_64). Ensuite, le mappage direct à l'adresse fantôme associée à l'adresse mémoire par échelle et décalage.

Here is the function which translates an address to its corresponding shadow address:

Ici, la fonction qui traduit l'adresse associée à l'adresse shadow est ...


static inline void *kasan_mem_to_shadow(const void *addr)
{
    return ((unsigned long)addr >> KASAN_SHADOW_SCALE_SHIFT)
            + KASAN_SHADOW_OFFSET;
}

where KASAN_SHADOW_SCALE_SHIFT = 3.

Compile-time instrumentation is used to insert memory access checks. Compiler inserts function calls (__asan_load*(addr), __asan_store*(addr)) before each memory access of size 1, 2, 4, 8 or 16. These functions check whether memory access is valid or not by checking corresponding shadow memory.

L'instrumentation au moment de la compilation est utilisée pour insérer le contrôle d'accès à la mémoire. Le compilateur insère l'appel de fonction kasan_load * (addr), __asan_store * (addr)) avant tout accès mémoire de taille 1,2,4,8. Ces fonctions vérifient si l'accès à la mémoire est activé en vérifiant la mémoire fantôme associée.

GCC 5.0 has possibility to perform inline instrumentation. Instead of making function calls GCC directly inserts the code to check the shadow memory. This option significantly enlarges kernel but it gives x1.1-x2 performance boost over outline instrumented kernel.

Avec GCC 5.0, il est possible d'effectuer une instrumentation en ligne. Au lieu de faire un appel de fonction, GCC insère le code que la mémoire miroir vérifie directement. Cela rend le noyau légèrement gonflé, mais fournit une accélération des performances x1.1-x2 par rapport au noyau instrumenté.

Software tag-based KASAN

Tag-based KASAN uses the Top Byte Ignore (TBI) feature of modern arm64 CPUs to store a pointer tag in the top byte of kernel pointers. Like generic KASAN it uses shadow memory to store memory tags associated with each 16-byte memory cell (therefore it dedicates 1/16th of the kernel memory for shadow memory).

Le KASAN basé sur des balises enregistre la balise du pointeur dans l'octet tio du pointeur du noyau en utilisant les fonctionnalités Top Byte Ignore (TBI), qui est une fonctionnalité du dernier processeur arm64. Comme generi KASAN, shadow mamory est utilisé pour enregistrer la balise mémoire associée à chaque cellule de mémoire de 16 octets (donc la mémoire shadow occupe 1/16 de la mémoire du noyau).

On each memory allocation tag-based KASAN generates a random tag, tags the allocated memory with this tag, and embeds this tag into the returned pointer. Software tag-based KASAN uses compile-time instrumentation to insert checks before each memory access. These checks make sure that tag of the memory that is being accessed is equal to tag of the pointer that is used to access this memory. In case of a tag mismatch tag-based KASAN prints a bug report.

Pour chaque allocation de mémoire, le KASAN basé sur des balises générera une balise aléatoire. La mémoire allouée est marquée avec cette balise et le pointeur renvoyé est incorporé avec cette balise. Le logiciel KASAN basé sur des balises utilise une instrumentation à la compilation et insère une vérification avant chaque accès mémoire. Cette vérification vérifie que l'étiquette de la mémoire en cours d'accès correspond à l'étiquette du pointeur utilisé pour accéder à cette mémoire. Si les balises ne correspondent pas, KASAN basé sur les balises imprimera un rapport de bogue.

Software tag-based KASAN also has two instrumentation modes (outline, that emits callbacks to check memory accesses; and inline, that performs the shadow memory checks inline). With outline instrumentation mode, a bug report is simply printed from the function that performs the access check. With inline instrumentation a brk instruction is emitted by the compiler, and a dedicated brk handler is used to print bug reports.

Le logiciel KASAN basé sur des étiquettes possède également deux modes d'instrumentation. (Émettez un callmback pour vérifier le contour, l'accès à la mémoire et exécute en ligne la vérification de la mémoire fantôme en ligne) En mode d'instrumentation de contour, un rapport de bogue est simplement sorti de la fonction qui a exécuté le contrôle d'accès. Dans l'instrumentation en ligne, les instructions brk sont émises par le compilateur et le gestionnaire brk est utilisé exclusivement pour générer des rapports de bogue.

A potential expansion of this mode is a hardware tag-based mode, which would use hardware memory tagging support instead of compiler instrumentation and manual shadow memory manipulation.

Une extension potentielle de ce mode est le mode basé sur les balises matérielles, où le matériel prend en charge le marquage de la mémoire au lieu de l'instrumentation du compilateur ou de la manipulation manuelle de la mémoire fantôme.

What memory accesses are sanitised by KASAN?

The kernel maps memory in a number of different parts of the address space. This poses something of a problem for KASAN, which requires that all addresses accessed by instrumented code have a valid shadow region.

Le noyau mappe une certaine mémoire là où l'espace adrec est différent. Cela soulève le problème dans KASAN. Toutes les adresses doivent être accédées par un code instrumenté avec une région d'ombre normale.

The range of kernel virtual addresses is large: there is not enough real memory to support a real shadow region for every address that could be accessed by the kernel.

La plage d'adresses virtuelles dans le noyau est très large. Il est peu probable que la mémoire réelle puisse prendre en charge toutes les régions d'ombre auxquelles le noyau accède.

By default

By default, architectures only map real memory over the shadow region for the linear mapping (and potentially other small areas). For all other areas - such as vmalloc and vmemmap space - a single read-only page is mapped over the shadow area. This read-only shadow page declares all memory accesses as permitted.

Par défaut, l'architecture mappe la mémoire réelle à la région d'ombre uniquement par mappage linéaire (d'autres zones potentiellement petites). Pour toutes les autres zones, par exemple dans les espaces vmalloc et vmemmmap, une simple page en lecture seule correspond à la zone d'ombre. Cette page fantôme en lecture seule déclare tous les accès mémoire autorisés.

This presents a problem for modules: they do not live in the linear mapping, but in a dedicated module space. By hooking in to the module allocator, KASAN can temporarily map real shadow memory to cover them. This allows detection of invalid accesses to module globals, for example.

Cela provoque des problèmes pour le module. Ceux-ci ne sont pas valides pour le mappage linéaire et résident dans leur propre espace de module. En s'accrochant à l'allocateur moduke, KASAN implémente temporairement une véritable mémoire fantôme et un mappage temporaire qui les couvre. Cela permet, par exemple, de détecter les accès non autorisés au module global.

This also creates an incompatibility with VMAP_STACK: if the stack lives in vmalloc space, it will be shadowed by the read-only page, and the kernel will fault when trying to set up the shadow data for stack variables.

Cela crée également une incompatibilité avec VMAP_STACK. Si la pile est dans l'espace vmalloc, elle sera masquée par la page en lecture seule et le noyau échouera lors de la tentative de configuration des données d'ombre pour la variable shack.

CONFIG_KASAN_VMALLOC

With CONFIG_KASAN_VMALLOC, KASAN can cover vmalloc space at the cost of greater memory usage. Currently this is only supported on x86.

Si vous définissez CONFIG_KASAN_VMALLOC, KASAN peut également couvrir l'espace vmalloc au prix de l'utilisation de la mémoire. Pour le moment, cela n'est pris en charge que sur x86.

This works by hooking into vmalloc and vmap, and dynamically allocating real shadow memory to back the mappings.

Cela fonctionne en accrochant vmalloc et vmap. Il alloue ensuite dynamiquement une véritable mémoire fantôme pour renvoyer le mappage.

Most mappings in vmalloc space are small, requiring less than a full page of shadow space. Allocating a full shadow page per mapping would therefore be wasteful. Furthermore, to ensure that different mappings use different shadow pages, mappings would have to be aligned to KASAN_SHADOW_SCALE_SIZE * PAGE_SIZE.

Beaucoup de mappingu sont petits dans l'espace vmalloc et font des requêtes plus petites que la page entière dans l'espace d'ombre. Sécuriser une page d'ombre complète avec le mappage est inutile. De plus, si différents mappages mappent différentes pages fantômes, le mappage doit être aligné sur KASAN_SHADOW_SCALE_SIZE * PAGE_SIZE.

Instead, we share backing space across multiple mappings. We allocate a backing page when a mapping in vmalloc space uses a particular page of the shadow region. This page can be shared by other vmalloc mappings later on.

Au lieu de cela, il conserve un espace de sauvegarde sur plusieurs mappages. La page de support est réservée lorsque l'espace vmalloc utilise certaines pages de la zone d'ombre. Cette page sera partagée une fois que d'autres mappages de malloc auront été réalisés.

We hook in to the vmap infrastructure to lazily clean up unused shadow memory.

Accrochez l'infrastructure vmap pour différer et effacer la mémoire fantôme inutilisée.

To avoid the difficulties around swapping mappings around, we expect that the part of the shadow region that covers the vmalloc space will not be covered by the early shadow page, but will be left unmapped. This will require changes in arch-specific code.

swapping mapping Attendez-vous à ce que la partie de la zone d'ombre évite de traiter les parties difficiles autour de vous. Autrement dit, l'espace vmalloc n'est pas couvert par la première page d'ombre. Cependant, il existe des cas où la cartographie ubn reste. Cela nécessitait une demande de changement dans la spécifion de l'arc.

This allows VMAP_STACK support on x86, and can simplify support of architectures that do not have a fixed module region.

La prise en charge de VMAP_STACK est autorisée sur x86. Il peut prendre en charge les architectures qui n'ont pas de région de module fixe.

Recommended Posts

Le désinfectant d'adresses du noyau (KASAN) (2/2)
Le désinfectant d'adresse de noyau (KASAN) (1/2)
Essayez le mécanisme de verrouillage du noyau Linux
Obtenir une adresse à partir d'un code postal