\浅谈ARM64基于硬件tag的KASAN

原创 Linux阅码场 2022-03-03 08:00

作者简介

bang,linux内核爱好者,目前就职于杭州某安防公司,主要从事于SOC的bring up及驱动开发,喜欢分析linux内核内存管理和调度子系统。



本文所述的基于硬件 tag 的 KASAN 只有理论没有实践,主要参考了一些国外的文献,以及自己对源码的阅读和手册的理解,算是对硬件 tag 的 KASAN 的抛砖引玉。由于水平有限,只能浅谈。内核版本为 kernel-5.16


1.概述


踩内存是非常让人头疼的一类问题,导致的现象也是千奇百怪。如果踩的内存位于数据区域,则可能只是导致逻辑异常,并不会直接产生 kernel painc。虽然只是逻辑错误,但可能会产生各种奇怪的现象,严重时可能会出现系统宕机。如果踩的内存存储的是指针,可能会导致 kernel panic,而且产生 kernel panic的元凶很可能不能直接通过 log 定位出来,因为被踩的指针只是受害者,元凶还在逍遥法外,这时候检测踩内存的工具就呼之欲出了。目前常用的检测内核态踩内存工具有 hardware breakpointSLUB_DEBUGKCSANKASAN 等,其中检测类型最全面最有效的要属 KASAN 工具了。KernelAddressSANitizer(KASAN)是一个动态的内存错误检测工具,主要用来发现 use-after-free out-of-bounds等内存访问异常问题。KASAN 目前有三种实现方法,分别为 Generic KASANSoftware tag-based KASANHardware tag-based KASAN,其中 Generic KASANSoftware tag-based KASAN 是基于软件实现,Hardware tag-based KASAN 是基于硬件实现的。下面我们先了解下三种 KASAN 的基本原理,然后重点分析下基于硬件 tag 的 KASAN 的实现。


1.1 Generic KASAN


软件 KASAN 模式使用影子内存来记录每个内存字节是否可以安全访问,并在编译时插入影子内存检查指令。Generic KASAN 将 1/8 的内存专用于其影子内存,并使用固定偏移映射方式将对应内存地址转换为其相应的影子地址。地址转换关系如下函数:

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


编译器在每次访问大小为 1、2、4、8 或 16 字节的内存之前插入检测函数(``__asan_load*(addr)``、``__asan_store*(addr)``),这些函数会检测内存的访问是否有效。


1.2 Software tag-based KASAN


基于软件 tag 的 KASAN 使用软件内存标记方法来检查访问的内存是否有效,目前仅在 arm64 架构上实现。基于软件 tag 的 KASAN 使用 arm64 CPUTop Byte Ignore(TBI)功能将指针 tag 存储在指针的顶部字节中。它使用影子内存来存储与每个 16 字节内存单元关联的内存 tag(因此,它将内核内存的 1/16 专用于影子内存)。在每次内存分配时,生成一个随机 tag,用这个 tag 标记分配的内存,并将相同的 tag 嵌入到返回的指针中。编译时,在每次内存访问之前插入检测指 令,这些检测指令会比较正在访问的内存的 tag(影子区)和用于访问该内存的指针的 tag 是否匹配。如果不匹配,基于软件 tag 的 KASAN 会打印错误报告。Software tag-based KASAN 使用 0xFF 作为匹配所有指针 tag(不检查通过带有 0xFF 指针 tag 的指针进行的访问)。0xFE 用于标记释放的内存区域。目前Software tag-based KASAN 只支持 slab 和 page_alloc 内存检测。我们简单总结下 Software tag-based KASAN 的特点:1、编译时插入用于检测内存访问指令。2、专用的影子内存大小为检测内存大小的 1/16。3、通过指令对比内存 tag(影子区域)和指针 tag。


1.3 Hardware tag-based KASAN


基于硬件 tag 的 KASAN 和基于软件 tag 的 KASAN 原理非常类似,Software tag-based KASAN 的内存的 tag(影子区)和用于访问该内存的指针的 tag 的比较是由插入的汇编指令完成的,而 Hardware tag-based KASAN 是由硬件自动完成比较的,对于软件是透明的。Hardware tag-based KASAN 目前也是仅支持 arm64 架构,并且它的实现是基于 ARMv8.5 指令集架构中引入的内存标记扩展 (MTE) 和 Top Byte Ignore(TBI)。在每次内存访问时,硬件都会比较正在访问的内存的 tag 和用于访问该内存指针的 tag。如果 tag 不匹配,则会触发一个异常。基于硬件 tag 的 KASAN 使用 0xFF 作为匹配所有指针 tag(不检查通过带有0xFF 指针 tag 的指针进行的访问)。0xFE 用于标记释放的内存区域。目前只支持slab page_alloc 检测。这些特性和 Software tag-based KASAN 一样。如果硬件不支持 MTE(ARMv8.5 之前),则不会启用 Hardware tag-based KASAN。在这种情况下,所有 KASAN 引导参数都将被忽略。


