danwalsh


Dan Walsh's Blog

Got SELinux?


Previous Entry Add to Memories Share Next Entry
Understanding MCS Separation.
danwalsh
We designed a new way of using MCS, Multi Category Security, when we developed sVirt (Secure Virtualization) a few years ago.

To understand MCS it is helpful to understand something about MLS.

When Red Hat Enterprise Linux 5 came out, we had a done a lot of work adding MLS, Multi Level Security.  MLS requires the Belle & La Padula model of security.  This model takes into account the "Level and Category" of the data, and adds rules like a higher level process (TopSecret) is not allowed to write down (Secret) and a lower level (Secret) process is not allowed to read a higher level data (TopSecret).  The simple description of categories would be in order to read or write your process must have all the categories of the target.    Levels can go from s0 (SystemLow) to s15 (SystemHigh).  Then you can have any combination of 1024 categories.

In MCS we stole the idea of categories and dropped the concept of levels.

As I mentioned above the process category most include ALL of the categories of the target, otherwise MCS separation would block the access.   It is best to see an example of this.

Say I have a process labeled system_u:system_r:svirt_t:s0:c1,c2 from MCS Separation point of view.  This process would be allowed to access any file with any of these 4 MCS labels.

  • s0

  • s0:c1

  • s0:c2

  • s0:c1,c2

Since most files on a targeted system have the MCS label s0.  MCS Labeling does not block much mcs constrained applications.

By convention MCS confinement always uses two categories, and the categories can not be the same.  s0:c1,c1 == s0:c1.  Secondarily tools that launch MCS separate apps like libvirt and sandbox, make sure they never launch two processes with the same MCS label.  Which means we guarantee that two svirt_t always have two MCS labels that no other svirt_t or svirt_image_t would have.  Therefore a process running svirt_t:s0:c1,c2 would not be prevented by  MCS from access to any file with a MCS label of s0 or s0:c1,c2.  It would be denied from reading any file labeled s0:c1,c3 or s0:c2,c4 or s0:c4,c6.

But looking at MCS separation as the only control, misses out on type enforcement controls.

svirt_t access

We define our virtual machines as svirt_t type, and then we define rules about which types an svirt_t type is allowed access to.  If I wanted to see which types svirt_t is allowed to write, I could execute the following command.


# sesearch -A -s svirt_t -c file -p write -C | grep open | grep -v ^D
   allow virt_domain svirt_tmp_t : file { ioctl read write create getattr setattr lock append unlink link rename open } ;
   allow svirt_t xen_image_t : file { ioctl read write getattr lock append open } ;
   allow virt_domain svirt_image_t : file { ioctl read write create getattr setattr lock append unlink link rename open } ;
   allow virt_domain svirt_tmpfs_t : file { ioctl read write create getattr setattr lock append unlink link rename open } ;
   allow virt_domain virt_cache_t : file { ioctl read write create getattr setattr lock append unlink link rename open } ;
   allow virt_domain qemu_var_run_t : file { ioctl read write create getattr setattr lock append unlink link rename open } ;
   allow virt_domain anon_inodefs_t : file { ioctl read write getattr lock append open } ;
   allow virt_domain svirt_home_t : file { ioctl read write create getattr setattr lock append unlink link rename open } ;
   allow svirt_t svirt_t : file { ioctl read write getattr lock append open } ;
ET allow virt_domain dosfs_t : file { ioctl read write create getattr setattr lock append unlink link rename open } ; [ virt_use_usb ]
ET allow virt_domain usbfs_t : file { ioctl read write getattr lock append open } ; [ virt_use_usb ]

This means a confined virtual machine running as svirt_t:s0:c1,c2 would ONLY allowed to write to the following file types IFF they are MCS labeled s0 or s0:c1,c2

svirt_tmp_t, svirt_image_t, svirt_tmpfs_t, virt_cache_t, qemu_var_run_t, svirt_home_t,

dosfs_t and usbfs_t iff the virt_use_usb boolean is turned on, perhaps we should turn this off by default.

anon_inodefs_t and svirt_t are not file types, svirt_t is a process types which would be in /proc.

libvirt and the kernel need to ensure that non of these files get labeled with s0.

Openshift domains are allowed to write/open

Kernel file systems anon_inodefs_t, openshift_t,hugetlbfs_t,  security_t

openshift_tmp_t, openshift_rw_file_t, openshift_tmpfs_t

MCS Constrained Types

Thee following types are MCS Constrained.

seinfo  -amcs_constrained_type -x
   mcs_constrained_type
      svirt_lxc_net_t
      openshift_app_t
      openshift_min_t
      openshift_net_t
      openshift_min_app_t
      openshift_net_app_t
      svirt_tcg_t
      netlabel_peer_t
      sandbox_x_t
      svirt_t
      sandbox_min_t
      sandbox_net_t
      sandbox_web_t
      openshift_t
      sandbox_t

Yes libvirt's goal is to pick an Unique MCS Label for svirt_t (the process) and svirt_image_t (the image label).

When it gets a unique one, it assigns it to all of that virtual machines content, then launches the process.

It always picks a 2 UNIQUE category MCS label, and there for no two labels are able to write to each others labels.

When libvirt stops a virtual machine, it relabels all of the content back to a TYPE label which no virtual machines can read or write.

For example say you had a virtual machine with an image file

/var/lib/libvirt/images/RHEL6.5.img

When the virtual machine is running as svirt_t:s0:c1,c2 this image will be labeled svirt_image_t:s0:c1,c2 When the VM is stopped libvirt will relabel the image to virt_image_t:s0.

Type enforcement prevents any svirt_t from reading or writing virt_image_t.

You are viewing danwalsh