76范文网为您提供各类范文参考!
当前位置:76范文网 > 知识宝典 > 范文大全 > 嵌入式系统内存破坏问题定位方法

嵌入式系统内存破坏问题定位方法

来源:76范文网 | 时间:2019-10-14 22:30:56 | 移动端:嵌入式系统内存破坏问题定位方法

嵌入式系统内存破坏问题定位方法 本文关键词:嵌入式系统,破坏,定位,内存,方法

嵌入式系统内存破坏问题定位方法 本文简介:Linux是当今应用最为广泛的服务器及嵌入式设备操作系统。作为一款开源通用操作系统,Linux具备多平台兼容性、多线程支持、多核支持、虚拟内存管理、良好的文件系统支持、丰富的硬件外设支持等特性。在消费级和企业级嵌入式设备中,Linux都扮演者重要的角色。在嵌入式系统开发中,通常涉及到Linux用户态

嵌入式系统内存破坏问题定位方法 本文内容:

Linux是当今应用最为广泛的服务器及嵌入式设备操作系统。作为一款开源通用操作系统,Linux具备多平台兼容性、多线程支持、多核支持、虚拟内存管理、良好的文件系统支持、丰富的硬件外设支持等特性。在消费级和企业级嵌入式设备中,Linux都扮演者重要的角色。在嵌入式系统开发中,通常涉及到Linux用户态的应用程序开发,以及内核态的设备驱动程序开发。如无线接入点设备,为了拥有网络通信能力,需要开发和适配无线网卡的内核驱动,同时又需要开发面向用户的Linux用户态应用。在内核驱动程序的开发过程中,自研或移植代码可能出现不规范的内存操作,出现内存越界访问,内存释放后重用等行为。由于内核内存缺乏保护机制,所有模块共用一个地址空间,因此上述的不规范操作通常会导致系统的数据被破坏、改写,引发系统崩溃。当前Linux内核支持一些内存问题的定位和调试手段,但对于复杂嵌入式系统中的改写问题,存在一定的限制。本文研究了当前的调试方法,并提出一种针对内核模块内内存监控和调试的改进方法,对于复杂内存改写问题,具有很好的改进作用。

1研究现状

当前应用在嵌入式Linux系统内核态的常用内存越界、改写的定位手段有以下5种(为了简化描述,本文限定在ARM32平台上)。

1.1Oops信息分析

内存改写通常会触发系统异常、崩溃。通过Linux的Oops调试信息可以分析导致崩溃的直接原因。但对于改写类问题,Oops调试信息中的堆栈和寄存器都不是源自第一现场,大部分情况是改写后的内存在下一次被使用时才会触发异常打印调试信息,因此这种方法分析出改写源头的成功率很低。

1.2DEBUG_PAGEALLOC

Linux的基本内存单元称为页(page),页的管理系统采用BuddyMemoryAllocation的算法,降低了碎片页产生的概率。内核中直接对于页的申请一般是针对大块的连续物理内存的申请,如Slab的内存池或网络设备收发的Buffer区域等。对于页的访问,BuddyAllocator提供了对于空闲页的监控功能。该调试功能会在内存释放回系统时修改对应内存的页表属性,将该区域置为不可访问。这样在有异常访问到这段空闲内存的时候就会触发MMU异常,抓取第一现场。ARM平台在Kernel4.6版本提供了对该功能的完整支持。此外,该功能有2个限制:①使能该功能会导致所有内存页按照4kB的粒度进行页表映射,以确保每个内存页的访问属性可以精细控制,这在一定程度上增加了TLB缺页交换的开销;②擅长空闲内存区域的监控和问题定位,对于模块内申请的内存区域不适用。

1.3SLAB_DEBUG/SLUB_DEBUG

