gvisor实现的容器中启动新内核

gvisor

gvisor是google发布的安全容器。
gVisor 工作的核心,在于它为应用进程(用户容器),启动了一个名叫 Sentry 的进程。 而 Sentry 进程的主要职责,就是提供一个传统的操作系统内核的能力,即:运行用户程序,执行系统调用。所以说,Sentry 并不是使用 Go 语言重新实现了一个完整的 Linux 内核,而只是一个对应用进程“冒充”内核的系统组件。(这段是抄的)
作为安全容器,利用容器中的内核来隔离大部分内核攻击,确实是一个不错的想法,然而这个新内核属于定制内核,估计很多功能还不完善,据说用了ptrace和kvm两种方式实现,我这里来探索下kvm的实现方式。

kvm

kvm是linux的硬件虚拟化的的抽象模块,方便用户构建硬件虚拟化的虚拟机。最全的资料应该还是intel或amd各家的硬件开发手册,我之前有几篇相关的文章,所以就不啰嗦VT虚拟化了。

gviosr如何劫持容器中的系统调用

根据我的观察,gvisor对于VT技术(kvm)的使用核心逻辑图如下:
在这里插入图片描述
这里在信号里创建了个VMM(虚拟机管理器)。简单讲就是初始化客户机状态,和VMM状态,设置各种vm_exit标识,用来劫持客户机的各种硬件或软件行为。之后在kvm的设备句柄中 发送_KVM_RUN状态就可以运行客户机代码,也就是我们需要的新内核的代码。

kvm中设置系统调用表地址

在这里插入图片描述
MSR_LSTAR代表内核可以操作的系统寄存器,一般用来存放系统调用表。如上图,linux内核也是这样做的,存放了entry_SYSCALL_64。
gvisor利用kvm对虚拟机化中的系统表进行改写位于kernel——amd64.go(startGo)

func startGo(c *CPU) {
	// Save per-cpu.
	WriteGS(kernelAddr(c.kernelEntry))

	//
	// TODO(mpratt): Note that per the note above, this should be done
	// before entering Go code. However for simplicity we leave it here for
	// now, since the small critical sections with undefined FPU state
	// should only contain very limited use of floating point instructions
	// (notably, use of XMM15 as a zero register).
	fninit()
	// Need to sync XCR0 with the host, because xsave and xrstor can be
	// called from different contexts.
	xsetbv(0, sentryXCR0)

	// Set the syscall target.
	wrmsr(_MSR_LSTAR, kernelFunc(addrOfSysenter()))
	wrmsr(_MSR_SYSCALL_MASK, KernelFlagsClear|_RFLAGS_DF)

	// NOTE: This depends on having the 64-bit segments immediately
	// following the 32-bit user segments. This is simply the way the
	// sysret instruction is designed to work (it assumes they follow).
	wrmsr(_MSR_STAR, uintptr(uint64(Kcode)<<32|uint64(Ucode32)<<48))
	wrmsr(_MSR_CSTAR, kernelFunc(addrOfSysenter()))
}
TEXT ·sysenter(SB),NOSPLIT,$0
	-->kernelSyscall(SB)
		-->ring0.SaveFloatingPoint(c.floatingPointState.BytePointer())
		-->ring0.HaltAndWriteFSBase(regs) 

如上实现了虚拟化的系统调用表。这之后就可以猜测,系统调用大部分逻辑可以被重新实现,少数重定位到真实内核中的系统调用。

这里有个疑问,为什么要放在信号里创建VMM, 直接创建也可以吧。可能是容器中启动程序,用信号来劫持容器执行流更方便,有看过的可以交流下。

一些后续的想法

1.能否启动完整的内核?利用kvm我的想法是可以启动完整的内核。因为这里完全可以实现完整的虚拟机管理器,之所以采用简化的内核,可能是考虑到性能问题,毕竟完整的虚拟机还是有一定的消耗的。
2.安全性。安全性有了较大的提升,但还是存在攻破的可能,因为是虚拟化技术,有可能发生逃逸。
3.维护新内核的成本估计也不低。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值