The Kernel Address Sanitizer (KASAN) (2/2)

もともと、Linux Kernelのソースコードの一部なので、GPLv2扱いになる（はずの認識）。

> 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.

高いレベルから、メモリエラー検知の我々のアプロ―とというのはkmemcheckと類似している。メモリそれぞれのbyteにアクセスが安全であるかどうかを記録するためのshadow memoryを用い、コンパイル時にそれぞれのメモリアクセスおいてshadow memoryのチェックを挿入する。

> 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.

Generic KASANでは、カーネルメモリの1/8をshadow memoryに割り当てます（例えば、x86_64であれば128TBをカバーするために16TB)。そして、scaleとoffsetによってメモリアドレスと関連するshadow addressにdirect mappingします。

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

ここで、shadow addressと関連付けられたaddressを翻訳する関数は…

```c

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.

コンパイル時のinstrumentationは、memory access checkを挿入するために用いられます。Compilerは、1,2,4,8 サイズのメモリアクセスが行われる前に、関数コール kasan_load*(addr), __asan_store*(addr)) を挿入します。これらの関数では、メモリアクセスが有効であるかどうかを関連付けられたshadow memoryを確認する事でチェックします。

> 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.

GCC 5.0では、inline instrumentationを実行することが可能です。関数コールを作る代わりに、GCCが直接shadow memoryのチェックするコードを挿入します。これは、カーネルをわずかに肥大化させますが、outline instrumented kernelに比べてx1.1-x2のパフォーマンス高速化をもたらします。

## 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).

Tag-based KASANでは、最新のarm64 CPUの特徴であるTop Byte Ignore(TBI) featuresを用いて、kernel pointerのtio byteにおけるpointer tagを記録します。generi KASANと同じように、shadow mamory は それぞれ16byte memory cellに関連付けられたmemory tagを記録するために用いられます（そのため、shadow memoryにはkernel memoryの1/16が占有されます）。

> 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.

それぞれのメモリ確保では、tag-based KASANではrandom tagを生成します。割り当てられたメモリはこのタグにタグ付けされ、返却されたポインタにはこのタグが埋め込まれます。Software tag-based KASANでは、コンパイル時instrumentationが用いられ、それぞれのメモリアクセスの前にチェックが挿入されます。このチェックでは、アクセスされているメモリのタグが、このメモリへのアクセスに利用されているポインタのタグと一致していることを検証します。tagが一致しないケースの場合、tag-based KASANはバグレポートを出力します。

> 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.

Software tag-based KASANではまた、２つのinstrumentation modesを有します。(outline, memory access をチェックするcallmbackを発する。そして、inlineではshadow memory checkをinlineで実行する）。outline instrumentation modeでは、アクセスチェックを実行した関数からバグレポートがシンプルに出力されます。inline instrumentationでは、brk instructionがcompilerによって発行され、brk handlerがバグレポートを出力するために占有的に用いられます。

> 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.

このモードの潜在的な拡張としては、compiler instrumentation や手動でのshadow memory manipulationの代わりに、hardwareによってmemory tagging がサポートされる、hardware tag-based modeがあります。

# 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.

カーネルでは、アドレク空間が異なる部分のいくつかのメモリをマップします。これは、KASANにおける問題を引き起足ます。すべてのアドレスは正常なshadow regionを持つinstrumented codeによってアクセスされることを要求しています。

> 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.

kernelの仮想アドレスの範囲は非常に広大です。実際のメモリは、kernelがアクセスするであろうすべてのアクセスされる実際のshadow regionをサポートできるほとありません。

## 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.

デフォルトでは、アーキテクチャは実際のmemoryをshadow regionに、線形マッピング（潜在的に小さいそのほかのエリア）によってだけマッピングします。他の全てのエリアについては、例えばvmallocやvmemmmap 空間では、単純なread only pageがshadow areaにマッピングされます。このread only shadow pageでは許可された、すべてのメモリアクセスが宣言されます。

> 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.

これはモジュールに対して問題を引き起こします。これらは、線形マッピングでは有効ではなく、専用のモジュール空間に存在します。moduke allocator内でフックすることで、KASANは一時的にreal shadow memoryとそれらをカバーする一時的なマッピングを実現します。これは、例えば、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.

これはまた、VMAP_STACKと非互換性も作成します。もし、stackがvmalloc空間内に存在するならば、それはread-only pageによって隠され、kernelは、shack 変数に対するshadow dataのセットアップにトライするときに、失敗するでしょう。

## 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.

CONFIG_KASAN_VMALLOCを設定すると、KASANはメモリ使用量のコストによって、vmallocスペースもカバーすることができます。現時点では、これはx86だけでサポートされています。

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

これは、vmallocとvmapをフックする事で動作します。そして、mappingを戻すために、real shadow memoryを動的に確保します。

> 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.

vmalloc空間では多くのmappinguは小さく、shadow spaceのfull pageよりも小さい要求をします。マッピングととのfull shadow pageを確保する事は、無駄になります。更に、異なるマッピングが異なるshadow pagesをマッピングする場合、マッピングはKASAN_SHADOW_SCALE_SIZE * PAGE_SIZEにalignされなければなりません。

> 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.

その代わりに、複数のmappingを横断したbacking spaceを保持します。backing pageは、vmalloc spaceがshadow regionの一部のページを用いた時に、確保されます。このページは、他のmallocマッピングが行われた後に共有されます。

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

未使用のshadow memory を遅延してクリアするために、vmap infrastructreをフックします。

> 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 aroud周辺の難しい部分を取り扱わないために、shadow regionの部分を予期します。それは、vmalloc spaceがearly shadow pageによってカバーされていない。しかし、ubnmapingが残っている場合もあります。これは、arch-specifionの中で変化を要求が必要となりました。

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

x86においてはVMAP_STACKのサポートが許容されています。これは、fixed module regionを持たないアーキテクチャをサポートできます。