2.基本概念和实现原理


Hardware tag-based KASAN目前仅支持ARM64架构,具体实现依赖Top Byte Ignore(TBI)Memory Tagging Extension(MTE)机制。

2.1 TBI

Top Byte Ignore(TBI)顾名思义高字节忽略。TBIARMv8引入的一项硬件功能,对于ARM64架构会使用64位指针来寻址内存,TBI允许软件使用64位指针的8 bits用于其它用途。此功能可以通过设置TCR_EL1寄存器的TBI1对应的bit[38]位来实现。启用后,虚拟地址的高八位([63:56])将自动被忽略。通常只有48位被硬件实际使用到了,如果启用了特殊的large-address-space选项,则是52位。所以有12-16位(其中TBI使用了高8bit[63-56])可以拿来用做其它用途。memory tagging extension(MTE)就是其用途之一。



 
2.2 MTE

memory tagging extension(MTE)是ARMv8.5引入的一个新的特性,在指针的高字节中存储一个4 bits的tag,即是key(运用TBI特性)。每16字节的内存块中使用专用的内存(tagging memory)存储tag,即是lock。通过keylock把指针和要访问的16字节内存块关联起来,当通过一个指针来访问内存区域时,存储在指针中的key值会与指针所引用的内存块的lock值进行比较,如果两者不匹配,则会触发异常。

2.2.1 MTE检测原理

MTE的检测过程是由硬件自动完成的。当使能MTE功能,执行Load/Stroe指令时,MTE会检测pointer tags ([59:56])对应的keymemory tags对应的lock是否相等?如果相等,则可以正常访问内存。如果不相等,则抛出异常。


从上图可以看出MTE的基础模型是一个“锁和钥匙”方案。对于图中的前两个指针,该pointer tagskey值和memory tagslock值一致,则使用这些指针对内存的访问和我们平时的使用没什么区别。但是,对于下面两个指针的访问,keylock值并不相等,这将被CPU捕获,然后触发异常。通过这种机制,可以很容易地检测到难以捕获的内存安全问题。这意味着即使是概率很低的问题,一旦触发tag mismatch,也会立即被发现,有助于一般性问题的调试。 

对于MTE的检测我们主要关注pointer tagsmemory tags,下面我们先了解下它们的特性。

2.3 pointer/memory tags

存放在指针中的tag称为pointer tags或者logical tags,内存块对应的tag称之为memory tags或者allocation tags

2.3.1 pointer tags
 


  • 1、 MTEpointer tags就是利用Armv8-ATBI(Top Byte Ignore)特性,使用指针的高4 bits存储tag。因为用4 bits表示,所以共有16种不同的tag。


  • 2、 pointer tags存放在虚拟地址的[59:56] bit。


  • 3、 pointer tags可以通过使用自定义算法或者新增的MTE汇编指令(如IRG指令)生成对应的tag


  • 4、 MTEpointer tags也称为logical tags



2.3.2  memory tags
 


  • 1、 MTEmemory tags放在专用内存中,存储的位置对软件是透明的,无需软件参与显示分配。


  • 2、 每一个tag占用4 bits,所以有16种不同的tag


  • 3、 4-bits tag对应16字节内存块,则memory tags的内存消耗~3%。


  • 4、 memory tags生成和pointer tags类似,而存储是通过新增的MTE汇编指令实现(如STG指令)的。每一个memory tags对应16字节内存块,对于大内存的申请,这意味需要多次执行STG指令才能完全覆盖分配的内存。


  • 5、 MTE memory tags也称为allocation tags。



2.3.3 tags

从上面的描述我们可以知道memory tags由4个bits组成,则理论上的取值范围为[0x0,0xF],从内核头文件中我们可以看到random tags的取值范围为[0xF0,0xFD]。最小值为0xF0,最大值为0xFD。其中0xFF表示匹配所有指针tag(不检查通过0xff标记的指针的内存访问)。0xFE表示是释放的内存区域。

