非侵入式故障注入技术研究与实现*

2017-03-15 02:45杜阳华
指挥控制与仿真 2017年1期
关键词:调用应用程序内存

杜阳华

(江苏自动化研究所,江苏 连云港 222061)

非侵入式故障注入技术研究与实现*

杜阳华

(江苏自动化研究所,江苏 连云港 222061)

可靠性验证过程需要模拟一些较为苛刻的测试场景,如出现网络带宽受限、内存过载、文件拒绝访问等故障类型,而传统方法常常会对系统资源或被测软件造成破坏或影响。在Windows 环境下利用Detours的截获机制研究了三种非侵入式故障注入技术,对常见的资源故障进行模拟。然后,设计开发了一款故障注入工具,能够快速自动地在软件测试或可靠性验证中实施故障注入试验,最后,通过试验验证了软件实现的正确性和功能的适用性。

非侵入式;故障注入;测试场景仿真;截获调用;故障注入工具

故障注入技术是指按照选定的故障模型,用人工的方法有意识地产生故障并施加于特定的目标系统中,观察记录被测系统对故障检测及隔离的结果,并对试验数据进行统计分析,进而给出被测系统测试性评估结果[1]。故障注入作为一种灵活方便、便宜有效的方法,可广泛应用于计算机系统容错性、可靠性的测试与评价领域。常用的故障注入技术主要有三种[2-4]:仿真故障注入、硬件故障注入和软件故障注入。其中,软件故障注入作为一种比较成熟的评测系统可靠性的关键技术,以其对硬件无损伤、易实现、易移植等特点,引起众多工程设计者和研究人员的重视。国外较为常见的软件故障注入技术主要有:可注入处理器或内存故障的Xeption[5]和HYBRID[6];可注入网络或通信故障的ORCHESTRA[7]和FTAPE[8];可注入输入错误的Ballista[9]和Fuzz[10];可模拟操作系统环境扰动的Holodeck[11]和FIG[12];直接向源代码中注入错误的思想[13]。

除了在软件可靠性领域得到广泛的应用之外,故障注入技术在软件测试验证领域的应用具有更深刻的影响和意义。软件测试过程中往往需要模拟一些较为苛刻的测试条件以验证被测系统的稳定性,如文件读写、内存分配及网络访问等资源类故障。而传统的强制关机方式、硬件故障注入方式、被测软件代码等方式不仅会对系统的硬件器件造成损伤,而且会影响计算机系统内存资源及其它软件程序。更为重要的是,难以满足被测软件尤其是可靠性安全性要求较高的软件对测试环境的精确性要求,如以100Kbps/s读写网络数据,文件读写时间超过10分钟等场景。

潘庆和[14]等人在Windows环境下利用Detours库对截获的系统调用注入故障,模拟各种文件系统错误,却没有研究如何解决上述的一些测试场景构建问题。本文正是在此基础上利用Windows下Detours库提供的系统调用截获机制,在不破坏系统资源且不改变被测软件代码的情况下模拟文件、内存、网络等资源故障,并开发出一款资源故障注入工具,辅助故障注入过程中场景的构建。

1 可注入故障类型分析

为了研究故障注入技术,需要研究软件的失效机理,并根据失效机理总结可注入的故障层次和故障类型。

1.1 软件失效原理分析

软件缺陷是指存在与软件中、不期望的或不可接受的偏差,以静态的方式存在于软件内部。当软件运行于某一特定环境或接收特定的输入时,该软件缺陷会被激活,若软件设计过程中未考虑相应的容错机制,则该缺陷将会导致软件发生失效,如图1所示。

图1 软件失效机理示意图

为了尽可能多地发现软件内部潜藏的缺陷以触发软件发生失效,需要模拟各种可能的输入或操作。因此,需要从软件架构及软件运行环境出发,分析软件运行过程中所有可能的输入,并实施故障注入测试。

1.2 故障注入层次及类型分析

