一种程序控制流错误检测方法.pdf

上传人:a**** 文档编号:998315 上传时间:2018-03-24 格式:PDF 页数:17 大小:1.12MB
返回 下载 相关 举报
摘要
申请专利号:

CN200910226768.X

申请日:

2009.12.30

公开号:

CN101763291A

公开日:

2010.06.30

当前法律状态:

授权

有效性:

有权

法律详情:

授权|||实质审查的生效IPC(主分类):G06F 11/00申请日:20091230|||公开

IPC分类号:

G06F11/00; G06F9/45

主分类号:

G06F11/00

申请人:

中国人民解放军国防科学技术大学

发明人:

谭庆平; 徐建军; 宁洪; 周会平; 李建立; 李剑明; 罗宇; 邓胜兰

地址:

410073 湖南省长沙市砚瓦池正街47号

优先权:

专利代理机构:

国防科技大学专利服务中心 43202

代理人:

郭敏

PDF下载: PDF下载
内容摘要

本发明公开了一种程序控制流错误检测方法,目的是克服已有方法提高控制流错误的检测率,解决基本块内部、过程间控制流检测难点问题。技术方案是先标识基本块并确定基本块之间的路由关系;然后根据基本块内部控制流检测的需求和基本块的构成特征,确定单个基本块最多需要多少条内部控制流检测指令,在此基础上设计基本块标签,并为每个基本块分配唯一的静态标签;然后在程序中的每个基本块的头部、内部和尾部分别插入检测指令,将插入了控制流检测指令的汇编程序重新汇编链接,生成可执行的实现控制流错误检测的程序。采用本发明能解决检测盲点问题,检测率很高;且能有效解决基本块内部、过程间控制流检测的难点问题。

权利要求书

1.  一种程序控制流错误检测方法,其特征在于包括以下步骤:
第一步,通过编译器将需要进行控制流错误检测的程序编译成汇编代码;
第二步,基于程序汇编代码标识出程序的基本块并确定基本块之间的路由关系,具体分为三个步骤:

2.
  1依次遍历程序汇编代码的指令序列,根据指令操作码字段识别出程序控制指令,然后基于程序控制指令标注基本块的入口指令,方法为:所有函数的第一条指令标注为基本块的入口指令;对于条件分支指令和无条件跳转指令,分支或跳转的目标指令标注为基本块的入口指令;所有程序控制指令的后继指令标注为基本块的入口指令;在标注入口指令的同时,还根据指令的操作数字段识别出程序中所有使用过的寄存器,得出哪些寄存器还没有被程序使用过;

2.
  2重新依次遍历汇编程序的指令序列,将一个被标注为基本块入口指令到下一个入口指令之间的指令划分为一个基本块;如果基本块的入口指令有标识符,就以标识符作为基本块的名称;基本块以函数为单位按照在程序代码中出现的顺序列表组织,形成函数基本块列表,且在函数基本块列表中,第一个基本块标记为函数入口基本块,最后一个基本块被标记为函数退出基本块;所有函数基本块列表构成程序总的基本块列表;

2.
  3依次遍历汇编程序的所有基本块,按照基本块的最后一条指令确定基本块之间的路由关系,具体方法如下:如果基本块最后一条指令是条件分支指令和无条件跳转指令,则根据指令的分支或跳转目标地址查找对应的目标基本块,在程序对应的控制流图中从当前块向该目标基本块划一条有向边;如果基本块的最后一条指令是条件分支指令或普通指令——即不是无条件跳转指令、函数调用指令和函数返回指令,则在控制流图中从当前块向其直接后继基本块划一条有向边;如果基本块最后一条指令是函数调用指令,则在控制流图中从当前块向被调用函数的入口基本块划一条有向边,并且从被调用函数的退出基本块向当前块在所属函数基本块列表中的下一个块划一条有向边,表示函数返回的控制流转移;
第三步,根据用户对基本块内部控制流错误检测的需求和基本块的构成特征,设计基本块标签,并为每个基本块分配唯一的静态标签,采用可配置的方法进行内部控制流校验,即当基本块内部的指令计数每超过阈值Ω时才进行一次内部控制流校验,Ω由用户根据可靠性、性能的需求及程序运行环境自定义,具体步骤为:

3.
  1依次遍历程序中所有基本块,根据基本块包含指令的条数对阈值Ω的比例∑,计算在该基本块的内部检测指令计数,该内部检测指令计数等于再根据程序中每个基本块的内部检测指令计数得到整个程序中所有基本块最大的内部检测指令计数;

3.
  2根据整个程序中所有基本块最大的内部检测指令计数,设计基本块标签,基本块标签由基本标签编码和用于基本块内部控制流检测的编码两部分组成,每个基本块的基本标签编码是该基本块在程序总基本块列表中的序列号的二进制编码,是唯一的,基本块内部控制流检测的编码是该块所需的内部控制流检测指令计数的二进制编码,占整个基本块标签的最末几位;在基本块标签的末端为块内部控制流检测分配位编码,N为3.1步分析得出的整个程序中一个基本块中最多需要的内部检测指令条数;

3.
  3依次为每个基本块分配唯一的静态标签,所有静态标签中用于基本块内部控制流检测的编码都保持为0;