#define KASAN_TAG_KERNEL 0xFF /* native kernel pointers tag */#define KASAN_TAG_INVALID 0xFE /* inaccessible memory tag */ #define KASAN_TAG_MAX 0xFD /* maximum value for random tags */#define KASAN_TAG_MIN 0xF0 /* minimum value for random tags */


Hardware tag-based KASAN的tag既可以通过软件算法生成,又可以通过硬件生成。而linux内核是通过irg指令获取随机tag的。

/* Generate a random tag. */static inline u8 mte_get_random_tag(void){void *addr;asm(__MTE_PREAMBLE "irg %0, %0": "=r" (addr));return mte_get_ptr_tag(addr);}static inline u8 mte_get_ptr_tag(void *ptr) {/* Note: The format of KASAN tags is 0xF */u8 tag = 0xF0 | (u8)(((u64)(ptr)) >> MTE_TAG_SHIFT);return tag;}


mte_get_ptr_tag函数中,我们可以看出Hardware tag-based KASANtag值从irg获取后,会再或上0xF0。从上面的描述我们可以猜测irg生成随机tag的取值范围为[0x0,0xD]。通过下表我们可以了解下其它MTE的新增指令


Instruction
Name
说明
IRG
Insert Random Tag
生成随机的pointer tag
LDG
Load Allocation Tag
获取memory tag
STG
Store Allocation Tag
存储memory tag
STZG
Store Allocation Tag, Zeroing
存储memory tag,并将内存数据归零,比STG单独标记和把数据清0性能好。

其它更多指令见https://en.wikichip.org/wiki/arm/mte

2.4 sync/async

当执行Load/Store指令时,检测到lockkey不匹配,可选择触发一个异常。异常类型可以通过配置SCTLR_EL1寄存器中的TCF([41:40])来选择。


TCF=0忽略Tag checks Faults。
TCF=1Tag checks Faults触发一个同步数据异常(data abort),同时会把造成异常的地址写入到FAR_ELx寄存器中。
TCF=2Tag checks Faults触发一个异步异常,会更新TFSR_EL1中的TF1值 


当发生tag check fault时,如果虚拟地址bit[55]为0,则会把TF0置1。如果bit[55]为1,则会把TF1置1。在内核态产生的异常自然会把TF1置1。
TCF=3当发生tag check fault时,如果是读指令造成的,则触发一个同步异常。如果是写指令造成的,则触发一个异步异常。

下面是三种异常模式的对比

Mode
Tag check runs
Speed
Detection
Sync
During instruction execution
Slower
Precise
Async
Asynchronously
Faster
Imprecise
Asymm
Sync for reads,async for writes



目前内核实现了sync模式async模式asymm模式sync检测对问题的定位更高效,因为它可以精确识别导致异常的指令和地址。但是sync模式检测的overhead比较高,这种性能影响在开发环境中可能是可以被接受的,但对于部署来说太高了。async测的overhead较低,这意味着即使在生产系统上也可以使用。尽管async测触发异常的report信息不太精确,但它可以提供一些额外信息用于分析,缩小了定位问题的范围。

2.4.1 sync触发流程

当在同步模式发生tag mismatch时,会触发一个Synchronous Tag Check Fault异常,同时会把ESR_EL1寄存器的DFSC设置为0x11。然后在同步异常里输出异常信息。
  



代码流程如下:

do_mem_abort->do_tag_check_fault /* 1 */->do_bad_area->__do_kernel_fault->do_tag_recovery /* 2 */->report_tag_fault->sysreg_clear_set


  • 1、 产生异常后,读取ESR_EL1寄存器的值,若该值为0x11,判定是一个Synchronous Tag Check Fault异常,然后执行do_tag_check_fault函数。


  • 2、 Report同步异常相关信息,同时关闭tag检测功能。



2.4.2 async触发流程

当在异步模式发生tag mismatch时,会异步更新TFSR_EL1寄存器,并把TF1位置1。为了检测是否发生了异步异常,我们需要在合适的时间点检查TFSR_EL1寄存器的TF1位是否置位?如果被置位,则说明发生了异步异常。

Linux内核主要会在以下时间点检测是否发生了tag check fault

  • 1. Context switching


  • 2. Return to user/EL0 (Not required in entry from EL0 since the kernel did not run)


  • 3. Kernel entry from EL1


  • 4. Kernel exit to EL1



