当前位置:   article > 正文

linux kernel 内存踩踏之KASAN_HW_TAGS(MTE)(三)

linux kernel 内存踩踏之KASAN_HW_TAGS(MTE)(三)

一、背景

linux kernel 内存踩踏之KASAN(一)_kasan版本跟hasan版本区别-CSDN博客

linux kernel 内存踩踏之KASAN_SW_TAGS(二)-CSDN博客

最后来介绍一下KASAN_HW_TAGS,ARM64上就是MTE,这个特性在ARMv8.5支持,实际目前市面支持MTE的芯片都是ARMv9了; 由于这个特性依赖硬件支持,本文利用qemu 学习这个feature。

二、KASAN_HW_TAGS (MTE)使能相关配置

内核相关配置

  1. CONFIG_HAVE_ARCH_KASAN=y
  2. CONFIG_HAVE_ARCH_KASAN_SW_TAGS=y
  3. CONFIG_HAVE_ARCH_KASAN_HW_TAGS=y
  4. CONFIG_HAVE_ARCH_KASAN_VMALLOC=y
  5. CONFIG_CC_HAS_KASAN_GENERIC=y
  6. CONFIG_CC_HAS_KASAN_SW_TAGS=y
  7. CONFIG_KASAN=y
  8. # CONFIG_KASAN_GENERIC is not set
  9. # CONFIG_KASAN_SW_TAGS is not set
  10. CONFIG_KASAN_HW_TAGS=y //mte相关
  11. CONFIG_KASAN_VMALLOC=y

MTE 相关feature 是否打开

  1. 502 # ARMv8.5 architectural features
  2. 503 #
  3. 504 CONFIG_AS_HAS_ARMV8_5=y
  4. ......
  5. 508 CONFIG_ARM64_AS_HAS_MTE=y
  6. 509 CONFIG_ARM64_MTE=y

确认MTE是否正常打开

geek@geek-virtual-machine:~/workspace/linux/qemu$ ./linux_boot.sh

qemu-system-aarch64: MTE requested, but not supported by the guest CPU

调试时遇到,MTE未打开的情况,可以打断点在 kasan_init_hw_tags

  1. void __init kasan_init_hw_tags(void)
  2. {
  3. /* If hardware doesn't support MTE, don't initialize KASAN. */
  4. if (!system_supports_mte())
  5. return;
  6. ......
  7. /* KASAN is now initialized, enable it. */
  8. static_branch_enable(&kasan_flag_enabled);
  9. pr_info("KernelAddressSanitizer initialized (hw-tags, mode=%s, vmalloc=%s, stacktrace=%s)\n",
  10. kasan_mode_info(),
  11. kasan_vmalloc_enabled() ? "on" : "off",
  12. kasan_stack_collection_enabled() ? "on" : "off");
  13. }

上面的异常最终确认是之前所使用的CPU类型不支持,修改的qemu启动脚本如下:

主要是machine增加mte=on字段,CPU选择支持mte的架构,如:cortex-a710

  1. qemu-system-aarch64 \
  2. -machine virt,gic-version=3,mte=on \
  3. -nographic \
  4. -m size=2048M \
  5. -cpu cortex-a710 \
  6. -smp 8 \
  7. -kernel Image \
  8. -drive format=raw,file=rootfs.img \
  9. -append "root=/dev/vda rw nokaslr kasan=on kasan.mode=sync kasan.stacktrace=on kasan.fault=report " \
  10. -s

成功打开时,内核kmsg会打印:

kasan: KernelAddressSanitizer initialized (hw-tags, mode=sync, vmalloc=on, stacktrace=on)

三、KASAN_HW_TAGS(MTE)基本原理

MTE的lock和key模型

MTE中key存放在指针高byte中,lock则是对内存的标记,只有key和lock匹配时,才能正常访问和操作内存。

MTE新增的指令

InstructionName
ADDGAdd with Tag
CMPPCompare with Tag
GMITag Mask Insert
IRGInsert Random Tag
LDGLoad Allocation Tag
LDGVLoad Tag Vector
ST2GStore Allocaton Tags to two granules
STGStore Allocation Tag
STGPStore Allocation Tag and Pair
STGVStore Tag Vector
STZ2GStore Allocation Tags to two granules Zeroing
STZGStore Allocation Tag, Zeroing
SUBGSubtract with Tag
SUBPSubtract Pointer
SUBPSSubtract Pointer, setting Flags
...

基本上MTE的使用分为三步:

