Difference between revisions of "NB VM"

From SELinux Wiki
Jump to: navigation, search
(Shared Image Mode)
(Xen Support)
(3 intermediate revisions by 2 users not shown)
Line 1: Line 1:
 
= SELinux Virtual Machine Support =
 
= SELinux Virtual Machine Support =
SELinux support is available in the KVM/QEMU and Xen virtual machine (VM) technologies<ref name="ftn29">KVM (Kernel-based Virtual Machine) and Xen are classed as 'bare metal' hypervisors and they rely on other services to manage the overall VM environment. QEMU (Quick Emulator) is an emulator that emulates the BIOS and I/O device functionality and can be used standalone or with KVM and Xen.</ref> that are discussed in the sections that follow, however the package documentation should be read for how these products actually work and how they are configured.  
+
SELinux support is available in the KVM/QEMU and Xen virtual machine (VM) technologies<ref name="ftn25">KVM (Kernel-based Virtual Machine) and Xen are classed as 'bare metal' hypervisors and they rely on other services to manage the overall VM environment. QEMU (Quick Emulator) is an emulator that emulates the BIOS and I/O device functionality and can be used standalone or with KVM and Xen.</ref> that are discussed in the sections that follow, however the package documentation should be read for how these products actually work and how they are configured.  
  