根据软件的体系架构及软件运行环境分析可知,软件所有的输入层次可分为界面操作层、函数/组件调用层、系统资源访问层、硬件层和网络层等层次,如图2所示。

图2 故障注入层次图

1)人机界面操作层

人机界面是软件接收外部输入的主要接口。用户通过界面可以输入任何不可控的数据,因此,对人机界面输入或操作进行故障注入较容易发现程序中潜藏的缺陷。由于该类故障注入较易实现,因此,不属于本文的研究对象。

2)函数/组件集成层

软件系统由许多配置项(CSCI)集成而来;每个配置项实现一组独立的功能,且配置项由多个独立的软件部件(CSC)集成而来;而部件是多个单元(CSU)组装后的结果。由于大型软件集成了很多的小单元、小部件,集成过程错综复杂,当某个单元或模块出错时,可能引发多处错误。所以有必要对集成过程进行故障注入,模拟某单元或部件出错时,软件是否能够正确可靠地运行。据研究文献统计,在对1200个软件缺陷进行因果关系分析后,得出软件中组件内部故障、组件功能故障和组件外部接口故障分别占10% 、30%和60%。由于软件组件化技术的应用,软件开发周期的后续阶段中组件接口故障相对于其他类型故障占据主要地位。

3)系统资源访问层

应用软件运行的基础平台由操作系统、驱动程序和CPU等资源组成。应用软件通过调用操作系统的API接口、内存、寄存器等软硬件资源以完成不同的计算任务。因此,CPU、驱动程序、操作系统发生故障都有可能影响应用软件的正常运行。所以,对应用软件进行测试时,需模拟基础平台故障注入,验证应用软件的容错能力。

4)网络层

网络的广泛应用使得软件之间的数据交互变得更为频繁。网络传输的可靠性由通信设备及网络模块保障。对数据传输性能有较高要求的软件系统来说,如果网络受到其他因素干扰影响信息传递的及时性,极有可能导致软件的运行偏离预期行为。因此,为了提高应用软件的可靠性和稳定性,需要注入网络层故障。

综上所述,本文研究的故障类型包括3个层次、15种故障,不同故障类型所对应的实现机制如表1所示。

表1 故障注入技术实现机制

软件故障注入的目标可以是应用程序或操作系统。如果目标为应用程序,故障注入程序插入到应用程序中或作为应用程序和操作系统之间的一层。如果目标是操作系统,注入程序只能嵌入到操作系统中[15]。本文研究对象是应用程序,且故障注入程序处于应用程序和操作系统的中间层,而不会改变应用程序本身,因此属于非侵入式注入方式。

2 非侵入式故障注入技术

2.1 基于系统API返回值截获的资源类故障注入技术

为了不对实际的系统资源产生任何影响,本文采用一种“欺骗”应用程序的方式实现内存、文件、网络等系统资源的故障注入。当应用程序访问系统资源时,通常需要调用Windows提供的各种系统API函数,故障注入正是截获实际的API调用,并按照故障类型直接向应用程序返回资源访问结果。该方法不修改被测软件的源码,而是通过重写系统API对应的二进制映像,并将系统调用截获转向自定义的函数中,从而实现故障注入,与传统的故障注入技术相比,既不会修改软件代码,又不会对硬件资源产生影响,其具体实现机理如图3所示。

图3 资源类故障注入机理

截获调用是由Win32下Detours库提供的一种系统调用截获机制。Detours定义了三个概念:

① Target函数:要截获的函数,即Windows的API;

② Trampoline函数:目标函数的复制品,在Detours改写目标函数前,需要先将目标函数复制保存,一方面仍然保存目标函数的过程调用语义,另一方面便于恢复;

③ Detour函数:用以替代目标函数的自定义函数。

Detours用一个转向用户自定义Detour函数的非条件跳转指令取代目标函数的前几条指令(共5个字节)。此时,Trampoline函数由两部分构成:一部分是从目标函数中移除的指令,另一部分是指向目标函数剩余部分的非条件跳转指令。