我们以第一点为例,在上下文切换的时候检测是否发生了tag check fault
代码具体调用流程如下:

__schedule  ->context_switch->__switch_to->mte_thread_switch->mte_check_tfsr_el1


重点关注mte_check_tfsr_el1函数实现。

void mte_check_tfsr_el1(void){    u64 tfsr_el1 = read_sysreg_s(SYS_TFSR_EL1);                                                                                                                                                                                                            if (unlikely(tfsr_el1 & SYS_TFSR_EL1_TF1)) {        write_sysreg_s(0, SYS_TFSR_EL1);        kasan_report_async();    }   }

从代码中可以看到,在进程上下文切换的时候会检测TFSR_EL1寄存器的TF1位,如果置位,先失能tag check功能,然后再调用kasan_report_async输出异步异常信息。其它三点类似不再分析。

2.5 小结

发生tag mismatch后,不管是同步异常还是异步异常只报告第一次触发的异常,之后MTE tags检查功能被禁用。通过本小结的描述,我们应该可以回答以下几个问题?

  • 1、pointer tags是如何分配和储存的?


  • 2、memory tags是如何分配和存储的?


  • 3、有多少不同的tag


  • 4、何时对tag进行检测的?


  • 5、发生tag mismatch会发生什么?



基于MTE的特性,我们可以将其应用于use-after-freeout-of-bounds等问题的定位。目前内核实现了对page_allocslab的支持,暂不支持vmalloc, stack and globals的检测。下面我们重点分析下page_allocslab在内核中的实现原理。

3.MTE在kernel中的使用


Hardware Tag-Based KASAN 是基于 MTE 实现的,MTE 的特性上面已经描述了,下面我们重点分析下 page_alloc kmalloc 的申请和释放的 memory tagspointer tags 的变化。

3.1 Buddy allocator 申请和释放

首先看一下伙伴系统的释放流程中 memory tags 的变化。


3.1.1 free page(s)


  • 1、假设我们释放 4 个 pages 到伙伴系统中。


  • 2、在释放过程中会调用 kasan_free_pages 函数填充 memory tags 为 0xe,表示此内存块已经被释放,不能直接访问,需要先申请后使用。


  • 3、填充 memory tags 的大小为 512 bytes。



3.1.2 allocate page(s)


  • 1、假设我们从伙伴系统申请 4 个 pages。系统首先从 order=2 的链表中摘下一块连续的内存块。


  • 2、在获取内存块的过程中会调用 kasan_unpoison_pages 函数填充 pointer tagsmemory tags。在填充 tag 之前,我们首先会通过 kasan_random_tag函数 irg 指令获取一个随机的 tag(假设生成的 tag 为 0x2),然后或上 0xf0,最后再通过 page_kasan_tag_set 函数把 pointer tags 设置到 struct page flags 字段中,如下函数:




static inline void page_kasan_tag_set(struct page *page, u8 tag){  unsigned long old_flags, flags;  if (!kasan_enabled())    return;  tag ^= 0xff;  old_flags = READ_ONCE(page->flags);  do {    flags = old_flags;    flags &= ~(KASAN_TAG_MASK << KASAN_TAG_PGSHIFT);    flags |= (tag & KASAN_TAG_MASK) << KASAN_TAG_PGSHIFT;  } while (unlikely(!try_cmpxchg(&page->flags, &old_flags, flags)));}


从上述代码中我们可以看到设置到page->flagstagtag^0xff后的值为0x0d,page->flags = 0x0d << KASAN_TAG_PGSHIFT

tag的异或值存放在pageflags中,那我们如何使用呢?首先我们需要把物理page转换为虚拟地址,然后再去访问对应的虚拟地址。我们找到线性映射的page_to_virt宏,通过宏我们可以看到,在拿虚拟地址之前会通过__tag_set函数flags中获取异或前的tag(0xf2),并填充到虚拟地址的高位。这样我们就可以正常访问对应的内存区域了。

#define page_to_virt(x)({\__typeof__(x) __page = x;\u64 __idx = ((u64)__page - VMEMMAP_START) / sizeof(struct page);\u64 __addr = PAGE_OFFSET + (__idx * PAGE_SIZE);\(void *)__tag_set((const void *)__addr, page_kasan_tag(__page));\})


  • 3、通过kasan_unpoison函数填充memory tags为0x2。

  • 4、填充 memory tags 的大小为 512 bytes。



