1 of 100

Memory Tagging + Linux kernel =

or Mitigating Linux kernel memory corruptions with Arm Memory Tagging

Andrey Konovalov, xairy.io

Linux Security Summit

October 1st 2021

2 of 100

Bugs

  • Linux kernel has lots of bugs

3 of 100

4 of 100

5 of 100

Vulnerabilities

  • Some bugs are vulnerabilities

6 of 100

Bad Binder

  • Use-after-free in the Android Binder driver
  • LPE on Pixel and Samsung devices
  • Evidence of in-the-wild exploitation
  • Discovered by Project Zero in October 2019
  • (As it turned out) Reported by syzbot in November 2017

7 of 100

Android vulnerabilities by cause

Queue the Hardening Enhancements, Google Online Security Blog

OOB write

OOB read

Use-after-free

Integer overflow

Other

Incorrect crypto

Uninitialized memory

8 of 100

Android vulnerabilities by cause

Queue the Hardening Enhancements, Google Online Security Blog

OOB write

OOB read

Use-after-free

Integer overflow

Other

Incorrect crypto

Uninitialized memory

90%

Memory corruptions!

9 of 100

Mitigating memory corruptions

  • Fixing security bugs is infeasible, not enough resources

⇒ Invest into mitigations instead

  • Memory corruptions are the majority

⇒ Focus on them first

  • There are many memory corruption mitigations: PAN, PXN, CFI, ...
  • But they prevent exploitation techniques

  • Memory tagging aims to prevent memory corruptions

10 of 100

Who am I?

Andrey Konovalov

xairy.io

11 of 100

Agenda

  • Intro
  • Memory tagging as a concept
  • Arm Memory Tagging Extension
  • In-kernel MTE aka Hardware Tag-Based KASAN
  • Weaknesses of in-kernel MTE
  • Outro

12 of 100

Memory tagging

13 of 100

Memory tagging

  • A technique to detect (and prevent) memory corruptions

14 of 100

Concept

  • Memory is divided into granules of a fixed size

Granule #1

#2

...

#N

15 of 100

Concept

  • Memory is divided into granules of a fixed size
  • Each memory granule has a tag (aka color)

Granule #1

#2

...

#N

16 of 100

Concept

  • Memory is divided into granules of a fixed size
  • Each memory granule has a tag (aka color)
  • Every pointer has a tag

char *p1

char *p2

17 of 100

Concept

  • Memory is divided into granules of a fixed size
  • Each memory granule has a tag (aka color)
  • Every pointer has a tag
  • On allocation, both memory and pointer get a matching random tag

18 of 100

Concept

  • Memory is divided into granules of a fixed size
  • Each memory granule has a tag (aka color)
  • Every pointer has a tag
  • On allocation, both memory and pointer get a matching random tag

char *p1

char *p2

19 of 100

Concept

  • Memory is divided into granules of a fixed size
  • Each memory granule has a tag (aka color)
  • Every pointer has a tag
  • On allocation, both memory and pointer get the same random tag
  • On pointer dereference, pointer tag must match memory tag

==

*p1 = ...;

All is good,

proceed

20 of 100

Concept

  • Memory is divided into granules of a fixed size
  • Each memory granule has a tag (aka color)
  • Every pointer has a tag
  • On allocation, both memory and pointer get the same random tag
  • On pointer dereference, pointer tag must match memory tag

!=

*(p1 + N) = ...;

Raise an

exception!

21 of 100

From concept to implementation

  • This is a nice concept, but what about an implementation?
    • We need a mechanism for assigning and checking tags

  • Software implementations (based on compiler instrumentation) are slow

  • Hardware implementations require hardware support
    • The only one existed was SPARC ADI
    • But none in modern widely-used CPUs: x86, Arm
    • Up until...

22 of 100

Arm Memory Tagging Extension

23 of 100