1、memtag create(lock)

2、address tag(指针key)

MTE 需要结合ARM64的TBI(Top Byte Ignore)特性,在指针最高byte存储tag信息,这个实现和前面介绍的KASAN_SW_TAGS类似,不过MTE只需要4bit就够了。

3、tag check

四、Linux中KASAN_HW_TAGS(MTE)关键实现

4.1 先看一个例子日志

还是使用之前的测试程序 linux kernel 内存踩踏之KASAN(一)_kasan版本跟hasan版本区别-CSDN博客

  1. /test # echo 0 > /dev/kasan_test
  2. [ 156.628134] kmalloc_oob_right f9ff0000038b5000
  3. [ 156.629125] ==================================================================
  4. [ 156.633409] BUG: KASAN: invalid-access in kmalloc_oob_right.constprop.0+0x48/0x64 [kasan_driver]
  5. [ 156.634892] Write at addr f9ff0000038b5081 by task sh/179
  6. [ 156.635552] Pointer tag: [f9], memory tag: [fe]
  7. [ 156.635990]
  8. [ 156.636490] CPU: 4 PID: 179 Comm: sh Tainted: G N 6.6.1-gf1e080ccc5c5-dirty #19
  9. [ 156.637310] Hardware name: linux,dummy-virt (DT)
  10. [ 156.637771] Call trace:
  11. [ 156.638111] dump_backtrace+0x90/0xe8
  12. [ 156.638721] show_stack+0x18/0x24
  13. [ 156.639046] dump_stack_lvl+0x48/0x60
  14. [ 156.639391] print_report+0x100/0x600
  15. [ 156.639703] kasan_report+0x84/0xac
  16. [ 156.640034] __do_kernel_fault+0xa4/0x194
  17. [ 156.640376] do_tag_check_fault+0x78/0x8c
  18. [ 156.640724] do_mem_abort+0x44/0x94
  19. [ 156.641052] el1_abort+0x40/0x60
  20. [ 156.641367] el1h_64_sync_handler+0xa4/0xe4
  21. [ 156.641719] el1h_64_sync+0x64/0x68
  22. [ 156.642042] kmalloc_oob_right.constprop.0+0x48/0x64 [kasan_driver]
  23. [ 156.642511] kasan_test_case+0x38/0xb0 [kasan_driver]
  24. [ 156.642921] kasan_testcase_write+0x7c/0xf4 [kasan_driver]
  25. [ 156.643350] vfs_write+0xc8/0x300
  26. [ 156.643666] ksys_write+0x74/0x10c
  27. [ 156.643986] __arm64_sys_write+0x1c/0x28
  28. [ 156.644336] invoke_syscall+0x48/0x110
  29. [ 156.644681] el0_svc_common.constprop.0+0x40/0xe0
  30. [ 156.645082] do_el0_svc+0x1c/0x28
  31. [ 156.645415] el0_svc+0x40/0x114
  32. [ 156.645728] el0t_64_sync_handler+0x120/0x12c
  33. [ 156.646092] el0t_64_sync+0x19c/0x1a0
  34. [ 156.646528]
  35. [ 156.646749] The buggy address belongs to the object at ffff0000038b5080
  36. [ 156.646749] which belongs to the cache kmalloc-128 of size 128
  37. [ 156.647547] The buggy address is located 1 bytes inside of
  38. [ 156.647547] 128-byte region [ffff0000038b5080, ffff0000038b5100)
  39. [ 156.648270]
  40. [ 156.648533] The buggy address belongs to the physical page:
  41. [ 156.649067] page:00000000ffd93f36 refcount:1 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x438b5
  42. [ 156.650024] flags: 0x3fffc0000000800(slab|node=0|zone=0|lastcpupid=0xffff|kasantag=0x0)
  43. [ 156.651089] page_type: 0xffffffff()
  44. [ 156.651723] raw: 03fffc0000000800 f6ff000002c02600 dead000000000122 0000000000000000
  45. [ 156.652262] raw: 0000000000000000 0000000080200020 00000001ffffffff 0000000000000000
  46. [ 156.652786] page dumped because: kasan: bad access detected
  47. [ 156.653183]
  48. [ 156.653375] Memory state around the buggy address:
  49. [ 156.653836] ffff0000038b4e00: f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7
  50. [ 156.654346] ffff0000038b4f00: f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7
  51. [ 156.654857] >ffff0000038b5000: f9 f9 f9 f9 f9 f9 f9 f9 fe fe fe fe fe fe fe fe
  52. [ 156.655342] ^
  53. [ 156.655870] ffff0000038b5100: fe fe fe fe fe fe fe fe fe fe fe fe fe fe fe fe
  54. [ 156.656351] ffff0000038b5200: fe fe fe fe fe fe fe fe fe fe fe fe fe fe fe fe
  55. [ 156.656842] ==================================================================
  56. [ 156.657836] Disabling lock debugging due to kernel taint
  57. [ 156.659261] kasan_test_case type 0