3.2 kmalloc 申请和释放

slubtag 填充和 kmalloc 类似,下面以 kmalloc 的申请和释放流程为例进行分析[注 SLUB DEBUG is off]。首先看下 kmalloc 申请过程中的 pointer tagsmemory tags 的填充过程。

3.2.1 kmalloc

slub 系统刚刚创建出来,第一次申请内存,此时 kmem_cache_cpukmem_cache_node 中没有任何可用的 slubobject 对象,因此只能向伙伴系统申请空闲的内存页。同时会通过 kasan_poison_slab 函数把获取到的内存页的memory tags 填充为 0xe,具体见 allocate_slab 函数。



  • 1、假设通过 kmalloc 申请 35 bytes,对于 ARM64 而言会匹配到 kmalloc-128 的kmem_cache,因此实际分配的 object 大小是 128 bytes。至于为什么不是匹配到 kmalloc-64,可以从__kmalloc_index 函数中找到答案。


  • 2、通过 kasan_slab_alloc 函数填充 pointer tagsmemory tags。首先会通过 kasan_random_tag 函数(irg 指令)生成一个随机的 tag(say,0xc),或上0xf0 后的 tag 是 0xfc。其次再通过 set_tag(object, tag)函数把 tag 设置到pointer 中,最后通过 kasan_unpoison 函数把 0xc 设置到 memory tags 中。


  • 3、kmalloc(35)只申请了 35 个字节,由于 mte 的特性,会把前 48 个字节的 memory tags 标记为 0xc,表示能够正常访问。当使用完成之后,会调用 kfree 进行释放,释放之后的 memory tags 情况又是怎样的呢?往下看。




3.2.2 kfree


  • 1、根据释放地址 p,找到对应的 object,然后释放 object


  • 2、在释放 object 的过程中调用 kasan_slab_free 函数填充 memory tags 为 0xe,表示释放的内存,不能再访问。


  • 3、把释放的 object 的前 48 bytes 对应 memory tags 填充为 0xe。


3.2.3 Preventing memory corruptions

了解了 kmalloc 申请和释放过程中的 pointer tagsmemory tags 的变化后,下面我们通过图示的方式来说明下 kmalloc 申请和释放过程中,内存访问可能产生的各种情况。

allocating memory


  • 1、kmalloc(35)会从kmalloc-128 slub描述符中获取object


  • 2、通过IRG指令生成一个random tag (say,0x2)。 


  • 3、用0x2标记pointer tags and memory tags,其中memory tags以16 bytes向上取整,即对应[0,48)。


  • 4、用 KASAN_TAG_INVALID(0xe)标记剩余内存 80 bytes[48,128),表示不能使用的内存。


  • 5、不同颜色的内存块对应的 memory tags 不同。


In-bounds


上图表示,我们访问的指针在 kmalloc 申请的地址范围内,属于 In-bounds。由于 pointer tags == memory tags,因此能正常访问 p[20]的数据。 

Preventing out-of-bounds


  • A:p 申请的内存大小为 35 bytes,访问 p[70]属于越界访问。由于 pointer tags != memory tags,会触发一个异常(out-of-bounds),表示非法访问。


  • B:如果 p[136]对应的 memory tags 和 p 对应的内存块的 memory tags 不一样,则同样会触发一个异常(out-of-bounds)。


Not Preventing out-of-bounds


  • A:kmaollc(35)申请 35 bytes,因为 memory tags 以 16 bytes 为大小向上取整填充,所以[32,48)这个范围内的 memory tags pointer tags 一样。所以如果我们访问 p[36],MTE 是无法检测出来的(out-of-bounds),因为此时的 pointer tags == memory tags


  • B:对于 p[136]属于越界访问,填充的 memory tags 值有可能和 p 对应的内存块的 memory tags 一样,由于 pointer tags == memory tags,此时就无法检测出来(out-of-bounds)。


prevnting use-after-free


如果申请的内存块使用完后释放,对应的内存块的 memory tags 会用 0xe 进 行填充。如果再次访问释放的内存块,如 p[8]这个位置的数据,因为 pointer tags !=memory tags(0xe),则会触发一个异常(use-after-free)。 

preventing use-after-realloc


如果通过 kmalloc(35)函数申请的内存块在使用完后释放。然后再通过kmalloc(60)重新申请,假设拿到同一个 object。如果 kmalloc(60)申请的内存块填充的 memory tags kmaolloc(35)的不一样,此时再访问 p[8], pointer tags != memory tags,则会触发一个异常(use-after-realloc)。 