Arm Memory Tagging Extension (MTE)

  • Arm released an architecture extension that adds memory tagging support

  • This is only a specification, not an actual implementation
    • Manufacturers of Arm-based CPUs can choose to include MTE

  • CPUs that implement MTE will have built-in support for memory tagging

24 of 100

25 of 100

Implementation details

  • How pointer tags are assigned and stored?
  • How memory tags are assigned and stored?
  • How big are memory granules?
  • How many different tags are there?
  • How and when tags are compared?
  • What happens on tag mismatch?

26 of 100

Arm Top Byte Ignore (TBI)

  • An option to ignore 8 most significant bits of virtual addresses on accesses
  • The top byte can be used to store pointer tags
  • 256 different tags if the whole byte is used

  • (Enabled by setting TBI0/TBI1 bits in TCR_EL1 register)

0x42ff801234567800

27 of 100

MTE pointer tags

  • MTE relies on TBI
  • MTE uses 4 bits from the top byte to store pointer tag
  • Therefore, MTE allows 16 different tags

  • (MTE pointer tags are also called logical tags)

0xf2ff801234567800

28 of 100

MTE memory tags

  • Each memory granule is 16 bytes; each memory tag is 4 bits
  • Memory tags are stored in a reserved part of RAM
  • 4-bits tag for each 16 bytes ⇒ memory tags take up 3% of RAM

[-16, 0)

[0, 16)

[16, 32)

[32, 48)

[48, 64)

[64, 80)

0xA

0x2

0x2

0x2

0xE

0xB

Memory tags

Memory granules

29 of 100

MTE memory tags

  • (MTE memory tags are also called allocation tags)

30 of 100

MTE instructions

Instruction

Action

STG [<Xn/SP>], #<simm>

Store Allocation (memory) Tag

LDG <Xt>, [<Xn/SP>]

Load Allocation (memory) Tag

IRG <Xd/SP>, <Xn/SP>

Insert Random [pointer] Tag

GMI <Xd>, <Xn/SP>, <Xm>

Tag Mask Insert

STZG [<Xn/SP>], #<simm>

Store Allocation Tag, Zeroing

ADDG ...

Add with Tag

And more...

31 of 100

MTE tag checking modes

  • On mismatch, sync: raise exception, async: set bit in TFSR_EL1
  • (Mode selected via TCF bits of SCTLR_EL1 register)
  • CPU checks tags when executing normal Load/Store instructions

Mode

Tag check runs

Speed

Detection

Sync

During instruction execution

Slower

Precise

Async

Asynchronously

Faster

Imprecise

Mixed

Sync for reads, async for writes

32 of 100

Summary

  • MTE is a hardware implementation of memory tagging for Arm CPUs

  • MTE provides:
    • A way to store pointer and memory tags
    • Instructions to manipulate memory tags
    • Built-in CPU checks to validate them

33 of 100

Detailed summary

  • Introduced in Armv8.5 Instruction Set Architecture; 64-bit only
  • No hardware yet, but there's QEMU (-machine virt,mte=on) and Clang/GCC support

  • Every aligned 16 bytes of memory have a 4-bit tag stored in a dedicated RAM region
  • Every pointer has a 4-bit tag stored in the top byte relying on TBI
  • New instructions to manipulate memory tags
  • Normal Load/Store instructions check tags and report exceptions on mismatch
  • Exceptions reported either synchronously or asynchronously

  • More details in the paper

34 of 100

Next step

  • Now we need to integrate MTE into the kernel

35 of 100

In-kernel MTE

or Hardware Tag-Based KASAN

36 of 100

Integration parts

  1. arm64 infrastructure
    • Properly set up system registers during boot
    • Provide routines for setting and getting memory tags
    • Allow receiving tag mismatches notifications (for both, sync and async)
    • Thanks to Vincenzo Frascino and Catalin Marinas for implementing this

  • Use part #1 to implement a memory-tagging–based mitigation in the kernel
    • Focus of this talk

37 of 100