SLAB/SLUB是构建于页管理系统之上的另一层内存管理系统,通常用于小块的物理内存的申请。SLUB是SLAB更新的一代的实现方式,优点是性能更好、扩展性更强,简化的数据结构使得管理的开销更小。SLUB和SLAB通过申请大块的物理页内存,构建用于申请不同大小内存块的内存池,提高了内存申请的效率和空间利用率。同时,SLUB也提供了丰富的调试支持。通过SLUB_DEBUG宏,可以在SLUB的关键数据结构中增加Redzone和Poisoning操作,用于定位区域内的越界改写问题以及UAF(use-after-free)问题,并能在监测到问题时提供消息的错误提示。但是这种调试方式也有限制:①不能用于监测越界读取的异常,只能监测越界改写;②只能在内存申请/释放的动作时对特定的内存区块进行监测,难以发现改写的第一现场,如果改写的内容不具备足够的规律,很难和特定的模块联系起来。

1.4Kmemcheck

可以用于监测UAF类型的错误,以及对未初始化内存的读操作。Kmemcheck能够准确定位到这些异常操作的源头,但是也有很大的使用限制。由于其实现的原理是在每次内存访问时产生pagefault异常,在异常处理中监测当前的访问是否合法,会带来巨大的处理开销;同时为了记录内存状态,会增加一倍的内存消耗。因此对于嵌入式设备来说,该手段可操作性差,一方面设备的计算能力有限,正常处理被严重拖慢,会影响系统的行为和问题的复现;另一方面大部分嵌入式系统没有那么充裕的空闲内存。

1.5KASAN

KASAN(KernelAddressSANitizer)比上述几种调试方式出现的更晚。它利用了GCC编译器的特殊调试功能,可以在每次内存访问前插入检查程序。它提供了相对快速和全面的内存异常访问行为的调试手段。相比Kmemcheck,KASAN优势有:可以全面地对堆栈或全局变量的溢出、UAF、User-memory-access问题进行监控;运行速度比Kmemleak快,Kmemleak的开销为10倍,KASAN仅为1.5倍。但是KASAN也有限制:①内核版本(Kernel4.x)和工具链版本(GCC5.0)的要求。因为该功能需要借助新版本工具链才具备的调试功能;②内存空间要求,KASAN需要构建影子(shadow)内存区域来跟踪和监控内存的访问情况,约需要消耗1/8的系统内存,对于部分小的嵌入式系统是一个挑战;③当前仅支持X86和ARM64系统,缺乏对ARM32的支持。上述5种手段是当前定位内核内存异常问题时的常用手段。可以看到,每种方法都有自己的特点和限制,在定位特殊问题时可能存在不足。本文介绍的MMUTRAP方法,就是在项目实践中开发出来的内存调试手段,弥补了其他方法的部分不足。实践证明对于一些特定的内存问题调试起到了很好的作用,具备良好的可靠性和扩展性。

2原理介绍

MMUTRAP利用MMU控制器对内存地址的访问控制功能,与DEBUG_PAGEALLOC的基本原理类似,如图1所示。ARM32平台上,当启用MMU功能后,所有的虚拟地址或逻辑地址的访问从CPU发出后,都会经过MMU的地址翻译,转换成物理地址。(1)当TLB中有缓存当前访问的虚拟地址的表项时,即TLBhit,可以直接转换物理地址。(2)当TLB中没有找到虚拟地址对应的表项,即TLBmiss,此时MMU需要重新访问内存中的多级页表(pagetable)数据结构找到对应虚拟地址的表项,从而转换出物理地址,并将该页表项缓存到TLB中。MMU在通过页表转换物理地址时,会检查页表数据结构内的AP字段,该字段用于表示对应内存区域的访问权限。例如,在ARMCortex-A平台上,AP字段为0时表示不能被读/写,此时如果CPU对于该地址的访问会触发MMU的exception,通过exception信息可以获取到访问改地址的模块,如图2所示。MMU-TRAP在内核中构建了一个用于监控的内存链表,链表上每个entry为一个4kB大小的内存页。内存页在入队后,将其对应页表的AP字段置为不可访问,从而形成对其的监控;内存页出队前,将AP字段置为正常,释放回内核。链表的大小可以根据需要和系统空余内存的大小灵活调整。当某个模块访问了监控链表中的内存时,系统会抛出MMU异常信息,其中包含异常访问的栈回溯及寄存器信息,可以精确定位异常访问的源头。

