APP下载

一种结合eBPF与KFENCE的Linux内核态内存漏洞检测方法的研究

2021-09-26中国船舶重工集团公司第七一六研究所王凯龙

电子世界 2021年16期
关键词:内核漏洞内存

中国船舶重工集团公司第七一六研究所 王凯龙

内存漏洞包括内存泄漏(Memory Leak)、重复释放内存(Double Free)和释放后读写(Use after Free),均源于内存的动态分配过程。内存泄漏是指应用程序运行过程中未及时将动态分配的堆区内存释放,导致可用内存持续减少,进而造成系统内存耗尽,运行缓慢甚至崩溃的严重问题。重复释放同一块内存、释放后读写会造成指针访问未知区域,这两种漏洞均会导致不可预测的结果。

Linux内核基于C语言编写,在具有高运行效率的同时也存在着较大的内存泄漏隐患。内核在管理内存资源的同时,也占用内存资源,不合理的使用可能会造成各种异常。

目前定位内存漏洞的方法主要有静态检测与动态检测。静态检测方法通过直接检视源码,可以较早发现问题,以较低的代价进行修复,但误报漏报的风险较大。动态检测方法通过插入检测代码到目标程序中,实时跟踪内存操作,可以得到较准确的检测结果。但目前多数动态检测方法不支持内存泄漏检测,且有概率引入新的安全风险,不适合在生产环境中大量使用。

eBPF技术是近年来linux系统领域的一个重大创新,具备较高的执行效率和生产环境安全性,支持用户可编程,加入系统后无需重复编译内核。将eBPF技术与内存漏洞动态检测方法相结合,可有效支持内存泄漏检测,并在保证检测准确性的同时有效降低对系统性能的影响。

1 原理和方法

1.1 eBPF/BCC

诞生于1992年的伯克利包过滤伯克利包过滤(Berkeley Bag过滤),可以免去内核到用户空间的无用数据包拷贝。BPF程序包含一个简单的字节码,可经用户空间注入内核,经过验证程序进行检查(防止内核崩溃或安全问题)后附加到套接字。BPF的语言简洁易用,同时BPF为编译而设计实现了内核即时(JIT)虚拟机,这是该工具的杰出特色。

2013年,BPF在原有基础上增加了map与tail call等新功能,性能也得到显著提高。修改后版本称eBPF,与经典BPF做区别。同时,JIT虚拟机被重写。eBPF比经典BPF更接近本机语言,且在内核中开放了新的挂载点,可以基于Event运行程序,非常高效,可支持内核内编程,并可以增强其他跟踪器。

eBPF在功能上做了较大拓展,可通过kprobe得到内核函数运行信息,无需额外加入插桩代码重新编译内核,也无需借助类似gdb的调试工具。除此之外可以即时获取代码执行当前的寄存器状态以及调用栈信息。其原理类似在指令中增加保存点,内核执行至此会自动保存当前寄存器状态与栈信息,然后进入断点处挂载的处理程序。程序执行完毕,内核返回到保存点位置,并将寄存器状态恢复。

BCC(BPF Compiler Collection)是基于eBPF的开发工具包。它封装了一系列高效的内核跟踪和操作接口,并提供了开箱即用的检测工具和Demo。BCC在eBPF提供的接口基础上进行封装,同时提供高级语言对应编程接口。

图1 eBPF运行流程图

1.2 内核态动态内存漏洞检测方法

KFENCE是一个低采样的内存错误检测工具,可以Patch形式编入内核。它根据采样间隔进行受保护的内存分配,采样间隔到期后,通过主分配器(SLAB或SLUB)进行的下一次分配将由KFENCE的对象池提供,同时重置计时器,等待到期后的下一次分配。每个KFENCE对象都驻留在专用页面上,对象页面左右两侧的页面是受保护页面,其属性为受保护状态,对它们的任何访问都会导致页面错误,KFENCE拦截此类页面错误并报告越界访问。在KFENCE对象被释放后,对象的页面将再次受到保护,并被标记为已释放,对该对象的任何访问都会导致故障。KFENCE拦截此故障,并报告use-after-free错误。

图2 KFENCE保护内存分布图