Implementing part #2

  • We need to assign memory and pointer tags in the allocator
  • Can call MTE routines directly
  • But there's a tool that does almost this — KASAN

38 of 100

KASAN Overview

  • KASAN (KernelAddressSANitizer) — dynamic bug detector for the Linux kernel

  • Finds use-after-frees and out-of-bounds in heap, stack, and globals
  • Easy to use: build with CONFIG_KASAN=y and run the kernel
  • No false positives (except for occasional bugs in KASAN)

  • ~2x slowdown, ~2x memory overhead

39 of 100

KASAN vs MTE implementation

  • Performs checks before every memory access
    • Exactly like MTE
  • Compiler instrumentation for insert those checks
    • With MTE, CPU does checks internally
  • Shadow memory for storing memory metadata
    • With MTE, tags are stored in a reserved RAM region
  • Allocator annotations
    • This part we can adapt and reuse

40 of 100

Software Tag-Based KASAN

  • The way KASAN works is very similar to MTE
  • KASAN even has a software memory tagging mode
  • (This mode was implemented knowing that MTE is coming)

41 of 100

Hardware Tag-Based KASAN

  • Hardware Tag-Based KASAN
    • "Tag-Based": based on memory tagging concept
    • "Hardware": uses hardware memory tagging — ARM MTE (and TBI)
    • I also refer to this mode as MTE-based KASAN or in-kernel MTE

  • Intended to be used in production as a mitigation

  • Builds on top of MTE routines provided by arm
  • Reuses KASAN annotations and adapts their implementation
  • Prints bug reports on MTE exceptions

42 of 100

Allocator annotations

void *kmalloc(size) {

void *ptr = ...;

return ptr;

}

void *kmalloc(size) {

size = round_up(size, 16);

void *ptr = ...;

return kasan_kmalloc(ptr);

}

  • With in-kernel MTE, kmalloc():
    • Rounds up object size to granule size
    • Calls kasan_kmalloc(), which:
      • Generates a random tag
      • Tags allocated memory and the returned pointer

43 of 100

Preventing memory corruptions

with Hardware Tag-Based KASAN

44 of 100

Allocating memory

char *p = kmalloc(35);

45 of 100

Allocating memory

char *p = kmalloc(35); // ends up in kmalloc-64 cache

  • Align object size (35) up to granule size (16)�and choose a suitable location for the object

[-16, 0)

[0, 16)

[16, 32)

[32, 48)

[48, 64)

[64, 80)

46 of 100

Allocating memory

char *p = kmalloc(35);

[-16, 0)

[0, 16)

[16, 32)

[32, 48)

[48, 64)

[64, 80)

?

?

?

?

?

?

Memory tags

47 of 100

Allocating memory

char *p = kmalloc(35);

  • Align object size (35) up to granule size (16)
  • Choose a random tag (say, 0x2)

[-16, 0)

[0, 16)

[16, 32)

[32, 48)

[48, 64)

[64, 80)

48 of 100

Allocating memory

char *p = kmalloc(35); // 0xf2ff801234567800

  • Align object size (35) up to granule size (16)
  • Choose a random tag (say, 0x2)
  • Mark pointer and memory with the chosen tag

[-16, 0)

[0, 16)

[16, 32)

[32, 48)

[48, 64)

[64, 80)

49 of 100

Allocating memory

char *p = kmalloc(35); // 0xf2ff801234567800

  • Align object size (35) up to granule size (16)
  • Choose a random tag (say, 0x2)
  • Mark pointer and memory with the chosen tag
  • Mark leftover memory with a reserved tag (0xE == KASAN_TAG_INVALID)

[-16, 0)

[0, 16)

[16, 32)

[32, 48)

[48, 64)

[64, 80)

50 of 100

Allocating memory

char *p = kmalloc(35); // 0xf2ff801234567800

  • Align object size (35) up to granule size (16)
  • Choose a random tag (say, 0x2)
  • Mark pointer and memory with the chosen tag
  • Mark leftover memory with a reserved tag (0xE == KASAN_TAG_INVALID)
  • Return tagged pointer