当执行至目标函数时,将自动跳转至用户自定义的Detour函数,Detour函数可以直接返至应用程序,或者可以调用Trampoline函数,该函数将调用原始的目标函数,当目标函数完成,它将控制权返还给Detour函数。Detour函数执行适当的处理并且将控制权返回给应用程序。其具体截获调用过程如图4所示。

图4 Detours库截获应用程序调用过程

事实上,系统API的截获和跳转是Detours库自动实现的,因此,研究故障注入技术的关键步骤是定义自己的Detour函数。根据实现的具体方式不同,可将Windows下的故障分为基于返回值错误代码的故障注入技术和基于Sleep函数的故障注入技术两类。为了便于区分,命名时所有真实的Win32 API统一定义为Real-,其对应的Detour函数定义为Mine-

1)基于API返回值错误代码的故障注入技术

该故障注入技术的实现过程中,应用程序并不需要调用真实的API,而是在Detour函数中模拟系统函数向应用程序返回一个故障代码。

本文以注入读文件故障为例,真实的读文件API为Real-ReadFile,其对应的Detour函数Mine-ReadFile,Mine-ReadFile的部分代码如下所示。

BOOL WINAPI Mine-ReadFile(

HANDLE hFile,LPVOID pBuffer, DWORD nNumberOfBytes, LPDWORD lpNumberOfBytes, LPOVERLAPPED lpOverlapped

)

{

DWORD error;

BOOL rv;

… …

∥模拟文件读故障

error=

evaluateReadFileFaults(handle2name(hFile), NULL);

SetLastError(error);

return false;

}

事实上,Mine-ReadFile中并没有直接调用真实的Real-ReadFile,而是通过直接向应用程序返回false,即意味着应用程序进行读文件时发生错误。类似可模拟故障包括文件打开故障、文件写故障、内存分配故障等故障类型。

2)基于Sleep函数的故障注入技术

基于sleep函数的故障注入技术可以实现的故障类型包括文件过大、网络数据读写带宽受限等类型。与基于API返回值故障代码的故障注入方式不同,基于Sleep函数的故障注入技术需调用真实的系统API,并利用Sleep函数实现延迟效果,间接模拟出各类带宽受限故障。

本文以发送网络数据的带宽受限故障为例,真实的API为Real-send,其对应的Detour函数Mine-send,Mine-send的部分代码如下所示。

int WINAPI Mine-send(SOCKET a, char* b, int netWRdata, int t)

{

int rv;

… …

∥模拟发送网络数据的带宽受限故障

rv=Real-send(a, b, netWRdata, t);

DWORD time=(DWORD)((float)(netWRdata)/netWRBandwidth);

Sleep(time);

return rv;

}

在上述代码中,Detour函数首先调用真实的系统函数Real-send完成网络数据的发送,然后计算出在限定带宽下发送网络数据所需的时间,并利用Sleep函数实现延迟的效果。读文件所需时间的计算公式为:

time=netWRdata/netWRBandwidth

其中,netWRBandwidth代表用户设置的带宽大小,netWRdata代表文件的大小。因此,可以通过延迟读写文件的时间模拟出文件过大的故障现象。

2.2 基于符号表的内存扰动故障注入技术

代码故障注入技术是利用编译器生成的符号表来实现故障注入。符号表是一种用于编译器中的数据结构,符号表中保存程序源代码中的每个标识符及其声明、使用信息,如数据类型、作用域及内存信息,如图5所示。

通过在软件运行期间,根据内存地址动态修改被测软件源代码的全局变量、函数参数、函数返回值方式实现故障注入,其具体过程如图6所示。

图5 gcc符号表示例

图6 基于符号表的故障注入思路

步骤1:根据故障注入的需要,制定类符号表模板

符号表为存放源程序中出现的有关名字的属性信息的文件,属性信息反应了名字的语义特征属性,符号表中包含编译时节点的各种属性,包括类型、作用域、分配空间大小、函数的参数类型等;

