KASan介绍

目录

概括介绍

配置说明

单独关闭读或写检查

操作使用

影响及注意事项

结果解读

使用注意

实现原理简介

KASAN原理

malloc原理

内容参考


概括介绍

  1. KernelAddressSANitizer (KASAN) 是一个动态内存错误检测器。它提供了一个快速而全面的解决方案,用于查找释放后使用(use-after-free)和越界等错误。
  2. KASAN 使用编译插桩来检查每次内存访问,因此您需要 GCC 版本 4.9.2 或更高版本。如果希望能够对栈或者全局变量的越界访问做检测,那么需要GCC 5.0或者更高的版本。
  3. 插桩主要是针对在llvm/gcc编译器级别对访问内存的操作(store,load,alloca等),将它们进行处理。动态运行库主要提供一些运行时的复杂的功能(比如poison/unpoison shadow memory)以及将malloc,free等系统调用函数hook住。
  4. 该算法的思路是:ASAN用的是shade memory直接标记内存的状态(global、stack、heap、free),每次内存读写,先检查标记再操作实际内存。

配置说明

# 启用KASan
CONFIG_MM_KASAN=y
# 全局开启KASan,可能会导致image大小暴涨,通常会翻倍
CONFIG_MM_KASAN_ALL=y

也可以对单个文件或者应用启用KASan来有效减少KASan带来的体积增加,例如,如果只想对apps/examples/hello应用程序进行检测,可以在它的Makefile(apps/examples/hello/Makefile)中添加:

CFLAGS   += -fsanitize=kernel-address
CXXFLAGS += -fsanitize=kernel-address

想对某个目录去掉kasan:
CFLAGS += -fno-sanitize=kernel-address

单独关闭读或写检查

默认Kasan对读写都做检查,会显著降低系统的性能、增大image大小。

当确定发生的问题是内存写导致的错误时,可以关闭读检查,提高系统性能和运行速度,进而间接提高问题的复现度。

关闭读检查后,flash占用空间overhead也将大幅降低,对于穿戴设备,关闭读检查后,flash空间减小约1MB。

# 开启改选项将会关闭Kasan读检查
CONFIG_MM_KASAN_DISABLE_READS_CHECK=y

# 开启该选项将关闭Kasan写检查
CONFIG_MM_KASAN_DISABLE_WRITES_CHECK=y

操作使用

void __asan_handle_no_return(void);

void __asan_report_load_n_noabort(FAR void *addr, size_t size);

void __asan_report_store_n_noabort(FAR void *addr, size_t size);

void __asan_report_load16_noabort(FAR void *addr);

void __asan_report_store16_noabort(FAR void *addr);

void __asan_report_load8_noabort(FAR void *addr);

void __asan_report_store8_noabort(FAR void *addr);

void __asan_report_load4_noabort(FAR void *addr);

void __asan_report_store4_noabort(FAR void *addr);

void __asan_report_load2_noabort(FAR void *addr);

void __asan_report_store2_noabort(FAR void *addr);

void __asan_report_load1_noabort(FAR void *addr);

void __asan_report_store1_noabort(FAR void *addr);

void __asan_loadN_noabort(FAR void *addr, size_t size);

void __asan_storeN_noabort(FAR void * addr, size_t size);

void __asan_load16_noabort(FAR void *addr);

void __asan_store16_noabort(FAR void *addr);

void __asan_load8_noabort(FAR void *addr);

void __asan_store8_noabort(FAR void *addr);

void __asan_load4_noabort(FAR void *addr);

void __asan_store4_noabort(FAR void *addr);

void __asan_load2_noabort(FAR void *addr);

void __asan_store2_noabort(FAR void *addr);

void __asan_load1_noabort(FAR void *addr);

void __asan_store1_noabort(FAR void *addr);

void __asan_loadN(FAR void *addr, size_t size);

void __asan_storeN(FAR void *addr, size_t size);

void __asan_load16(FAR void *addr);

void __asan_store16(FAR void *addr);

void __asan_load8(FAR void *addr);

void __asan_store8(FAR void *addr);

void __asan_load4(FAR void *addr);