[-16, 0)

[0, 16)

[16, 32)

[32, 48)

[48, 64)

[64, 80)

51 of 100

Allocating memory

char *p = kmalloc(35); // 0xf2ff801234567800

[-16, 0)

[0, 16)

[16, 32)

[32, 48)

[48, 64)

[64, 80)

?

0x2

0x2

0x2

0xE

?

Memory tags

52 of 100

In-bounds

char *p = kmalloc(35);

p[20] = ...;

==

[-16, 0)

[0, 16)

[16, 32)

[32, 48)

[48, 64)

[64, 80)

53 of 100

Preventing out-of-bounds

char *p = kmalloc(35);

p[..] = ...;

[-16, 0)

[0, 16)

[16, 32)

[32, 48)

[48, 64)

[64, 80)

54 of 100

Preventing out-of-bounds

char *p = kmalloc(35);

p[50] = ...;

[-16, 0)

[0, 16)

[16, 32)

[32, 48)

[48, 64)

[64, 80)

55 of 100

Preventing out-of-bounds

char *p = kmalloc(35);

p[50] = ...; // out-of-bounds:

!=

Raise an

exception!

[-16, 0)

[0, 16)

[16, 32)

[32, 48)

[48, 64)

[64, 80)

56 of 100

Preventing out-of-bounds

char *p = kmalloc(35);

p[70] = ...;

[-16, 0)

[0, 16)

[16, 32)

[32, 48)

[48, 64)

[64, 80)

57 of 100

Preventing out-of-bounds

char *p = kmalloc(35);

p[70] = ...; // out-of-bounds:

!=

Raise an

exception!

[-16, 0)

[0, 16)

[16, 32)

[32, 48)

[48, 64)

[64, 80)

58 of 100

(Not) preventing out-of-bounds

char *p = kmalloc(35);

p[70] = ...;

[-16, 0)

[0, 16)

[16, 32)

[32, 48)

[48, 64)

[64, 80)

Could be the same,

if tags are random

59 of 100

(Not) preventing out-of-bounds

char *p = kmalloc(35);

p[70] = ...; // out-of-bounds missed:

==

  • Memory tagging limitation: misses bugs if tags happen to be the same
  • The chance is about 1/16 ≅ 6%

[-16, 0)

[0, 16)

[16, 32)

[32, 48)

[48, 64)

[64, 80)

Could be the same,

if tags are random

60 of 100

(Not) preventing out-of-bounds

char *p = kmalloc(35);

p[40] = ...;

[-16, 0)

[0, 16)

[16, 32)

[32, 48)

[48, 64)

[64, 80)

61 of 100

(Not) preventing out-of-bounds

char *p = kmalloc(35);

  • Even though offset 40 is out-of-bounds of requested 35-byte region
  • Memory tagging limitation: can't detect small out-of-bounds in the last granule

p[40] = ...; // out-of-bounds missed:

==

[-16, 0)

[0, 16)

[16, 32)

[32, 48)

[48, 64)

[64, 80)

62 of 100

Preventing use-after-free

char *p = kmalloc(35);

kfree(p);

p[8] = ...;

[-16, 0)

[0, 16)

[16, 32)

[32, 48)

[48, 64)

[64, 80)

63 of 100

Preventing use-after-free

char *p = kmalloc(35);

kfree(p); // retag memory:

[-16, 0)

[0, 16)

[16, 32)

[32, 48)

[48, 64)

[64, 80)

64 of 100

Preventing use-after-free

char *p = kmalloc(35); // 0xf2ff801234567800

kfree(p); // retag memory:

[-16, 0)

[0, 16)

[16, 32)

[32, 48)

[48, 64)

[64, 80)

0x2

0xE

[-16, 0)

[0, 16)

[16, 32)

[32, 48)

[48, 64)

[64, 80)

?

0xE

0xE