根据故障注入的需要,只需要符号表中的部分信息,包括:函数/变量与内存地址的对应关系以及占用内存空间的大小;

类符号表模板为二维表模型,包括序号、过程标识、标识符名称、地址和符号类型;

需要根据类符号表提取的信息包括:待注入故障的变量及函数的标识、地址、类型;其中,要求标识能在被测软件类符号表中唯一地标识一个函数或变量;通过读取符号表,地址、类型可以直接确定,对于过程中存在的重名变量或函数,不同符号表由不同的组织方式,需要两个字段来唯一地确定。

步骤2:根据类符号表模板建立类符号表

类符号表模板是为实现快速查询符号信息而建议的统一数据格式,要对被测软件实施故障注入,需要解析源符号表,把可用信息解析成符合类符号表模板的格式,生成类符号表。

从分表结构的符号表到类符号表需要满足如下条件:

R1:对符号表取唯一标识对应类符号表模板中的过程标识;

R2:将符号表填充到类符号表的过程标识列,遍历该符号表,取标识符名称填充到类符号表中的标识符名称列,取标识符类型填充到类符号表中的符号类型列,取地址填充到类符号表中的地址列;

R3:当类符号表中增加一条数据时,类符号表中的序号自增;

R4:类符号表中的过程标识列不可为空。

从单表结构的符号表到类符号表需要满足如下条件:

R1:遍历符号表中的所有标识符,当类符号表中增加一条数据时,类符号表中的序号自增;

R2:取标识符名称填充到类符号表中的标识符名称列,取标识符类型填充到类符号表中的符号类型列,取地址填充到类符号表中的地址列;

R3:符号表中层次填充到类符号表中的过程标识列。

通过遍历被测软件符号表的方法,根据以上制定的填充规则,填充类符号表模板,生成被测软件的类符号表。

步骤3:根据故障注入四元组建立类符号表对应的故障模型;其中四元组包括故障类型、故障持续时间、故障位置和故障触发条件

采用四元组来描述故障模型:故障类型(M)、故障持续时间(D)、故障位置(L)和故障触发条件(T),故障模型表示为:(M,D,L,T);

故障类型(M)包括:对指定的变量、函数参数以及返回值取反、置零、置1、与设定的掩码进行与/或运算;

故障持续时间(D)包括两种形式:时钟时间,以ms为单位,从触发后开始计时;两个事件发生的间隔时间,第一个事件发生时,故障注入触发,记为开始事件,第二个事件发生时,故障注入结束,记为结束事件,持续时间为结束事件发生时刻减去开始事件发生时刻得到的时间差;

故障位置(L)通过查找类符号表确定;L为一个地址范围,通过查询条件“过程标识”和“标识符名称”唯一地检索到符号表中某条记录的“地址”字段,该字段即为L的起始地址,由于各符号存在不同的数据类型,占用的内存空间大小不一,所以还需要检索类符号表中的符号类型,作为确定L地址范围的依据;

故障触发条件(T)包括两种方式:时间和事件;当故障触发条件(T)为时间时,故障持续时间(D)为时钟时间;当故障触发条件(T)为事件时,故障持续时间(D)为两事件之间的时间间隔。

步骤4:根据类符号表对应的故障模型,通过查找类符号表,确定冗余空间大小和注入故障后软件的运行路径,实现故障注入。

采用更改被测软件运行时内存访问路径的方式,实现故障注入。故障注入机制如下:

1) 根据故障模型中的故障位置,在内存中开辟一段冗余内存空间,大小与故障位置中的符号类型相符;

2) 根据故障模型中的故障类型,在新开辟的冗余内存空间中填写设定的故障值;

3) 改变被测软件的运行路径,用冗余内存空间替代源内存空间;当CPU加载故障位置中指定的地址指令时,改变被测软件运行路径,访问冗余内存空间,之后跳转回源路径。