上面的例子触发越界访问, key 是f9, 访问到越界内存,而越界内存的 memory tag(lock)是fe, 所以触发异常。

4.2 关键代码分析:

测试代码中函数kmalloc_oob_right分析,转化成汇编之后可以看到基于MTE的实现方法在触发越界时不需要像之前kasan/sw_tag kasan那样有读取tag对比的代码了,MTE中这些都是硬件实现的

  1. (gdb) disassemble
  2. Dump of assembler code for function kmalloc_oob_right:
  3. 0xffff80007a8801b0 <+0>: paciasp
  4. => 0xffff80007a8801b4 <+4>: adrp x0, 0xffff800081a2d000 <cpucap_ptrs+272>
  5. 0xffff80007a8801b8 <+8>: stp x29, x30, [sp, #-32]!
  6. 0xffff80007a8801bc <+12>: mov x2, #0x80 // #128
  7. 0xffff80007a8801c0 <+16>: mov w1, #0xcc0 // #3264
  8. 0xffff80007a8801c4 <+20>: mov x29, sp
  9. 0xffff80007a8801c8 <+24>: ldr x0, [x0, #1752]
  10. 0xffff80007a8801cc <+28>: str x19, [sp, #16]
  11. 0xffff80007a8801d0 <+32>: bl 0xffff80008022e498 <kmalloc_trace>
  12. 0xffff80007a8801d4 <+36>: mov x19, x0
  13. 0xffff80007a8801d8 <+40>: adrp x1, 0xffff80007a884000
  14. 0xffff80007a8801dc <+44>: add x1, x1, #0x110
  15. 0xffff80007a8801e0 <+48>: mov x2, x0
  16. 0xffff80007a8801e4 <+52>: add x1, x1, #0x30
  17. 0xffff80007a8801e8 <+56>: adrp x0, 0xffff80007a884000
  18. 0xffff80007a8801ec <+60>: add x0, x0, #0x50
  19. 0xffff80007a8801f0 <+64>: bl 0xffff8000800f45a0 <_printk>
  20. 0xffff80007a8801f4 <+68>: mov w1, #0x79 // #121
  21. 0xffff80007a8801f8 <+72>: strb w1, [x19, #129] //触发越界写入
  22. 0xffff80007a8801fc <+76>: mov x0, x19
  23. 0xffff80007a880200 <+80>: bl 0xffff80008022f5d0 <kfree>
  24. 0xffff80007a880204 <+84>: ldr x19, [sp, #16]
  25. 0xffff80007a880208 <+88>: ldp x29, x30, [sp], #32
  26. 0xffff80007a88020c <+92>: autiasp
  27. 0xffff80007a880210 <+96>: ret

设置memtag, 还是用kmalloc为例:

  1. kmalloc
  2. -->kmalloc_trace
  3. -->__kmem_cache_alloc_node
  4. -->slab_alloc_node
  5. -->slab_post_alloc_hook
  6. -->kasan_slab_alloc
  7. void * __must_check __kasan_slab_alloc(struct kmem_cache *cache,
  8. void *object, gfp_t flags, bool init)
  9. {
  10. ....
  11. /*
  12. * Generate and assign random tag for tag-based modes.
  13. * Tag is ignored in set_tag() for the generic mode.
  14. */
  15. tag = assign_tag(cache, object, false); // 1、随机数分配tag
  16. tagged_object = set_tag(object, tag); // 2、设置tag 到指针
  17. /*
  18. * Unpoison the whole object.
  19. * For kmalloc() allocations, kasan_kmalloc() will do precise poisoning.
  20. */
  21. kasan_unpoison(tagged_object, cache->object_size, init);
  22. 3、设置memtag
  23. /* Save alloc info (if possible) for non-kmalloc() allocations. */
  24. if (kasan_stack_collection_enabled() && !is_kmalloc_cache(cache))
  25. kasan_save_alloc_info(cache, tagged_object, flags);
  26. return tagged_object;
  27. }
  28. #if defined(CONFIG_KASAN_SW_TAGS) || defined(CONFIG_KASAN_HW_TAGS)
  29. #define __tag_shifted(tag) ((u64)(tag) << 56)
  30. #define __tag_reset(addr) __untagged_addr(addr)
  31. #define __tag_get(addr) (__u8)((u64)(addr) >> 56)
  32. 1、分配tag
  33. static inline u8 assign_tag(struct kmem_cache *cache,
  34. const void *object, bool init)
  35. {
  36. if (IS_ENABLED(CONFIG_KASAN_GENERIC))
  37. return 0xff;
  38. /*
  39. * If the cache neither has a constructor nor has SLAB_TYPESAFE_BY_RCU
  40. * set, assign a tag when the object is being allocated (init == false).
  41. */https://www.kernel.org/doc/html/v5.15/arm64/memory-tagging-extension.html
  42. if (!cache->ctor && !(cache->flags & SLAB_TYPESAFE_BY_RCU))
  43. return init ? KASAN_TAG_KERNEL : kasan_random_tag();
  44. /* For caches that either have a constructor or SLAB_TYPESAFE_BY_RCU: */
  45. #ifdef CONFIG_SLAB
  46. /* For SLAB assign tags based on the object index in the freelist. */
  47. return (u8)obj_to_index(cache, virt_to_slab(object), (void *)object);
  48. #else
  49. /*
  50. * For SLUB assign a random tag during slab creation, otherwise reuse
  51. * the already assigned tag.
  52. */
  53. return init ? kasan_random_tag() : get_tag(object);
  54. #endif
  55. }
  56. static inline u8 kasan_random_tag(void) { return hw_get_random_tag(); }
  57. #ifdef CONFIG_KASAN_HW_TAGS
  58. ...
  59. #define hw_get_random_tag() arch_get_random_tag()
  60. #define hw_get_mem_tag(addr) arch_get_mem_tag(addr)
  61. #define hw_set_mem_tag_range(addr, size, tag, init) \
  62. arch_set_mem_tag_range((addr), (size), (tag), (init))
  63. #ifdef CONFIG_KASAN_HW_TAGS
  64. ...
  65. #define arch_get_random_tag() mte_get_random_tag()
  66. #define arch_get_mem_tag(addr) mte_get_mem_tag(addr)
  67. #define arch_set_mem_tag_range(addr, size, tag, init) \
  68. mte_set_mem_tag_range((addr), (size), (tag), (init))
  69. #endif /* CONFIG_KASAN_HW_TAGS */
  70. /* Generate a random tag. */
  71. static inline u8 mte_get_random_tag(void)
  72. {
  73. void *addr;
  74. asm(__MTE_PREAMBLE "irg %0, %0"
  75. : "=r" (addr));
  76. return mte_get_ptr_tag(addr);
  77. }
  78. 设置memtag
  79. static inline void kasan_poison(const void *addr, size_t size, u8 value, bool init)
  80. {
  81. addr = kasan_reset_tag(addr);
  82. /* Skip KFENCE memory if called explicitly outside of sl*b. */
  83. if (is_kfence_address(addr))
  84. return;
  85. if (WARN_ON((unsigned long)addr & KASAN_GRANULE_MASK))
  86. return;
  87. if (WARN_ON(size & KASAN_GRANULE_MASK))
  88. return;
  89. hw_set_mem_tag_range((void *)addr, size, value, init);
  90. }
  91. 对比之前的定义:
  92. #define hw_set_mem_tag_range(addr, size, tag, init) \
  93. arch_set_mem_tag_range((addr), (size), (tag), (init))
  94. #define arch_set_mem_tag_range(addr, size, tag, init) \
  95. mte_set_mem_tag_range((addr), (size), (tag), (init))
  96. static inline void mte_set_mem_tag_range(void *addr, size_t size, u8 tag,
  97. bool init)
  98. {
  99. u64 curr, mask, dczid, dczid_bs, dczid_dzp, end1, end2, end3;
  100. /* Read DC G(Z)VA block size from the system register. */
  101. dczid = read_cpuid(DCZID_EL0);
  102. dczid_bs = 4ul << (dczid & 0xf);
  103. dczid_dzp = (dczid >> 4) & 1;
  104. curr = (u64)__tag_set(addr, tag);
  105. mask = dczid_bs - 1;
  106. /* STG/STZG up to the end of the first block. */
  107. end1 = curr | mask;
  108. end3 = curr + size;
  109. /* DC GVA / GZVA in [end1, end2) */
  110. end2 = end3 & ~mask;
  111. /*
  112. * The following code uses STG on the first DC GVA block even if the
  113. * start address is aligned - it appears to be faster than an alignment
  114. * check + conditional branch. Also, if the range size is at least 2 DC
  115. * GVA blocks, the first two loops can use post-condition to save one
  116. * branch each.
  117. */
  118. #define SET_MEMTAG_RANGE(stg_post, dc_gva) \
  119. do { \
  120. if (!dczid_dzp && size >= 2 * dczid_bs) {\
  121. do { \
  122. curr = stg_post(curr); \
  123. } while (curr < end1); \
  124. \
  125. do { \
  126. dc_gva(curr); \
  127. curr += dczid_bs; \
  128. } while (curr < end2); \
  129. } \
  130. \
  131. while (curr < end3) \
  132. curr = stg_post(curr); \
  133. } while (0)
  134. if (init)
  135. SET_MEMTAG_RANGE(__stzg_post, __dc_gzva);
  136. else
  137. SET_MEMTAG_RANGE(__stg_post, __dc_gva);
  138. #undef SET_MEMTAG_RANGE
  139. }
  140. static inline u64 __stg_post(u64 p)
  141. {
  142. asm volatile(__MTE_PREAMBLE "stg %0, [%0], #16"
  143. : "+r"(p)
  144. :
  145. : "memory");
  146. return p;
  147. }

上面的核心实现可以看到,主要是两个指令:一个是IRG, 一个是STG, 完成了key和lock的填充。

4.3 tag存在哪里?

MTE将tags分成两类:

Address Tag:也就是key, 是4bit存放在虚拟地址的最高byte中(利用ARM64的TBI 特性)

Memory Tag:也叫lock, Memeory tag也是4bit, 每4byte代表16 byte, 与kasan, sw tag kasan 不同,MTE中Memory tag的存储是由硬件实现的。

看上图实际MTE的tag也是存储在memory上的,按照tag的消耗是4bit标记16byte, 开启MTE后也是会消耗1/32的物理内存,但是这个memory 的地址我们在内核是看不到的,kernel也没有看到设定的地方。

翻看ARM手册,如上图所示有一个Memory Tag Unit(MTU)管理和区分tag storage和data storage。

翻看CI-700的手册中有介绍设置MTE tag存储的物理地址的起始地址,其中还描述了这个寄存器只能在secure(EL3)操作,这也是为什么在内核找不到设置的地方(通常MTE使能的硬件平台会在设备树中增加一个保留内存,这个内存也就是在TZ中被设置,用来存储tag信息)

五、用户空间MTE使用方法

前面讲了内核中的MTE实现和使用,用户空间也是类似的,arm官网提供了一个很好的例子:

  1. /*
  2. * Memory Tagging Extension (MTE) example for Linux
  3. *
  4. * Compile with gcc and use -march=armv8.5-a+memtag
  5. * gcc mte-example.c -o mte-example -march=armv8.5-a+memtag
  6. *
  7. * Compilation should be done on a recent Arm Linux machine for the .h files to include MTE support.
  8. *
  9. */
  10. #include <stdio.h>
  11. #include <stdlib.h>
  12. #include <unistd.h>
  13. #include <sys/auxv.h>
  14. #include <sys/mman.h>
  15. #include <sys/prctl.h>
  16. /*
  17. * Insert a random logical tag into the given pointer.
  18. * IRG instruction.
  19. */
  20. #define insert_random_tag(ptr) ({ \
  21. uint64_t __val; \
  22. asm("irg %0, %1" : "=r" (__val) : "r" (ptr)); \
  23. __val; \
  24. })
  25. /*
  26. * Set the allocation tag on the destination address.
  27. * STG instruction.
  28. */
  29. #define set_tag(tagged_addr) do { \
  30. asm volatile("stg %0, [%0]" : : "r" (tagged_addr) : "memory"); \
  31. } while (0)
  32. int main(void)
  33. {
  34. unsigned char *ptr; // pointer to memory for MTE demonstration
  35. /*
  36. * Use the architecture dependent information about the processor
  37. * from getauxval() to check if MTE is available.
  38. */
  39. if (!((getauxval(AT_HWCAP2)) & HWCAP2_MTE))
  40. {
  41. printf("MTE is not supported\n");
  42. return EXIT_FAILURE;
  43. }
  44. else
  45. {
  46. printf("MTE is supported\n");
  47. }
  48. /*
  49. * Enable MTE with synchronous checking
  50. */
  51. if (prctl(PR_SET_TAGGED_ADDR_CTRL,
  52. PR_TAGGED_ADDR_ENABLE | PR_MTE_TCF_SYNC | (0xfffe << PR_MTE_TAG_SHIFT),
  53. 0, 0, 0))
  54. {
  55. perror("prctl() failed");
  56. return EXIT_FAILURE;
  57. }
  58. /*
  59. * Allocate 1 page of memory with MTE protection
  60. */
  61. ptr = mmap(NULL, sysconf(_SC_PAGESIZE), PROT_READ | PROT_WRITE | PROT_MTE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
  62. if (ptr == MAP_FAILED)
  63. {
  64. perror("mmap() failed");
  65. return EXIT_FAILURE;
  66. }
  67. /*
  68. * Print the pointer value with the default tag (expecting 0)
  69. */
  70. printf("pointer is %p\n", ptr);
  71. /*
  72. * Write the first 2 bytes of the memory with the default tag
  73. */
  74. ptr[0] = 0x41;
  75. ptr[1] = 0x42;
  76. /*
  77. * Read back to confirm the writes
  78. */
  79. printf("ptr[0] = 0x%hhx ptr[1] = 0x%hhx\n", ptr[0], ptr[1]);
  80. /*
  81. * Generate a random tag and store it for the address (IRG instruction)
  82. */
  83. ptr = (unsigned char *) insert_random_tag(ptr);
  84. /*
  85. * Set the key on the pointer to match the lock on the memory (STG instruction)
  86. */
  87. set_tag(ptr);
  88. /*
  89. * Print the pointer value with the new tag
  90. */
  91. printf("pointer is now %p\n", ptr);
  92. /*
  93. * Write the first 2 bytes of the memory again, with the new tag
  94. */
  95. ptr[0] = 0x43;
  96. ptr[1] = 0x44;
  97. /*
  98. * Read back to confirm the writes
  99. */
  100. printf("ptr[0] = 0x%hhx ptr[1] = 0x%hhx\n", ptr[0], ptr[1]);
  101. /*
  102. * Write to memory beyond the 16 byte granule (offsest 0x10)
  103. * MTE should generate an exception
  104. * If the offset is less than 0x10 no SIGSEGV will occur.
  105. */
  106. printf("Expecting SIGSEGV...\n");
  107. ptr[0x10] = 0x55;
  108. /*
  109. * Program only reaches this if no SIGSEGV occurs
  110. */
  111. printf("...no SIGSEGV was received\n");
  112. return EXIT_FAILURE;
  113. }

上面的例子很简单,就是利用irg和stg指令给指定的内存生成lock, 指针tag(生成key),然后进行越界访问,会触发异常。

在qemu中执行结果:

六、小结

对比kernel中内存踩踏检测工具

类型shadow内存占用cpu占用优缺点
KASAN1/8复杂,每次内存访问,需要计算对比shadow值定位准确,8byte内的踩踏也能检测;32位/64位均能使用
KASAN_SW_TAGS1/16每次内存访问,需要计算对比shadow值16 byte内的踩踏无法区分, 仅64才能使用(因为依赖arm64 TBI feature)
KASAN_HW_TAGS(MTE)1/325%左右消耗,tag的生成和检查由硬件完成16 byte内的踩踏无法区分, 仅支持MTE的平台才能使用

其实对比KASAN_SW_TAGS, MTE主要是性能上的提升,缺点和能力与KASAN_SW_TAGS接近,MTE的诞生其实不是用来debug, 而是google希望推动MTE在商用版本上落地,最根本的目的是解决内存安全的问题,当前目前的确有性能上的影响(目前厂商均未应用到用户端),随着MTE本身的优化和CPU性能的进一步提升,也许不久的将来会看到MTE落地到产品商用版本上。

参考:

Memory Tagging Extension (MTE) in AArch64 Linux

Learn about the Arm Memory Tagging Extension: Build and run an example application to learn about MTE

Arm 内存标记扩展 (MTE) | Android NDK | Android Developers

ARM MTE简介-CSDN博客

https://www.qemu.org/docs/master/system/arm/virt.html

https://www.kernel.org/doc/html/v5.15/arm64/memory-tagging-extension.html

Documentation - Arm Developer

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小丑西瓜9/article/detail/160006
推荐阅读
相关标签
  

闽ICP备14008679号