0xE

0xE

?

Memory tags

65 of 100

Preventing use-after-free

char *p = kmalloc(35);

kfree(p); // retag memory:

p[8] = ...;

[-16, 0)

[0, 16)

[16, 32)

[32, 48)

[48, 64)

[64, 80)

[-16, 0)

[0, 16)

[16, 32)

[32, 48)

[48, 64)

[64, 80)

66 of 100

Preventing use-after-free

char *p = kmalloc(35);

kfree(p); // retag memory:

p[8] = ...; // use-after-free:

!=

[-16, 0)

[0, 16)

[16, 32)

[32, 48)

[48, 64)

[64, 80)

[-16, 0)

[0, 16)

[16, 32)

[32, 48)

[48, 64)

[64, 80)

Raise an

exception!

67 of 100

Preventing use-after-realloc

char *p = kmalloc(35);

kfree(p); q = kmalloc(60);

[-16, 0)

[0, 16)

[16, 32)

[32, 48)

[48, 64)

[64, 80)

68 of 100

Preventing use-after-realloc

char *p = kmalloc(35);

kfree(p); q = kmalloc(60); // if lands on p:

p[8] = ...;

[-16, 0)

[0, 16)

[16, 32)

[32, 48)

[48, 64)

[64, 80)

[-16, 0)

[0, 16)

[16, 32)

[32, 48)

[48, 64)

[64, 80)

69 of 100

Preventing use-after-realloc

char *p = kmalloc(35);

kfree(p); q = kmalloc(60); // if lands on p:

p[8] = ...; // use-after-free:

!=

[-16, 0)

[0, 16)

[16, 32)

[32, 48)

[48, 64)

[64, 80)

[-16, 0)

[0, 16)

[16, 32)

[32, 48)

[48, 64)

[64, 80)

Raise an

exception!

70 of 100

(Not) preventing use-after-realloc

char *p = kmalloc(35);

kfree(p); q = kmalloc(60); // if lands on p:

p[8] = ...;

[-16, 0)

[0, 16)

[16, 32)

[32, 48)

[48, 64)

[64, 80)

[-16, 0)

[0, 16)

[16, 32)

[32, 48)

[48, 64)

[64, 80)

71 of 100

(Not) preventing use-after-realloc

char *p = kmalloc(35);

kfree(p); q = kmalloc(60); // if lands on p:

p[8] = ...; // use-after-free missed:

==

[-16, 0)

[0, 16)

[16, 32)

[32, 48)

[48, 64)

[64, 80)

[-16, 0)

[0, 16)

[16, 32)

[32, 48)

[48, 64)

[64, 80)

72 of 100

Implementation details

of Hardware Tag-Based KASAN

73 of 100

Reserved tags

  • "Invalid" memory tag — 0xE
    • Used to tag freed memory and leftover granules in slab objects
    • This is a memory tag, no pointers with the "invalid" tag are generated

  • Match-all pointer tag — 0xF
    • Accesses through pointers with this tag are not checked
    • This a pointer tag, there are no match-all memory tags
    • Simplifies object handling in allocator (also see this)
    • 0xF chosen to match top byte of native kernel pointers 0xFF

74 of 100

Tagged memory

  • Currently: slab and page_alloc
  • Future: vmalloc, stack and globals

75 of 100

