IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    XSM-FLASK学习笔记

    Liu Yutao发表于 2015-06-10 10:40:00
    love 0

    XSM-FLASK全称为:Xen Security Modules - FLux Advanced Security Kernel。这篇博文对其进行一个简单的介绍,资料主要翻译自这里。

    XSM是Xen提供的一个安全框架,允许管理者对整个系统进行细粒度的控制,换句话说,即运行管理者定义一套规则来管理虚拟机之间,虚拟机与Xen之间的交互,以及对系统资源(memory,device)的访问。

    FLASK是XSM中的一个模块实现,当然,之后可能还有其他的模块,那就是后话了。下面是一些例子,列举了XSM-FLASK可以做的几件事:

    • 禁止两台虚拟机之间通过event channel和grant table进行通信;
    • 将一些需要特权级别的操作安全地grant给某些非特权级虚拟机;
    • 控制哪些虚拟机能使用device passthrough;
    • 限制或者审计特权虚拟机中进行的某些特定操作;
    • 限制特权虚拟机对其他虚拟机的任意内存映射;
    • 将hypervisor中的不同模块(比如qemu和xenstore)进行隔离,防止它们之间互相影响。

    以上是一些基本说明,下面会具体介绍如何使用FLASK,以及FLASK中规则的一些语法定义。


    FLASK及其policy的编译流程

    在Xen 4.3之后的版本都对FLASK进行了比较全面的支持,如果要开启FLASK,需要在编译Xen之前修改Config.mk文件,将XSM_ENABLE和FLASK_ENABLE设成y,然后再开始编译。

    编译完Xen之后,需要编译FLASK的policy,在这之前需要先安装checkpolicy:

    $ aptitude install checkpolicy
    

    然后编译:

    $ cd $XEN
    $ make -C tools/flask/policy
    

    之后会在$XEN/tools/flask/policy目录下生成一个叫做xenpolicy-$XEN_FULLVESION的文件,这个就是生成的flask policy。


    启动Xen(with FLASK)

    在重启机器之前,我们需要在grub的配置中加上flask的选项,修改/etc/default/grub文件:

    GRUB_CMDLINE_XEN_DEFAULT="flask=

    其中,OPTIONs包括:

    • permissive表示:如果在bootloader阶段找到了一个policy,则会被加载;如果没有,或者发生错误,错误报告会被写到一个buffer,但是不会阻止系统启动。该模式可以通过xl setenforce改为enforcing模式;
    • enforcing表示:在创建domain0之前会强制要求提供一个policy,否则无法启动系统;
    • late表示:在bootloader阶段不会load相关的policy,可以在系统启动之后通过xl loadpolicy加载相应的policy,一旦policy被加载则进入enforcing模式;
    • disabled表示:XSM会被设成dummy module,该模块和没有编译XSM所产生的效果是一样的,另外,一旦采用这个模式之后,FLASK是无法被重新加载的。

    需要注意的一点是,FLASK的policy需要被放在一个grub可以访问的目录下,如/boot/flask/,否则FLASK不会开启。另外,该policy选项需要写入grub的配置中,放在multiboot下面,如下所示:

    multiboot /boot/xen-VERSION.gz dom0_mem=1024M,max:1024M flask=enforcing
    module /boot/vmlinuz-X.Y-amd64 root=/dev/mapper/vg_system-root ro quiet
    module /boot/initrd.img-X.Y
    module /boot/flask/xenpolicy-VERSION
    

    利用XSM security label创建虚拟机

    当通过上面所提到的方式启动Xen之后,FLASK也就开启了,那么我们在创建虚拟机的时候就需要在其配置中增加一个security label(安全标签),否则,该虚拟机会被标记为“unlabeled”,例子如下所示:

    seclabel='system_u:system_r:domU_t'
    

    安全标签有user,role和type表示,这些会在之后进行介绍。另外我们需要在policy中对相应的主体进行正确的权限设置。对于“unlabeled”的虚拟机,如果FLASK并没进入enforcing模式,或者进入了enforcing模式但定义了相关标签的权限,则不会有问题,否则,在其调用某些操作的时候会被禁止。

    通过xl list -Z命令可以查看当前虚拟机所具有的安全标签。

    通过xl dmesg | grep avc命令可以查看FLASK相关的log记录。


    FLASK policies

    增加一个security module

    我们可以把security module(安全模块)当做将一系列规则进行封装所产生的集合,如果要增加一个自定义的安全模块,我们需要在$XEN/tools/flask/policy/policy/modules.conf文件中加一行:

     = on
    

    同时在$XEN/tools/flask/policy/policy/modules/目录下增加两个文件:

    .te
    .if
    

    其中.te文件定义了相应规则的的描述,而.if文件定义了一系列在.te文件中会被用到的宏(macros)。

    在XSM-FLASK中有一个默认的模块:xen。如果存在多个模块(比如用户自己定义了多个模块),那么这些模块中不能有重复的type和role的定义。当模块定义好之后,可以参照’FLASK policy的编译流程’进行编译,并将其放在目标目录中(如/boot/flask),这样在xen启动的时候就会加载,或者通过xl loadpolicy进行手动加载。

    定义Types, roles, users和attributes

    在安全模块中会定义许多规则,对于一个特定的规则,说白了就是规定了某个主体(source subject)对另一个主体(target subject)进行的一系列访问和操作(如hypercall)的权限(deny or allow),比如规定:

    某个集合中的虚拟机(source)不能向(deny)虚拟机监控器Xen(target)调用某个hypercall(operation)
    

    那么这些集合就需要通过一系列的层级进行定义,也就引入了接下来需要讨论的type, role, users和attributes。可以结合$XEN/tools/flask/policy/policy/modules/xen.te文件中的例子进行更具体的了解。

    Policy Attribute

    attribute定义了一个抽象的属性,它可以被附属在接下来要介绍的type主体上,即表示某个type具备哪些attributes。

    Policy Type

    type是整个policy定义规范中最低的一个主体级别,它可以被用来在某个规则中指定source和target的类型。定义type的方式是:

    type new_type_t ;
    

    比如在示例文件中,定义了一个type:

    type xen_t, xen_type, mls_priv;
    

    其中xen_t即为type的标示符,而后面的xen_type和mls_priv则是相应的attribute,也就是说每个type可能会带有多个不同的attributes。

    当我们需要定义一个规则的时候,可以通过type来指定对应的源和目标主体。比如需要定义某个hypercall的调用是被允许的,可以这么写:

    allow  : ;
    

    其中,security class会在之后介绍,简单来说,它定义了一系列具有相关性的hypercall的集合。一个具体的例子:

    allow dom0_t security_t:security check_context;
    

    定义了dom0_t type的主体可以向security_t type主体调用security class中的check_context hypercall。

    另外,如果同时定义多个同一个class中的hypercall,可以用{}将其括起来,例如:

    allow dom0_t dom0_t:resource { add remove };
    

    除了用type表示的主体,我们也可以直接用attribute来表示主体,如:

    allow domain_type xen_t:xen tmem_op;
    

    即表示所有具有domain_type属性的type主体都可以向xen_t type主体调用xen class中的tmem_op hypercall。

    Policy Role

    role是处于type上一层级的主体级别,用户可以定义某个role由多个types组成,比如:

    role system_r
    role system_r types { xen_type domain_type };
    

    可以看到,role的types是采用attribute的方式定义的,即定义具有某个attribute的所有types都属于这个role。如果要定义具有某个attribute的除掉某个type的所有types,则通过在该type之前加上一个-进行标示,如:

    role vm_r
    role vm_r types {domain_type -dom0_t };
    

    Policy Users

    user作为policy中的最高层级的主体级别,它并不被定义在.te文件中,它们是被定义在$XEN/tools/flask/policy/policy/users文件中。因此我们可以跨安全模块共用同一个user。在默认情况下,FLASK定义了三个users:system_u, customer_t和customer_2。

    增加Policy constraints

    FLASK可以通过在$XEN/tools/flask/policy/policy/constraints文件中定义规则来限制某些操作。在默认的情况下,FLASK规则定义了两条constraints(限制规则)来防止不同用户之间event channel和grant table的交互。一条限制规则语法如下:

    constrain  {  } ( expression );
    

    比如例子中的:

    constrain grant { map_read map_write copy } (
      u1 == system_u or
      u2 == system_u or
      u1 == u2
    );
    

    这条限制规则表示如果属于grant class的这些hypercall可以被执行,当且仅当expression中的条件成立。其中,expression可以包含之前定义好的所有user, role和type主体,其语法规则如下:

    expression : (expresion)
          | not expression
          | expression and expression
          | expression or expression
          | u1 op u2
          | r1 role_op r2
          | t1 op t2
          | u1 op names
          | u2 op names
          | r1 op names
          | r2 op names
          | t1 op names
          | t2 op names
    
    op : == | !=
    role_op : == | != | eq | dom | domby | incomp
    
    names : name | { name_list }
    name_list : name | name_list name
    

    Security classes

    security class被定义在$XEN/xen/xsm/flask/policy/access_vectors文件中,每个hypercall被分配在了其中一个class中,需要注意的是,每一个class最多只能有32个hypercalls。下面简单介绍下默认的几个classes,相关的hypercall的描述可以直接看这里。

    • class xen包含了所有在hypervisor中进行的操作,其source为执行hypercall的domain,target为xen (xen_t type);
    • class domain & class domain2包含了某个domain调用另一个domain或者调用自己的操作,source为执行hypercall的domain,target为被调用的domain(包括_self和_target的type);
    • class hvm类似于domain,除了它是针对HVM domain;
    • class event用于描述event channels;
    • class grant用于描述grant mapping;
    • class mmu用于描述不是采用grant机制映射的内存页;
    • class shadow(这个不清楚是干嘛的);
    • class resource用于描述硬件设备passthrough所使用的资源,包括IRQ, MMIO regions, I/O ports, PCI device等;
    • class security用于描述和FLASK相关的操作。

    以上即为XSM-FLASK最基本的介绍,我也还正处于学习阶段,其它更细节的部分和更直观的实例会在以后的博文中进行说明。



沪ICP备19023445号-2号
友情链接