3.
  4从步骤2.1确定的空闲寄存器中选择四个寄存器分别定义为DSR、ASR、SVR和RAR,分别保存程序运行过程中产生的动态标签DS、静态标签AS、标签差异值SV和函数调用返回地址RA;其中,SV是两个基本块的静态标签异或运算的结果;如果程序没有四个空闲寄存器可供使用,则通知用户无法实现控制流错误检测,用户选择采用编译器的其它寄存器分派策略以重新生成汇编程序;
第四步,依次在程序每个基本块的头部、内部和尾部分别插入相应指令,具体步骤包括:

4.
  1进入一个函数后,首先针对函数入口基本块Bentry和函数退出基本块Bexit进行特殊处理:在调用函数的基本块Bcaller把返回的目的基本块Breturn的静态标签通过寄存器RAR传递给被调用函数,被调用函数的Bentry块把RAR中的数据写到分配给本函数的栈区间,最后被调用函数的Bexit块把保存的Breturn静态标签从栈区间重新读出,实现对过程间控制流的跟踪,所述Breturn是指在调用函数的基本块列表中当前基本块的下一个块,具体包括三个步骤:

4.
  1.1首先确定分配给本函数的栈区间中是否有空闲单元可用于存放RAR中的数据,如果确实没有空闲区域,则修改Bentry块入口处用于分配栈区间的指令,使得该函数的栈区间有一个机器字长的空闲存储单元可用于控制流检测使用;然后从函数的栈空间的空闲区域中,选择其中一个机器字长的存储单元,记为mem;

4.
  1.2在Bentry块分配栈区间的指令后加入指令“store RAR,mem”,表示把RAR中的数据写到分配给本函数栈区间的mem单元之中;

4.
  1.3如果Bentry块入口处修改了分配栈区间的指令,则相应修改Bexit块入口处回收栈区间的指令,使得函数栈区间的分配和回收保持一致;

4.
  2在当前基本块头部插入指令“xor DSR=DSR,SVR”,表示将动态标签与标签差异值异或运算生成新的动态标签DS,所述当前基本块头部是指基本块第一条指令之前,对于函数入口基本块来说则在4.1.2步骤的指令“store RAR,mem”之后;

4.
  3按照设定的Ω值,在基本块内部插入将DSR减1的内部控制流检测指令,方法是依次遍历基本块的指令序列,每隔Ω大小的指令数就插入一条内部控制流检测指令“subDSR=DSR,1”,直到剩下的指令总数不大于Ω值;对于那些本身包含指令的数目小于Ω值的基本块则不需要进行内部控制流检测,基本块内部保持不变;

4.
  4在基本块的尾部按照基本块的类型将DSR与后继基本块的静态标签进行异或运算,产生新的标签差异值SV,所述基本块的尾部是指基本块最后一条指令之后,如果最后一条指令是程序控制指令,则在该程序控制指令之前;具体方法如下:

4.
  4.1如果当前基本块既不是函数调用基本块又不是函数退出基本块,而且只有一个后继基本块,则在当前基本块的尾部插入指令“xor SVR=DSR,ASnext”,表示直接把后继块的静态标签值ASnext与DSR进行异或运算,求得新的标签差异值后赋给SVR;如果后继基本块需要进行块内控制流检测,ASnext等于后继基本块静态标签加上相应的内部控制流检测指令计数;

4.
  4.2如果当前基本块的最后一条指令是分支指令,则采取分支预测方法提前判断将要执行哪条分支,然后把所预测分支对应的后继基本块的静态标签与DSR进行异或运算,求得新的标签差异值SV;具体方法是:设ASthen和ASelse分别表示分支条件满足和不满足的目的基本块静态标签,首先在当前基本块的尾部插入指令“xor SVR=DSR,ASthen”,表示先假设分支条件满足,将DSR与ASthen进行异或运算求SVR值;然后在“xor SVR=DSR,ASthen”之后插入分支预测指令“br L1′,brcond”,分支条件“brcond”与实际的分支指令相同,而分支的目标“L1′”必须是一个没有在程序中出现过的语句标示符,具体指向4.5步即将插入的校验DSR数据的指令;最后在“br L1′,brcond”之后插入指令“xor SVR=DSR,ASelse”,表示将DSR与分支条件不满足的目的基本块的静态标签进行异或运算求得SVR值;如果分支条件满足,分支预测指令“br L1′,brcond”执行结果将使得程序跳过指令“xor SVR=DSR,ASelse”,即SVR中的值是DSR与ASthen异或运算的执行结果,否则SVR中的值是DSR与ASelse异或运算的运算结果;如果后继基本块需要进行内部控制流检测,则ASthen或ASelse分别等于其静态标签加上对应的内部控制流检测指令计数;

4.
  4.3如果当前基本块是函数调用基本块,其后续执行的基本块是被调用函数的入口基本块,先在当前基本块的尾部插入指令“xor SVR=DSR,AScallee”,实现DSR与被调用函数入口基本块静态标签AScallee的异或运算,并把标签差异值赋予SVR;然后在“xor SVR=DSR,AScallee”之后插入指令“mov RAR=ASreturn”,表示把函数调用返回的目的基本块的静态标签ASreturn赋予寄存器RAR;如果后续执行的被调用函数的入口基本块或者函数返回的目的基本块需要进行基本块内部的控制流检测,则AScallee或ASreturn分别等于其静态标签加上对应的内部控制流检测指令计数;所述函数调用返回的目的基本块是指当前基本块在所属函数的基本块列表中的下一个块;