KFENCE牺牲了一定的检测精度换取了较小的性能开销,相比于与同类方法,更适合在产品环境中部署,用于检测内存漏洞。

2 基于eBPF/KFENCE的linux内核态内存漏洞检测方法

KFENCE检测方法可用于检查内存访问越界、重复释放和use-after-free问题,但无法检测内存泄漏问题,另外,仅支持内存监测,无法对内存错误做即时处理。本文通过加入eBPF模块,补足了内存泄漏检测功能,同时在KFENCE接口处挂载内存错误处理ePBF模块,对所报错误进行即时处理,可有效降低内存错误对系统运行造成的负面影响。

针对内存泄漏问题,Linux公开了用于内存分配的跟踪点,可以通过eBPF程序对其进行检测。本文采用的内存泄漏检测方法跟踪并匹配内存分配和重新分配请求,并收集记录每个分配的调用堆栈,最终可以打印一个概要,其中统计了调用堆栈申请后没有释放的内存数量。

方法流程如图3所示。

图3 基于eBPF/KFENCE的linux内核态内存漏洞检测方法流程图

(1)各线程的每次内存申请和释放均由eBPF模块记录,模块通过判断分配和释放操作的不匹配,定位出泄漏内存的调用栈。

(2)KFENCE按预设时间间隔进行采样,每次时间间隔到期后的下一次内存分配将从KFENCE对象池进行分配,对此块内存的操作将受到KFENCE的监控。

(3)若内存访问出现越界错误或释放后使用错误,系统抛出故障,由KFENCE接收,转交eBPF模块处理。

(4)内存占用期间由ePBF模块监控,可实时获取不同内核线程的内存占用情况,某线程内存占用持续增长达到阈值后报出内存泄漏风险。

(5)若内存释放出现重复释放错误,系统抛出故障,由KFENCE接收,转交ePBF模块处理。

3 验证测试

本次测试环境为x86平台,单CPU四核,4G内存,linux内核版本5.9.1。为更好体现本方法对系统响应时间的影响,预先加入内核实时补丁,版本为5.9.1-rt20。测试内容包括内存漏洞检测功能测试与检测方法对系统性能影响测试。

3.1 内存漏洞检测方法功能测试

本文选取了KFENCE测试集,并从内存漏洞测试集Juliet Test Suite中选取了CWE-401 Memory Leak的一部分移植至内核态用于功能验证。将本文提出的内存漏洞检测方法在该测试集中进行实验。

测试集具体信息如表1所示。

表1 测试集具体信息

3.2 检测方法对系统性能影响测试

测试关注的性能项为系统响应时间与内存占用率,本文选取的测试工具为开源测试工具rt-test和系统内存统计工具free。测试阶段分两次运行系统,一次执行检测,另一次不执行检测。系统响应时间记录1000000次,并统计响应时间分布情况,测试结果如表2所示。

表2 测试结果

3.3 测试结论

功能测试结果显示,本文提出的测试模块可以较准确地检测到各个种类的内核态内存漏洞。性能测试结果显示,测试模块对系统响应时间的影响保持在us级,未产生过大延迟,最大响应延迟增加3us,内存占用率提高0.07%,未对系统性能产生明显影响。

Linux内核中在具有高运行效率的同时也存在着较大的内存泄漏隐患,可能会引发不可预测的系统异常,有必要进行运行时的动态检测,但现有的动态检测方法不能较好的覆盖所有种类的内存漏洞,且对系统性能有一定的影响,不适合在生产环境中大量使用。本文提出了一种基于eBPF/KFENCE的linux内核态内存漏洞检测方法,经实验验证,该方法可以较准确地检测所有常见种类的内存漏洞,且对系统性能影响小,具有较高的实用价值。

猜你喜欢

内核漏洞内存
漏洞
强化『高新』内核 打造农业『硅谷』
“春夏秋冬”的内存
基于嵌入式Linux内核的自恢复设计
Linux内核mmap保护机制研究
三明:“两票制”堵住加价漏洞
漏洞在哪儿
微生物内核 生态型农资
高铁急救应补齐三漏洞
内存搭配DDR4、DDR3L还是DDR3?