一种虚拟机管理器的客户操作系统内核代码动态替换方法转让专利

申请号 : CN200910081513.9

文献号 : CN101539868B

文献日 :

基本信息:

PDF:

法律信息:

相似专利:

发明人 : 罗英伟汪小林李宇孙逸峰李晓明

申请人 : 北京大学

摘要 :

本发明公开了一种虚拟机管理器的客户操作系统内核代码动态替换方法,属于软件技术领域。本发明为:1)在宿主操作系统中加入一CID进程,并分配一植入空间以容纳植入的替换代码,然后VMM将植入空间映射到Guest OS的内核进程空间;2)VMM统计所需替换的代码片断;3)CID根据统计结果为其指定一段替换代码;4)将指定的替换代码写入植入空间,并获取其所处的调用堆栈;5)CID通过调用堆栈信息,找到所需替换代码在Guest OS中的调用点,VMM将调用点的跳转地址改为所指定的替换代码的偏移地址。本发明将半虚拟化方法的优势融入全虚拟化技术之中成为可能,可以在二进制层面对GuestOS内核代码做动态替换。

权利要求 :

1.一种虚拟机管理器的客户操作系统内核代码动态替换方法,其步骤为:

1)在宿主操作系统中加入一代码植入守护进程CID;

2)在CID的进程空间分配一植入代码空间以容纳植入的替换代码,然后全虚拟化虚拟机管理器将植入代码空间映射到客户操作系统的内核进程空间;

3)全虚拟化虚拟机管理器根据CID的输入指令搜集所需替换的代码片段,并将统计结果返回给CID进程;所述统计结果包括:所需替换代码的位置、替换代码处的二进制代码片段信息;

4)CID根据所需替换代码的二进制代码片段类型,为其生成或指定一段替换代码;

5)将生成或指定的替换代码写入植入代码空间,并在CID进程中做相应的记录;同时根据所需替换代码在客户操作系统中的代码地址,获取所需替换代码所处的调用堆栈;

6)CID通过调用堆栈信息,找到所需替换代码在客户操作系统中的调用点,全虚拟化虚拟机管理器将调用点的跳转地址改为所生成或指定的替换代码的偏移地址。

2.如权利要求1所述的方法,其特征在于所述搜集所需替换的代码片段的方法为:在全虚拟化虚拟机管理器中,按照陷入代码在客户操作系统中的位置,对其做统计计数,找出导致大量虚拟计算机-虚拟机管理器切换的代码片段。

3.如权利要求1所述的方法,其特征在于所述步骤2)中,通过全虚拟化虚拟机管理器修改客户操作系统的页表,将植入代码空间映射到客户操作系统的内核进程空间。

4.如权利要求1所述的方法,其特征在于所述CID记录所有替换代码的替换,以及替换代码调用点的修改,以便将虚拟机切换回原有的模式。

5.如权利要求1或4所述的方法,其特征在于所述将生成或指定的替换代码写入植入代码空间时,首先判断所述植入代码空间大小是否满足所述生成或指定的替换代码;如果满足则直接写入;如果不满足则以函数为基本单位,对所需替换代码所在的函数体取出,并用所述生成或指定的替换代码替换原有的代码片段,得到一个新的函数体。

6.如权利要求5所述的方法,其特征在于如果所述植入代码空间满足所述生成或指定的替换代码,则所述CID记录对应的所需替换代码的代码片段位置、长度和内容;如果所述植入代码空间小于所述生成或指定的替换代码,则所述CID记录对应的函数替换,以及函数调用点的修改。

7.如权利要求1所述的方法,其特征在于所述植入代码空间由全虚拟化虚拟机管理器监控,当虚拟机管理器发现客户操作系统使用了所述植入代码空间,由虚拟机管理器取消代码植入,并尝试寻找新的空闲空间做再次植入。

说明书 :

一种虚拟机管理器的客户操作系统内核代码动态替换方法

技术领域

[0001] 本发明涉及一种虚拟化技术,特别是涉及一种虚拟机管理器的客户操作系统内核代码动态替换方法,属于计算机软件技术领域。