void __asan_store4(FAR void *addr);

void __asan_load2(FAR void *addr);

void __asan_store2(FAR void *addr);

void __asan_load1(FAR void *addr);

void __asan_store1(FAR void *addr);

影响及注意事项

使能KASAN后,会让程序明显变慢,如果这时使能了看门狗,很可能导致看门狗复位,实际使用中建议同时关闭看门狗。

使用ASAN会增加额外1/8的内存消耗用于shadow memory。

ASAN通过每8字节对应1字节的映射的方式建立影子内存区。

相同功能下,开启asan后,代码rom大小多了约20%-30%(每个对内存访问的指令前都会增加一个跳转指令),data没有变化,因为heap大小是自适应的,实际应该多消耗1/32的heap空间。如果以后功能增强,资源占用会变化。

结果解读

测试演示:

如下所示,测试代码第一条printf未越界,第二条pritnf越界立即上报并打印PANIC信息,通过backtrace信息可以直接定位到越界访问处。

int main(int argc, FAR char *argv[])
{
  char *p = malloc(1024);
  printf("Hello, World!!,%d\n", p[1023]);
  printf("Hello, World!!,%d\n", p[1024]);
  return 0;
}

利用printf()分别访问已申请的p[1023]和未申请的空间p[1024]

使用注意

  1. M55核心,memset 使用 v8.1m 里的 vstrb 指令,不是传统意义的 LDR 或 STR,因此 asan 检查无法插入,故不会针对 memset 的越界进行报错提醒。 
  2. asan 以内存管理分配器实际 alloc 的内存大小作为是否越界判断,故实际分配 size 可能大于申请 size,因此 asan 检测可能出现延迟触发报错提醒的情况。(例如申请大小为10,实际可能在写超到 index 24才报错)

实现原理简介

KASAN原理

进程的虚拟内存空间被ASAN划分为2个独立的部分:

  1. 主应用内存区 (Mem): 专门提供给普通APP代码内存使用区。

  2. 影子内存区 (Shadow): 该内存区仅ASAN感知,影子顾名思义是指该内存区与主应用内存区存在一种类似“影子”的对应关系。ASAN在将主内存区的一个字节标记为“中毒”状态时,也会在对应的影子内存区写一个特殊值,该值称为“影子值”。

这两个内存区需要精心划分,确保可以快速从主应用内存区映射到影子内存区(MemToShadow)。

主应用内存与影子内存Shadow bytes映射

KASAN将8字节的主应用区内存映射为1bit影子区内存。

针对任何8字节对齐的主应用区内存,总共有1种不同的影子内存值:

8字节中的有一个字节未“中毒”(可访问的),影子值是1。

8字节中的全部字节都“中毒”(不可访问的),影子值是0。

malloc原理

#include "mm_heap/mm.h"
struct mm_freenode_s
{
#if CONFIG_MM_BACKTRACE >= 0
  pid_t pid;                                /* The pid for caller */
#  if CONFIG_MM_BACKTRACE > 0
  FAR void *backtrace[CONFIG_MM_BACKTRACE]; /* The backtrace buffer for caller */
#  endif
#endif
  mmsize_t size;                            /* Size of this chunk */
  mmsize_t preceding;                       /* Size of the preceding chunk */
  FAR struct mm_freenode_s *flink;          /* Supports a doubly linked list */
  FAR struct mm_freenode_s *blink;
};

malloc()有两种申请内存的方式。

brk()

小于128KB的内存,往往是通过brk()申请,malloc 通过 brk() 方式申请的内存,free 释放内存的时候,并不会把内存归还给操作系统,而是缓存在 malloc 的内存池中,待下次使用;

mmap()

大于128KB的内存,一般是通过mmap()申请,malloc 通过 mmap() 方式申请的内存,free 释放内存的时候,会把内存归还给操作系统,内存得到真正的释放。

定义于 mm_hap/mm.h的相关宏

内容参考

利用ASAN在单片机上查找内存错误(英文)

tinyK22_FreeRTOS_ASAN

KASAN实现原理

kasan部分源码

