Page 325 - 《软件学报》2021年第10期
P. 325
陈兴蜀 等:VMOffset:虚拟机自省中一种语义重构改进方法 3297
复模块判断是否已获取全部所需进程偏移量:若尚未获取完毕,则进行相关模拟操作后执行 VM-
ENTRY 进入 TVM 完成内核函数的正常执行流程;否则恢复对 TVM 中相关内核函数的修改,使进程/
线程的创建及消亡动作不再产生 VM-EXIT 陷入至 VMM,减少了对 TVM 的影响,并将所得进程偏移
量提供给开源或自研的 VMI 应用程序,完成 TVM 的自省过程.
2 VMOffset 关键技术
2.1 拦截内核函数调用的事件监控机制
VMOffset 通过监控 TVM 中进程创建及消亡的内核函数调用事件,触发 VMM 中进程偏移量的获取流程,
并基于此触发点得到 TVM 的状态信息,作为后续获取进程偏移量的条件与依据.Linux 用户进程的创建通过系
统调用 fork()、clone()和 vfork()实现,进程的消亡通过系统调用 exit()、wait()实现.
可通过修改 SYSENTER_CS_MSR 寄存器 [23] 或系统调用表 [24] 等方式拦截上述系统调用,以监控进程的创建
及消亡.但该种方式存在如下缺陷.
1) 系统调用是用户进程访问内核服务的一个接口,内核线程直接通过调用内核函数使用内核提供的服
务.因此在 TVM 系统启动阶段,产生用户进程之前,并不会发生系统调用事件,故该种方式无法监控
TVM 整个时期的进程创建及消亡动作;
2) 在虚拟化环境下,为了在 VMM 层捕获到 TVM 中的系统调用事件,通常需要设置虚拟机控制结构体的
相关字段 [24] ,用于在 VMM 中捕获缺页异常或一般保护异常.这样会引入大量与系统调用无关的异常
陷入,对 TVM 系统性能带来较大影响.
针对上述不足,VMOffset 通过监控特定内核函数的调用来感知 TVM 中进程创建及消亡的动作,这种方式
可监控 TVM 各个阶段的进程创建及消亡动作,且不会引入无关的异常陷入.系统调用 fork()、clone()和 vfork()
的服务例程分别为 sys_fork()、sys_clone()和 sys_vfork(),这 3 个函数最终都会调用 do_fork()函数实现具体创
建工作.系统调用 exit()和 wait()的服务例程分别为 sys_exit()、sys_wait(),分别调用内核函数 do_exit()及 do_
wait(),这两个内核函数最终都会调用函数 release_task()释放待消亡进程的进程描述符.因此,VMOffset 通过监
控内核函数 do_fork()及 release_task()的调用,实时感知 TVM 中进程创建及消亡事件,其实现原理如图 3 所示.
Fig.3 Principle of event monitoring
图 3 事件监控原理
函数之间的调用通过栈来实现,函数执行时所用栈被称为函数栈帧,EBP 寄存器作为帧指针,指向函数栈帧
的开始位置;ESP 寄存器作为栈指针,则指向栈顶位置.当调用函数以 call 方式调用被调用函数时,call 指令首先
将调用函数 call 指令的下一条指令地址压入栈中,然后将被调用函数地址保存至 EIP 寄存器.执行流程从 EIP