3 故障注入工具的设计与实现

3.1 故障注入工具框架设计

基于上述技术研究,本文开发实现了一款非侵入式故障注入工具,该工具由FIM(Fault Injection Manager)和FIK(Fault Injection Kernel)两部分组成。

其中,FIM的设计遵循MVC架构,并且以插件形式嵌入在Eclipse平台中运行。FIM的界面如图7所示。

图7 FIM主界面图

FIK是一个使用C/C++开发,仅有20K左右的轻量级软件。FIK运行在被测设备上,可在FIM的控制下向被测软件进行故障注入。FIK包含FIKLauncher和FIKDLL两部分,其中,FIKLauncher为FIK界面,负责与FIM建立连接并通信;FIKDLL为FIK的核心程序,用于实现具体的故障注入。FIKLauncher界面如图8所示。

图8 FIKLauncher界面

FIM与FIK之间通过以太网进行通信,交互信息采用XML的形式。FIK启动后向FIM发出连接请求,由FIM确认后将需要注入的故障信息发给FIK。

3.2 故障注入实例

软件测试不仅要验证正常情况下软件的实现是否正确,更应该验证错误输入或非法操作时,软件的异常处理能力,将故障注入机制引入软件测试可以有助于提高软件的稳定性和健壮性。

JariFI可以注入文件、内存、网络、进程等数十种故障类型,实例验证时逐一对各种故障进行实验和验证,由于篇幅所限,表2中仅显示了文件访问故障、文件读写带宽受限两类故障注入试验的记录,使用故障注入工具向被测程序resource-test.exe注入上述两类故障,具体过程如表2所示。

表2 故障注入试验记录

试验数据表明, 故障注入工具的实现是正确的,另外,在对被测程序进行故障注入时,我们同时打开Windows中的notepad.exe,并无异常现象,由此可以说明文中研究提出的故障注入技术仅仅对被测程序有效,而不会影响到系统中的其它软件程序,即故障注入的范围得到有效控制,这也是JariFI与其它同类故障注入工具相比的优势之一。

4 结束语

故障注入技术不仅可以广泛应用于软件可靠性、容错性评估验证领域,还可以应用于软件测试领域,以模拟一些手工方式难以控制或实现的测试条件。本文利用研究提出了三种系统资源故障注入技术,并详细叙述了如何利用Detours库的截获机制来模拟文件读写错误、网络数据读写带宽受限故障、内存过载故障等资源访问故障,且并不会对实际的系统资源和被测软件代码产生破坏。最后,开发了一款故障注入工具JariFI,可以辅助测试人员自动实现各类资源故障注入过程。本文的研究成果可以辅助开发人员、测试人员进行软件测试及可靠性验证,具有一定的现实指导意义。

未来可以从以下两个方面对故障注入工具展开进一步的研究:

1)事实上,每一个系统API或API的组合都可以对应一类可注入故障,只要该故障具有实际的应用场景及价值。

2)故障触发机制是控制故障注入过程的核心,JariFI中提供了事件和时间两种故障触发机制,事件类型及多事件间的顺序控制有待进一步研究。

[1] Jarboui T Alart J, Crouzet Y, et al.Experimental Analysis of the Errors Induced into Linux by Three Fault Injection Technology[C]. IEEE Proceedings of the International Conference on Dependable Systems and Networks, 2002:6-11.

[2] Barbosa R, Silva N, Duraes J, Madeira H. Verification and Validation of (Real Time) COTS Products Using Fault Injection Techniques[C]. Proc. of the 6th Int’l IEEE Conf. on Commercial-off-the-Shelf (COTS)-Based Software Systems (ICCBSS 2007). Los Alamitos: IEEE CS, 2007: 233-242.

[3] Lopez-Ongil C, Entrena L, Garcia-Valderas, et al. A Unified Environment for Fault Injection at Any Design Level Based on Emulation[J]. IEEE Trans. On Nuclear Science, 2007, 54(4): 946-950.