Armv8.1-M architecture: PACBTI extensions - Architectures and Processors blog - Arm Community blogs - Arm Community

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: 您好!您想知道如何在 Android 设备上打开 KASAN 吗? KASAN(KernelAddressSANitizer)是一种 Linux 内核检测工具,用于检测内核代码中的内存访问错误。它是通过在内核启动时启用内存布局随机化(KASLR)和插入许多内存访问检查来实现的。 要在 Android 设备上使用 KASAN,您需要先编译内核并启用 KASAN 支持。这通常需要使用特定的内核配置选项来启用 KASAN,然后重新编译内核。具体来说,您需要在内核配置文件中启用以下选项: - CONFIG_KASAN - CONFIG_KASAN_INLINE 然后,您可以在内核启动时通过命令行参数启用 KASAN。具体来说,您可以在内核命令行中添加 "kasan" 选项来启用 KASAN。 例如,如果您使用的是 GRUB 引导程序,则可以在 /etc/default/grub 文件中的 GRUB_CMDLINE_LINUX 变量中添加 "kasan" 选项,然后运行 "update-grub" 命令重新生成 GRUB 配置文件。 希望这些信息能帮助您!如果您有其他问题,请随时联系我。 ### 回答2: KASAN(Kernel Address Sanitizer)是Android系统中用于检测内核地址错误的一种工具。 要在Android设备上打开KASAN,首先需要一个已经编译了KASAN的内核镜像。通常,你可以在Android源代码的内核目录中找到已经编译好的内核。之后,你需要按照以下步骤进行操作: 1. 首先,将已编译的内核镜像刷入你的设备。你可以使用adb工具将内核镜像传输到设备,并使用fastboot命令将其刷入设备的内存中。 2. 接下来,你需要启动设备进入bootloader模式。这可以通过按下设备特定的组合键进行操作。 3. 进入bootloader模式后,你可以使用fastboot命令来启动已刷入的内核镜像。例如,你可以运行以下命令: ``` fastboot boot <path_to_image> ``` 其中,`<path_to_image>`是你刷入的内核镜像的路径。 4. 内核启动后,你可以通过启用KASAN来调试和检测内核地址错误。可以通过在内核启动参数中开启KASAN选项来实现。这取决于你的设备和内核版本,你可以在启动命令中添加`kasan.enabled=1`或者`asan=1`参数来开启。 当KASAN被启用后,每次内核运行时,KASAN会检查和报告任何潜在的内核地址错误。这有助于发现和解决内核空间的地址错误问题,并提高系统的稳定性和安全性。 请注意,启用KASAN需要一定的技术和安全意识。在实践中,请确保你明白其影响和使用方法,并确保有备份和恢复的手段,以防意外或错误发生。 ### 回答3: KASAN(Kernel Address SANitizer)是Android内核的一个代码分析工具,用于检测和修复内核中的堆缓冲区溢出和使用未初始化的内存等问题。KASAN通过在内存中插入摘要信息和附加的元数据来实现,以对内存访问进行跟踪和检查。 要在Android设备上打开KASAN,首先需要确保设备的内核版本支持该功能。然后,按照以下步骤进行操作: 1. 在Android设备上访问开发者选项。可以通过连续点击设备的“设置”> “关于手机”> “版本号”几次来激活开发者选项。 2. 进入开发者选项后,找到并打开“调试”部分。 3. 在调试选项中,查找名为“开启KASAN”或“打开内核地址SANitizer”等类似选项。 4. 打开“开启KASAN”选项,如果需要,系统可能会要求输入密码或确认。 5. 如果一切顺利,系统将在后台配置KASAN并启动该功能。一旦完成,KASAN将开始监视和检测内核中的潜在内存问题。 请注意,启用KASAN可能会导致系统性能略微下降,并可能增加资源消耗。因此,建议只在需要分析和调试内核问题时才开启KASAN功能。此外,由于不同的Android设备和内核版本之间有所差异,上述步骤在不同设备上可能会有所不同。因此,在启用KASAN之前,建议查找设备的特定文档和指南,以确保操作的准确性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

repinkply

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值