Not preventing use-after-realloc


和上面 preventing use-after-realloc 类似,如果 kmalloc(60)申请的内存块填充的 memory tags kmaolloc(35)的一样,此时访问 p[8],pointer tags== memory tags,则无法检测出来(use-after-realloc)。简单总结一下, Hardware Tag-Based KASAN 能检测出来 slab page_alloc相关问题,但并不是所有的 slab page_alloc 问题都能被检测出来,存在两个连续内存分配相同的 memory tags,也就会出现 1/16 概率无法被检测出来的情况。如果能保证相邻的 memory tags 不同,tag mismatch 的概率会大大降低。

4.使用方法


4.1 内核配置宏

需要添加以下内核配置
CONFIG_KASAN=y
CONFIG_KASAN_HW_TAGS=y
如果启用 CONFIG_KASAN_HW_TAGS 宏,则会默认启用ARM64的TBI特性。

4.2 启动参数

启动参数
内容
kasan=on/off
是否开启kasan,默认on。
kasan.mode=sync/async/asymm
选择不同的模式(同步/异步/混合),默认sync模式。
kasan.stacktrace=on/off
是否使能alloc and free stack traces,默认on。
kasan.fault=report/panic
是report还是panic,默认report。


5.案例分析


从其它地方找了两份log信息,一份是sync模式下触发的异常信息,另一份是async模式下触发的异常信息,首先看下sync模式。

5.1 Report: mode=sync, stacktrace=on
==================================================================
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
...
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)
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
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
==================================================================

从上面的log我们能获取到以下信息:

  • 1、触发问题的位置是kmalloc_oob_right+0x1ac/0x23c。



  • 2、CPU0,PID为102的kunit_try_catch进程读取0xf2ff0000039ca880地址数据造成的tag mismatch,其中pointer tag:0xf2, memory tag:0xfe。同时能获取到造成异常时的call trace信息。



  • 3、触发异常的内存块的申请和释放的call trace信息及对应的进程pid号。



  • 4、kmalloc-128的kmem_cache中分配的objectkmalloc起始地址是0x ffff0000039ca800,申请的内存大小为(96,112]字节之间,触发异常的地址位于object起始地址偏移128 bytes的位置,属于out-of-bounds问题。



从上面的分析可以看出sync模式下的report信息非常丰富,我们通过log信息可以快速有效的定位到问题所在。下面我们看一下在async模式下,能获取到哪些信息?

5.2 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)
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
...
====================================================================

log信息中我们可以知道,异常发生在CPU1上,pid为102的kunit_try_catch进程中,同时也能获取到report异常时的call trace信息。

虽然async模式report信息相比sync模式少很多,但是也提供了一些有效的信息,可以缩小排查问题的范围。同时由于其性能开销小,可以部署在生产环境中。