[4] Blanc S, Gracia J, Gil P J. A Fault Hypothesis Study on the TTP/C Using VHDL-Based and Pin-Level Fault Injection Techniques[C]∥Proc. of the 17th IEEE International Symposium on Defect and Fault Tolerance in VLSI Systems. Los Alamitos: IEEE CS, 2002: 254-262.

[5] Carreira J, Madeira H, Silva J G. Xception: Software Fault Injection and Monitoring in Processor Functional Units[J]. IEEE Trans on Software Engineering, 1998, 24(2):1-25.

[6] Young L T, Iyer R K, Goswami K K, et al. A Hybrid Monitor Assisted Fault Injection Environment[C]∥The Third IFIP Working Confernce on Dependable Computing for Critical Application, 1992.

[7] Dawson S, Jahanian F, Mitton T. ORCHESTRA: A Probing and Fault Injection Environment for Testing Protocol Implementions[C]∥Proceedings of IEEE International Computer Performance and Dependability Symposium, 1996: 56.

[8] Tsai T K, Iyer R K. Measuring Fault Tolerance with the FTAPE Fault Injection Tool[C]∥Proceedings of the Eighth International Conference on Modeling Techniques and Tools for Computer Performance Evaluation. 1995: 26-40.

[9] Kropp N P, Koopman P J, Siewiorek D P. Automated Robustness Testing of Off-the Shelf Software Components[C]∥Proceedings of the 28th International Symposium on Fault-Tolerant Computing, 1998:464-468.

[10]Miller B P, Fredriksen L, So B. An Empirical Study of the Reliability of UNIX Utilities[J]. Communications of the ACM, 1990, 33(12):32-44.

[11]Center for Software Engineering Research[EB/OL]. Holodeck. http:∥se.fit.edu/holodeck/, 2002.

[12]Broadwell P, Sastry N, Traupman J. FIG: Fault Injection in Glibc[C]∥In Workshop on Self-Healing, Adaptive, and Self-Managed Systems (SHAMAN), New York, 2002.

[13]Barton J H.Fault Injection Experiments Using FIAT[J].IEEE Transactions on Computers,1990,39(4):575-582.

[14]潘庆和. 软件故障注入关键技术研究[D]. 哈尔滨:哈尔滨工业大学,2011.

[15]潘庆和. 基于软件的故障注入方法研究[D]. 哈尔滨:哈尔滨工业大学,2005.

Research and Implementation of Non-Intrusive Resource Fault Injection Tool

DU Yang-hua

(Jiangsu Automation Research Institute, Lianyungang 222061, China)

There are some traditional methods to simulate those falults, but these methods often make damage on the system resource or the code of the SUT. Using the interception service of Windows system, non-intrusive resource fault injection methods are proposed to simulate some common resource faults. Then, a fault injection tool named JariFI is designed and it can inject faults needed in software testing and reliability evaluation。At last, the accuracy and the function applicability about the software are verified by the experiment.

non-intrusive; fault injection; simulation of testing scenario; intercept call; fault injection tool

2016-11-03

总装备部“十二五”预研项目

杜阳华(1979-),男,湖北武汉人,硕士,高级工程师,研究方向为系统工程、软件仿真与测试性。

1673-3819(2017)01-0109-07

TP311;E917

A

10.3969/j.issn.1673-3819.2017.01.024

修回日期: 2016-11-29

猜你喜欢
调用应用程序内存
核电项目物项调用管理的应用研究
笔记本内存已经在涨价了,但幅度不大,升级扩容无须等待
删除Win10中自带的应用程序
“春夏秋冬”的内存
系统虚拟化环境下客户机系统调用信息捕获与分析①
谷歌禁止加密货币应用程序
内存搭配DDR4、DDR3L还是DDR3?
利用RFC技术实现SAP系统接口通信
三星电子将开设应用程序下载商店
微软软件商店开始接受应用程序