背景技术

[0002] 虚拟机(Virtual Machine,VM)技术源于上世纪60年代,其核心思想是:在一台物理主机上虚拟出多个虚拟计算机(VM),其上能同时运行多个独立的操作系统,这些客户操作系统(Guest OS)通过虚拟机管理器(Virtual Machine Monitor,VMM)访问实际的物理资源。当前存在几种不同的虚拟技术:一种是半虚拟化技术(Paravirtualization),需要对Guest OS的源代码做一些修改;另一种是全虚拟化技术(Full Virtualization),Guest OS无需任何修改。
[0003] 我们知道,半虚拟化通过修改Guest OS源代码可以获得很好的性能,而全虚拟化技术则是以降低性能来提高兼容性(无需修改Guest OS的源代码)。近来新处理器的开发缩短了这方面的差距,如Intel VT(虚拟技术,Virtualization Technology)和AMD SVM(安全虚拟机,Secure Virtual Machine)芯片从硬件上支持了虚拟技术,试图取代半虚拟化技术。
[0004] 以Intel VT为例,它增加了在虚拟状态下的两种处理器工作模式:Root操作模式和Non-root操作模式。VMM运行在Root操作模式下,Guest OS运行在Non-root操作模式下。开始时通过执行VMXON指令进入虚拟化状态,处理器运行在Root操作模式下,执行VMM的代码,当VMM要运行一个VM时,执行VMLAUNCH指令使处理器发生VM entry,进入Non-root操作模式,运行Guest OS指令。此时,若遇到敏感指令,处理器会发生VM-VMM切换,回到Root操作模式,由VMM进行处理。处理完成后,通过VMRESUME指令,再次发生VM entry,进入Non-root操作模式继续运行Guest OS的指令。硬件辅助虚拟化技术很好地支持了全虚拟化(不修改Guest OS源码)并降低了VMM的实现难度(不需要动态二进制翻译)。
[0005] 但是加入了硬件辅助的全虚拟化性能仍然和半虚拟化技术有一定差距。其主要原因是Guest OS仍然有过多的VM-VMM切换,频繁从Non-root模式切换到Root模式,使得虚拟化的开销太大。经过测试,每次VM-VMM切换导致的系统开销达到几千个CPU时钟周 期。特别是在客户虚拟机存在大量页表操作和I/O操作的时候,会产生大量的VM-VMM切换,性能下降尤其明显。
[0006] 半虚拟化技术可以达到很好的性能,它可以通过修改Guest OS的源代码来避免VM-VMM切换。但是因为其要修改客户操作系统的源代码,使得它无法运行那些流行的非开源操作系统,比如Window系列操作系统。而且由于用户需要获取和安装修改过的客户操作系统,使得这个安装和配置过程过于繁琐,不利于在非专业用户中普及。 [0007] 全虚拟化技术虽然无需修改客户操作系统,但是由于VM-VMM切换的大量存在,使得全虚拟化的性能指标不甚理想。性能指标的限制,使得全虚拟化技术在性能要求较高的场合下难以发挥作用。比如在数据中心和网络服务中,全虚拟化技术带来的性能损失是无法接受的。
[0008] 一个合理的做法就是:将半虚拟化和全虚拟化技术结合起来,在不修改Guest OS内核源代码的前提下,在二进制代码层面上,动态替换Guest OS的内核代码,达到和半虚拟化方法相似的效果。要达到这个目标,有两件事情需要完成:一是如何动态替换Guest的内核代码,二是替换成怎样的代码。本发明主要是为解决第一个问题而提出。 发明内容
[0009] 本发明的目的是要在全虚拟化技术的基础之上,提出一种虚拟机管理器的客户操作系统内核代码动态替换方法,以解决全虚拟化方法无法修改Guest OS的问题。此项发明使得将半虚拟化方法的优势融入全虚拟化技术之中成为可能,可以在二进制层面对Guest OS内核代码做动态替换,从而避免了半虚拟化方法必须修改Guest OS源代码的局限。 [0010] 针对以上问题,本发明提出了虚拟机Guest OS的内核代码动态替换方法。虚拟机GuestOS内核代码动态替换允许VMM在虚拟机运行时,动态地替换虚拟机Guest OS的内核代码。从而能够在虚拟机正常和正确运行的情况下,改变虚拟机代码执行路径。 [0011] 虚拟机内核代码动态替换方案主要涉及如何将替换代码植入Guest OS之中,使得新的代码片段能够替代原有的内核代码片段,即代码植入机制。VMWare虚拟机在用户态下,可以动态地翻译和执行Guest OS代码【参考:Vmware white paper 2008:Performance ofVMware VMI第1页】,不同的是:我们的内核代码植入机制是建立在硬件虚拟化基础之上的,并不改变内核代码的执行环境,并且我们提供的机制能够为用户提供代码替换的接口。用户可以利用这个机制,将Guest OS中的代码片段替换成任何自己想要的代码。代码植入的主要流程如图1所示。
[0012] 我们首先在虚拟机管理器(VMM)中增加了一个代码替换引擎,它可以打开或关闭代码替换机制、收集需要替换的代码信息,同时也可以修改客户操作系统(Guest OS)的页表,辅助完成代码的植入。然后我们又在宿主操作系统(Host OS)中增加了一个代码植入守护进程CID(Code Implantation Daemon),这是一个用于完成代码分析和植入替换代码的用户态进程。CID进程通过IOCTL等系统调用与VMM进行交互,以取得所需替换代码的信息。随后CID将对需要替换的代码替换成用户指定的代码。我们在CID的进程空间分配一段物理内存区以容纳植入的替换代码,然后通过代码替换引擎修改Guest OS的页表,将这段内存映射到Guest OS的内核进程空间。CID还会分析需要替换代码处的函数调用堆栈,从而能改变Guest OS的函数调用路径,使得我们植入的代码可以被执行。 [0013] 本发明的技术方案为:
[0014] 一种虚拟机管理器的客户操作系统内核代码动态替换方法,其步骤为: [0015] 1)在宿主操作系统中加入一代码植入守护进程CID;
[0016] 2)在CID的进程空间分配一植入代码空间以容纳植入的替换代码,然后全虚拟化虚拟机管理器将植入代码空间映射到Guest OS的内核进程空间;
[0017] 3)全虚拟化虚拟机管理器根据CID的输入指令搜集所需替换的代码片段,并将统计结果返回给CID进程;所述统计结果包括:所需替换代码的位置、替换代码处的二进制代码片段信息;
[0018] 4)CID根据所需替换代码的二进制代码片段类型,为其生成或指定一段替换代码;
[0019] 5)将生成或指定的替换代码写入植入代码空间,并在CID进程中做相应的记录;同时根据所需替换代码在Guest OS中的代码地址,获取所需替换代码所处的调用堆栈; [0020] 6)CID通过调用堆栈信息,找到所需替换代码在GuestOS中的调用点,全虚拟化虚拟机管理器将调用点的跳转地址改为所生成或指定的替换代码的偏移地址。 [0021] 所述搜集所需替换的代码片段的方法为:在全虚拟化虚拟机管理器中,按照陷入代码在Guest OS中的位置,对其做统计计数,找出导致大量VM-VMM切换的代码片段。 [0022] 所述方法的步骤2)中,通过全虚拟化虚拟机管理器修改Guest OS的页表,将植入代码空间映射到GuestOS的内核进程空间。
[0023] 所述CID记录所有替换代码的替换,以及替换代码调用点的修改,以便将虚拟机切换回原有的模式。
[0024] 所述将生成或指定的替换代码写入植入代码空间时,首先判断所述植入代码空间大小是否满足所述生成或指定的替换代码;如果满足则直接写入;如果不满足则以函数为基本单位,对所需替换代码所在的函数体取出,并用所述生成或指定的替换代码替换原有的代码片段,得到一个新的函数体。
[0025] 所述方法中,如果所述植入代码空间满足所述生成或指定的替换代码,则所述CID记录对应的所需替换代码的代码片段位置、长度和内容;如果所述植入代码空间小于所述生成或指定的替换代码,则所述CID记录对应的函数替换,以及函数调用点的修改。 [0026] 所述植入代码空间由全虚拟化虚拟机管理器监控,当VMM发现Guest OS使用了所述植入代码空间,由VMM取消代码植入,并尝试寻找新的空闲空间做再次植入。 [0027] 本发明的过程有以下几点需要说明:
[0028] 1.植入代码必须映射到Guest OS中不会使用的地址空间
[0029] 这是为了保证植入代码和Guest OS的完整性。如果Guest OS修改了植入代码,或者植入代码映射时破坏了Guest OS原有的数据,都会导致Guest OS无法正常运行。我们采取的方法是,在Guest OS中预留出一段空闲的内核地址空间,植入的代码放在内核地址空间内。为此,需要根据具体Guest OS的特点,在Guest OS的内核地址空间中找一块Guest OS不经常访问的空间,由VMM监控以保证Guest OS只会按我们的安排访问这段空间。当VMM发现Guest OS违背我们的安排时,由VMM取消代码植入,并尝试寻找新的空闲空间做再次植入。比如,对于Guest OS为32位Linux系统来说,进程虚拟地址的范围是0到4G,其中分配给内核地址空间的范围是3G至4G。而对于低于896M的物理内存来说,Linux采用“直接映射”的方式。也就是将0至896M的物理内存映射到3G至3G+896M的虚拟地址空间,我们将这个空间称作“内核直接映射空间”。如果我们给Guest OS配置的物理内存小于896M,则Linux会在“内核直接映射空间”中留出一个空洞,而这个空洞即为我们要寻找的Guest OS不经常访问的空间。我们可以将代码植入到此空间中,以使Guest OS能够执行所植入的代码。
[0030] 2.代码替换可以以函数为替换的基本单位
[0031] 如果生成的新的替换代码和旧的代码片段长度不一致,直接对旧代码做本地替换,原来代码空间内一般无法容下替换后的代码,并且一旦做了代码替换,还可能对原代码所在函数内所有代码的布局产生影响,从而引起原函数代码复杂的变化。为了避免本地代码替换带来的复杂性,我们采用了一种以函数为基本替换单元的代码替换方法。我们在进行代 码替换时,会把所需替换代码所在的函数体取出,并用新的指令片段替换原有的代码片段,得到一个新的函数体。这个新的函数体映射到Guest OS中后,我们修改所有已经探知的对原函数体的调用,使之调用植入的新函数。这样做的另一个好处是如果我们要取消植入,只需要先把所有修改的函数调用点恢复,在确保Guest OS不再访问植入代码时,把植入代码从Guest OS中清除。一般来说,修改调用点不会引起函数调用指令代码长度的变化 [0032] 3.分析函数调用堆栈,获得被替换函数的在客户操作系统内核中的调用点 [0033] 由于要修改对原函数体的调用处的Call指令的偏移地址,首先我们必须找到被替换的函数调用堆栈,也就是我们平时称作的Call Stack。由于函数调用时会返回地址压栈,我们可以取出Guest OS执行到需替换代码处的堆栈,通过指令分析,从堆栈中找到各级返回地址,从而找出各级函数调用关系。获得这些函数调用关系,可以确保我们能做函数级的代码替换。
[0034] 4.VMM是CID进程和Guest OS之间的桥梁
[0035] CID进程通过VMM取得所需替换代码的位置,替换代码处的二进制代码片段,执行替换代码的堆栈等信息;并且通过VMM将植入代码映射到Guest OS的进程空间中去。由于CID进程无法和Guest OS直接交互,因此VMM在这里起到了一个桥梁的作用,这正是我们增加代码替换引擎的原因所在。VMM和CID进程之间的交互通过IOCTL等系统调用来实现。 [0036] 发明的优点与积极效果
[0037] 本发明提出的基于虚拟机管理器的客户操作系统函数级内核代码动态替换方法具有以下优点与积极效果:
[0038] 1.平台无关性。无需修改Guest OS的源代码,完全将Guest OS看作一个黑盒,我们所做的内核代码动态替换完全是在二进制代码层面上做的。从这点来看,我们遵从了全虚拟化方法的基本原则,而避免了半虚拟化需要修改Guest OS源代码的局限性。 [0039] 2.通用性。我们提出的内核代码动态替换机制,可以替换任何我们想要替换的代码片段。这种机制的通用性还可以从另外一个角度得到体现,就是我们并不限制VMM的类型,凡是支持硬件辅助全虚拟化的VMM,都可以使用我们提出的动态代码替换机制。 [0040] 3.透明性。我们的代码替换对于普通用户来说完全是透明的,也就是说普通用户无需知道任何关于代码替换机制的细节。Guest OS启动以后,代码动态替换会自动的进行,无需任何用户干预。
[0041] 4.可逆性。可以通过控制CID进程,开启和关闭代码替换机制。这是为了适应某些特殊需求场合,比如要将虚拟机从一个引入替换机制的VMM迁移至一个未引入替换机制的VMM之前,为了保证两边虚拟机状态的一致性,应先关闭代码替换的机制,随后再进行迁移。
[0042] 附图说明
[0043] 图1、代码植入的主要流程。
[0044] 具体实施方式
[0045] 下面是本发明的一个具体的实施方案,该实现是基于开源的全虚拟化虚拟机管理器KVM来完成的。
[0046] 首先需要在KVM中加入一代码替换引擎,用于打开或关闭代码替换机制、收集需要替换的代码信息,同时也可以修改客户操作系统(Guest OS)的页表,辅助完成代码的植入;在宿主操作系统中加入一CID,用于完成代码分析和植入替换代码的用户态进程。接下来按照如下步骤实施:
[0047] 步骤1:首先启动CID(Code Implantation Daemon)进程,我们在CID的进程空间分配一段物理内存区域以容纳植入的替换代码,我们将这段物理内存区域称为植入代码空间。然后通过VMM的代码替换引擎修改GuestOS的页表,将植入代码空间映射到GuestOS的内核进程空间。
[0048] 步骤2:CID进程通过IOCTL系统调用通知KVM虚拟机管理器中的代码替换引擎,开始搜集所需替换的代码片段。一个常用的方法是在VMM中,按照陷入代码在Guest OS中的位置,对其做统计计数,以便找出那些导致大量VM-VMM切换的代码片段,因为这些代码片段的执行会造成过多的额外开销,所以非常有替换价值。
[0049] 步骤3:代码替换引擎统计出所需替换代码的位置、替换代码处的二进制代码片段等信息。得出统计结果后,将需要替换的代码信息返回给CID进程。
[0050] 步骤4:CID根据代码替换引擎报告的需替换二进制代码片段的类型,为其生成一段替换代码(这不是本发明关注的内容,现有技术人员根据二进制代码可以生成任意的替换代码)。由于没有足够的空间将替换代码放在原来的位置,我们将对需替换代码所处的函数进行整体替换。新函数的二进制代码将写入植入代码空间,并在CID进程中做相应的记录。
[0051] 步骤5:CID进程获得需替换代码在客户操作系统中的代码地址后,再次通过代码替换引擎获取运行时的堆栈信息,得出需替换代码所处的调用堆栈。
[0052] 步骤6:CID通过步骤5中分析出的调用堆栈信息,找到被替换函数在Guest OS中的调用点,通过代码替换引擎,将调用点的跳转地址改为新函数的偏移地址,以使得植入的新函数能够被替代执行。
[0053] 步骤7:CID将记录所有的函数替换,以及函数调用点的修改,以便在需要的时候,能够取消内核代码动态替换机制,将虚拟机切换回原有的模式。
[0054] 我们所提出的基于虚拟机管理器的客户操作系统函数级内核代码动态替换方法,其主要技术特征是允许VMM在虚拟机运行时,在二进制代码层面上,动态地替换客户操作系统的内核代码,改变客户操作系统的某些执行行为。因此,凡是符合虚拟机内核代码动态替换的虚拟机技术都在本专利的保护范围之内。