4.
  4.4如果当前基本块是函数退出基本块,先在当前基本块的尾部插入指令“load RAR,mem”,表示从mem中读出数据,写回到寄存器RAR中;然后在“load RAR,mem”后插入指令“xor SVR=DSR,RAR”,表示将DSR与RAR进行异或运算求新标签差异值;最后在“xor SVR=DSR,RAR”后插入指令“clear mem”,表示将使用的内存单元mem中的数据清除;

4.
  5在基本块的尾部加入校验DSR数据的指令“br faultDet,DSR!=AScurrent”,其中AScurrent表示分派给当前基本块的静态标签;如果基本块的最后一条指令是程序控制指令,校验DSR数据的指令在程序控制指令之前插入;
第五步,通过编译器,将插入了控制流检测指令的汇编程序重新汇编并链接,生成可执行的实现控制流错误检测的程序。

说明书

一种程序控制流错误检测方法
技术领域
本发明涉及一种针对程序控制流错误的检测方法,尤其是对在空间辐射环境下由硬件瞬态故障所导致的控制流错误进行检测的方法。
背景技术
空间探测活动投入大、风险高,对计算可靠性有着极高的要求。太空中影响空间探测器安全的主要因素是宇宙射线的辐射,因为宇宙环境中存在大量包括电子、质子、粒子和重离子在内的高能粒子,当由这些粒子构成的宇宙射线轰击航天计算机的半导体电路时,就可能导致PN结构中的存储电量发生瞬态变化,这种瞬态故障通常也被称为单粒子效应SEE(Single Event Effect)。虽然单粒子效应一般不会对硬件设备造成持久伤害,但是却可以通过改变传输信号和存储单元值等方式影响系统的正常运行,严重时甚至会造成系统崩溃,所以一直是航天计算机所面临的最主要威胁之一。而现代处理器逐步采用深亚微米制造工艺,在性能得到大幅提高的同时,处理器对于能引起瞬态故障的各种噪声干扰也变得越来越敏感,同时单芯片所集成的晶体管数呈指数级增长,也使得芯片整体的瞬态故障率快速增加。当前,在继性能和功耗之后,瞬态故障所导致的处理器可信性问题已日益成为业界关注的热点。
硬件瞬态故障对系统可靠性影响的具体体现可分为数据流错误和控制流错误。数据流错误主要指故障影响应用程序使用的寄存器和存储器中的数据等;而控制流错误指的是故障改变了程序正常执行轨迹,例如一条存储指令被SEE篡改成分支指令,无条件跳转指令的目标地址被瞬态故障临时修改。当发生控制流错误后,程序行为会变得复杂且难以预测:有时由于执行了非法的指令而被操作系统或底层硬件检测出,也有可能导致程序进入死循环,最坏的情况是程序正常退出而执行结果却是错误的。以往的实际经验和各种故障注入实验结果表明,控制流错误占瞬态故障所引起的各种系统错误总数的33%~77%。所以,对于航天计算机这样的高可靠计算机系统来说,必须具备一定的控制流错误检测能力。
在空间环境中,为了防止空间辐射的影响,航天计算机一般使用经过特殊硬件工艺设计与加工的抗辐照器件。抗辐照器件通过硬件冗余实现容错,具有很高的可靠性,能够有效解决空间辐射所导致的硬件瞬态故障问题。但是抗辐照器件设计非常复杂、研制周期长、产业规模和产量都很小、价格非常昂贵,而且抗辐照器件的性能通常落后于同时代的商用器件COTS(Commercial Off-The-Shelf)很多代。此外,目前专门针对控制流错误也已提出一些通过改造硬件实现的检测技术,例如Watchdog辅助处理器技术。Watchdog技术先对程序的控制流结构进行分析,并为这种高层结构附上标签,然后由Watchdog处理器在运行时监测主处理器产生的总线事务。但是这种技术对于具有缓存的现代主处理器无法使用,除非协处理器是主处理器的一部分。总的来说,基于硬件实现的容错技术或需要修改硬件的体系结构,或要开发和配置具有检错能力的专门设备,实现成本太高是主要问题。
计算机发展的历史表明,很多原本用硬件实现的方法同样可以用软件来实现,在COTS微处理器上,通过实现面向硬件瞬态故障的软件容错技术可以弥补COTS器件在容错能力方面的不足。国内外已经开展很多实验探讨在空间环境中应用COTS处理器,结果表明:面向硬件故障的软件容错方法可以有效提高基于COTS器件的空间计算机的可靠性,能够很好地应对空间辐射的影响,同时在COTS器件上利用软件容错方法所实现的性能可以比抗辐照器件高一个数量级,而成本却要降低一个数量级。所以,随着计算机硬件资源的极大丰富,以牺牲部分性能来换取较高的可靠性已成为可能,并且软件容错方法在成本、功耗和灵活性方面都有拥有巨大的优势。实际上,基于COTS器件的软件容错方法目前已经成为各国航天领域的核心机密技术之一!
针对控制流错误,目前软件容错方法通常是以基本块为单位,在程序正常指令流中插入一些额外指令以实现对程序的控制流的校验。一个基本块是一个依次顺序执行的指令序列,其中除最后一条指令外其他指令都不能是程序控制指令(程序控制指令指能够改变程序原来执行顺序的指令,通常包括条件分支指令、无条件跳转指令、函数调用指令和函数返回指令等),除第一条指令外其它指令都不能是程序控制指令的转移目标。基于基本块,程序可以表示为由基本块以及连接基本块之间的有向边所构成的控制流图,其中的有向边表示实际的程序控制流转移。如果从基本块Bi到基本块Bj有一条边,则表示程序中存在Bi到Bj的路由,Bi记为Bj的前驱基本块,Bj记为Bi的后继基本块。
程序运行时,在执行一个指令后会转向执行另一条指令,这个过程称为一次控制流转移。基于基本块和程序控制流图,合法的控制流转移有下面两层含义:
1)基本块内部:控制流转移发生在一个基本块内部。由于基本块内部指令顺序执行,所以除了块最后一条指令外,每个指令只有唯一的后继指令。
2)基本块之间:控制流转移发生在基本块之间。对于基本块的最后一条指令,其后继指令可能有多个,但都必须是控制流图中所属基本块的后继基本块的第一条指令。
除此之外的所有控制流转移都是非法的,控制流错误检测技术的目标就是要尽可能高效地检测出所有非法的控制流转移。
当前,软件实现的控制流检测方法通常采用基于基本块的标签分析法(SignatureAnalysis)。基本块标签是基本块的数字标识,在预处理(如编译)时为每个基本块分配唯一的标签(称为静态标签AS,Assigned Signature),程序在运行过程中根据当前控制流由插入的检测指令维持一个标签(称为动态标签DS,Dynamic Signature),然后将两个标签进行比较,匹配则说明控制流没有被破坏,否则表示控制流出现了错误。
美国斯坦福大学提出的CFCSS方法就是这方面的典型代表。作为针对基本块之间的控制流错误进行检测的方法,CFCSS在编译时为每个基本块生成一个静态标签,并且为每个基本块计算与其前驱基本块的静态标签之间的异或差异值D。在运行时,CFCSS使用一个通用寄存器G保存产生的动态标签。当进入一个基本块后,先将G与当前基本块的D值异或运算产生新的动态标签。由于运算之前G值等于前驱基本块的静态标签,所以运算得到的结果应该与当前基本块的静态标签相等,否则说明检测到控制流错误。其他的标签分析法的基本原理与CFCSS相同,只是在基本块标签和检测指令序列的设计方面各有区别,由此导致错误检测率和性能消耗等方面存在差异。
但是总的来说,基于软件实现的控制流错误检测方法目前主要存在以下几个方面的问题:
(1)存在检测盲点:已有方法能够检测出绝大部分的控制流错误,但是各种方法也都不同程度地存在检测盲点。例如CFCSS无法检测从一个基本块的内部直接跳转到其后继基本块的头部的控制流错误。单粒子效应可能修改控制流指令本身,例如把不等于分支指令变成等于分支指令,这导致条件判断指令本应执行THEN分支,结果错误地跳转到ELSE分支。由于这种错误分支在程序控制流结构上是合法的,但语义却是错误的,通常被称为伪分支。伪分支会导致程序正常退出而执行结果却是错误,所以危险性很大,同时它也是控制流错误检测中的难点,目前很多方法不能解决这个问题。
(2)基本块内部的控制流错误检测:已有的控制流检测方法主要关注基本块之间的控制流正确性,而对于基本块内部的控制流错误并没有比较完善的解决办法。有方法在静态分析时对基本块包含的指令进行计数,然后运行时每执行一条指令则执行一条将计数减1的指令,当执行到基本块出口时,计数器的值应该为0。但这种方式增加的指令与基本块本身包含的指令一样多,对程序性能影响显然太大。
(3)过程间的控制流错误检测:这是控制流检测中的一个难点问题。有的方法在实现时不考虑过程间的控制流检测,即不把函数调用指令作为划分基本块的一个依据;有的方法虽然实现了过程间的控制流错误检测,但是难以处理嵌套调用和递归调用等复杂情况。
(4)无法解决可靠性和性能之间的矛盾:为了解决检测盲点,有些方法设计了一些复杂的检测指令序列。但是由于加入了过多的检测指令,对程序性能的影响也随之增大,甚至检测指令自身受瞬态故障影响而出错的概率也变大。
因为已有软件实现的控制流错误检测方法存在上述问题,必须研究检测效率更高而对程序本身性能影响较小的控制流错误检测方法。
发明内容
本发明要解决的技术问题是:克服已有方法存在的检测盲点(如伪分支),提高控制流错误的检测率,解决基本块内部的控制流检测和过程间的控制流检测等难点问题,并且对程序本身性能的影响较小。
为了解决上述技术问题,本发明提出的技术方案为:首先,基于程序汇编代码标识基本块并确定基本块之间的路由关系;然后根据用户对基本块内部控制流检测的需求和基本块的构成特征,确定单个基本块最多需要多少条内部控制流检测指令,在此基础上设计基本块标签,并为每个基本块分配唯一的静态标签;最后在程序中的每个基本块的头部、内部和尾部分别插入检测指令。
具体技术方案为:
第一步,通过编译器将需要进行控制流错误检测的程序编译成汇编代码,例如在GCC中可以使用‘-S’参数生成汇编程序。
第二步,基于程序汇编代码标识出程序的基本块并确定基本块之间的路由关系,具体细分为三个步骤:
2.1依次遍历程序汇编代码的指令序列,根据指令操作码字段识别出程序控制指令(程序控制指令指能够改变程序原来执行顺序的指令,通常包括条件分支指令、无条件跳转指令、函数调用指令和函数返回指令等)。然后基于程序控制指令标注基本块的入口指令,具体方法为:所有函数的第一条指令标注为基本块的入口指令;对于条件分支指令和无条件跳转指令,分支或跳转的目标指令标注为基本块的入口指令;所有程序控制指令的后继指令标注为基本块的入口指令。在标注入口指令的同时,还根据指令的操作数字段识别出程序中所有使用过的寄存器,得出哪些寄存器还没有被程序使用过。
2.2重新依次遍历汇编程序的指令序列,将一个被标注为基本块入口指令到下一个入口指令之间的指令划分为一个基本块。如果基本块的入口指令有标识符,就以标识符作为基本块的名称。基本块以函数为单位按照在程序代码中出现的顺序列表组织,形成函数基本块列表,且在函数基本块列表中,第一个基本块标记为函数入口基本块,最后一个基本块被标记为函数退出基本块。所有函数基本块列表构成程序总的基本块列表。
2.3依次遍历汇编程序的所有基本块,按照基本块的最后一条指令确定基本块之间的路由关系,具体方法如下:如果基本块最后一条指令是条件分支指令和无条件跳转指令,则根据指令的分支或跳转目标地址查找对应的目标基本块,在程序对应的控制流图中从当前块向该目标基本块划一条有向边;如果基本块的最后一条指令是条件分支指令或普通指令(即不是无条件跳转指令、函数调用指令和函数返回指令),则在控制流图中从当前块向其直接后继基本块划一条有向边;如果基本块最后一条指令是函数调用指令,则在控制流图中从当前块向被调用函数的入口基本块划一条有向边,并且从被调用函数的退出基本块向当前块在所属函数基本块列表中的下一个块划一条有向边,表示函数返回的控制流转移。
第三步,根据用户对基本块内部控制流错误检测的需求和基本块的构成特征,设计基本块标签(含静态标签和动态标签)的格式,并为每个基本块分配唯一的静态标签。基本块内部控制流错误是很多控制流检测方法的检测盲点,但是基本块包含的指令数有限,控制流错误导致恰好转移到基本块自身的概率非常小,即内部控制流错误发生概率比较低。如果每执行一条指令就进行一次内部控制流校验,成本显然太高。一般情况下基本块所包含的指令数越多,则出现内部控制流错误的概率越大,所以采用一种可配置的方法——当基本块内部的指令计数每超过阈值Ω时才进行一次内部控制流校验,Ω由用户根据可靠性、性能的需求及程序运行环境自定义。具体步骤包括:
3.1依次遍历程序中所有基本块,根据基本块的规模(即包含指令的条数)对阈值Ω的比例∑,计算在该基本块的内部检测指令计数(即需要多少条内部控制流检测指令),该内部检测指令计数等于再根据程序中每个基本块的内部检测指令计数,得到整个程序中所有基本块最大的内部检测指令计数。
3.2根据程序中所有基本块最大的内部检测指令计数,设计基本块标签。基本块标签由基本标签编码和用于基本块内部控制流检测的编码两部分组成。每个基本块的基本标签编码是该基本块在程序总基本块列表中的序列号的二进制编码,是唯一的;而基本块内部控制流检测的编码则是该块所需的内部控制流检测指令计数的二进制编码,占整个基本块标签的最末几位。在基本块标签的末端为块内部控制流检测分配位编码,N为3.1步分析得出的整个程序中一个基本块中最多需要的内部检测指令条数。
3.3依次为每个基本块分配唯一的静态标签。所有静态标签中用于基本块内部控制流检测的编码都保持为0。
3.4步骤2.1已确定有哪些寄存器还没有被程序使用,从这些空闲寄存器中选择四个寄存器分别定义为DSR、ASR、SVR和RAR,分别保存程序运行过程中产生的动态标签DS、静态标签AS、标签差异值SV(Signature Variance)和函数调用返回地址RA(ReturnAddress)。其中,SV是两个基本块的静态标签异或运算的结果,具体表征了实际控制流在基本块之间的转移。如果程序没有四个空闲寄存器可供使用,则通知用户无法实现控制流错误检测,用户可以选择采用编译器的其它寄存器分派策略以重新生成汇编程序。
第四步,依次在程序每个基本块的头部、内部和尾部分别插入相应指令,因为程序基本块是以函数为单位列表组织,插入控制流检测指令时也是以函数为单位进行。具体步骤包括:
4.1进入一个函数后,首先针对函数入口基本块(记为Bentry)和函数退出基本块(记为Bexit)进行特殊处理:在调用函数的基本块(记为Bcaller)把返回的目的基本块(即在调用函数的基本块列表中当前基本块的下一个块,记为Breturn)的静态标签通过寄存器RAR传递给被调用函数,被调用函数的Bentry块把RAR中的数据写到分配给本函数的栈区间,最后被调用函数的Bexit块把保存的Breturn静态标签从栈区间重新读出,实现对过程间控制流的跟踪。具体包括三个步骤:
4.1.1首先确定分配给本函数的栈区间中是否有空闲单元可用于存放RAR中的数据。通常编译器为每个函数实际分配的栈区间会有一些空闲区域,如果确实没有空闲区域,则修改Bentry块入口处用于分配栈区间的指令,使得该函数的栈区间有一个机器字长的空闲存储单元可用于控制流检测使用。例如把指令“sub $sp=$sp,36”改成“sub $sp=$sp,40”,可以将函数的栈区间增加4个字节($sp是栈地址寄存器)。然后从函数的栈区间的空闲区域中,选择其中一个机器字长的存储单元,记为mem。
4.1.2在Bentry块分配栈区间的指令后加入指令“store RAR,mem”,表示把RAR中的数据写到分配给本函数栈区间的mem单元之中。
4.1.3如果Bentry块入口处修改了分配栈区间的指令,则相应修改Bexit块入口处回收栈区间的指令,使得函数栈区间的分配和回收保持一致。例如把指令“add $sp=$sp,36”改成“add $sp=$sp,40”。
4.2在当前基本块头部(即基本块第一条指令之前,对于函数入口基本块来说则在4.1.2步骤的指令“store RAR,mem”之后)插入指令“xor DSR=DSR,SVR”,表示将动态标签与标签差异值异或运算生成新的动态标签。进入一个基本块时,寄存器DSR值应该等于其前驱基本块的静态标签,SVR中应该是前驱基本块的静态标签与当前基本块的静态标签经过异或运算得到的标签差异值SV。所以,如果当前基本块不需要进行内部控制流检测,指令“xor DSR=DSR,SVR”运算结果会使得DSR值等于分派给当前基本块的静态标签,否则DSR值应该等于当前基本块的静态标签加上对应的内部控制流检测指令计数。
4.3按照设定的Ω值,在基本块内部插入将DSR减1的内部控制流检测指令。依次遍历基本块的指令序列,每隔Ω大小的指令数就插入一条内部控制流检测指令“sub DSR=DSR,1”,直到剩下的指令总数不大于Ω值。这样做的结果是根据Ω参数将基本块划分为更小的区域,每个小区域中包含指令数小于等于Ω,然后在每两个区域之间插入的内部检测指令可以确保执行基本块内部指令时必须经过这些点。如果因为发生内部控制流错误而绕过这些内部检测指令,直接从一个区域跳转另一个区域,那么执行到块尾时动态标签中用于块内检测的几位肯定不都为0,即DSR与当前基本块的静态标签AS肯定不同,将会检测到该错误。对于那些本身包含指令的数目小于Ω值的基本块则不需要进行内部控制流检测,基本块内部保持不变。
4.4当执行到一个基本块的末尾时,动态标签寄存器DSR的值应该等于分配给该块的静态标签。在基本块的尾部(即基本块最后一条指令之后,如果最后一条指令是程序控制指令,则在该程序控制指令之前),按照基本块的类型将DSR与后继基本块的静态标签进行异或运算,产生新的标签差异值SV。具体方法如下:
4.4.1如果当前基本块既不是函数调用基本块又不是函数退出基本块,而且只有一个后继基本块,设该后继基本块静态标签为ASnext,则在当前基本块的尾部插入指令“xorSVR=DSR,ASnext”,表示直接把后继块的静态标签值ASnext与DSR进行异或运算,求得新的标签差异值后赋给SVR。如果后继基本块需要进行块内控制流检测,ASnext等于后继基本块静态标签加上相应的内部控制流检测指令计数。
4.4.2如果当前基本块的最后一条指令是分支指令(即有两个合法后继基本块),则采取分支预测方法提前判断将要执行哪条分支,然后把所预测分支对应的后继基本块的静态标签与DSR进行异或运算,求得新的标签差异值SV。具体方法是:设ASthen和ASelse分别表示分支条件满足和不满足的目的基本块静态标签。首先在当前基本块的尾部插入指令“xor SVR=DSR,ASthen”,表示先假设分支条件满足,将DSR与ASthen进行异或运算求SVR值。然后在“xor SVR=DSR,ASthen”之后插入分支预测指令“br L1′,brcond”,分支条件“brcond”与实际的分支指令相同,而分支的目标“L1′”必须是一个没有在程序中出现过的语句标示符,具体指向4.5步骤即将插入的校验DSR数据的指令。最后在“br L1′,brcond”之后插入指令“xor SVR=DSR,ASelse”,表示将DSR与分支条件不满足的目的基本块的静态标签进行异或运算求得SVR值。如果分支条件满足,分支预测指令“br L1′,brcond”执行结果将使得程序跳过指令“xor SVR=DSR,ASelse”,即SVR中的值是DSR与ASthen异或运算的执行结果,否则SVR中的值是DSR与ASelse异或运算的运算结果。如果后继基本块需要进行内部控制流检测,则ASthen或ASelse分别等于其静态标签加上对应的内部控制流检测指令计数。
4.4.3如果当前基本块是函数调用基本块,其后续执行的基本块是被调用函数的入口基本块。先在当前基本块的尾部插入指令“xor SVR=DSR,AScallee”,实现DSR与被调用函数入口基本块静态标签AScallee的异或运算,并把标签差异值赋予SVR。然后在“xor SVR=DSR,AScallee”之后插入指令“movRAR=ASreturn”,表示把函数调用返回的目的基本块(即当前基本块在所属函数的基本块列表中的下一个块)的静态标签ASreturn赋予寄存器RAR。同样,如果后续执行的被调用函数的入口基本块或者函数返回的目的基本块需要进行基本块内部的控制流检测,则AScallee或ASreturn分别等于其静态标签加上对应的内部控制流检测指令计数。
4.4.4如果当前基本块是函数退出基本块,其后续执行基本块的静态标签由4.1.2步骤存放在本函数栈区间的mem存储单元中。先在当前基本块的尾部插入指令“load RAR,mem”,表示从mem中读出数据,写回到寄存器RAR中。然后在“load RAR,mem”后插入指令“xor SVR=DSR,RAR”,表示将DSR与RAR进行异或运算求新标签差异值。最后在“xor SVR=DSR,RAR”后插入指令“clear mem”,表示将使用的内存单元mem中的数据清除。
4.5在基本块的尾部加入校验DSR数据的指令“br faultDet,DSR!=AScurrent”,其中AScurrent表示分派给当前基本块的静态标签。当正常执行到基本块尾部时,寄存器DSR中的值应该等于AScurrent,如果不相同则表示检测到控制流错误,则转向错误处理例程。该指令放在最后插入可以防止出现在校验指令之后再改变控制流的检测盲点。但如果基本块的最后一条指令是程序控制指令,那么校验DSR数据的指令仍要在程序控制指令之前插入。
第五步,通过编译器,将插入了控制流检测指令的汇编程序重新汇编并链接,生成可执行的实现控制流错误检测的程序。
与已有的控制流检测方法相比,采用本发明可以达到以下技术效果:
(1)本发明是一种纯软件方法,不需要修改底层机器硬件。而且本发明是通过在程序编译时自动向程序插装一些检测指令,能够做到对用户屏蔽具体实现,对被加固的程序也无特别限制,不需要操作系统的多线程支持。
(2)本发明对控制流错误的检测率很高,能够解决很多传统软件实现的控制流检测方法的检测盲点。例如伪分支问题,由于本发明实现了分支预测机制,在执行原有分支指令之前,先执行同样的指令进行分支判断,相当于对分支指令进行了冗余计算,所以能够过解决控制流指令本身出错的问题。故障注入实验的结果表明,本发明的控制流错误检测率在99.2%以上。
(3)本发明能够有效解决基本块内部的控制流检测问题,而且检测效率很高。假设基本块中原有指令n条,加入了m条的内部检测指令,如果是按指令数平均划分区域,那么被漏检的可能向前跳转的内部控制流错误有(m+1)×((n/(m+1))!)个。假设所有可能的前向内部控制流错误的概率相同,那么对于前向内部控制流错误的检测率可以达到1-(m+1)×((n/(m+1))!)/((n+m)!)。设n=30,m=1,代入计算得可能漏检的错误仅占3.18×10-22。所以虽然只加入了很少的内部检测指令,但是对于基本内部控制流的检测率非常高。本发明对于内部控制流错误检测的优势还在于可以根据具体需求进行配置,用户可以根据可靠性、性能的需求及程序运行环境自定义Ω值,通过设置Ω来决定实施块内部控制流检测的力度,而对于不需要内部控制流检测机制的基本块来说则没有额外开销。相比已有方法来说,本发明在成本和灵活性方面要好很多。当然如果基本块内部控制流错误恰好发生在4.3步所划分区域的内部(这种情况发生概率非常小),那么仍然不能检测这种控制流错误。
(4)本发明能够有效解决过程间控制流检测的难点问题。由于在调用函数时通过RAR将返回目的基本块标签传递给了调用函数,而且RAR中值存放在被调用函数的栈区间,所以本发明可以很好地处理嵌套调用和递归调用等复杂情况。
(5)本发明对程序本身性能影响很小,除内部的控制流检测指令外,单个基本块最多插入5条指令(对应于函数入口基本块同时有两个合法后继基本块的特殊情况),最少只插入2条指令。已有性能分析实验的结果表明,在使用本发明的控制流检测后,程序的性能开销仅为15%~37%。
附图说明
图1是基本块标签的格式;
图2是本发明的总流程图;
图3是本发明的第二步标识程序的基本块并确定基本块之间的路由关系的流程图;
图4是本发明的第三步基本块标签格式设计和静态标签分配的流程图;
图5是本发明的第四步向被检测程序加入控制流检测指令的流程图。
具体实施方式
图1是基本块标签格式的示意图。
基本块标签由基本标签编码和用于基本块内部控制流检测的编码两部分组成。每个基本块的基本标签编码是对基本块在程序总基本块列表中的序号进行的编码,是唯一的;而基本块内部控制流检测的编码则是该块所需的内部控制流检测指令计数的二进制编码,占整个基本块标签的最末几位。
图2是本发明的总流程图。包括以下步骤:
第一步,首先通过编译器将需要进行控制流检测的程序编译成汇编代码。
第二步,基于程序汇编代码标识出程序的基本块并确定基本块之间的路由关系,即程序的控制流结构。
第三步,根据用户对基本块内部控制流检测的需求和基本块的构成特征,设计基本块标签,并为每个基本块分配唯一的静态标签。
第四步,以函数为单位依次在程序每个基本块的头部、内部和尾部分别插入控制流检测指令。
第五步,通过编译器,将插入控制流检测指令的汇编程序重新汇编并链接,生成可执行的实现控制流检测的程序。
图3是本发明的第二步标识程序的基本块并确定基本块之间的路由关系的流程图,主要包括三大步骤:
1.依次遍历汇编程序的指令序列,根据其中的程序控制指令标注基本块的入口指令。同时根据指令的操作数字段识别出程序中所有使用过的寄存器,最后得出哪些寄存器还没有被程序使用过。
2.重新依次遍历汇编程序的指令序列,将一个被标注为基本块入口指令到下一个入口指令之间的指令划分为一个基本块。
3.依次遍历程序的所有基本块,根据基本块的最后一条指令确定基本块之间的路由关系。
图4是本发明的第三步基本块标签格式设计和静态标签分配的流程图,该过程主要包括四个步骤:
1.依次遍历程序中所有基本块,根据基本块包含的指令的条数对阈值Ω的比例,计算在该基本块的内部检测指令计数(即需要多少条内部控制流检测指令),得到整个程序中所有基本块最大的内部检测指令计数。
2.根据整个程序中所有基本块最大的内部检测指令计数,设计基本块标签。
3.依次为每个基本块分配唯一的静态标签AS。在所有静态标签中,用于基本块内部控制流检测的几位编码都保持为0。
4.从没有被程序使用的空闲寄存器中选择四个,分别指派给DSR、ASR、SVR和RAR。这四个寄存器分别用于保存程序运行过程中产生的动态标签DS,基本块的静态标签AS,标签差异值SV和函数调用返回地址RA。
图5是本发明的第四步插入控制检测指令的流程图,表示分别向每个基本块头部、内部和尾部插入指令,该过程主要包括三大步骤:
1.根据基本块的类型在基本块头部插入指令:如果基本块是函数入口基本块,则先插入指令“store RAR,mem”,“mem”是该函数的空闲栈区间中的存储单元;然后对于所有基本块,需要插入指令“xor DSR=DSR,SVR”。
2.根据基本块包含的指令数在基本块内部插入内部控制流检测指令:按照用户定义的基本块内部检测指令的间隔指令阈值Ω,依次每隔Ω大小的指令数就插入内部检测指令“sub DSR=DSR,1”,直到剩下的指令总数不大于Ω。
3.根据基本块的类型及其后继基本块,在基本块的尾部插入指令。
1)如果当前基本块不是函数调用基本块和函数退出基本块,而且只有一个后继基本块,则插入如下指令:
xor SVR=DSR,ASnext
其中ASnext表示后继基本块的静态标签。如后继基本块需要进行块内的控制流检测,则ASnext等于后继基本块的静态标签加上相应的块内部控制流检测指令计数。
2)如果当前基本块不是函数调用基本块和函数返回基本块,而且有两个后继基本块(即基本块最后一条指令是分支指令),则依次插入如下代码:
xor SVR=DSR,ASthen
br  L1′,brcond
xor SVR=DSR,ASelse
L1′:
新插入的3条指令实现了分支预测功能,其中ASthen和ASelse分别表示分支条件满足的后继块和分支条件不满足的后继块的静态标签。且分支预测指令“br L1′,brcond”的指令操作码和分支条件“brcond”与实际的分支指令相同,但是分支的目标改成L1′,而且L1′必须是一个没有在程序中出现过的语句标示符。同样,如果后继基本块需要进行内部控制流检测,则ASthen或ASelse分别等于其静态标签加上对应的内部控制流检测指令计数。
3)如果当前基本块是函数调用基本块,则依次加入如下指令:
xor SVR=DSR,AScallee
mov RAR=ASreturn
其中,“xor SVR=DSR,AScallee”表示把DSR与被调用函数的入口基本块的静态标签AScallee异或运算求标签差异值,指令“mov RAR=ASreturn”表示把函数返回的目的基本块的静态标签ASreturn赋予寄存器RAR。同样,如果被调用函数的入口基本块和把函数返回的目的基本块需要进行块内部的控制流检测,则AScallee或ASreturn分别等于其静态标签加上对应的内部控制流检测指令计数。
4)如果当前基本块是函数退出基本块,则依次加入如下指令:
load RAR,mem
xor SVR=DSR,RAR
clear mem
其中,指令“load RAR,mem”表示从保存函数返回目的基本块静态标签的内存区域mem中读出数据,写回到寄存器RAR中。然后由指令“xor SVR=DSR,RAR”将DSR与RAR进行异或运算求标签差异值。“clear mem”表示需要将使用的内存区域中的数据清除。
对于所有类型的基本块,在尾部最后插入指令:
br faultDet DSR!=AScurrent
表示把当前块的静态标签AScurrent与DSR进行比较。如果不相等,则意味着检测到控制流错误,需要转向错误处理例程。
当指令集中没有可以把寄存器和立即数直接进行比较的指令,则要先插入指令
mov ASR=AScurrent
表示先把AScurrent读取到寄存器ASR中,然后插入
br faultDet DSR!=ASR
表示将ASR与DSR进行比较。

一种程序控制流错误检测方法.pdf_第1页
第1页 / 共17页
一种程序控制流错误检测方法.pdf_第2页
第2页 / 共17页
一种程序控制流错误检测方法.pdf_第3页
第3页 / 共17页
点击查看更多>>
资源描述

《一种程序控制流错误检测方法.pdf》由会员分享,可在线阅读,更多相关《一种程序控制流错误检测方法.pdf(17页珍藏版)》请在专利查询网上搜索。

本发明公开了一种程序控制流错误检测方法,目的是克服已有方法提高控制流错误的检测率,解决基本块内部、过程间控制流检测难点问题。技术方案是先标识基本块并确定基本块之间的路由关系;然后根据基本块内部控制流检测的需求和基本块的构成特征,确定单个基本块最多需要多少条内部控制流检测指令,在此基础上设计基本块标签,并为每个基本块分配唯一的静态标签;然后在程序中的每个基本块的头部、内部和尾部分别插入检测指令,将插。

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 物理 > 计算;推算;计数


copyright@ 2017-2020 zhuanlichaxun.net网站版权所有
经营许可证编号:粤ICP备2021068784号-1