Linux阅码场 专业的Linux技术社区和Linux操作系统学习平台,内容涉及Linux内核,Linux内存管理,Linux进程管理,Linux文件系统和IO,Linux性能调优,Linux设备驱动以及Linux虚拟化和云计算等各方各面.
评论
  • 在当前人工智能(AI)与物联网(IoT)的快速发展趋势下,各行各业的数字转型与自动化进程正以惊人的速度持续进行。如今企业在设计与营运技术系统时所面临的挑战不仅是技术本身,更包含硬件设施、第三方软件及配件等复杂的外部因素。然而这些系统往往讲究更精密的设计与高稳定性,哪怕是任何一个小小的问题,都可能对整体业务运作造成严重影响。 POS应用环境与客户需求以本次分享的客户个案为例,该客户是一家全球领先的信息技术服务与数字解决方案提供商,遭遇到一个由他们所开发的POS机(Point of Sal
    百佳泰测试实验室 2025-01-09 17:35 78浏览
  •  在全球能源结构加速向清洁、可再生方向转型的今天,风力发电作为一种绿色能源,已成为各国新能源发展的重要组成部分。然而,风力发电系统在复杂的环境中长时间运行,对系统的安全性、稳定性和抗干扰能力提出了极高要求。光耦(光电耦合器)作为一种电气隔离与信号传输器件,凭借其优秀的隔离保护性能和信号传输能力,已成为风力发电系统中不可或缺的关键组件。 风力发电系统对隔离与控制的需求风力发电系统中,包括发电机、变流器、变压器和控制系统等多个部分,通常工作在高压、大功率的环境中。光耦在这里扮演了
    晶台光耦 2025-01-08 16:03 87浏览
  • HDMI 2.2 规格将至,开启视听新境界2025年1月6日,HDMI Forum, Inc. 宣布即将发布HDMI规范2.2版本。新HDMI规范为规模庞大的 HDMI 生态系统带来更多选择,为创建、分发和体验理想的终端用户效果提供更先进的解决方案。新技术为电视、电影和游戏工作室等内容制作商在当前和未来提供更高质量的选择,同时实现多种分发平台。96Gbps的更高带宽和新一代 HDMI 固定比率速率传输(Fixed Rate Link)技术为各种设备应用提供更优质的音频和视频。终端用户显示器能以最
    百佳泰测试实验室 2025-01-09 17:33 84浏览
  • 1月7日-10日,2025年国际消费电子产品展览会(CES 2025)盛大举行,广和通发布Fibocom AI Stack,赋智千行百业端侧应用。Fibocom AI Stack提供集高性能模组、AI工具链、高性能推理引擎、海量模型、支持与服务一体化的端侧AI解决方案,帮助智能设备快速实现AI能力商用。为适应不同端侧场景的应用,AI Stack具备海量端侧AI模型及行业端侧模型,基于不同等级算力的芯片平台或模组,Fibocom AI Stack可将TensorFlow、PyTorch、ONNX、
    物吾悟小通 2025-01-08 18:17 72浏览
  • 「他明明跟我同梯进来,为什么就是升得比我快?」许多人都有这样的疑问:明明就战绩也不比隔壁同事差,升迁之路却比别人苦。其实,之间的差异就在于「领导力」。並非必须当管理者才需要「领导力」,而是散发领导力特质的人,才更容易被晓明。许多领导力和特质,都可以通过努力和学习获得,因此就算不是天生的领导者,也能成为一个具备领导魅力的人,进而被老板看见,向你伸出升迁的橘子枝。领导力是什么?领导力是一种能力或特质,甚至可以说是一种「影响力」。好的领导者通常具备影响和鼓励他人的能力,并导引他们朝着共同的目标和愿景前
    优思学院 2025-01-08 14:54 93浏览
  • 在智能网联汽车中,各种通信技术如2G/3G/4G/5G、GNSS(全球导航卫星系统)、V2X(车联网通信)等在行业内被广泛使用。这些技术让汽车能够实现紧急呼叫、在线娱乐、导航等多种功能。EMC测试就是为了确保在复杂电磁环境下,汽车的通信系统仍然可以正常工作,保护驾乘者的安全。参考《QCT-基于LTE-V2X直连通信的车载信息交互系统技术要求及试验方法-1》标准10.5电磁兼容试验方法,下面将会从整车功能层面为大家解读V2X整车电磁兼容试验的过程。测试过程揭秘1. 设备准备为了进行电磁兼容试验,技
    北汇信息 2025-01-09 11:24 80浏览
  • 村田是目前全球量产硅电容的领先企业,其在2016年收购了法国IPDiA头部硅电容器公司,并于2023年6月宣布投资约100亿日元将硅电容产能提升两倍。以下内容主要来自村田官网信息整理,村田高密度硅电容器采用半导体MOS工艺开发,并使用3D结构来大幅增加电极表面,因此在给定的占位面积内增加了静电容量。村田的硅技术以嵌入非结晶基板的单片结构为基础(单层MIM和多层MIM—MIM是指金属 / 绝缘体/ 金属) 村田硅电容采用先进3D拓扑结构在100um内,使开发的有效静电容量面积相当于80个
    知白 2025-01-07 15:02 158浏览
  • 根据环洋市场咨询(Global Info Research)项目团队最新调研,预计2030年全球中空长航时无人机产值达到9009百万美元,2024-2030年期间年复合增长率CAGR为8.0%。 环洋市场咨询机构出版了的【全球中空长航时无人机行业总体规模、主要厂商及IPO上市调研报告,2025-2031】研究全球中空长航时无人机总体规模,包括产量、产值、消费量、主要生产地区、主要生产商及市场份额,同时分析中空长航时无人机市场主要驱动因素、阻碍因素、市场机遇、挑战、新产品发布等。报告从中空长航时
    GIRtina 2025-01-09 10:35 74浏览
  • 本文介绍编译Android13 ROOT权限固件的方法,触觉智能RK3562开发板演示,搭载4核A53处理器,主频高达2.0GHz;内置独立1Tops算力NPU,可应用于物联网网关、平板电脑、智能家居、教育电子、工业显示与控制等行业。关闭selinux修改此文件("+"号为修改内容)device/rockchip/common/BoardConfig.mkBOARD_BOOT_HEADER_VERSION ?= 2BOARD_MKBOOTIMG_ARGS :=BOARD_PREBUILT_DTB
    Industio_触觉智能 2025-01-08 00:06 111浏览
  • 故障现象一辆2017款东风风神AX7车,搭载DFMA14T发动机,累计行驶里程约为13.7万km。该车冷起动后怠速运转正常,热机后怠速运转不稳,组合仪表上的发动机转速表指针上下轻微抖动。 故障诊断 用故障检测仪检测,发动机控制单元中无故障代码存储;读取发动机数据流,发现进气歧管绝对压力波动明显,有时能达到69 kPa,明显偏高,推断可能的原因有:进气系统漏气;进气歧管绝对压力传感器信号失真;发动机机械故障。首先从节气门处打烟雾,没有发现进气管周围有漏气的地方;接着拔下进气管上的两个真空
    虹科Pico汽车示波器 2025-01-08 16:51 111浏览
  • 光伏逆变器是一种高效的能量转换设备,它能够将光伏太阳能板(PV)产生的不稳定的直流电压转换成与市电频率同步的交流电。这种转换后的电能不仅可以回馈至商用输电网络,还能供独立电网系统使用。光伏逆变器在商业光伏储能电站和家庭独立储能系统等应用领域中得到了广泛的应用。光耦合器,以其高速信号传输、出色的共模抑制比以及单向信号传输和光电隔离的特性,在光伏逆变器中扮演着至关重要的角色。它确保了系统的安全隔离、干扰的有效隔离以及通信信号的精准传输。光耦合器的使用不仅提高了系统的稳定性和安全性,而且由于其低功耗的
    晶台光耦 2025-01-09 09:58 62浏览
  • 职场是人生的重要战场,既是谋生之地,也是实现个人价值的平台。然而,有些思维方式却会悄无声息地拖住你的后腿,让你原地踏步甚至退步。今天,我们就来聊聊职场中最忌讳的五种思维方式,看看自己有没有中招。1. 固步自封的思维在职场中,最可怕的事情莫过于自满于现状,拒绝学习和改变。世界在不断变化,行业的趋势、技术的革新都在要求我们与时俱进。如果你总觉得自己的方法最优,或者害怕尝试新事物,那就很容易被淘汰。与其等待机会找上门,不如主动出击,保持学习和探索的心态。加入优思学院,可以帮助你快速提升自己,与行业前沿
    优思学院 2025-01-09 15:48 69浏览
  • 一个真正的质量工程师(QE)必须将一件产品设计的“意图”与系统的可制造性、可服务性以及资源在现实中实现设计和产品的能力结合起来。所以,可以说,这确实是一种工程学科。我们常开玩笑说,质量工程师是工程领域里的「侦探」、「警察」或「律师」,守护神是"墨菲”,信奉的哲学就是「墨菲定律」。(注:墨菲定律是一种启发性原则,常被表述为:任何可能出错的事情最终都会出错。)做质量工程师的,有时会不受欢迎,也会被忽视,甚至可能遭遇主动或被动的阻碍,而一旦出了问题,责任往往就落在质量工程师的头上。虽然质量工程师并不负
    优思学院 2025-01-09 11:48 97浏览
  • 在过去十年中,自动驾驶和高级驾驶辅助系统(AD/ADAS)软件与硬件的快速发展对多传感器数据采集的设计需求提出了更高的要求。然而,目前仍缺乏能够高质量集成多传感器数据采集的解决方案。康谋ADTF正是应运而生,它提供了一个广受认可和广泛引用的软件框架,包含模块化的标准化应用程序和工具,旨在为ADAS功能的开发提供一站式体验。一、ADTF的关键之处!无论是奥迪、大众、宝马还是梅赛德斯-奔驰:他们都依赖我们不断发展的ADTF来开发智能驾驶辅助解决方案,直至实现自动驾驶的目标。从新功能的最初构思到批量生
    康谋 2025-01-09 10:04 75浏览
我要评论
0
点击右上角,分享到朋友圈 我知道啦
请使用浏览器分享功能 我知道啦