More details

  • Command-line parameters to disable KASAN, choose MTE mode, disable stack trace collection, enable panic on tag-mismatch
  • No redzones when stack collection is disabled. Otherwise, stack traces stored in redzones
  • Integration with memory init: set tags and initialize memory at the same time
  • Don't disable cache merging without stack trace collection, unlike other modes
  • Checks for invalid/double-free, invalid-krealloc, invalid-ksize
  • Preassigned tags for caches with constructors and SLAB_TYPESAFE_BY_RCU caches
  • page_alloc tags stored in page flags
  • Tests to check that MTE-based KASAN detects memory corruptions
  • Relevant source code files: ls mm/kasan/*; find arch/arm64 -name *mte*
  • Open KASAN bugs

76 of 100

RAM impact

From what

How much

Memory tags

~3% (4 bits for each 16 bytes)

Aligning memory objects

Negligible

Stack traces and redzones

0 (no stack traces in prod mode, no redzones)

77 of 100

Performance impact

  • No CPUs released, so no one knows. Expected:

Mode

How much

Sync

< 10% (Faster if combined with memory init)

Async

Faster than sync

Disabled via command line

0

78 of 100

Summary

  • New KASAN mode called Hardware Tag-Based KASAN based on MTE
  • Detects out-of-bounds and use-after-frees, sometimes probabilistically
  • Can be used as either a production mitigation or a fast memory bug detector

  • Merged into mainline in 5.11
  • Testing requires fresh QEMU and Clang/GCC with MTE support
  • Enabled with CONFIG_KASAN_HW_TAGS
    • Command line arguments for prod mode:�stack_depot_disable=on kasan.stacktrace=off

79 of 100

Weaknesses

of Hardware Tag-Based KASAN

80 of 100

Non-tagged memory

  • vmalloc, stack and globals are not tagged

⇒ Can be targeted by an exploit

  • However, these will be covered by MTE in the future

81 of 100

Probabilistic detection

  • Probability of MTE missing a bug is ~7%

  • We could detect linear-buffer-overflows with a 100% guarantee
    • Give different (but still random) tags to neighbouring memory blocks
    • Also use-after-realloc with a similar approach

  • If attacker can retry the exploit ⇒ will succeed sooner or later

⇒ Need to panic on mismatches

⇒ Single attempt to run the exploit

82 of 100

Async window

  • Async mode is expected to be faster than sync
  • But with async, there’s a window between a tag mismatch and its detection
  • Might be possible to execute payload before the bug is detected

83 of 100

Match-all tag

  • If attacker can craft arbitrary pointers with match-all tag

⇒ Can access any memory

  • But if crafting pointers requires corrupting memory

⇒ MTE will detect this

  • Might be possible to get rid of the match-all tag
    • Need to carefully annotate allocator
    • (And also deal with this)

84 of 100

Intra-object-overflows

  • MTE can’t detect intra-object-overflows
    • E.g. buffer-overflows within a struct
    • The whole object is marked with the same tag

  • MTE can detect certain intra-object-overflows
    • E.g. overflows between blocks in custom allocators
    • Via additional annotations:�assigning different tags to blocks or adding redzones

85 of 100

More

  • MTE can’t detect type-confusions
    • E.g. casting a pointer to incorrect struct and accessing fields
    • (Unless the access is out-of-bounds)

  • MTE can’t detect logical bugs
    • (Unless there's a memory corruption)

86 of 100

Summary

  • MTE has weaknesses, but detects the main types of memory corruptions
  • A long road of bypasses and fixes awaits

87 of 100

Outro

88 of 100

Summary

  • MTE is supported in the kernel via Hardware Tag-Based KASAN
  • Detects many memory corruptions with a ~93% probability
  • Can be used as a mitigation in production or a fast memory bug detector

89 of 100

Promising future

  • MTE-enabled Armv9 CPU microarchitectures announced
    • Cortex-X2, Cortex-A710, and Cortex-A510

  • In-kernel MTE enabled in the Android 12 Generic Kernel Image
    • Might still be disabled via command line on actual devices
    • In the worst case, we will have a fast KASAN :)

90 of 100

Call to action

(For device manufacturers, distro vendors, and kernel developers)

  1. Run tests with KASAN
    • At least make sure the kernel boots without reports
  2. Use Software Tag-Based KASAN on testing devices
    • To prepare for MTE and find potential incompatibilities
  3. Enable Hardware Tag-Based KASAN when CPUs are released
    • To mitigate memory corruptions

91 of 100

Thanks!

Andrey Konovalov, xairy.io

92 of 100

Extra

93 of 100

Report: mode=sync, stacktrace=on [1/4]

==================================================================

BUG: KASAN: invalid-access in kmalloc_oob_right+0x1ac/0x23c lib/test_kasan.c:144

Read at addr f2ff0000039ca880 by task kunit_try_catch/102

Pointer tag: [f2], memory tag: [fe]

CPU: 0 PID: 102 Comm: kunit_try_catch Tainted: G B 5.14.0-rc5 #389

Hardware name: linux,dummy-virt (DT)

Call trace:

...

el1h_64_sync_handler+0x50/0x80 arch/arm64/kernel/entry-common.c:318

el1h_64_sync+0x78/0x7c arch/arm64/kernel/entry.S:569

kmalloc_oob_right+0x1ac/0x23c lib/test_kasan.c:144

...

94 of 100

Report: mode=sync, stacktrace=on [2/4]

Allocated by task 102:

...

kasan_kmalloc include/linux/kasan.h:264

kmem_cache_alloc_trace include/linux/slab.h:489

kmalloc include/linux/slab.h:591

kmalloc_oob_right+0x60/0x23c lib/test_kasan.c:127

...

Freed by task 0:

(stack is not available)

95 of 100

Report: mode=sync, stacktrace=on [3/4]

The buggy address belongs to the object at ffff0000039ca800

which belongs to the cache kmalloc-128 of size 128

The buggy address is located 0 bytes to the right of

128-byte region [ffff0000039ca800, ffff0000039ca880)

The buggy address belongs to the page:

page:(____ptrval____) refcount:1 mapcount:0

mapping:0000000000000000 index:0xf6ff0000039ca600 pfn:0x439ca

flags: 0xffff00000000200(slab|node=0|zone=0|lastcpupid=0xffff|kasantag=0x0)

raw: 0ffff00000000200 0000000000000000 dead000000000122 f5ff000002401200

raw: f6ff0000039ca600 000000008010000f 00000001ffffffff 0000000000000000

page dumped because: kasan: bad access detected

96 of 100

Report: mode=sync, stacktrace=on [4/4]

Memory state around the buggy address:

ffff0000039ca600: fe fe fe fe fe fe fe fe fe fe fe fe fe fe fe fe

ffff0000039ca700: f6 f6 f6 f6 f6 f6 f6 fe fe fe fe fe fe fe fe fe

>ffff0000039ca800: f2 f2 f2 f2 f2 f2 f2 fe fe fe fe fe fe fe fe fe

^

ffff0000039ca900: fe fe fe fe fe fe fe fe fe fe fe fe fe fe fe fe

ffff0000039caa00: fe fe fe fe fe fe fe fe fe fe fe fe fe fe fe fe

==================================================================

97 of 100

Report: mode=async

==================================================================

BUG: KASAN: invalid-access

Asynchronous mode enabled: no access details available

CPU: 1 PID: 102 Comm: kunit_try_catch Not tainted 5.14.0-rc5 #389

Hardware name: linux,dummy-virt (DT)

98 of 100

Report: mode=async

Call trace:

...

kasan_report_async+0xf0/0x170 mm/kasan/report.c:378

mte_check_tfsr_el1+0x40/0x44 arch/arm64/kernel/mte.c:191

mte_check_tfsr_entry arch/arm64/include/asm/mte.h:108

enter_from_kernel_mode+0x24/0x48 arch/arm64/kernel/entry-common.c:49

enter_el1_irq_or_nmi+0x10/0x1c arch/arm64/kernel/entry-common.c:113

el1_interrupt+0x28/0xa0 arch/arm64/kernel/entry-common.c:350

el1h_64_irq_handler+0x18/0x24 arch/arm64/kernel/entry-common.c:367

el1h_64_irq+0x78/0x7c arch/arm64/kernel/entry.S:570

kmalloc_type include/linux/slab.h:348

...

==================================================================

99 of 100

Links

100 of 100

Thanks