Currently the main SELinux support for virtualisation is via <tt>libvirt</tt> that is an open-source virtualisation API that can be used to dynamically load guest VMs on behalf of the virtualisation product. Security extensions were added as a part of the [http://selinuxproject.org/page/SVirt Svirt] project and the SELinux implementation for the KVM/QEMU package (<tt>qemu-kvm</tt> and <tt>libvirt</tt> rpms) is discussed using some examples. The Xen product has Flask/TE services that can be builtas an optional service, although it can also use the security enhanced <tt>libvirt</tt> services as well.
+
Currently the main SELinux support for virtualisation is via <tt>libvirt</tt> that is an open-source virtualisation API used to dynamically load guest VMs. Security extensions were added as a part of the [http://selinuxproject.org/page/SVirt Svirt] project and the SELinux implementation for the KVM/QEMU package (<tt>qemu-kvm</tt> and <tt>libvirt</tt> rpms) is discussed using some examples. The Xen product has Flask/TE services that can be built as an optional service, although it can also use the security enhanced <tt>libvirt</tt> services as well.
  
The sections that follow give an introduction to KVM/QEMU and then the <tt>libvirt</tt> support with some examples that make use of the Virtual Machine Manager (<tt>virt-manager</tt> rpm) to configure VMs, an overview of the Xen implementation then follows.
+
The sections that follow give an introduction to KVM/QEMU, then <tt>libvirt</tt> support with some examples using the Virtual Machine Manager to configure VMs, then an overview of the Xen implementation follows.
 +
 
 +
To ensure all dependencies are installed run:
 +
<pre>
 +
yum install libvirt
 +
yum install qemu
 +
yum install virt-manager
 +
</pre>
  
 
== KVM / QEMU Support ==
 
== KVM / QEMU Support ==
KVM is a kernel loadable module that uses the Linux kernel as a hypervisorand makes use of a modified QEMU emulator to support the hardware I/O emulation. The "[http://www.redhat.com/f/pdf/rhev/DOC-KVM.pdf Kernel-based Virtual Machine]" document gives a good overview of how KVM and QEMU are implemented. It also provides an introduction the virtualisation in general.  
+
KVM is a kernel loadable module that uses the Linux kernel as a hypervisor and makes use of a modified QEMU emulator to support the hardware I/O emulation. The "[http://www.redhat.com/f/pdf/rhev/DOC-KVM.pdf Kernel-based Virtual Machine]" document gives a good overview of how KVM and QEMU are implemented. It also provides an introduction to virtualisation in general. Note that KVM requires virtulisation support in the CPU (Intel-VT or AMD-V extensions).
 
+
The SELinux support for VMs is implemented by the <tt>libvirt</tt> sub-system that is used to manage the VM images using a Virtual Machine Manager, and as KVM is based on Linux it has SELinux support by default. There are also Reference Policy modules to support the overall infrastructure (KVM support is in various kernel and system modules with a <tt>virt</tt> module supporting the <tt>libvirt</tt> services). The [http://taiga.selinuxproject.org/~rhaines/diagrams/20-KVM.png KVM Environment] diagram shows a high level overview with two VMs running in their own domains. The libsvirt Support section below shows how to configure these and their VM image files.
+
  
 +
The SELinux support for VMs is implemented by the <tt>libvirt</tt> sub-system that is used to manage the VM images using a Virtual Machine Manager, and as KVM is based on Linux it has SELinux support by default. There are also Reference Policy modules to support the overall infrastructure (KVM support is in various kernel and system modules with a <tt>virt</tt> module supporting the <tt>libvirt</tt> services).The [http://taiga.selinuxproject.org/~rhaines/NB4-diagrams/18-kvm.png KVM Environment] diagram shows a high level overview with two VMs running in their own domains. The [[#libsvirt Support | libvirt Support]] section shows how to configure these and their VM image files.
  
 
== libvirt Support ==
 
== libvirt Support ==
The Svirt project added security hooks into the <tt>libvirt</tt> library that is used by the <tt>libvirtd</tt> daemon. This daemon is used by a number of VM products (such as KVM/QEMU and Xen) to start their VMs running as guest operating systems.  
+
The Svirt project added security hooks into the <tt>libvirt</tt> library that is used by the <tt>libvirtd</tt> daemon. This daemon is used by a number of VM products (such as KVM, QEMU and Xen) to start their VMs running as guest operating systems.
 +
 
 +
The VM supplier can implement any security mechanism they require using a product specific libvirt [http://libvirt.org/drvqemu.html driver] that will load and manage the images. The SELinux implementation supports four methods of labeling VM images, processes and their resources with support from the Reference Policy <tt>modules/services/virt.*</tt> loadable module<ref name="ftn26">The various images would have been labeled by the <tt>virt</tt> module installation process (see the <tt>virt.fc</tt> module file or the policy <tt>file_contexts</tt> file <tt>libvirt</tt> entries). If not, then need to ensure it is relabeled by the most appropriate SELinux tool.</ref>. To support this labeling, <tt>libvirt</tt> requires an MCS or MLS enabled policy as the <tt>level</tt> entry of the security context is used (<tt>user:role:type:level</tt>).
 +
 
 +
The link [http://libvirt.org/drvqemu.html#securityselinux http://libvirt.org/drvqemu.html#securityselinux] has details regarding the QEMU driver and the SELinux confinement modes it supports.
 +
 
 +
== VM Image Labeling ==
 +
This sections assumes VM images have been generated using the simple Linux kernel available at: [http://wiki.qemu.org/Testing http://wiki.qemu.org/Testing] (the <tt>linux-0.2.img.bz2</tt> disk image), this image was renamed to reflect each test, for example '<tt>Dynamic_VM1.img</tt>'.
  
The security hooks can be utilised by any security mechanism by the VM supplier providing a product specific libvirt [http://libvirt.org/drvqemu.html driver] that loads and manages the images. The SELinux implementation (when SELinux is enabled on the host system) supports four methods of labeling VM images, processes and their resources with support from the Reference Policy <tt>modules/services/virt.*</tt> loadable module<ref name="ftn30">The various images would have been labeled by the <tt>virt</tt> module installation process (see the <tt>virt.fc</tt> module file or the policy <tt>file_contexts</tt> file <tt>libvirt</tt> entries). If not, then need to ensure it is relabeled by the most appropriate SELinux tool.</ref>. To support this labeling, <tt>libvirt</tt> requires an MCS or MLS enabled policy as the <tt>level</tt> entry of the security context is used (<tt>user:role:type:level</tt>) .
+
These images can be generated using the VMM by selecting the 'Create a new virtual machine' menu, 'importing existing disk image' then in step 2 Browse... selecting 'Choose Volume: <tt>Dynamic_VM1.img</tt>' with OS type: <tt>Linux</tt>, Version: <tt>Generic 2.6.x kernel</tt> and change step 4 'Name' to <tt>Dynamic_VM1</tt>.
  
=== Default Mode ===
+
=== Dynamic Labeling ===
The default mode is where each VM is run under its own dynamically configured domain and image file therefore isolating the VMs from each other (i.e. every time the system is rebooted a different and unique MCS label will be generated to confine each VM to its own domain). This mode is implemented as follows:
+
The default mode is where each VM is run under its own dynamically configured domain and image file therefore isolating the VMs from each other (i.e. every time the VM is run a different and unique MCS label will be generated to confine each VM to its own domain). This mode is implemented as follows:
  
* An initial context for the process is obtained from the <tt>/etc/selinux/<policy_name>/contexts/virtual_domain_context</tt> file (the default is <tt>system_u:system_r:svirt_t:s0</tt>).
+
# An initial context for the process is obtained from the <tt><nowiki>/etc/selinux/<</nowiki>SELINUXTYPE>/contexts/virtual_domain_context</tt> file (the default is <tt>system_u:system_r:svirt_tcg_t:s0</tt>).
* An initial context for the image file label is obtained from the <tt>/etc/selinux/<policy_name>/contexts/virtual_image_context</tt> file. The default is <tt>system_u:system_r:svirt_image_t:s0</tt> that allows read/write of image files.
+
# An initial context for the image file label is obtained from the <tt><nowiki>/etc/selinux/<</nowiki>SELINUXTYPE>/contexts/virtual_image_context</tt> file. The default is <tt>system_u:system_r:svirt_image_t:s0</tt> that allows read/write of image files.
* When the image is used to start the VM a random MCS <tt>level</tt> is generated and added to the process context and the image object context. The process and image objects are then transitioned to the context by the<tt> libselinux</tt> API calls <tt>setfilecon</tt> and <tt>setexeccon</tt> respectively (see <tt>security_selinux.c</tt> in the <tt>libvirt </tt>source). The following example shows two VM sessions having different label as they were launched during the same boot session:
+
# When the image is used to start the VM, a random MCS <tt>level</tt> is generated and added to the process context and the image file context. The process and image files are then transitioned to the context by the<tt> libselinux</tt> API calls <tt>setfilecon</tt> and <tt>setexeccon</tt> respectively (see <tt>security_selinux.c</tt> in the <tt>libvirt </tt>source). The following example shows two running VM sessions each having different labels:
  
 
{| border="1"
 
{| border="1"
| '''VM'''
+
| '''VM Name'''
 
| '''Object'''
 
| '''Object'''
 
| '''Dynamically assigned security context '''
 
| '''Dynamically assigned security context '''
  
 
|-
 
|-
VM1
+
Dynamic_VM1
 
| Process
 
| Process
<tt>system_u:system_r:svirt_t:s0:c585,c813</tt>
+
|  system_u:system_r:svirt_tcg_t:s0:c585,c813
  
 
|-
 
|-
VM1
+
|   
 
| File
 
| File
<tt>system_u:system_r:svirt_image_t:s0:c585,c813</tt>
+
|  system_u:system_r:svirt_image_t:s0:c585,c813
  
 
|-
 
|-
VM2
+
Dynamic_VM2
 
| Process
 
| Process
<tt>system_u:system_r:svirt_t:s0:c535,c601</tt>
+
|  system_u:system_r:svirt_tcg_t:s0:c535,c601
  
 
|-
 
|-
VM2
+
|   
 
| File
 
| File
<tt>system_u:system_r:svirt_image_t:s0:c535,c601</tt>
+
|  system_u:system_r:svirt_image_t:s0:c535,c601
  
 
|}
 
|}
  
  
The running image <tt>ls -Z</tt> and <tt>ps -eZ</tt> are as follows and for completeness an <tt>ls -Z</tt> is shown when both VMs have been stopped:
+
The running image <tt>ls -Z</tt> and <tt>ps -eZ</tt> are as follows, and for completeness an <tt>ls -Z</tt> is shown when both VMs have been stopped:
 
<pre>
 
<pre>
 
# Both VMs running:
 
# Both VMs running:
 
ls -Z /var/lib/libvirt/images
 
ls -Z /var/lib/libvirt/images
system_u:object_r:svirt_image_t:s0:c585,c813 Test_VM1.img
+
system_u:object_r:svirt_image_t:s0:c585,c813 Dynamic_VM1.img
system_u:object_r:svirt_image_t:s0:c535,c601 Test_VM2.img
+
system_u:object_r:svirt_image_t:s0:c535,c601 Dynamic_VM2.img
  
 
ps -eZ | grep qemu
 
ps -eZ | grep qemu
system_u:system_r:svirt_t:s0:c585,c813 8707 ? 00:00:44 qemu
+
system_u:system_r:svirt_tcg_t:s0:c585,c813 8707 ? 00:00:44 qemu-system-x86
system_u:system_r:svirt_t:s0:c1022,c535 8796 ? 00:00:37 qemu
+
system_u:system_r:svirt_tcg_t:s0:cc535,c601 8796 ? 00:00:37 qemu-system-x86
  
# Both VMs stopped (note that the categories are now missing AND the type has changed from svirt_image_t to virt_image_t):
+
# Both VMs stopped (note that the categories are now missing AND
 +
# the type has changed from svirt_image_t to virt_image_t):
 
ls -Z /var/lib/libvirt/images
 
ls -Z /var/lib/libvirt/images
system_u:object_r:virt_image_t:s0 Test_VM1.img
+
system_u:object_r:virt_image_t:s0 Dynamic_VM1.img
system_u:object_r:virt_image_t:s0 Test_VM2.img
+
system_u:object_r:virt_image_t:s0 Dynamic_VM2.img
 
</pre>
 
</pre>
  
 +
=== Shared Image ===
 +
If the disk image has been set to shared, then a dynamically allocated <tt>level</tt> will be generated for each VM process instance, however there will be a single instance of the disk image.
  
=== Shared Image Mode ===
+
The Virtual Machine Manager can be used to set the image as shareable by checking the <tt>Shareable</tt> box as shown in the [http://taiga.selinuxproject.org/~rhaines/NB4-diagrams/19-shareable.png Setting the Virtual Disk as Shareable] screen shot.
If the disk image has been set to shared, then a dynamically allocated <tt>level</tt> will be generated for each VM process instance, however there will be a single instance of the disk image.  
+
  
The Virtual Machine Manager can be used to set the image as shareable by checking the <tt>Shareable</tt> box as shown in the [http://taiga.selinuxproject.org/~rhaines/diagrams/21-Shareable.png Setting the image as Shareable or Readonly] screen.
+
This will set the image (<tt>Shareable_VM.xml</tt>) resource XML configuration file located in the <tt>/etc/libvirt/qemu</tt> directory <tt><nowiki><disk></nowiki></tt> contents as follows:
 
+
This will set the image (<tt>Test_VM1.xml</tt>) resource XML configuration file located in the <tt>/etc/libvirt/qemu</tt> directory <tt><disk></tt> contents as follows:
+
 
<pre>
 
<pre>
# /etc/libvirt/qemu/Test_VM1.xml:
+
# /etc/libvirt/qemu/Shareable_VM.xml:
 +
 
 
<disk type='file' device='disk'>
 
<disk type='file' device='disk'>
<driver name='qemu' type='raw'/>
+
    <driver name='qemu' type='raw'/>
<source file='/var/lib/libvirt/images/Test_VM1.img'/>
+
    <source file='/var/lib/libvirt/images/Shareable_VM.img'/>
<target dev='hda' bus='ide'/>
+
    <target dev='hda' bus='ide'/>
<shareable/>
+
    <shareable/>
 +
    <address type='drive' controller='0' bus='0' unit='0'/>
 
</disk>
 
</disk>
 
</pre>
 
</pre>
  
As the two VMs will share the same image, the <tt>Test_VM1</tt> image needs to be cloned and its XML file <tt><disk></tt> contents are as follows (note that it has the same shared image source file name):
+
As the two VMs will share the same image, the <tt>Shareable_VM</tt> service needs to be cloned and the VM resource name selected was <tt>Shareable_VM-clone</tt> as shown in this [http://taiga.selinuxproject.org/~rhaines/NB4-diagrams/20-clone.png screen shot].
 +
 
 +
The resource XML file <tt><nowiki><disk></nowiki></tt> contents generated are shown - note that it has the same <tt>source file</tt> name as the <tt>Shareable_VM.xml</tt> file shown above.
 
<pre>
 
<pre>
# /etc/libvirt/qemu/Test_VM1-clone.xml:
+
# /etc/libvirt/qemu/Shareable_VM-clone.xml:
 +
 
 
<disk type='file' device='disk'>
 
<disk type='file' device='disk'>
<driver name='qemu' type='raw'/>
+
    <driver name='qemu' type='raw'/>
<source file='/var/lib/libvirt/images/Test_VM1.img'/>
+
    <source file='/var/lib/libvirt/images/Shareable_VM.img'/>
<target dev='hda' bus='ide'/>
+
    <target dev='hda' bus='ide'/>
<shareable/>
+
    <shareable/>
 +
    <address type='drive' controller='0' bus='0' unit='0'/>
 
</disk>
 
</disk>
 
</pre>
 
</pre>
  
Now that the image has been configured as shareable, the following initialisation process will take place:
 
  
* An initial context for the process is obtained from the <tt>/etc/selinux/<policy_name>/contexts/virtual_domain_context</tt> file (the default is <tt>system_u:system_r:svirt_t:s0</tt>).
+
With the targeted policy on F-20 the shareable option gave a error when the VMs were run as follows:
* An initial context for the image file label is obtained from the <tt>/etc/selinux/<policy_name>/contexts/virtual_image_context</tt> file. The default is <tt>system_u:system_r:svirt_image_t:s0</tt> that allows read/write of image files.
+
* When the image is used to start the VM a random MCS level is generated and added to the process context (but not the image object). The process and image objects are then transitioned to the appropriate context by the<tt> libselinux</tt> API calls <tt>setfilecon</tt> and <tt>setexeccon</tt> respectively. The following example shows each VM having the same file label but different process labels:
+
 
+
{| border="1"
+
| '''VM'''
+
| '''Object'''
+
| '''Default security context '''
+
 
+
|-
+
|  VM1
+
| Process
+
|  <tt>system_u:system_r:svirt_t:s0:c231,c245</tt>
+
 
+
|-
+
|  VM1
+
| File
+
|  <tt>system_u:system_r:svirt_image_t:s0</tt>
+
 
+
|-
+
|  VM2
+
| Process
+
|  <tt>system_u:system_r:svirt_t:s0:c695,c894</tt>
+
 
+
|-
+
|  VM1
+
| File
+
|  <tt>system_u:system_r:svirt_image_t:s0</tt>
+
 
+
|}
+
 
+
 
+
The running image <tt>ls -Z</tt> and <tt>ps -eZ</tt> are as follows and for completeness an <tt>ls -Z</tt> is shown when both VMs have been stopped:
+
 
<pre>
 
<pre>
# Both VMs running and sharing same image as Test_VM1 was cloned:
+
Could not allocate dynamic translator buffer
ls -Z /var/lib/libvirt/images
+
system_u:object_r:svirt_image_t:s0 Test_VM1.img
+
 
+
ps -eZ | grep qemu
+
system_u:system_r:svirt_t:s0:c231,c254 6748 ? 00:01:17 qemu
+
system_u:system_r:svirt_t:s0:c695,c894 7664 ? 00:00:03 qemu
+
 
+
# Both VMs stopped (note that the type has remained as svirt_image_t)
+
ls -Z /var/lib/libvirt/images
+
system_u:object_r:svirt_image_t:s0 Test_VM1.img
+
 
</pre>
 
</pre>
  
=== Readonly Image Mode ===
+
The audit log contained the following AVC message:
The <tt>readonly</tt> configuration sequence is similar to the <tt>shared</tt> option shown above with a dynamically allocated level generated for each VM process instance and the disk image can be shared. The major differences are that the disk image will be read only by setting the image context to <tt>virt_content_t</tt> (that enforces read only - see the <tt>virt.if</tt> module interface file - <tt>read_blk_files_pattern</tt>) instead of <tt>svirt_image_t</tt> (that allows read/write - <tt>rw_blk_files_pattern</tt>).
+
 
+
The Virtual Machine Manager can be used to set the image as read only by checking the <tt>Readonly</tt> box as shown in  the [http://taiga.selinuxproject.org/~rhaines/diagrams/21-Sharable.png Setting the image as Shareable or Readonly] screen. This will set the image (<tt>Test_VM1.xml</tt>) resource XML configuration file located in the <tt>/etc/libvirt/qemu</tt> directory <tt><disk></tt> contents as follows:
+
 
<pre>
 
<pre>
# /etc/libvirt/qemu/Test_VM1.xml:
+
type=AVC msg=audit(1326028680.405:367): avc: denied { execmem } for pid=5404 comm="qemu-system-x86"
<disk type='file' device='disk'>
+
scontext=system_u:system_r:svirt_t:s0:c121,c746 tcontext=system_u:system_r:svirt_t:s0:c121,c746 tclass=process
<driver name='qemu' type='raw'/>
+
<source file='/var/lib/libvirt/images/Test_VM1.img'/>
+
<target dev='hda' bus='ide'/>
+
<readonly/>
+
</disk>
+
 
</pre>
 
</pre>
  
As the two VMs will share the same image the <tt>Test_VM1</tt> image needs to be cloned and its XML file <tt><disk></tt> contents will be as follows:
+
To overcome this error, the following boolean needs to be enabled with <tt>'''setsebool'''(8)</tt> to allow access to shared memory (the <tt>-P</tt> option will set the boolean across reboots):
 
<pre>
 
<pre>
# /etc/libvirt/qemu/Test_VM1-clone.xml:
+
setsebool -P virt_use_execmem on
<disk type='file' device='disk'>
+
<driver name='qemu' type='raw'/>
+
<source file='/var/lib/libvirt/images/Test_VM1.img'/>
+
<target dev='hda' bus='ide'/>
+
<readonly/>
+
</disk>
+
 
</pre>
 
</pre>
  
Now that the image has been configured as <tt>readonly</tt>, the following initialisation process will take place:
+
Now that the image has been configured as shareable, the following initialisation process will take place:
 
+
* An initial context for the process is obtained from the <tt>/etc/selinux/<policy_name>/contexts/virtual_domain_context</tt> file (the default is <tt>system_u:system_r:svirt_t:s0</tt>).
+
* An initial context for the image file label is obtained from the <tt>/etc/selinux/<policy_name>/contexts/virtual_image_context</tt> file. The default for read only images is <tt>system_u:system_r:virt_content_t:s0</tt> as discussed above.
+
* When the image is used to start the VM a random MCS level is generated and added to the process context (but not the image object). The process and image objects are then transitioned to the appropriate context by the<tt> libselinux</tt> API calls <tt>setfilecon</tt> and <tt>setexeccon</tt> respectively. The following example shows each VM having the same file label but different process labels:
+
  
 +
# An initial context for the process is obtained from the <tt><nowiki>/etc/selinux/<</nowiki>SELINUXTYPE>/contexts/virtual_domain_context</tt> file (the default is <tt>system_u:system_r:svirt_tcg_t:s0</tt>).
 +
# An initial context for the image file label is obtained from the <tt><nowiki>/etc/selinux/<</nowiki>SELINUXTYPE>/contexts/virtual_image_context</tt> file. The default is <tt>system_u:system_r:svirt_image_t:s0</tt> that allows read/write of image files.
 +
# When the image is used to start the VM a random MCS level is generated and added to the process context (but not the image file). The process is then transitioned to the appropriate context by the<tt> libselinux</tt> API calls <tt>setfilecon</tt> and <tt>setexeccon</tt> respectively. The following example shows each VM having the same file label but different process labels:
  
 
{| border="1"
 
{| border="1"
| '''VM'''
+
| '''VM Name'''
 
| '''Object'''
 
| '''Object'''
| '''Default security context '''
+
| '''Security context '''
  
 
|-
 
|-
VM1
+
Shareable_VM
 
| Process
 
| Process
<tt>system_u:system_r:svirt_t:s0:c103,c950</tt>
+
|  system_u:system_r:svirt_tcg_t:s0:c231,c245
 
+
|-
+
|  VM1
+
| File
+
|  <tt>system_u:system_r:virt_content_t:s0</tt>
+
  
 
|-
 
|-
VM2
+
Shareable_VM-clone
 
| Process
 
| Process
<tt>system_u:system_r:svirt_t:s0:c312,c820</tt>
+
|  system_u:system_r:svirt_tcg_t:s0:c695,c894
  
 
|-
 
|-
| VM1
+
|  
 
| File
 
| File
<tt>system_u:system_r:virt_content_t:s0</tt>
+
|  system_u:system_r:svirt_image_t:s0
  
 
|}
 
|}
Line 208: Line 164:
 
The running image <tt>ls -Z</tt> and <tt>ps -eZ</tt> are as follows and for completeness an <tt>ls -Z</tt> is shown when both VMs have been stopped:
 
The running image <tt>ls -Z</tt> and <tt>ps -eZ</tt> are as follows and for completeness an <tt>ls -Z</tt> is shown when both VMs have been stopped:
 
<pre>
 
<pre>
# Both VMs running and sharing same image as Test_VM1 was cloned:
+
# Both VMs running and sharing same image:
 
ls -Z /var/lib/libvirt/images
 
ls -Z /var/lib/libvirt/images
system_u:object_r:virt_content_t:s0 Test_VM1.img
+
system_u:object_r:svirt_image_t:s0 Shareable_VM.img
  
 +
# but with separate processes:
 
ps -eZ | grep qemu
 
ps -eZ | grep qemu
system_u:system_r:svirt_t:s0:c103,c950 8756 ? 00:01:08 qemu
+
system_u:system_r:svirt_t:s0:c231,c254 6748 ? 00:01:17 qemu-system-x86
system_u:system_r:svirt_t:s0:c312,c820 9246 ? 00:01:03 qemu
+
system_u:system_r:svirt_t:s0:c695,c894 7664 ? 00:00:03 qemu-system-x86
  
# Both VMs stopped (note that the type remained as virt_content_t),
+
# Both VMs stopped (note that the type has remained as svirt_image_t)
# however if the disk type was reset to <shared/>, then it would be
+
# reset back to virt_image_t:s0 once the VM was running again.
+
 
ls -Z /var/lib/libvirt/images
 
ls -Z /var/lib/libvirt/images
system_u:object_r:virt_content_t:s0 Test_VM1.img
+
system_u:object_r:svirt_image_t:s0 Shareable_VM.img
 
</pre>
 
</pre>
 
  
 
=== Static Labeling ===
 
=== Static Labeling ===
It is possible to set static labels on each image file, however a consequence of this is that the image cannot be cloned therefore an image for each VM will be required. This is the method used to configure VMs on MLS systems as there is a known label that would define the security level. With this method it is also possible to configure two or more VMs with the same security context so that they can share resources.
+
It is possible to set static labels on each image file, however a consequence of this is that the image cannot be cloned using the VMM, therefore an image for each VM will be required. This is the method used to configure VMs on MLS systems as there is a known label that would define the security level. With this method it is also possible to configure two or more VMs with the same security context so that they can share resources. A useful reference is at: [http://libvirt.org/formatdomain.html#seclabel http://libvirt.org/formatdomain.html#seclabel].
  
If using the Virtual Machine Manager GUI, then by default it will start each VM running as they are built, therefore they need to be stopped and then configured for static labels and the image file will also need to be relabeled. An example VM configuration follows where the VM has been created as <tt>Static_VM1</tt> using the F-12 <tt>targeted</tt> policy in enforcing mode (just so all errors are flagged during the build):
+
If using the Virtual Machine Manager GUI, then by default it will start each VM running as they are built, therefore they need to be stopped and restarted once configured for static labels, the image file will also need to be relabeled. An example VM configuration follows where the VM has been created as <tt>Static_VM1</tt> using the F-20 <tt>targeted</tt> policy in enforcing mode (just so all errors are flagged during the build):
  
* Once the VM has been built, it will need to be stopped from the <tt>Static_VM1 Virtual Machine</tt> screen. Display the <tt>Security</tt> menu and select <tt>selinux</tt> as the <tt>Model</tt> and check the <tt>Static</tt> check box. The required security context can then be set - for this example <tt>svirt_t</tt> has been chosen as it is a valid context as shown in the [http://taiga.selinuxproject.org/~rhaines/diagrams/22-Static.png Static Configuration] screen.
+
* To set the required security context requires editing the <tt>Static_VM1</tt> configuration file using <tt>'''virsh'''(1)</tt> as follows:
 +
<pre>
 +
virsh edit Static_VM1
 +
</pre>
  
This context will be written to the <tt>Static_VM1.xml</tt> file in the <tt>/etc/libvirt/qemu</tt> directory as follows:
+
Then add the following at the end of the file:
 
<pre>
 
<pre>
<seclabel type='static' model='selinux'>
+
....
<label>system_u:system_r:svirt_t:s0:c1022.c1023</label>
+
</devices>
</seclabel>
+
 
 +
<!-- The <seclabel> tag needs to be placed btween the existing
 +
    </devices> and </domain> tags -->
 +
 
 +
    <seclabel type='static' model='selinux' relabel='no'>
 +
        <label>system_u:system_r:svirt_t:s0:c1022,c1023</label>
 +
    </seclabel>
 +
 
 +
</domain>
 
</pre>
 
</pre>
  
* If the VM is now started an error will be shown as follows as shown in the [http://taiga.selinuxproject.org/~rhaines/diagrams/23-image-start-error.png Image Start Error] screen.
+
: For this example <tt>svirt_t</tt> has been chosen as it is a valid context (however it will not run as explained in the text). This context will be written to the <tt>Static_VM1.xml</tt> configuration file in <tt>/etc/libvirt/qemu</tt>.
  
 +
* If the VM is now started an error will be shown as show in the this [http://taiga.selinuxproject.org/~rhaines/NB4-diagrams/21-error.png screen shot].
 
: This is because the image file label is incorrect as by default it is labeled <tt>virt_image_t</tt> when the VM image is built (and <tt>svirt_t</tt> does not have read/write permission for this label):
 
: This is because the image file label is incorrect as by default it is labeled <tt>virt_image_t</tt> when the VM image is built (and <tt>svirt_t</tt> does not have read/write permission for this label):
 
<pre>
 
<pre>
Line 246: Line 212:
 
</pre>
 
</pre>
  
There are a number of ways to fix this, such as adding an allow rule or changing the image file label. In this example the image file label will be changed using <tt>chcon</tt> as follows:
+
: There are a number of ways to fix this, such as adding an allow rule or changing the image file label. In this example the image file label will be changed using <tt>'''chcon'''(1)</tt> as follows:
 
<pre>
 
<pre>
 
# This command is executed from /var/lib/libvirt/images
 
# This command is executed from /var/lib/libvirt/images
Line 254: Line 220:
 
</pre>
 
</pre>
  
If required, the image can also be relabeled so that the <tt>[level]</tt> is the same as the process using <tt>chcon</tt> as follows:
+
: Optionally, the image can also be relabeled so that the <tt><nowiki>[level]</nowiki></tt> is the same as the process using <tt>chcon</tt> as follows:
 
<pre>
 
<pre>
 
# This command is executed from /var/lib/libvirt/images
 
# This command is executed from /var/lib/libvirt/images
Line 264: Line 230:
 
* Now that the image has been relabeled, the VM can now be started.  
 
* Now that the image has been relabeled, the VM can now be started.  
  
The following example shows two VMs (the <tt>unconfined_t</tt> configuration is discussed below):
+
The following example shows two static VMs (one is configured for <tt>unconfined_t</tt> that is allowed to run under the targeted policy - this was possible because the 's<tt>etsebool -P virt_transition_userdomain on</tt>'<tt> </tt>boolean was set that allows <tt>virtd_t</tt> domain to transition to a user domain (e.g. <tt>unconfined_t</tt>).
 
+
  
 
{| border="1"
 
{| border="1"
| '''VM'''
+
| '''VM Name'''
 
| '''Object'''
 
| '''Object'''
 
| '''Static security context '''
 
| '''Static security context '''
  
 
|-
 
|-
VM1
+
Static_VM1
 
| Process
 
| Process
<tt>system_u:system_r:svirt_t:s0:c1022,c1023</tt>
+
|  system_u:system_r:svirt_t:s0:c1022,c1023
  
 
|-
 
|-
| VM1
+
|  
 
| File
 
| File
<tt>system_u:system_r:svirt_image_t:s0:c1022,c1023</tt>
+
|  system_u:system_r:svirt_image_t:s0:c1022,c1023
  
 
|-
 
|-
VM2
+
Static_VM2
 
| Process
 
| Process
<tt>system_u:system_r:unconfined_t:s0:c11,c22</tt>
+
|  system_u:system_r:unconfined_t:s0:c11,c22
  
 
|-
 
|-
| VM2
+
|  
 
| File
 
| File
<tt>system_u:system_r:virt_image_t:s0</tt>
+
|  system_u:system_r:virt_image_t:s0
  
 
|}
 
|}
Line 297: Line 262:
 
The running image <tt>ls -Z</tt> and <tt>ps -eZ</tt> are as follows, and for completeness an <tt>ls -Z</tt> is shown when both VMs have been stopped:
 
The running image <tt>ls -Z</tt> and <tt>ps -eZ</tt> are as follows, and for completeness an <tt>ls -Z</tt> is shown when both VMs have been stopped:
 
<pre>
 
<pre>
# Both VMs running:
+
# Both VMs running (Note that Static_VM2 did not have file level reset):
 
ls -Z /var/lib/libvirt/images
 
ls -Z /var/lib/libvirt/images
 
system_u:object_r:svirt_image_t:s0:c1022,c1023 Static_VM1.img
 
system_u:object_r:svirt_image_t:s0:c1022,c1023 Static_VM1.img
system_u:object_r:virt_image_t:s0:c11,c22 Static_VM2.img
+
system_u:object_r:virt_image_t:s0 Static_VM2.img
  
 
ps -eZ | grep qemu
 
ps -eZ | grep qemu
system_u:system_r:svirt_t:s0:c585,c813 6707 ? 00:00:45 qemu
+
system_u:system_r:svirt_t:s0:c585,c813 6707 ? 00:00:45 qemu-system-x86
system_u:system_r:unconfined_t:s0:c11,c22 6796 ? 00:00:26 qemu
+
system_u:system_r:unconfined_t:s0:c11,c22 6796 ? 00:00:26 qemu-system-x86
 
+
# Both VMs stopped (note that Static_VM1.img was relabeled svirt_image_t to enable it to run, however Static_VM2.img is still labeled
+
# virt_image_t and runs okay. This is because the process is run as unconfined_t that is allowed to use virt_image_t):
+
  
 +
# Both VMs stopped (note that Static_VM1.img was relabeled svirt_image_t
 +
# to enable it to run, however Static_VM2.img is still labeled
 +
# virt_image_t and runs okay. This is because the process is run as
 +
# unconfined_t that is allowed to use virt_image_t):
 
system_u:object_r:svirt_image_t:s0:c1022,c1023 Static_VM1.img
 
system_u:object_r:svirt_image_t:s0:c1022,c1023 Static_VM1.img
 
system_u:object_r:virt_image_t:s0 Static_VM2.img
 
system_u:object_r:virt_image_t:s0 Static_VM2.img
 
</pre>
 
</pre>
 
==== Configuring the unconfined_t image ====
 
The objective of this section is to configure a VM domain that the targeted policy does not currently support. The domain chosen is <tt>unconfined_t</tt> as that is the default for general users and requires a minimal additional policy module. The steps required to enable the VM are:
 
 
* Using the Virtual Machine Manager, generate a VM (this has been called <tt>Static_VM2</tt>).
 
* Stop the VM and set a static context of <tt>system_u:system_r:unconfined_t:s0:c11,c22</tt>. This context will be written to the <tt>Static_VM2.xml</tt> file in the <tt>/etc/libvirt/qemu</tt> directory as follows:
 
<pre>
 
<seclabel type='static' model='selinux'>
 
<label>system_u:system_r:unconfined_t:s0:c11,c22</label>
 
</seclabel>
 
</pre>
 
 
* Before attempting to start the VM clear the audit log first so that a module can be generated with <tt>audit2allow</tt> to allow the VM to start:
 
<pre>
 
> /var/log/audit/audit.log
 
</pre>
 
 
* Now if the VM is started the following [http://taiga.selinuxproject.org/~rhaines/diagrams/24-image-execution-error.png Image Execution Error] will be shown on the screen.
 
 
This is because the <tt>libvirt</tt> daemon does not have permission to transition the VM process to the <tt>unconfined_t</tt> domain. The audit log AVC entry would be:
 
<pre>
 
type=AVC msg=audit(1271080140.988:30): avc: denied { transition } for pid=2000 comm="libvirtd" path="/usr/bin/qemu" dev=dm-0 ino=71778 scontext=system_u:system_r:virtd_t:s0-s0:c0.c1023 tcontext=system_u:system_r:unconfined_t:s0:c11,c22 tclass=process
 
 
type=SYSCALL msg=audit(1271080140.988:30): arch=40000003 syscall=11 success=no exit=-13 a0=b425c470 a1=b427f610 a2=b42a4a68 a3=0 items=0 ppid=1999 pid=2000 auid=4294967295 uid=107 gid=107 euid=107 suid=107 fsuid=107 egid=107 sgid=107 fsgid=107 tty=(none) ses=4294967295 comm="libvirtd" exe="/usr/sbin/libvirtd" subj=system_u:system_r:virtd_t:s0-s0:c0.c1023 key=(null)
 
</pre>
 
 
* To generate a loadable module that will allow the transition use the following commands:
 
<pre>
 
# These cmds will generate an unconfinedvm.pp module package:
 
 
cat /var/log/audit/audit.log | audit2allow -M unconfinedvm > unconfinedvm.te
 
 
# Once the package has been generated, it needs to be activated:
 
semodule -i unconfinedvm.pp
 
</pre>
 
 
* Once the module has been loaded and the policy rebuilt, the VM can now be started. For reference the module file generated by <tt>audit2allow</tt> consists of the following:
 
<pre>
 
module unconfinedvm 1.0;
 
 
require {
 
type unconfined_t;
 
type virtd_t;
 
class process transition;
 
}
 
 
#============= virtd_t ==============
 
allow virtd_t unconfined_t:process transition;
 
</pre>
 
 
  
 
== Xen Support ==
 
== Xen Support ==
This is not supported by SELinux in the usual way as it is built into the actual Xen software as a 'Flask/TE' extension<ref name="ftn31">This is a version of the SELinux security server, avc etc. that has been specifically ported for the Xen implementation.</ref> for the XSM (Xen Security Module). Also the Xen implementation has its own built-in policy (<tt>xen.te</tt>) and supporting definitions for access vectors, security classes and initial SIDs for the policy. These Flask/TE components run in Domain 0 as part of the domain management and control supporting the Virtual Machine Monitor (VMM) as shown in the [http://taiga.selinuxproject.org/~rhaines/diagrams/25-xen.png Xen Hypervisor] diagram.  
+
This is not supported by SELinux in the usual way as it is built into the actual Xen software as a 'Flask/TE' extension<ref name="ftn27">This is a version of the SELinux security server, avc etc. that has been specifically ported for the Xen implementation.</ref> for the XSM (Xen Security Module). Also the Xen implementation has its own built-in policy (<tt>xen.te</tt>) and supporting definitions for access vectors, security classes and initial SIDs for the policy. These Flask/TE components run in Domain 0 as part of the domain management and control supporting the Virtual Machine Monitor (VMM) as shown in the [http://taiga.selinuxproject.org/~rhaines/NB4-diagrams/22-xen.png Xen Hypervisor] diagram.  
  
The "[http://www.xen.org/files/Marketing/HowDoesXenWork.pdf How Does Xen Work]document describes the basic operation of Xen, the "[http://www.xen.org/files/xensummit_4/xsm-summit-041707_Coker.pdf Xen Security Modules]" document describes the XSM/Flask implementation, and the <tt>xsm-flask.txt</tt> file in the Xen source package describes how SELinux and its supporting policy is implemented.
+
The "[http://www.xen.org/files/Marketing/HowDoesXenWork.pdf How Does Xen Work] document describes the basic operation of Xen, the "[http://www.xen.org/files/xensummit_4/xsm-summit-041707_Coker.pdf Xen Security Modules]" describes the XSM/Flask implementation, and the <tt>xsm-flask.txt</tt> file in the Xen source package describes how SELinux and its supporting policy is implemented.
  
 
However (just to confuse the issue), there is another Xen policy module (also called <tt>xen.te</tt>) in the Reference Policy to support the management of images etc. via the Xen console.
 
However (just to confuse the issue), there is another Xen policy module (also called <tt>xen.te</tt>) in the Reference Policy to support the management of images etc. via the Xen console.
  
 +
For reference, the Xen policy supports additional policy language statements: <tt>iomemcon</tt>, <tt>ioportcon</tt>, <tt>pcidevicecon</tt> and <tt>pirqcon</tt> that are discussed in the [[KernelPolicyLanguage#Xen Statements | SELinux Policy Xen Statements]].
  
 +
 +
{| style="width: 100%;" border="0"
 +
|-
 +
| [[NB_Networking | '''Previous''']]
 +
| <center>[[NewUsers | '''Home''']]</center>
 +
| <center>[[NB_SandBox | '''Next''']]</center>
 +
|}
  
  
 
----
 
----
 
<references/>
 
<references/>
 +
 +
[[Category:Notebook]]

Revision as of 10:19, 8 December 2014

SELinux Virtual Machine Support

SELinux support is available in the KVM/QEMU and Xen virtual machine (VM) technologies[1] that are discussed in the sections that follow, however the package documentation should be read for how these products actually work and how they are configured.

Currently the main SELinux support for virtualisation is via libvirt that is an open-source virtualisation API used to dynamically load guest VMs. Security extensions were added as a part of the Svirt project and the SELinux implementation for the KVM/QEMU package (qemu-kvm and libvirt rpms) is discussed using some examples. The Xen product has Flask/TE services that can be built as an optional service, although it can also use the security enhanced libvirt services as well.

The sections that follow give an introduction to KVM/QEMU, then libvirt support with some examples using the Virtual Machine Manager to configure VMs, then an overview of the Xen implementation follows.

To ensure all dependencies are installed run:

yum install libvirt
yum install qemu
yum install virt-manager

KVM / QEMU Support

KVM is a kernel loadable module that uses the Linux kernel as a hypervisor and makes use of a modified QEMU emulator to support the hardware I/O emulation. The "Kernel-based Virtual Machine" document gives a good overview of how KVM and QEMU are implemented. It also provides an introduction to virtualisation in general. Note that KVM requires virtulisation support in the CPU (Intel-VT or AMD-V extensions).

The SELinux support for VMs is implemented by the libvirt sub-system that is used to manage the VM images using a Virtual Machine Manager, and as KVM is based on Linux it has SELinux support by default. There are also Reference Policy modules to support the overall infrastructure (KVM support is in various kernel and system modules with a virt module supporting the libvirt services).The KVM Environment diagram shows a high level overview with two VMs running in their own domains. The libvirt Support section shows how to configure these and their VM image files.

libvirt Support

The Svirt project added security hooks into the libvirt library that is used by the libvirtd daemon. This daemon is used by a number of VM products (such as KVM, QEMU and Xen) to start their VMs running as guest operating systems.

The VM supplier can implement any security mechanism they require using a product specific libvirt driver that will load and manage the images. The SELinux implementation supports four methods of labeling VM images, processes and their resources with support from the Reference Policy modules/services/virt.* loadable module[2]. To support this labeling, libvirt requires an MCS or MLS enabled policy as the level entry of the security context is used (user:role:type:level).

The link http://libvirt.org/drvqemu.html#securityselinux has details regarding the QEMU driver and the SELinux confinement modes it supports.

VM Image Labeling

This sections assumes VM images have been generated using the simple Linux kernel available at: http://wiki.qemu.org/Testing (the linux-0.2.img.bz2 disk image), this image was renamed to reflect each test, for example 'Dynamic_VM1.img'.

These images can be generated using the VMM by selecting the 'Create a new virtual machine' menu, 'importing existing disk image' then in step 2 Browse... selecting 'Choose Volume: Dynamic_VM1.img' with OS type: Linux, Version: Generic 2.6.x kernel and change step 4 'Name' to Dynamic_VM1.

Dynamic Labeling

The default mode is where each VM is run under its own dynamically configured domain and image file therefore isolating the VMs from each other (i.e. every time the VM is run a different and unique MCS label will be generated to confine each VM to its own domain). This mode is implemented as follows:

  1. An initial context for the process is obtained from the /etc/selinux/<SELINUXTYPE>/contexts/virtual_domain_context file (the default is system_u:system_r:svirt_tcg_t:s0).
  2. An initial context for the image file label is obtained from the /etc/selinux/<SELINUXTYPE>/contexts/virtual_image_context file. The default is system_u:system_r:svirt_image_t:s0 that allows read/write of image files.
  3. When the image is used to start the VM, a random MCS level is generated and added to the process context and the image file context. The process and image files are then transitioned to the context by the libselinux API calls setfilecon and setexeccon respectively (see security_selinux.c in the libvirt source). The following example shows two running VM sessions each having different labels:
VM Name Object Dynamically assigned security context
Dynamic_VM1 Process system_u:system_r:svirt_tcg_t:s0:c585,c813
File system_u:system_r:svirt_image_t:s0:c585,c813
Dynamic_VM2 Process system_u:system_r:svirt_tcg_t:s0:c535,c601
File system_u:system_r:svirt_image_t:s0:c535,c601


The running image ls -Z and ps -eZ are as follows, and for completeness an ls -Z is shown when both VMs have been stopped:

# Both VMs running:
ls -Z /var/lib/libvirt/images
system_u:object_r:svirt_image_t:s0:c585,c813 Dynamic_VM1.img
system_u:object_r:svirt_image_t:s0:c535,c601 Dynamic_VM2.img

ps -eZ | grep qemu
system_u:system_r:svirt_tcg_t:s0:c585,c813 8707 ? 00:00:44 qemu-system-x86
system_u:system_r:svirt_tcg_t:s0:cc535,c601 8796 ? 00:00:37 qemu-system-x86

# Both VMs stopped (note that the categories are now missing AND
# the type has changed from svirt_image_t to virt_image_t):
ls -Z /var/lib/libvirt/images
system_u:object_r:virt_image_t:s0 Dynamic_VM1.img
system_u:object_r:virt_image_t:s0 Dynamic_VM2.img

Shared Image

If the disk image has been set to shared, then a dynamically allocated level will be generated for each VM process instance, however there will be a single instance of the disk image.

The Virtual Machine Manager can be used to set the image as shareable by checking the Shareable box as shown in the Setting the Virtual Disk as Shareable screen shot.

This will set the image (Shareable_VM.xml) resource XML configuration file located in the /etc/libvirt/qemu directory <disk> contents as follows:

# /etc/libvirt/qemu/Shareable_VM.xml:

<disk type='file' device='disk'>
    <driver name='qemu' type='raw'/>
    <source file='/var/lib/libvirt/images/Shareable_VM.img'/>
    <target dev='hda' bus='ide'/>
    <shareable/>
    <address type='drive' controller='0' bus='0' unit='0'/>
</disk>

As the two VMs will share the same image, the Shareable_VM service needs to be cloned and the VM resource name selected was Shareable_VM-clone as shown in this screen shot.

The resource XML file <disk> contents generated are shown - note that it has the same source file name as the Shareable_VM.xml file shown above.

# /etc/libvirt/qemu/Shareable_VM-clone.xml:

<disk type='file' device='disk'>
    <driver name='qemu' type='raw'/>
    <source file='/var/lib/libvirt/images/Shareable_VM.img'/>
    <target dev='hda' bus='ide'/>
    <shareable/>
    <address type='drive' controller='0' bus='0' unit='0'/>
</disk>


With the targeted policy on F-20 the shareable option gave a error when the VMs were run as follows:

Could not allocate dynamic translator buffer

The audit log contained the following AVC message:

type=AVC msg=audit(1326028680.405:367): avc: denied { execmem } for pid=5404 comm="qemu-system-x86" 
scontext=system_u:system_r:svirt_t:s0:c121,c746 tcontext=system_u:system_r:svirt_t:s0:c121,c746 tclass=process

To overcome this error, the following boolean needs to be enabled with setsebool(8) to allow access to shared memory (the -P option will set the boolean across reboots):

setsebool -P virt_use_execmem on

Now that the image has been configured as shareable, the following initialisation process will take place:

  1. An initial context for the process is obtained from the /etc/selinux/<SELINUXTYPE>/contexts/virtual_domain_context file (the default is system_u:system_r:svirt_tcg_t:s0).
  2. An initial context for the image file label is obtained from the /etc/selinux/<SELINUXTYPE>/contexts/virtual_image_context file. The default is system_u:system_r:svirt_image_t:s0 that allows read/write of image files.
  3. When the image is used to start the VM a random MCS level is generated and added to the process context (but not the image file). The process is then transitioned to the appropriate context by the libselinux API calls setfilecon and setexeccon respectively. The following example shows each VM having the same file label but different process labels:
VM Name Object Security context
Shareable_VM Process system_u:system_r:svirt_tcg_t:s0:c231,c245
Shareable_VM-clone Process system_u:system_r:svirt_tcg_t:s0:c695,c894
File system_u:system_r:svirt_image_t:s0


The running image ls -Z and ps -eZ are as follows and for completeness an ls -Z is shown when both VMs have been stopped:

# Both VMs running and sharing same image:
ls -Z /var/lib/libvirt/images
system_u:object_r:svirt_image_t:s0 Shareable_VM.img

# but with separate processes:
ps -eZ | grep qemu
system_u:system_r:svirt_t:s0:c231,c254 6748 ? 00:01:17 qemu-system-x86
system_u:system_r:svirt_t:s0:c695,c894 7664 ? 00:00:03 qemu-system-x86

# Both VMs stopped (note that the type has remained as svirt_image_t)
ls -Z /var/lib/libvirt/images
system_u:object_r:svirt_image_t:s0 Shareable_VM.img

Static Labeling

It is possible to set static labels on each image file, however a consequence of this is that the image cannot be cloned using the VMM, therefore an image for each VM will be required. This is the method used to configure VMs on MLS systems as there is a known label that would define the security level. With this method it is also possible to configure two or more VMs with the same security context so that they can share resources. A useful reference is at: http://libvirt.org/formatdomain.html#seclabel.

If using the Virtual Machine Manager GUI, then by default it will start each VM running as they are built, therefore they need to be stopped and restarted once configured for static labels, the image file will also need to be relabeled. An example VM configuration follows where the VM has been created as Static_VM1 using the F-20 targeted policy in enforcing mode (just so all errors are flagged during the build):

  • To set the required security context requires editing the Static_VM1 configuration file using virsh(1) as follows:
virsh edit Static_VM1

Then add the following at the end of the file:

....
</devices>

<!-- The <seclabel> tag needs to be placed btween the existing
     </devices> and </domain> tags -->

    <seclabel type='static' model='selinux' relabel='no'>
        <label>system_u:system_r:svirt_t:s0:c1022,c1023</label>
    </seclabel>

</domain>
For this example svirt_t has been chosen as it is a valid context (however it will not run as explained in the text). This context will be written to the Static_VM1.xml configuration file in /etc/libvirt/qemu.
  • If the VM is now started an error will be shown as show in the this screen shot.
This is because the image file label is incorrect as by default it is labeled virt_image_t when the VM image is built (and svirt_t does not have read/write permission for this label):
# The default label of the image at build time:
system_u:object_r:virt_image_t:s0 Static_VM1.img
There are a number of ways to fix this, such as adding an allow rule or changing the image file label. In this example the image file label will be changed using chcon(1) as follows:
# This command is executed from /var/lib/libvirt/images
#
# This sets the correct type:
chcon -t svirt_image_t Static_VM1.img
Optionally, the image can also be relabeled so that the [level] is the same as the process using chcon as follows:
# This command is executed from /var/lib/libvirt/images
#
# Set the MCS label to match the process (optional step):
chcon -l s0:c1022,c1023 Static_VM1.img
  • Now that the image has been relabeled, the VM can now be started.

The following example shows two static VMs (one is configured for unconfined_t that is allowed to run under the targeted policy - this was possible because the 'setsebool -P virt_transition_userdomain on' boolean was set that allows virtd_t domain to transition to a user domain (e.g. unconfined_t).

VM Name Object Static security context
Static_VM1 Process system_u:system_r:svirt_t:s0:c1022,c1023
File system_u:system_r:svirt_image_t:s0:c1022,c1023
Static_VM2 Process system_u:system_r:unconfined_t:s0:c11,c22
File system_u:system_r:virt_image_t:s0


The running image ls -Z and ps -eZ are as follows, and for completeness an ls -Z is shown when both VMs have been stopped:

# Both VMs running (Note that Static_VM2 did not have file level reset):
ls -Z /var/lib/libvirt/images
system_u:object_r:svirt_image_t:s0:c1022,c1023 Static_VM1.img
system_u:object_r:virt_image_t:s0 Static_VM2.img

ps -eZ | grep qemu
system_u:system_r:svirt_t:s0:c585,c813 6707 ? 00:00:45 qemu-system-x86
system_u:system_r:unconfined_t:s0:c11,c22 6796 ? 00:00:26 qemu-system-x86

# Both VMs stopped (note that Static_VM1.img was relabeled svirt_image_t
# to enable it to run, however Static_VM2.img is still labeled
# virt_image_t and runs okay. This is because the process is run as
# unconfined_t that is allowed to use virt_image_t):
system_u:object_r:svirt_image_t:s0:c1022,c1023 Static_VM1.img
system_u:object_r:virt_image_t:s0 Static_VM2.img

Xen Support

This is not supported by SELinux in the usual way as it is built into the actual Xen software as a 'Flask/TE' extension[3] for the XSM (Xen Security Module). Also the Xen implementation has its own built-in policy (xen.te) and supporting definitions for access vectors, security classes and initial SIDs for the policy. These Flask/TE components run in Domain 0 as part of the domain management and control supporting the Virtual Machine Monitor (VMM) as shown in the Xen Hypervisor diagram.

The "How Does Xen Work document describes the basic operation of Xen, the "Xen Security Modules" describes the XSM/Flask implementation, and the xsm-flask.txt file in the Xen source package describes how SELinux and its supporting policy is implemented.

However (just to confuse the issue), there is another Xen policy module (also called xen.te) in the Reference Policy to support the management of images etc. via the Xen console.

For reference, the Xen policy supports additional policy language statements: iomemcon, ioportcon, pcidevicecon and pirqcon that are discussed in the SELinux Policy Xen Statements.


Previous
Home
Next



  1. KVM (Kernel-based Virtual Machine) and Xen are classed as 'bare metal' hypervisors and they rely on other services to manage the overall VM environment. QEMU (Quick Emulator) is an emulator that emulates the BIOS and I/O device functionality and can be used standalone or with KVM and Xen.
  2. The various images would have been labeled by the virt module installation process (see the virt.fc module file or the policy file_contexts file libvirt entries). If not, then need to ensure it is relabeled by the most appropriate SELinux tool.
  3. This is a version of the SELinux security server, avc etc. that has been specifically ported for the Xen implementation.