3应用实例

3.1辅助DDR硬件问题定位

在某嵌入式设备项目中,设备在大规模试运行时出现极低概率的内存数据破坏现象,导致内核程序及用户程序崩溃。由于设备已经通过了常规的硬件及内存的信号测试,所以初期定位方向锁定在软件改写类问题。从内核崩溃的Oops信息的统计分析来看,改写的范围不存在固定规律,不能锁定改写的模块;DEBUG_PAGEALLOC调试方式由于ARM32平台不支持且Kernel3.x不支持,无法直接使用;通过搜集SLUB_DEBUG的调试信息可以发现改写存在一定的Bit规律,但是无法联系到具体的模块;Kmemcheck调试方式对系统的运行速度影响太大,且耗费太多内存,即使在清空非必要模块勉强运行后,也由于过慢而无法正常复现问题;而KASAN调试方式不支持ARM32平台,且当时设备是用的Kernel3.x也不符合要求;由于复杂度过高,自行移植KASAN到ARM32的尝试也以失败告终。经过长时间的问题复现和分析后,未能分析定位出改写的源头。但是通过统计分析,发现改写的位置十分随机,普通的模块越界和指针错误不太容易有这么广的范围;同时改写的内容存在一定的Bit规律,而代码的反复排查没有发现类似的规律。此时,问题的排查陷入了困境,需要一种轻量且可靠的定位技术来给出更多的线索。在这样的背景下,首次导入了MMUTRAP方法。通过反复的实验,首先证明了MMUTRAP检出问题的可靠性,不会出现对监控区域内存改写的误报或者遗漏的问题。通过导入MMUTRAP并大规模复现,最终发现被监控的内存区域中确实出现了数据的变化,但是却没有触发MMU异常。说明此时的数据变化源自硬件层面,如DDR自身的问题,或者DMA异常导致的改写。最终该问题被查明是某厂的DDR芯片存在自刷新是的缺陷,导致了数据变化。MMUTRAP在该例中起到了关键性的指导作用。

3.2定位网络设备转发处理问题

嵌入式网络设备,如路由器设备,需要进行大量的报文解析和转发的处理。这些处理通常在内核的网络协议栈中完成。对报文的不当解析或处理往往会导致越界,Buffer改写等问题。在某项目中,内核中的报文转发缓存区出现低概率的破坏现象。但由于改写的内容没有分析出规律性;对缓冲区的改写也不会引发直接的异常,Oops信息提供的现场不能提供有效的信息;DEBUG_PAGEALLOC只能监控空闲内存区域,对于已申请的业务内存区域不适用;其他的几种调试方法也不适用于当时的平台或场景。问题的定位缺乏头绪。通过导入MMUTRAP方法,将发送队列或缓存队列中的部分缓冲区加入到监控链表中,可以有效地对业务相关的内存进行监控。在简单修改相关代码后,通过测试复现很快定位到了异常改写缓冲区的代码段。在分析改写源头的代码后,问题很快得到了解决。

4结语

通过理论分析和反复的项目实践,证明MMUTRAP方法有良好的可靠性,能够准确检出异常改写的源头,具有易移植、易扩展的特点,在运行期的运算和内存开销低,易于部署和实施。适用于ARM32或ARM64平台的各种嵌入式系统中内核内存改写问题的辅助分析。同时由于其轻量的特点,可以长期运行于系统中,对于研发过程中的稳定性问题暴露、风险控制也有积极的作用。

作者:王靖天

嵌入式系统内存破坏问题定位方法  来源:网络整理

  免责声明:本文仅限学习分享,如产生版权问题,请联系我们及时删除。


嵌入式系统内存破坏问题定位方法》由:76范文网互联网用户整理提供;
链接地址:http://www.yuan0.cn/a/116985.html
转载请保留,谢谢!