博客
关于我
宋牧春: Linux内核内存corruption检查机制KASAN实现原理
阅读量:88 次
发布时间:2019-02-26

本文共 2189 字,大约阅读时间需要 7 分钟。

KASAN动态内存检测工具介绍

KASAN(Kernel Address Sanitizer)是一种动态检测内存错误的工具,专为检测内核中的use-after-free(UAF)和out-of-bounds(OOB)问题而设计。其核心原理是通过在内存访问时插入额外的检查代码,确保每次内存操作都在合法范围内进行。KASAN能够检测全局变量、栈和堆分配的内存越界访问,是一种功能强大的内核安全工具。


1. KASAN的功能与优势

KASAN的主要优势包括:

  • 全面性:能够检测多种内存错误类型,包括越界访问和释放已释放内存(UAF)。
  • 实时性:在内核运行时即时检测内存问题,无需停止系统运行。
  • 无缝集成:通过编译器插入检查点,适用于内核开发环境。
  • 兼容性:支持多种内核架构,包括ARM64和x86_64。

  • 2. KASAN的工作原理

    KASAN通过以下机制实现内存检测:

  • Shadow Memory:KASAN将1/8的内核地址空间划为shadow memory,用于记录内存访问情况。
  • 检测机制:在每次内存访问(load/store)前,编译器插入检查代码,验证对应的shadow memory值是否合法。
  • 内存标记:编译器为内存分配标记redzone区域,记录内存的可用状态。
  • 异常处理:当检测到越界访问或UAF时,记录错误信息,并由后续处理机制进行修复或报警。

  • 3. KASAN的配置与使用

    为了启用KASAN,需在内核配置中设置以下参数:

    CONFIG_SLUB_DEBUG=yCONFIG_KASAN=y

    3.1 为什么启用SLUB_DEBUG?

    KASAN最初依赖SLUB_DEBUG,但现在已不再依赖。启用SLUB_DEBUG可提供额外的日志信息,有助于调试和排查错误。建议在开发阶段保留该选项。

    3.2 编译内核

    启用KASAN后,重新编译内核。编译完成后,内核镜像大小会略微增加,但这只是为了检测内存错误而付出的代价。

    3.3 查看检测结果

    在内核运行时,KASAN会记录检测到的错误信息到内核日志中。可以通过查看dmesg输出,分析具体的内存错误类型和位置。


    4. KASAN的内部实现

    KASAN的核心逻辑主要集中在mm/kasan/kasan.c文件中。

    4.1 检测内存访问合法性

    KASAN通过以下步骤检测内存访问:

  • 加载检查:在每次内存加载操作前,调用__asan_load##size()函数,验证对应的shadow memory值。
  • 存储检查:在每次内存存储操作前,调用__asan_store##size()函数,验证写入的地址是否合法。
  • shadow memory计算:根据访问字节数N,判断shadow memory值是否有效。例如:
    • 0:表示8字节内存均可访问。
    • 1-7:表示部分字节可访问。
    • 负值:表示越界访问。
  • 4.2 shadow memory的分配

    KASAN将内核地址空间划分为8部分,每部分用于shadow memory。具体分配方式如下:

  • 映射关系:shadow memory地址通过公式shadow_addr = (kaddr >> 3) + KASAN_SHADOW_OFFSET与内核地址映射。
  • 初始值:shadow memory区域初始值为0,表示内存可用。

  • 5. 内存分配与KASAN的配合

    KASAN与内存分配器(如SLUB、伙伴系统)紧密配合,确保内存分配和释放过程中的每一步都可检测。

    5.1 伙伴系统内存分配

    伙伴系统在分配内存时,会记录shadow memory值。例如,分配4页内存时,shadow memory值初始化为0,表示内存可用。

    5.2 释放内存

    当释放内存时,KASAN将对应的shadow memory值标记为0xFF,表示内存已释放。若继续访问此区域,可检测到use-after-free错误。

    5.3 全局变量处理

    全局变量的redzone填充方式类似于内存分配。例如,定义char a[4];时,编译器会自动填充redzone区域,并记录shadow memory值。


    6. 栈分配变量的检测

    栈分配变量的redzone检测与全局变量类似。例如:

    void foo() {    char a[328];    char rz1[32];    char rz2[56];    int *shadow = (rz1 >> 3) + KASAN_SHADOW_OFFSET;    // 编译器会自动填充shadow memory值}

    7. 错误日志解读

    KASAN的错误日志通常包含以下信息:

  • 错误类型:如use-after-freeout-of-bounds
  • 对象信息:涉及的内存对象地址和大小。
  • Call Trace:错误发生时的调用链。
  • shadow memory状态:如0xffff800012345678的值。
  • 通过分析这些信息,可以快速定位内存问题的位置和原因。


    8. 参考文献

  • 如何在OpenStack环境中使用KASAN检测内存错误
  • Kernel Address Sanitizer (KASan)快速内存错误检测工具

  • KASAN为内核开发提供了强有力的内存安全保障。通过配置和使用KASAN,开发者可以快速定位和修复内存相关的安全问题,提升内核系统的稳定性。

    转载地址:http://yrnz.baihongyu.com/

    你可能感兴趣的文章
    Objective-C实现factorial阶乘算法(附完整源码)
    查看>>
    Objective-C实现factorial阶乘算法(附完整源码)
    查看>>
    Objective-C实现Factors因数算法(附完整源码)
    查看>>
    Objective-C实现Farey Approximation近似算法(附完整源码)
    查看>>
    Objective-C实现Fast Powering算法(附完整源码)
    查看>>
    Objective-C实现Fedwick树算法(附完整源码)
    查看>>
    Objective-C实现fenwick tree芬威克树算法(附完整源码)
    查看>>
    Objective-C实现FenwickTree芬威克树算法(附完整源码)
    查看>>
    Objective-C实现fermat little theorem费马小定理算法(附完整源码)
    查看>>
    Objective-C实现FermatPrimalityTest费马素数测试算法(附完整源码)
    查看>>
    Objective-C实现fft2函数功能(附完整源码)
    查看>>
    Objective-C实现FFT快速傅立叶变换算法(附完整源码)
    查看>>
    Objective-C实现FFT算法(附完整源码)
    查看>>
    Objective-C实现fibonacci search斐波那契查找算法(附完整源码)
    查看>>
    Objective-C实现fibonacci斐波那契算法(附完整源码)
    查看>>
    Objective-C实现fibonacci斐波那契算法(附完整源码)
    查看>>
    Objective-C实现FIFO(附完整源码)
    查看>>
    Objective-C实现FigurateNumber垛积数算法(附完整源码)
    查看>>
    Objective-C实现finding bridges寻找桥梁算法(附完整源码)
    查看>>
    Objective-C实现first come first served先到先得算法(附完整源码)
    查看>>