sVIrt概述

sVirt概述

前面已经对seLInux的基本原理做了分析,seLinux主要就是基于主体和客体的安全上下文,进行访问决策。那么安全上下文是不是又可以理解为一个标签呢?
基于以上seLInux的特性,便可以考虑吧seLinux这种基于标签的思想应用到保障Hypervisor的安全上,这里主要是解决两个问题:
  • 恶意虚拟机攻击Hypervisor
  • 恶意虚拟机攻击其他虚拟机
这样开发者们便想出了一个给虚拟机打标签然后借助于seLinux的策略配置解决上面两个问题。他们开始的想法是给虚拟机和镜像文件打同一个标签,这样一个虚拟机只能访问自身的镜像文件,而一个镜像文件也只能被它对应的虚拟机访问。但是起初他们是让管理员给镜像文件配置标签,这加重了管理员的负担,所以后来他们在libvirt中加入了支持。
准确来说就是在Libvirt中添加了一个安全架构插件,这样Libvirt会自动给镜像文件配置标签并且保证虚拟机以正确的标签启动。这些标签是无法更改的。这样管理员就不需要去记复杂的标签,提高了易用性。默认情况下,在F11中的虚拟机是svirt_t,镜像文件时svirt_image_t。
而seLinux的策略仅仅允许sVIrt_t的进程读写sVIrt_image_t的文件和设备。
这种情况下虚拟机便不能肆意访问宿主机,也就解决了第一个问题,但是这样并不能阻止虚拟机间的恶意访问,即第二个问题。
基于此,开发者便考虑我们要保证虚拟机和镜像的标签一致,同时不能让VM1访问具有相同标签的VM2的镜像文件。
 
这样便出现了MCS(Multiple Category Security)
 
这在red hat 5上默认提供支持,类似于MLS,MCS在seLInux的安全上下文中添加了第四个字段,其实之前我们也介绍过MCS和MLS的区别,MCS只不过是只采用一个敏感度,而MLS又多个敏感度,二者的侧重点是不同的,MCS重在分类,而MLS貌似重在等级。
 
这样MCS便可以用于分离以同一seLinux类型运行的虚拟机,Libvirt在加入支持后,同样也可以自动为虚拟机和其镜像文件分配随机MCS标签,同时保证标签的唯一性。
例如Libvirt为两台虚拟机分配的标签:
 

 

这样seLinux阻止了VM1( system_u:system_r:svirt_t:s0:c0,c10) 访问VM2的镜像文件 (system_u:object_r:svirt_image_t:s0:c101,c230) ,也就阻止了VM间的相互攻击。
如下是Livvirt分配的标签:

 

同时对sVirt也加入了静态标签的特性,用户可以为虚拟机选择特定的标签。这样虚拟机便一直以这个标签启动,但是设置静态标签的用户需要为镜像文件设置相应的标签。而Libvirt也永远不会去修改静态配置的标签,这样sVIrt便可以运行于MLS的环境,管理员就可以运行多个不同安全级别的虚拟机。
 
二、sVirt在seLInux中的使用
 
sVIrt其实最主要的还是给虚拟机打标签的过程,而目前主要有静态标签和动态标签两种方式
 
动态分配:
默认状态下,虚拟机运行在自己的被动态配置的域和image文件下,因此和其他的VM隔离开来(每个虚拟机会被随机分配MCS标签用于限制虚拟机活动在自己的域中),这种模式的实现方式如下:
a) 一个对进程的初始上下文是从/etc/selinux/<SELINUXTYPE>/contexts/virtual_domain_context 文件获得,意味着开启虚拟机后,代表虚拟机的qemu进程的安全上下文就是从这个文件中获取的。
b)一个对image镜像文件的安全上下文时从/etc/selinux/<SELINUXTYPE>/contexts/virtual_image_context 文件获得的,那么刚才不是说镜像文件在建立时已经有了安全上下文么??这里我也不太清楚,在虚拟机启动后,镜像文件的类型会被重新标记,至于原因,后续有待考究。
c)当一个镜像文件被用于启动一个虚拟机,selinux系统就生成一个随机的MCS level 并添加到相应qemu进程的安全上下文和image镜像文件的安全上下文。进程和image文件随后被libseLinux API 分别调用 setfilecon 和setexeccon来实现转化到相应的安全上下文(可以参考libvirt源代码中的security_selinux.c文件)。
下面的例子显示了两个运行的VM的安全上下文:
 

 

 

上面是Vm运行起来后,虚拟机进程和image镜像文件的安全上下文。
用命令查看VM运行状态和关机状态的相关信息:
 

 

那么观察上面的结果大致可以得到下面结论:
 
1、在虚拟机启动之前,镜像文件的类型是virt_image_t,而在虚拟机启动之后,镜像文件的类型是svirt_image_t.
2、在虚拟机启动之前是没有配置MCS标签的
3、虚拟机启动之后进程和镜像文件的MCS标签存在一一对应的关系,故因此保证独立性。
 
 
静态分配:
 
动态分配的方式很简单,只要系统安装了selinux模块,并设置seLInux的相关配置文件,建议设置seLinux-Type = targeted,此模式下会默认对网络和虚拟机设置访问控制,假如设置mls的话要考虑的事情太多,系统很有可能起不来(前车之鉴)。
 
那么静态分配的话就是手动给某个虚拟机分配标签,一般在用户层的虚拟机管理工具都会提供这个功能,以virt-manager为例:
 

 

这样配置后,在虚拟机对应的配置文件中会自动添加对标签:
启动虚拟机会以所配置的安全上下文启动,但是注意,因为前面提到过虚拟机运行起来后,镜像文件的安全上下文会被重新标记,而在静态方式下,镜像文件的安全上下文并不自动更改,那那么假如我们不手动修改镜像文件的安全上下文,虚拟机就会因为权限不足而无法启动。
 

 

那么出现这样情况也是意料之中,我们可以通过添加allow规则或者手动修改镜像文件的类型来解决。目前还没有掌握添加allow规则的方式,所以只能通过chcon命令修改镜像文件的类型。
 

 

 
这样设置便可以启动系统,但是为了保证镜像文件的安全性,还要把镜像文件的安全上下文设置和VM进程一样的MCS标签。
 

 

这样VM便可以正常启动了。
然而当我么设置静态标签的域类型为unconfined_t时,即使不修改image镜像文件的安全上下文也可以正常启动,因为unconfined类型具有所有的访问权限。
所以我们再看下两个虚拟机的进程和镜像文件的安全上下文:
 

 

然后查看系统运行和关闭状态,安全上下文的区别:
 

 

 注意:并不是所有的virt-manager版本都有静态标签设置的项,在centos下的virt-manager就没有这一项,那么我们可以通过直接修改xml文件的方式给虚拟机指定标签,但是静态标签的实际意义不大,至少我目前没有想到什么需求必须要使用静态标签,毕竟svirt的出现的目的就是要保证虚拟机之间的隔离性,没有必要非要指定一个静态标签。
 
posted @ 2016-09-27 20:52  jack.chen  Views(1611)  Comments(0Edit  收藏  举报

以马内利