Difference between revisions of "Xen Security Modules : XSM-FLASK"

From Xen
(Fix wikimedia formatting)
Line 1: Line 1:
 
XSM Documentation
 
XSM Documentation
   
Overview
 
   
  +
This is intended to be a hands-on description of Xen Security Modules (XSM) as well as their structure and operation. This document has been compiled based on docs/misc/xsm-flask.txt, mailing list discussions, Xen source code, and other support material contained within the Xen source-tree.
 
  +
'''Overview'''
  +
  +
  +
  +
This is intended to be a hands-on description of Xen Security Modules (XSM) as well as their structure and operation. This document has been compiled based on docs/misc<nowiki>/xsm-flask.tx</nowiki>t, mailing list discussions, Xen source code, and other support material contained within the Xen source-tree.
  +
  +
   
 
A reader of this document should be able to:
 
A reader of this document should be able to:
  +
1) Build and install Xen with XSM enabled
 
  +
1) Build and install Xen with XSM enabled
2) Create and load a security policy
 
  +
3) Tag virtual machines with security labels managed by the security policy
 
  +
2) Create and load a security policy
4) Utilize a simple application making use of privileges permitted by the policy
 
  +
  +
3) Tag virtual machines with security labels managed by the security policy
  +
  +
4) Utilize a simple application making use of privileges permitted by the policy
  +
  +
   
 
What is XSM
 
What is XSM
  +
  +
   
 
Xen offers a security framework called Xen Security Modules, or XSM, to enable an administrator or developer to exert fine-grained control over a Xen domain and its capabilities. Specifically, XSM makes it possible to define permissible interactions between domains, the hypervisor itself, and related resources such as memory and devices.
 
Xen offers a security framework called Xen Security Modules, or XSM, to enable an administrator or developer to exert fine-grained control over a Xen domain and its capabilities. Specifically, XSM makes it possible to define permissible interactions between domains, the hypervisor itself, and related resources such as memory and devices.
   
  +
Via XSM, Xen implements a type of mandatory access control via a security architecture called FLASK using a module of the same name. An abbreviation for Flux Advanced Security Kernel, FLASK has its origins in several trusted operating system research projects, managed jointly between the United States’ National Security Agency, the Secure Computing Corporation, and the University of Utah. The specific intent of FLASK is to separate security enforcement from security policy, better isolating logical components of security systems.
 
  +
  +
Via XSM, Xen implements a type of mandatory access control via a security architecture called FLASK using a module of the same name. An abbreviation for '''Fl'''ux '''A'''dvanced '''S'''ecurity '''K'''ernel, FLASK has its origins in several trusted operating system research projects, managed jointly between the United States’ National Security Agency, the Secure Computing Corporation, and the University of Utah. The specific intent of FLASK is to separate security enforcement from security policy, better isolating logical components of security systems.
  +
  +
   
 
As applied to operating system design, FLASK brings about security enhancements that improve auditing of actions and more granular control thereof. Today, it is perhaps best known through its expression in Security Enhanced Linux (SELinux).
 
As applied to operating system design, FLASK brings about security enhancements that improve auditing of actions and more granular control thereof. Today, it is perhaps best known through its expression in Security Enhanced Linux (SELinux).
  +
  +
   
 
In the same sense that SELinux is a collection of Linux security enhancements, auditing and policy mechanisms, so also is the FLASK Xen Security Module to Xen itself. Similarly, each rely upon a set of administration tools to craft security policies and guide their enforcement.
 
In the same sense that SELinux is a collection of Linux security enhancements, auditing and policy mechanisms, so also is the FLASK Xen Security Module to Xen itself. Similarly, each rely upon a set of administration tools to craft security policies and guide their enforcement.
  +
  +
  +
  +
  +
  +
  +
  +
   
   
Line 28: Line 56:
   
 
Below are some illustrative examples of what the FLASK Xen Security Module can make possible:
 
Below are some illustrative examples of what the FLASK Xen Security Module can make possible:
  +
 
- Prevent two domains from communicating via event channels or grants
 
- Prevent two domains from communicating via event channels or grants
  +
 
- Grant a set of privileged capabilities to otherwise unprivileged domains
 
- Grant a set of privileged capabilities to otherwise unprivileged domains
  +
 
- Control which domains can use device passthrough (and which devices)
 
- Control which domains can use device passthrough (and which devices)
  +
 
- Restrict or audit operations performed by privileged domains
 
- Restrict or audit operations performed by privileged domains
  +
 
- Prevent a privileged domain from arbitrarily mapping pages from other domains
 
- Prevent a privileged domain from arbitrarily mapping pages from other domains
  +
 
- Isolation hypervisor support components (such as qemu or xenstore) from each other, and provide assurance that each may only perform its designated actions
 
- Isolation hypervisor support components (such as qemu or xenstore) from each other, and provide assurance that each may only perform its designated actions
  +
  +
   
 
Linux and Xen version requirements for use of XSM
 
Linux and Xen version requirements for use of XSM
   
  +
● Xen version 4.3 and newer: Specifically, commit http://xenbits.xen.org/gitweb/?p=xen.git;a=commit;h=996cf47b8081fc6b2efd4fa9a69f6b77028719e6 and later. Earlier versions lack full XSM support (but may still be usable in a restricted sense, depending upon the use case). Prior to this commit, only the sysctl hypercalls and one domctl hypercall XEN_DOMCTL_getdomaininfo were truly usable by non-privileged domains.
 
  +
● Linux version 3.8 or newer, or alternatively, the adaptation of the following patch to an earlier version (known to apply cleanly to 3.7.1): https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=30d4b180e20c081f435143f8bc211c66a930608a
 
  +
* '''Xen version 4.3 and newer''': Specifically, commit [http://xenbits.xen.org/gitweb/?p=xen.git;a=commit;h=996cf47b8081fc6b2efd4fa9a69f6b77028719e6 http://xenbits.xen.org/gitweb/?p=xen.git;a=commit;h=996cf47b8081fc6b2efd4fa9a69f6b77028719e6] and later. Earlier versions lack full XSM support (but may still be usable in a restricted sense, depending upon the use case). Prior to this commit, only the sysctl hypercalls and one domctl hypercall XEN_DOMCTL_getdomaininfo were truly usable by non-privileged domains.
  +
* '''Linux version 3.8''' '''or newer''', or alternatively, the adaptation of the following patch to an earlier version (known to apply cleanly to 3.7.1): [https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=30d4b180e20c081f435143f8bc211c66a930608a https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=30d4b180e20c081f435143f8bc211c66a930608a]
  +
  +
  +
   
   
 
Enabling XSM in Xen
 
Enabling XSM in Xen
  +
  +
   
 
XSM is a compile-time option for Xen, and by default it is a disabled feature.
 
XSM is a compile-time option for Xen, and by default it is a disabled feature.
  +
 
To enable the framework, Xen must be compiled with XSM and FLASK explicitly enabled.
 
To enable the framework, Xen must be compiled with XSM and FLASK explicitly enabled.
   
  +
To do so, edit Config.mk or the .config file and set XSM_ENABLE and
 
  +
  +
To do so, edit <nowiki>Config.mk</nowiki> or the .config file and set XSM_ENABLE and
  +
 
FLASK_ENABLE to "y"
 
FLASK_ENABLE to "y"
  +
  +
   
 
NOTE: this change requires a make clean, rebuild, reinstall and reboot.
 
NOTE: this change requires a make clean, rebuild, reinstall and reboot.
  +
  +
   
 
Compiling the sample FLASK policy
 
Compiling the sample FLASK policy
  +
  +
   
 
During typical Xen compilation, compilation of the FLASK sample policy is not performed due to the necessary dependency upon the SElinux compiler, otherwise known as ‘checkpolicy.’ This tool must be installed before proceeding:
 
During typical Xen compilation, compilation of the FLASK sample policy is not performed due to the necessary dependency upon the SElinux compiler, otherwise known as ‘checkpolicy.’ This tool must be installed before proceeding:
  +
  +
   
 
Installing checkpolicy
 
Installing checkpolicy
  +
● apt-get install checkpolicy
 
● yum install checkpolicy
+
* apt-get install checkpolicy
  +
* yum install checkpolicy
● or similar
 
  +
* or similar
  +
  +
   
 
Next, to build the sample policy itself:
 
Next, to build the sample policy itself:
  +
● cd xen-source-tree/
 
  +
* cd xen-source-tree/
● make -C tools/flask/policy
 
  +
* make -C tools/flask/policy
  +
  +
   
 
The demonstrtion policy is generated from statements defined in files within the tools/flask/policy path.. After compilation, the resultant policy will be named xenpolicy.24 and reside within the directory tools/flask/policy.
 
The demonstrtion policy is generated from statements defined in files within the tools/flask/policy path.. After compilation, the resultant policy will be named xenpolicy.24 and reside within the directory tools/flask/policy.
  +
  +
   
 
Quoting from its description, this policy illustrates “most of the features of FLASK
 
Quoting from its description, this policy illustrates “most of the features of FLASK
  +
 
that can be used without dom0 disaggregation. The main types for domUs are:
 
that can be used without dom0 disaggregation. The main types for domUs are:
  +
  +
   
 
- domU_t is a domain that can communicate with any other domU_t
 
- domU_t is a domain that can communicate with any other domU_t
  +
 
- isolated_domU_t can only communicate with dom0
 
- isolated_domU_t can only communicate with dom0
  +
 
- prot_domU_t is a domain type whose creation can be disabled with a boolean
 
- prot_domU_t is a domain type whose creation can be disabled with a boolean
  +
 
- nomigrate_t is a domain that must be created via the nomigrate_t_building
 
- nomigrate_t is a domain that must be created via the nomigrate_t_building
  +
 
type, and whose memory cannot be read by dom0 once created
 
type, and whose memory cannot be read by dom0 once created
  +
  +
   
 
HVM domains with stubdomain device models use two types (one per domain):
 
HVM domains with stubdomain device models use two types (one per domain):
  +
 
- domHVM_t is an HVM domain that uses a stubdomain device model
 
- domHVM_t is an HVM domain that uses a stubdomain device model
  +
 
- dm_dom_t is the device model for a domain with type domHVM_t”
 
- dm_dom_t is the device model for a domain with type domHVM_t”
  +
  +
   
 
Booting Xen with FLASK
 
Booting Xen with FLASK
  +
  +
   
 
When Xen is compiled with XSM, the following grub command-line options can be used to set FLASK properties. Using Debian and Ubuntu as examples, these options can be placed in /etc/default/grub within the variable GRUB_CMDLINE_XEN_DEFAULT. Please consult distribution documentation for the recommended method. When package management scripts regenerate the grub configuration (e.g., during a kernel upgrade or at the request of a sysadmin), a system configured in this manner will be guaranteed to properly embed XSM parameters within the grub configuration. For testing purposes, manually editing the grub command line at boot will also suffice.
 
When Xen is compiled with XSM, the following grub command-line options can be used to set FLASK properties. Using Debian and Ubuntu as examples, these options can be placed in /etc/default/grub within the variable GRUB_CMDLINE_XEN_DEFAULT. Please consult distribution documentation for the recommended method. When package management scripts regenerate the grub configuration (e.g., during a kernel upgrade or at the request of a sysadmin), a system configured in this manner will be guaranteed to properly embed XSM parameters within the grub configuration. For testing purposes, manually editing the grub command line at boot will also suffice.
  +
  +
   
 
For example:
 
For example:
  +
● GRUB_CMDLINE_XEN_DEFAULT="flask_enforcing=1”
 
  +
* GRUB_CMDLINE_XEN_DEFAULT="flask_enforcing=1”
  +
  +
   
 
Xen XSM command line parameters
 
Xen XSM command line parameters
  +
● flask_enforcing
 
  +
* flask_enforcing
○ The default value for flask_enforcing is '0'. This parameter causes the platform to boot in permissive mode which means that the policy is loaded but not enforced. This mode is often helpful for developing new systems and policies as the policy violations are reported on the xen console and may be viewed in dom0 through 'xl dmesg'.
 
  +
** The default value for flask_enforcing is '0'. This parameter causes the platform to boot in permissive mode which means that the policy is loaded but not enforced. This mode is often helpful for developing new systems and policies as the policy violations are reported on the xen console and may be viewed in dom0 through 'xl dmesg'.
  +
  +
   
 
To boot the platform into enforcing mode, which means that the policy is loaded and enforced, append 'flask_enforcing=1' on the grub line.
 
To boot the platform into enforcing mode, which means that the policy is loaded and enforced, append 'flask_enforcing=1' on the grub line.
This parameter may also be changed through the flask hypercall.
+
** This parameter may also be changed through the flask hypercall.
This parameter may also be changed through the ‘xl setenforce’ command
+
** This parameter may also be changed through the ‘xl setenforce’ command
  +
  +
  +
  +
  +
  +
* flask_enabled
  +
** The default value for flask_enabled is '1'. This parameter causes the platform to enable the FLASK security module under the XSM framework. The parameter may be enabled/disabled only once per boot. If the parameter is set to '0', only a reboot can re-enable flask. When flask_enabled is '0' the DUMMY module is enforced; when this module name is encountered in XSM-related documentation and mailing list discussions, it should be interpreted as a “pass through” default XSM policy which matches behavior of a system without XSM enabled at compile-time.
  +
** This parameter may also be changed through the flask hypercall.
  +
** This parameter may also be queried through the ‘xl getenforce’ command
  +
** This parameter may be altered only once per boot.
   
   
● flask_enabled
 
○ The default value for flask_enabled is '1'. This parameter causes the platform to enable the FLASK security module under the XSM framework. The parameter may be enabled/disabled only once per boot. If the parameter is set to '0', only a reboot can re-enable flask. When flask_enabled is '0' the DUMMY module is enforced; when this module name is encountered in XSM-related documentation and mailing list discussions, it should be interpreted as a “pass through” default XSM policy which matches behavior of a system without XSM enabled at compile-time.
 
○ This parameter may also be changed through the flask hypercall.
 
○ This parameter may also be queried through the ‘xl getenforce’ command
 
○ This parameter may be altered only once per boot.
 
   
 
The compiled policy must be installed into a grub-accessible location (such as /boot where kernels are also stored), as it is loaded during the Xen boot process. Otherwise, FLASK will not be enabled at runtime. It is recommended by the authors of XSM to add an extra subdirectory, such as /boot/flask, to use as a repository for XSM policies.
 
The compiled policy must be installed into a grub-accessible location (such as /boot where kernels are also stored), as it is loaded during the Xen boot process. Otherwise, FLASK will not be enabled at runtime. It is recommended by the authors of XSM to add an extra subdirectory, such as /boot/flask, to use as a repository for XSM policies.
  +
  +
   
 
The policy has to be added to grub as a module after the Xen kernel multiboot line, for example as:
 
The policy has to be added to grub as a module after the Xen kernel multiboot line, for example as:
  +
  +
   
 
module /boot/flask/xenpolicy.24
 
module /boot/flask/xenpolicy.24
  +
  +
   
 
To automatically generate this line when running grub-update, the Xen grub-mkconfig helper script has to be modified in /etc/grub.d/20_linux_xen. This helper scripts are different depending on your grub version (and distribution).
 
To automatically generate this line when running grub-update, the Xen grub-mkconfig helper script has to be modified in /etc/grub.d/20_linux_xen. This helper scripts are different depending on your grub version (and distribution).
  +
  +
   
 
Once Xen is booted with the FLASK policy, the policy (or a new one) can be reloaded using the “xl loadpolicy” command.
 
Once Xen is booted with the FLASK policy, the policy (or a new one) can be reloaded using the “xl loadpolicy” command.
  +
  +
   
 
Creating domains with security labels
 
Creating domains with security labels
  +
  +
   
 
Once FLASK is loaded, domains need to be created using a security label in their configuration. Without this line, the domains will be classified “unlabeled”.
 
Once FLASK is loaded, domains need to be created using a security label in their configuration. Without this line, the domains will be classified “unlabeled”.
  +
  +
   
 
seclabel='system_u:system_r:domU_t'
 
seclabel='system_u:system_r:domU_t'
  +
  +
   
 
The label’s three sections are: user, role and type. These will be discussed further in this document.
 
The label’s three sections are: user, role and type. These will be discussed further in this document.
  +
  +
   
 
Monitoring XSM logs
 
Monitoring XSM logs
  +
 
XSM:Flask will emit avc: denied messages when a permission is denied by the
 
XSM:Flask will emit avc: denied messages when a permission is denied by the
  +
 
policy, just like SELinux, and can be viewed with xl dmesg:
 
policy, just like SELinux, and can be viewed with xl dmesg:
  +
  +
   
 
xl dmesg | grep avc
 
xl dmesg | grep avc
  +
  +
   
 
An example output looks like:
 
An example output looks like:
  +
  +
   
 
(XEN) avc: denied { setparam } for domid=0 scontext=system_u:system_r:dom0_t tcontext=system_u:system_r:domU_t tclass=hvm
 
(XEN) avc: denied { setparam } for domid=0 scontext=system_u:system_r:dom0_t tcontext=system_u:system_r:domU_t tclass=hvm
   
FLASK
 
   
  +
The sample FLASK policy can be found in tools/flask/policy/policy/modules/xen. The two files found here are xen.te, the policy description, and xen.if, a collection of macros to be used in the policy description.
 
  +
'''FLASK'''
  +
  +
  +
  +
The sample FLASK policy can be found in tools/flask/policy/policy/modules/xen. The two files found here are <nowiki>xen.te</nowiki>, the policy description, and <nowiki>xen.if</nowiki>, a collection of macros to be used in the policy description.
  +
  +
   
 
Users, roles, types and attributes
 
Users, roles, types and attributes
  +
  +
   
 
Flask provides multiple levels of categories to abstract away from hypercalls.
 
Flask provides multiple levels of categories to abstract away from hypercalls.
   
  +
On the most basic level, a “type” can be defined to specify the hypercalls that type is allowed to execute and how it is allowed to execute them. When XSM is enforcing the policy, only those hypercalls will be executable that are explicitly allowed in the policy.
 
  +
  +
On the most basic level, a '''“type”''' can be defined to specify the hypercalls that type is allowed to execute and how it is allowed to execute them. When XSM is enforcing the policy, only those hypercalls will be executable that are explicitly allowed in the policy.
  +
  +
   
 
The sample XSM policy defines several types, for example: xen_t, dom0_t and domU_t. A new type can be defined with the “type” keyword:
 
The sample XSM policy defines several types, for example: xen_t, dom0_t and domU_t. A new type can be defined with the “type” keyword:
  +
  +
   
 
type new_type_t;
 
type new_type_t;
  +
  +
   
 
Each type can be assigned into an attribute category, to easily reference each type having the attribute. The sample policy defines several attributes, for example: xen_type, domain_type, resource_type, etc.
 
Each type can be assigned into an attribute category, to easily reference each type having the attribute. The sample policy defines several attributes, for example: xen_type, domain_type, resource_type, etc.
  +
  +
   
 
A type can be assigned one or multiple attributes, for example
 
A type can be assigned one or multiple attributes, for example
  +
  +
   
 
type xen_t, xen_type, mls_priv;
 
type xen_t, xen_type, mls_priv;
  +
  +
   
 
assigns the xen_t type the attributes xen_type and mls_priv.
 
assigns the xen_t type the attributes xen_type and mls_priv.
  +
  +
   
 
Defining which hypercalls are allowed for each type is done using the “allow” keyword. Hypercalls are grouped into security classes (defined in xen/xsm/flask/policy/access_vectors) which will be discussed later. For example the following
 
Defining which hypercalls are allowed for each type is done using the “allow” keyword. Hypercalls are grouped into security classes (defined in xen/xsm/flask/policy/access_vectors) which will be discussed later. For example the following
  +
  +
   
 
allow dom0_t security_t:security check_context;
 
allow dom0_t security_t:security check_context;
  +
  +
   
 
enables the dom0_t type to execute the check_context hypercall in the security class targeting a security_t type. The allow line can be generalized as follows:
 
enables the dom0_t type to execute the check_context hypercall in the security class targeting a security_t type. The allow line can be generalized as follows:
   
  +
allow <source type> <target type>:<security class> <hypercall>;
 
  +
  +
allow &lt;source type&gt; &lt;target type&gt;:&lt;security class&gt; &lt;hypercall&gt;;
  +
  +
   
 
Multiple hypercalls belonging to the same security class can be defined by wrapping the hypercalls into {}, for example:
 
Multiple hypercalls belonging to the same security class can be defined by wrapping the hypercalls into {}, for example:
  +
  +
   
 
allow dom0_t dom0_t:resource { add remove };
 
allow dom0_t dom0_t:resource { add remove };
  +
  +
   
 
Using the attributes we can quickly allow each type with that attribute access to hypercalls:
 
Using the attributes we can quickly allow each type with that attribute access to hypercalls:
  +
  +
   
 
# Allow all domains to use (unprivileged parts of) the tmem hypercall
 
# Allow all domains to use (unprivileged parts of) the tmem hypercall
  +
 
allow domain_type xen_t:xen tmem_op;
 
allow domain_type xen_t:xen tmem_op;
   
  +
Roles are the second level above types, where we can define sets of types belonging to a role. While attributes are only accessible internally inside the policy (as a shortcut), a role is part of the security label. A role defines which types belong to that role, therefore it can prevent us from erroneously assigning a type to a VM when it’s role doesn’t have that type.
 
  +
  +
'''Roles''' are the second level above types, where we can define sets of types belonging to a role. While attributes are only accessible internally inside the policy (as a shortcut), a role is part of the security label. A role defines which types belong to that role, therefore it can prevent us from erroneously assigning a type to a VM when it’s role doesn’t have that type.
  +
  +
   
 
The sample FLASK policy defines two roles: system_r and vm_r. A role definition is as follows:
 
The sample FLASK policy defines two roles: system_r and vm_r. A role definition is as follows:
  +
  +
   
 
role system_r;
 
role system_r;
  +
 
role system_r types { xen_type domain_type };
 
role system_r types { xen_type domain_type };
  +
  +
   
 
The first line declares a new role while the second line assigns the types belonging to that role (using attributes). When we want to include all types with an attribute except some, we can exclude those types by placing “-” in front of them, like
 
The first line declares a new role while the second line assigns the types belonging to that role (using attributes). When we want to include all types with an attribute except some, we can exclude those types by placing “-” in front of them, like
  +
  +
   
 
role vm_r;
 
role vm_r;
  +
 
role vm_r types { domain_type -dom0_t };
 
role vm_r types { domain_type -dom0_t };
  +
  +
   
 
In the above, the vm_r role is defined as all types with the domain_type attribute, except the dom0_t type.
 
In the above, the vm_r role is defined as all types with the domain_type attribute, except the dom0_t type.
   
  +
On the highest level we can define users. Users are not defined in the .te (like roles and types), rather they are defined in tools/flask/policy/policy/users. This allows us to define a generic set of users across multiple security modules. By default the FLASK policy will create three users: system_u, customer_1 and customer_2.
 
  +
  +
On the highest level we can define '''users'''. Users are not defined in the .te (like roles and types), rather they are defined in tools/flask/policy/policy/users. This allows us to define a generic set of users across multiple security modules. By default the FLASK policy will create three users: system_u, customer_1 and customer_2.
  +
  +
   
 
A user can be assigned multiple roles but by default the system_u user is assigned the system_r role, and the customer_* users are assigned the vm_r role.
 
A user can be assigned multiple roles but by default the system_u user is assigned the system_r role, and the customer_* users are assigned the vm_r role.
  +
  +
   
 
A new user can be defined in the users file as
 
A new user can be defined in the users file as
   
  +
user <user name> roles { <role1> <role2> };
 
  +
  +
user &lt;user name&gt; roles { &lt;role1&gt; &lt;role2&gt; };
  +
  +
   
 
Constraints
 
Constraints
  +
  +
   
 
Constraints are defined in the file tools/flask/policy/policy/constraints. Constraints are a safety net to specifically disallow undesired operations that the policy may allow otherwise. The sample Flask policy defines two constraints to prevent event channels and grants between different customers. A constraints syntax is as follows:
 
Constraints are defined in the file tools/flask/policy/policy/constraints. Constraints are a safety net to specifically disallow undesired operations that the policy may allow otherwise. The sample Flask policy defines two constraints to prevent event channels and grants between different customers. A constraints syntax is as follows:
   
  +
constrain <security class> { <hypercall> } ( expression );
 
  +
  +
constrain &lt;security class&gt; { &lt;hypercall&gt; } ( expression );
  +
 
For example:
 
For example:
  +
  +
   
 
constrain grant { map_read map_write copy } (
 
constrain grant { map_read map_write copy } (
  +
 
u1 == system_u or
 
u1 == system_u or
  +
 
u2 == system_u or
 
u2 == system_u or
  +
 
u1 == u2
 
u1 == u2
  +
 
);
 
);
  +
  +
   
 
The constraint defines that the hypercalls belonging to the security class are only allowed when the expression is true. The expression can contain any user, role and type defined in the policy in the following format:
 
The constraint defines that the hypercalls belonging to the security class are only allowed when the expression is true. The expression can contain any user, role and type defined in the policy in the following format:
   
  +
# expression : ( expression )
 
  +
# | not expression
 
# | expression and expression
+
<nowiki># expression : ( expression )</nowiki>
  +
# | expression or expression
 
# | u1 op u2
+
<nowiki># | not expression</nowiki>
  +
# | r1 role_op r2
 
# | t1 op t2
+
<nowiki># | expression and expression</nowiki>
  +
# | u1 op names
 
# | u2 op names
+
<nowiki># | expression or expression</nowiki>
  +
# | r1 op names
 
# | r2 op names
+
<nowiki># | u1 op u2</nowiki>
  +
# | t1 op names
 
# | t2 op names
+
<nowiki># | r1 role_op r2</nowiki>
  +
#
 
  +
<nowiki># | t1 op t2</nowiki>
# op : == | !=
 
  +
# role_op : == | != | eq | dom | domby | incomp
 
  +
<nowiki># | u1 op names</nowiki>
#
 
  +
# names : name | { name_list }
 
  +
<nowiki># | u2 op names</nowiki>
# name_list : name | name_list name
 
  +
  +
<nowiki># | r1 op names</nowiki>
  +
  +
<nowiki># | r2 op names</nowiki>
  +
  +
<nowiki># | t1 op names</nowiki>
  +
  +
<nowiki># | t2 op names</nowiki>
  +
  +
<nowiki>#</nowiki>
  +
  +
<nowiki># op : == | !=</nowiki>
  +
  +
<nowiki># role_op : == | != | eq | dom | domby | incomp</nowiki>
  +
  +
<nowiki>#</nowiki>
  +
  +
<nowiki># names : name | { name_list }</nowiki>
  +
  +
<nowiki># name_list : name | name_list name</nowiki>
  +
  +
   
 
Macros
 
Macros
   
  +
Macros are used heavily across the sample Flask policy. For each security module a macro file can be defined as a .if file. The sample macro file (tools/flask/policy/policy/modules/xen/xen.if) contains several commonly used macros, for example for declaring a new domain type and it’s associated sub-types and to setup it’s common allow rules. Macros can call other macros. The macro .if file is required to exist for the policy to compile, even if no macros are defined for a module.
 
  +
  +
Macros are used heavily across the sample Flask policy. For each security module a macro file can be defined as a .if file. The sample macro file (tools/flask/policy/policy/modules/xen<nowiki>/xen.if</nowiki>) contains several commonly used macros, for example for declaring a new domain type and it’s associated sub-types and to setup it’s common allow rules. Macros can call other macros. The macro .if file is required to exist for the policy to compile, even if no macros are defined for a module.
  +
  +
   
 
Adding new security modules
 
Adding new security modules
New security modules can be easily added by editing tools/flask/policy/policy/modules.conf and adding the new modules name as such:
 
   
  +
New security modules can be easily added by editing tools/flask/policy/policy<nowiki>/modules.co</nowiki>nf and adding the new modules name as such:
<module_name> = on
 
  +
  +
  +
  +
&lt;module_name&gt; = on
  +
  +
  +
  +
The module has to defined in the folder tools/flask/policy/policy/modules/&lt;module_name&gt; with two files:
  +
  +
  +
  +
&lt;module_name&gt;.te
  +
  +
&lt;module_name&gt;.if
   
The module has to defined in the folder tools/flask/policy/policy/modules/<module_name> with two files:
 
   
<module_name>.te
 
<module_name>.if
 
   
 
When multiple security modules are present the modules can’t contain duplicate role or type declarations.
 
When multiple security modules are present the modules can’t contain duplicate role or type declarations.
  +
  +
   
 
The sample policy is recommended to be left turned on as it contains several definitions required to boot Xen.
 
The sample policy is recommended to be left turned on as it contains several definitions required to boot Xen.
  +
  +
   
 
Security classes
 
Security classes
  +
  +
   
 
Security classes are defined in xen/xsm/flask/policy/access_vectors and categorize each hypercall into one of the classes. Each class can hold a maximum of 32 members.
 
Security classes are defined in xen/xsm/flask/policy/access_vectors and categorize each hypercall into one of the classes. Each class can hold a maximum of 32 members.
  +
  +
   
 
class xen:
 
class xen:
  +
 
Class xen consists of operations dealing with the hypervisor itself. Unless otherwise specified, the source is the domain executing the hypercall, and the target is the xen initial sid (type xen_t).
 
Class xen consists of operations dealing with the hypervisor itself. Unless otherwise specified, the source is the domain executing the hypercall, and the target is the xen initial sid (type xen_t).
   
  +
Description Hypercall
 
  +
XENPF_settime settime
 
  +
{| class="prettytable"
XEN_SYSCTL_tbuf_op tbufcontrol
 
  +
|-
CONSOLEIO_read, XEN_SYSCTL_readconsole readconsole
 
  +
|
XEN_SYSCTL_readconsole with clear=1 clearconsole
 
  +
Description
XEN_SYSCTL_perfc_op perfcontrol
 
  +
XENPF_add_memtype mtrr_add
 
  +
|
XENPF_del_memtype mtrr_del
 
  +
Hypercall
XENPF_read_memtype mtrr_read
 
  +
XENPF_microcode_update microcode
 
  +
|-
XEN_SYSCTL_physinfo, XEN_SYSCTL_topologyinfo, XEN_SYSCTL_numainfo physinfo
 
  +
|
XENPF_platform_quirk quirk
 
  +
XENPF_settime
CONSOLEIO_write writeconsole
 
  +
PHYSDEVOP_apic_read, PHYSDEVOP_alloc_irq_vector readapic
 
  +
|
PHYSDEVOP_apic_write writeapic
 
  +
settime
Most XENOPROF_* privprofile
 
  +
XENOPROF_{init,enable_virq,disable_virq,get_buffer} nonprivprofile
 
  +
|-
kexec hypercall kexec
 
  +
|
XENPF_firmware_info, XENPF_efi_runtime_call firmware
 
  +
XEN_SYSCTL_tbuf_op
XENPF_enter_acpi_sleep sleep
 
  +
XENPF_change_freq frequency
 
  +
|
XENPF_getidletime getidle
 
  +
tbufcontrol
XEN_SYSCTL_debug_keys debug
 
  +
XEN_SYSCTL_getcpuinfo, XENPF_get_cpu_version, XENPF_get_cpuinfo getcpuinfo
 
  +
|-
XEN_SYSCTL_availheap heap
 
  +
|
  +
CONSOLEIO_read, XEN_SYSCTL_readconsole
  +
  +
|
  +
readconsole
  +
  +
|-
  +
|
  +
XEN_SYSCTL_readconsole with clear=1
  +
  +
|
  +
clearconsole
  +
  +
|-
  +
|
  +
XEN_SYSCTL_perfc_op
  +
  +
|
  +
perfcontrol
  +
  +
|-
  +
|
  +
XENPF_add_memtype
  +
  +
|
  +
mtrr_add
  +
  +
|-
  +
|
  +
XENPF_del_memtype
  +
  +
|
  +
mtrr_del
  +
  +
|-
  +
|
  +
XENPF_read_memtype
  +
  +
|
  +
mtrr_read
  +
  +
|-
  +
|
  +
XENPF_microcode_update
  +
  +
|
  +
microcode
  +
  +
|-
  +
|
  +
XEN_SYSCTL_physinfo, XEN_SYSCTL_topologyinfo, XEN_SYSCTL_numainfo
  +
  +
|
  +
physinfo
  +
  +
|-
  +
|
  +
XENPF_platform_quirk
  +
  +
|
  +
quirk
  +
  +
|-
  +
|
  +
CONSOLEIO_write
  +
  +
|
  +
writeconsole
  +
  +
|-
  +
|
  +
PHYSDEVOP_apic_read, PHYSDEVOP_alloc_irq_vector
  +
  +
|
  +
readapic
  +
  +
|-
  +
|
  +
PHYSDEVOP_apic_write
  +
  +
|
  +
writeapic
  +
  +
|-
  +
|
  +
Most XENOPROF_*
  +
  +
|
  +
privprofile
  +
  +
|-
  +
|
  +
XENOPROF_{init,enable_virq,disable_virq,get_buffer}
  +
  +
|
  +
nonprivprofile
  +
  +
|-
  +
|
  +
kexec hypercall
  +
  +
|
  +
kexec
  +
  +
|-
  +
|
  +
XENPF_firmware_info, XENPF_efi_runtime_call
  +
  +
|
  +
firmware
  +
  +
|-
  +
|
  +
XENPF_enter_acpi_sleep
  +
  +
|
  +
sleep
  +
  +
|-
  +
|
  +
XENPF_change_freq
  +
  +
|
  +
frequency
  +
  +
|-
  +
|
  +
XENPF_getidletime
  +
  +
|
  +
getidle
  +
  +
|-
  +
|
  +
XEN_SYSCTL_debug_keys
  +
  +
|
  +
debug
  +
  +
|-
  +
|
  +
XEN_SYSCTL_getcpuinfo, XENPF_get_cpu_version, XENPF_get_cpuinfo
  +
  +
|
  +
getcpuinfo
  +
  +
|-
  +
|
  +
XEN_SYSCTL_availheap
  +
  +
|
  +
heap
  +
  +
|-
  +
|
 
XEN_SYSCTL_get_pmstat, XEN_SYSCTL_pm_op, XENPF_set_processor_pminfo,
 
XEN_SYSCTL_get_pmstat, XEN_SYSCTL_pm_op, XENPF_set_processor_pminfo,
  +
XENPF_core_parking pm_op
 
  +
XENPF_core_parking
mca hypercall mca_op
 
  +
XEN_SYSCTL_lockprof_op lockprof
 
  +
|
XEN_SYSCTL_cpupool_op cpupool_op
 
  +
pm_op
tmem hypercall (any access) tmem_op
 
  +
TMEM_CONTROL command of tmem hypercall tmem_control
 
  +
|-
XEN_SYSCTL_scheduler_op with XEN_DOMCTL_SCHEDOP_getinfo, XEN_SYSCTL_sched_id getscheduler
 
  +
|
XEN_SYSCTL_scheduler_op with XEN_DOMCTL_SCHEDOP_putinfo setscheduler
 
  +
mca hypercall
  +
  +
|
  +
mca_op
  +
  +
|-
  +
|
  +
XEN_SYSCTL_lockprof_op
  +
  +
|
  +
lockprof
  +
  +
|-
  +
|
  +
XEN_SYSCTL_cpupool_op
  +
  +
|
  +
cpupool_op
  +
  +
|-
  +
|
  +
tmem hypercall (any access)
  +
  +
|
  +
tmem_op
  +
  +
|-
  +
|
  +
TMEM_CONTROL command of tmem hypercall
  +
  +
|
  +
tmem_control
  +
  +
|-
  +
|
  +
XEN_SYSCTL_scheduler_op with XEN_DOMCTL_SCHEDOP_getinfo, XEN_SYSCTL_sched_id
  +
  +
|
  +
getscheduler
  +
  +
|-
  +
|
  +
XEN_SYSCTL_scheduler_op with XEN_DOMCTL_SCHEDOP_putinfo
  +
  +
|
  +
setscheduler
  +
  +
|}
  +
  +
   
   
 
class domain and class domain2:
 
class domain and class domain2:
  +
 
Classes domain and domain2 consist of operations that a domain performs on
 
Classes domain and domain2 consist of operations that a domain performs on
  +
 
another domain or on itself. Unless otherwise specified, the source is the
 
another domain or on itself. Unless otherwise specified, the source is the
  +
 
domain executing the hypercall, and the target is the domain being operated on
 
domain executing the hypercall, and the target is the domain being operated on
  +
 
(which may result in a _self or _target type). Transitions in class domain are used to produce the _self and _target types.
 
(which may result in a _self or _target type). Transitions in class domain are used to produce the _self and _target types.
  +
  +
   
 
class domain:
 
class domain:
   
  +
Description Hypercall
 
  +
XEN_DOMCTL_setvcpucontext setvcpucontext
 
  +
{| class="prettytable"
XEN_DOMCTL_pausedomain pause
 
  +
|-
XEN_DOMCTL_unpausedomain unpause
 
  +
|
XEN_DOMCTL_resumedomain resume
 
  +
Description
XEN_DOMCTL_createdomain create
 
  +
  +
|
  +
Hypercall
  +
  +
|-
  +
|
  +
XEN_DOMCTL_setvcpucontext
  +
  +
|
  +
setvcpucontext
  +
  +
|-
  +
|
  +
XEN_DOMCTL_pausedomain
  +
  +
|
  +
pause
  +
  +
|-
  +
|
  +
XEN_DOMCTL_unpausedomain
  +
  +
|
  +
unpause
  +
  +
|-
  +
|
  +
XEN_DOMCTL_resumedomain
  +
  +
|
  +
resume
  +
  +
|-
  +
|
  +
XEN_DOMCTL_createdomain
  +
  +
|
  +
create
  +
  +
|-
  +
|
 
checked in FLASK_RELABEL_DOMAIN for any relabel operation:
 
checked in FLASK_RELABEL_DOMAIN for any relabel operation:
  +
 
source = the old label of the domain
 
source = the old label of the domain
  +
 
target = the new label of the domain
 
target = the new label of the domain
  +
see also the domain2 relabel{from,to,self} permissions transition
 
  +
see also the domain2 relabel{from,to,self} permissions
XEN_DOMCTL_max_vcpus max_vcpus
 
  +
XEN_DOMCTL_destroydomain destroy
 
  +
|
XEN_DOMCTL_setvcpuaffinity setvcpuaffinity
 
  +
transition
XEN_DOMCTL_getvcpuaffinity getvcpuaffinity
 
  +
XEN_DOMCTL_scheduler_op with XEN_DOMCTL_SCHEDOP_getinfo getscheduler
 
  +
|-
XEN_DOMCTL_getdomaininfo, XEN_SYSCTL_getdomaininfolist getdomaininfo
 
  +
|
XEN_DOMCTL_getvcpuinfo getvcpuinfo
 
  +
XEN_DOMCTL_max_vcpus
XEN_DOMCTL_getvcpucontext getvcpucontext
 
  +
XEN_DOMCTL_max_mem setdomainmaxmem
 
  +
|
XEN_DOMCTL_setdomainhandle setdomainhandle
 
  +
max_vcpus
XEN_DOMCTL_setdebugging setdebugging
 
  +
XEN_DOMCTL_hypercall_init hypercall
 
  +
|-
XEN_DOMCTL_settimeoffset settime
 
  +
|
  +
XEN_DOMCTL_destroydomain
  +
  +
|
  +
destroy
  +
  +
|-
  +
|
  +
XEN_DOMCTL_setvcpuaffinity
  +
  +
|
  +
setvcpuaffinity
  +
  +
|-
  +
|
  +
XEN_DOMCTL_getvcpuaffinity
  +
  +
|
  +
getvcpuaffinity
  +
  +
|-
  +
|
  +
XEN_DOMCTL_scheduler_op with XEN_DOMCTL_SCHEDOP_getinfo
  +
  +
|
  +
getscheduler
  +
  +
|-
  +
|
  +
XEN_DOMCTL_getdomaininfo, XEN_SYSCTL_getdomaininfolist
  +
  +
|
  +
getdomaininfo
  +
  +
|-
  +
|
  +
XEN_DOMCTL_getvcpuinfo
  +
  +
|
  +
getvcpuinfo
  +
  +
|-
  +
|
  +
XEN_DOMCTL_getvcpucontext
  +
  +
|
  +
getvcpucontext
  +
  +
|-
  +
|
  +
XEN_DOMCTL_max_mem
  +
  +
|
  +
setdomainmaxmem
  +
  +
|-
  +
|
  +
XEN_DOMCTL_setdomainhandle
  +
  +
|
  +
setdomainhandle
  +
  +
|-
  +
|
  +
XEN_DOMCTL_setdebugging
  +
  +
|
  +
setdebugging
  +
  +
|-
  +
|
  +
XEN_DOMCTL_hypercall_init
  +
  +
|
  +
hypercall
  +
  +
|-
  +
|
  +
XEN_DOMCTL_settimeoffset
  +
  +
|
  +
settime
  +
  +
|-
  +
|
 
checked in XEN_DOMCTL_set_target:
 
checked in XEN_DOMCTL_set_target:
  +
 
source = the new device model domain
 
source = the new device model domain
  +
 
target = the new target domain
 
target = the new target domain
  +
see also the domain2 make_priv_for and set_as_target checks set_target
 
  +
see also the domain2 make_priv_for and set_as_target checks
SCHEDOP_remote_shutdown shutdown
 
  +
XEN_DOMCTL_set{,_machine}_address_size setaddrsize
 
  +
|
XEN_DOMCTL_get{,_machine}_address_size getaddrsize
 
  +
set_target
XEN_DOMCTL_sendtrigger trigger
 
  +
XEN_DOMCTL_get_ext_vcpucontext getextvcpucontext
 
  +
|-
XEN_DOMCTL_set_ext_vcpucontext setextvcpucontext
 
  +
|
XEN_DOMCTL_getvcpuextstate getvcpuextstate
 
  +
SCHEDOP_remote_shutdown
XEN_DOMCTL_setvcpuextstate setvcpuextstate
 
  +
XENMEM_get_pod_target getpodtarget
 
  +
|
XENMEM_set_pod_target setpodtarget
 
  +
shutdown
XEN_DOMCTL_subscribe, XEN_DOMCTL_disable_migrate, XEN_DOMCTL_suppress_spurious_page_faults set_misc_info
 
  +
XEN_DOMCTL_set_virq_handler set_virq_handler
 
  +
|-
  +
|
  +
XEN_DOMCTL_set{,_machine}_address_size
  +
  +
|
  +
setaddrsize
  +
  +
|-
  +
|
  +
XEN_DOMCTL_get{,_machine}_address_size
  +
  +
|
  +
getaddrsize
  +
  +
|-
  +
|
  +
XEN_DOMCTL_sendtrigger
  +
  +
|
  +
trigger
  +
  +
|-
  +
|
  +
XEN_DOMCTL_get_ext_vcpucontext
  +
  +
|
  +
getextvcpucontext
  +
  +
|-
  +
|
  +
XEN_DOMCTL_set_ext_vcpucontext
  +
  +
|
  +
setextvcpucontext
  +
  +
|-
  +
|
  +
XEN_DOMCTL_getvcpuextstate
  +
  +
|
  +
getvcpuextstate
  +
  +
|-
  +
|
  +
XEN_DOMCTL_setvcpuextstate
  +
  +
|
  +
setvcpuextstate
  +
  +
|-
  +
|
  +
XENMEM_get_pod_target
  +
  +
|
  +
getpodtarget
  +
  +
|-
  +
|
  +
XENMEM_set_pod_target
  +
  +
|
  +
setpodtarget
  +
  +
|-
  +
|
  +
XEN_DOMCTL_subscribe, XEN_DOMCTL_disable_migrate, XEN_DOMCTL_suppress_spurious_page_faults
  +
  +
|
  +
set_misc_info
  +
  +
|-
  +
|
  +
XEN_DOMCTL_set_virq_handler
  +
  +
|
  +
set_virq_handler
  +
  +
|}
  +
   
 
class domain2 (continuation of class domain):
 
class domain2 (continuation of class domain):
   
  +
  +
  +
{| class="prettytable"
  +
|-
  +
|
 
checked in FLASK_RELABEL_DOMAIN with non-DOMID_SELF:
 
checked in FLASK_RELABEL_DOMAIN with non-DOMID_SELF:
  +
 
source = the domain making the hypercall
 
source = the domain making the hypercall
  +
target = the old label of the domain being relabeled relabelfrom
 
  +
target = the old label of the domain being relabeled
  +
  +
|
  +
relabelfrom
  +
  +
|-
  +
|
 
checked in FLASK_RELABEL_DOMAIN with non-DOMID_SELF:
 
checked in FLASK_RELABEL_DOMAIN with non-DOMID_SELF:
  +
 
source = the domain making the hypercall
 
source = the domain making the hypercall
  +
target = the new label of the domain being relabeled relabelto
 
  +
target = the new label of the domain being relabeled
  +
  +
|
  +
relabelto
  +
  +
|-
  +
|
 
checked in FLASK_RELABEL_DOMAIN, only with DOMID_SELF:
 
checked in FLASK_RELABEL_DOMAIN, only with DOMID_SELF:
  +
 
source = the old label of the domain
 
source = the old label of the domain
  +
 
target = the new label of the domain
 
target = the new label of the domain
  +
see also domain__transition relabelself
 
  +
see also domain__transition
  +
  +
|
  +
relabelself
  +
  +
|-
  +
|
 
checked in XEN_DOMCTL_set_target:
 
checked in XEN_DOMCTL_set_target:
  +
 
source = the domain making the hypercall
 
source = the domain making the hypercall
  +
 
target = the new device model domain
 
target = the new device model domain
  +
make_priv_for
 
  +
  +
  +
|
  +
make_priv_for
  +
  +
|-
  +
|
 
checked in XEN_DOMCTL_set_target:
 
checked in XEN_DOMCTL_set_target:
  +
 
source = the domain making the hypercall
 
source = the domain making the hypercall
  +
target = the new target domain set_as_target
 
  +
target = the new target domain
XEN_DOMCTL_set_cpuid set_cpuid
 
  +
XEN_DOMCTL_gettscinfo gettsc
 
  +
|
XEN_DOMCTL_settscinfo settsc
 
  +
set_as_target
XEN_DOMCTL_scheduler_op with XEN_DOMCTL_SCHEDOP_putinfo setscheduler
 
  +
  +
|-
  +
|
  +
XEN_DOMCTL_set_cpuid
  +
  +
|
  +
set_cpuid
  +
  +
|-
  +
|
  +
XEN_DOMCTL_gettscinfo
  +
  +
|
  +
gettsc
  +
  +
|-
  +
|
  +
XEN_DOMCTL_settscinfo
  +
  +
|
  +
settsc
  +
  +
|-
  +
|
  +
XEN_DOMCTL_scheduler_op with XEN_DOMCTL_SCHEDOP_putinfo
  +
  +
|
  +
setscheduler
  +
  +
|}
  +
   
 
class hvm:
 
class hvm:
  +
 
Similar to class domain, but primarily contains domctls related to HVM domains.
 
Similar to class domain, but primarily contains domctls related to HVM domains.
   
  +
XEN_DOMCTL_sethvmcontext sethvmc
 
  +
XEN_DOMCTL_gethvmcontext, XEN_DOMCTL_gethvmcontext_partial gethvmc
 
  +
{| class="prettytable"
HVMOP_set_param setparam
 
  +
|-
HVMOP_get_param getparam
 
  +
|
HVMOP_set_pci_intx_level (also needs hvmctl) pcilevel
 
  +
XEN_DOMCTL_sethvmcontext
HVMOP_set_isa_irq_level irqlevel
 
  +
HVMOP_set_pci_link_route pciroute, bind_irq
 
  +
|
XEN_DOMCTL_pin_mem_cacheattr cacheattr
 
  +
sethvmc
HVMOP_track_dirty_vram trackdirtyvram
 
  +
  +
|-
  +
|
  +
XEN_DOMCTL_gethvmcontext, XEN_DOMCTL_gethvmcontext_partial
  +
  +
|
  +
gethvmc
  +
  +
|-
  +
|
  +
HVMOP_set_param
  +
  +
|
  +
setparam
  +
  +
|-
  +
|
  +
HVMOP_get_param
  +
  +
|
  +
getparam
  +
  +
|-
  +
|
  +
HVMOP_set_pci_intx_level (also needs hvmctl)
  +
  +
|
  +
pcilevel
  +
  +
|-
  +
|
  +
HVMOP_set_isa_irq_level
  +
  +
|
  +
irqlevel
  +
  +
|-
  +
|
  +
HVMOP_set_pci_link_route
  +
  +
|
  +
pciroute, bind_irq
  +
  +
|-
  +
|
  +
XEN_DOMCTL_pin_mem_cacheattr
  +
  +
|
  +
cacheattr
  +
  +
|-
  +
|
  +
HVMOP_track_dirty_vram
  +
  +
|
  +
trackdirtyvram
  +
  +
|-
  +
|
 
HVMOP_modified_memory, HVMOP_get_mem_type, HVMOP_set_mem_type,
 
HVMOP_modified_memory, HVMOP_get_mem_type, HVMOP_set_mem_type,
  +
 
HVMOP_set_mem_access, HVMOP_get_mem_access, HVMOP_pagetable_dying,
 
HVMOP_set_mem_access, HVMOP_get_mem_access, HVMOP_pagetable_dying,
  +
HVMOP_inject_trap hvmctl
 
  +
HVMOP_inject_trap
XEN_DOMCTL_set_access_required mem_event
 
  +
  +
|
  +
hvmctl
  +
  +
|-
  +
|
  +
XEN_DOMCTL_set_access_required
  +
  +
|
  +
mem_event
  +
  +
|-
  +
|
 
XEN_DOMCTL_mem_sharing_op and XENMEM_sharing_op_{share,add_physmap} with:
 
XEN_DOMCTL_mem_sharing_op and XENMEM_sharing_op_{share,add_physmap} with:
  +
 
source = the domain making the hypercall
 
source = the domain making the hypercall
  +
target = domain whose memory is being shared mem_sharing
 
  +
target = domain whose memory is being shared
XEN_DOMCTL_audit_p2m audit_p2m
 
  +
HVMOP_inject_msi send_irq
 
  +
|
  +
mem_sharing
  +
  +
|-
  +
|
  +
XEN_DOMCTL_audit_p2m
  +
  +
|
  +
audit_p2m
  +
  +
|-
  +
|
  +
HVMOP_inject_msi
  +
  +
|
  +
send_irq
  +
  +
|-
  +
|
 
checked in XENMEM_sharing_op_{share,add_physmap} with:
 
checked in XENMEM_sharing_op_{share,add_physmap} with:
  +
 
source = domain whose memory is being shared
 
source = domain whose memory is being shared
  +
target = client domain share_mem
 
  +
target = client domain
  +
  +
|
  +
share_mem
  +
  +
|}
  +
   
 
class event:
 
class event:
  +
 
Class event describes event channels. Interdomain event channels have their own security label which is computed using a type transition between the source and target domains. Each endpoint has its own label, and the permission checks must pass on both endpoints for an event channel to be established.
 
Class event describes event channels. Interdomain event channels have their own security label which is computed using a type transition between the source and target domains. Each endpoint has its own label, and the permission checks must pass on both endpoints for an event channel to be established.
   
  +
  +
  +
{| class="prettytable"
  +
|-
  +
|
 
when creating an interdomain event channel endpoint:
 
when creating an interdomain event channel endpoint:
  +
 
source = event channel label
 
source = event channel label
  +
 
target = remote domain the event channel binds to. This may be a _self or _target label if the endpoints are related as such.
 
target = remote domain the event channel binds to. This may be a _self or _target label if the endpoints are related as such.
  +
This permission is checked when creating an unbound event channel and when the interdomain event channel is established. bind
 
  +
This permission is checked when creating an unbound event channel and when the interdomain event channel is established.
  +
  +
|
  +
bind
  +
  +
|-
  +
|
 
EVTCHNOP_send:
 
EVTCHNOP_send:
  +
 
source = domain sending the event
 
source = domain sending the event
  +
target = event channel label send
 
  +
target = event channel label
EVTCHNOP_status; same as _send status
 
  +
  +
|
  +
send
  +
  +
|-
  +
|
  +
EVTCHNOP_status; same as _send
  +
  +
|
  +
status
  +
  +
|-
  +
|
 
when creating an interdomain event channel endpoint:
 
when creating an interdomain event channel endpoint:
  +
 
source = the domain creating the channel (which might not be an endpoint)
 
source = the domain creating the channel (which might not be an endpoint)
  +
target = event channel label create
 
  +
target = event channel label
  +
  +
|
  +
create
  +
  +
|-
  +
|
 
EVTCHNOP_reset:
 
EVTCHNOP_reset:
  +
 
source = domain making the hypercall
 
source = domain making the hypercall
  +
target = domain whose event channels are being reset reset
 
  +
target = domain whose event channels are being reset
  +
  +
|
  +
reset
  +
  +
|}
  +
  +
   
   
 
class grant:
 
class grant:
  +
 
Class grant describes pages shared by grant mappings. Pages use the security label of their owning domain.
 
Class grant describes pages shared by grant mappings. Pages use the security label of their owning domain.
   
  +
GNTTABOP_map_grant_ref with any access map_read
 
  +
GNTTABOP_map_grant_ref with write access map_write
 
  +
{| class="prettytable"
GNTTABOP_unmap_grant_ref unmap
 
  +
|-
GNTTABOP_transfer transfer
 
  +
|
GNTTABOP_setup_table, GNTTABOP_get_status_frames (target is commonly _self) setup
 
  +
GNTTABOP_map_grant_ref with any access
GNTTABOP_copy copy
 
  +
GNTTABOP_query_size, GNTTABOP_get_version query
 
  +
|
  +
map_read
  +
  +
|-
  +
|
  +
GNTTABOP_map_grant_ref with write access
  +
  +
|
  +
map_write
  +
  +
|-
  +
|
  +
GNTTABOP_unmap_grant_ref
  +
  +
|
  +
unmap
  +
  +
|-
  +
|
  +
GNTTABOP_transfer
  +
  +
|
  +
transfer
  +
  +
|-
  +
|
  +
GNTTABOP_setup_table, GNTTABOP_get_status_frames (target is commonly _self)
  +
  +
|
  +
setup
  +
  +
|-
  +
|
  +
GNTTABOP_copy
  +
  +
|
  +
copy
  +
  +
|-
  +
|
  +
GNTTABOP_query_size, GNTTABOP_get_version
  +
  +
|
  +
query
  +
  +
|}
  +
   
 
class mmu:
 
class mmu:
  +
 
Class mmu describes pages of memory not accessed using grants. Permissions are checked using the domain ID used to access the page - the most common case is a domain's own ID (the _self label). Using DOMID_IO in the map command to restrict the mapping to IO memory will result in the target being domio_t, and migration uses read-only mappings with a target of DOMID_XEN (domxen_t).
 
Class mmu describes pages of memory not accessed using grants. Permissions are checked using the domain ID used to access the page - the most common case is a domain's own ID (the _self label). Using DOMID_IO in the map command to restrict the mapping to IO memory will result in the target being domio_t, and migration uses read-only mappings with a target of DOMID_XEN (domxen_t).
   
   
  +
  +
  +
  +
{| class="prettytable"
  +
|-
  +
|
 
checked when using mmu_update to map a page readably
 
checked when using mmu_update to map a page readably
  +
 
source = domain making the hypercall (which might not own the page table)
 
source = domain making the hypercall (which might not own the page table)
  +
target = domain whose pages are being mapped map_read
 
  +
target = domain whose pages are being mapped
  +
  +
|
  +
map_read
  +
  +
|-
  +
|
 
checked when using mmu_update to map a page writably
 
checked when using mmu_update to map a page writably
  +
# source = domain making the hypercall
 
# target = domain whose pages are being mapped
+
<nowiki># source = domain making the hypercall</nowiki>
  +
map_write
 
  +
<nowiki># target = domain whose pages are being mapped</nowiki>
XEN_DOMCTL_getpageframeinfo* pageinfo
 
  +
XEN_DOMCTL_getmemlist pagelist
 
  +
XENMEM_{increase,decrease}_reservation, XENMEM_populate_physmap adjust
 
  +
XENMEM_{current,maximum}_reservation, XENMEM_maximum_gpfn stat
 
  +
|
mmu_update MMU_MACHPHYS_UPDATE updatemp
 
  +
map_write
XENMEM_add_to_physmap, XENMEM_remove_from_physmap physmap
 
  +
MMUEXT_PIN_L*_TABLE pinpage
 
  +
|-
XENMEM_machine_memory_map (with target xen_t), XENMEM_set_memory_map (with domain target) memorymap
 
  +
|
  +
XEN_DOMCTL_getpageframeinfo*
  +
  +
|
  +
pageinfo
  +
  +
|-
  +
|
  +
XEN_DOMCTL_getmemlist
  +
  +
|
  +
pagelist
  +
  +
|-
  +
|
  +
XENMEM_{increase,decrease}_reservation, XENMEM_populate_physmap
  +
  +
|
  +
adjust
  +
  +
|-
  +
|
  +
XENMEM_{current,maximum}_reservation, XENMEM_maximum_gpfn
  +
  +
|
  +
stat
  +
  +
|-
  +
|
  +
mmu_update MMU_MACHPHYS_UPDATE
  +
  +
|
  +
updatemp
  +
  +
|-
  +
|
  +
XENMEM_add_to_physmap, XENMEM_remove_from_physmap
  +
  +
|
  +
physmap
  +
  +
|-
  +
|
  +
MMUEXT_PIN_L*_TABLE
  +
  +
|
  +
pinpage
  +
  +
|-
  +
|
  +
XENMEM_machine_memory_map (with target xen_t), XENMEM_set_memory_map (with domain target)
  +
  +
|
  +
memorymap
  +
  +
|-
  +
|
 
checked when using mmu_update to update the page tables of another domain
 
checked when using mmu_update to update the page tables of another domain
  +
 
source = domain making the hypercall
 
source = domain making the hypercall
  +
 
target = domain whose page tables are being modified
 
target = domain whose page tables are being modified
  +
remote_remap
 
  +
the mmuext_op hypercall acting on the target domain mmuext_op
 
  +
  +
|
  +
remote_remap
  +
  +
|-
  +
|
  +
the mmuext_op hypercall acting on the target domain
  +
  +
|
  +
mmuext_op
  +
  +
|-
  +
|
 
XENMEM_exchange:
 
XENMEM_exchange:
  +
 
source = domain making the hypercall
 
source = domain making the hypercall
  +
 
target = domain whose pages are being exchanged
 
target = domain whose pages are being exchanged
  +
exchange
 
  +
  +
  +
|
  +
exchange
  +
  +
|}
  +
   
 
class shadow:
 
class shadow:
  +
 
Control of the paging_domctl split by subop
 
Control of the paging_domctl split by subop
   
  +
Description Operation
 
  +
XEN_DOMCTL_SHADOW_OP_OFF disable
 
  +
{| class="prettytable"
enable, get/set allocation enable
 
  +
|-
enable, read, and clean log logdirty
 
  +
|
  +
Description
  +
  +
|
  +
Operation
  +
  +
|-
  +
|
  +
XEN_DOMCTL_SHADOW_OP_OFF
  +
  +
|
  +
disable
  +
  +
|-
  +
|
  +
enable, get/set allocation
  +
  +
|
  +
enable
  +
  +
|-
  +
|
  +
enable, read, and clean log
  +
  +
|
  +
logdirty
  +
  +
|}
  +
   
 
class resource:
 
class resource:
  +
Class resource is used to describe the resources used in hardware device passthrough. Resources include: hardware IRQs, MMIO regions, x86 I/O ports, and PCI devices; see docs/misc/xsm-flask.txt for how to label them.
 
  +
Class resource is used to describe the resources used in hardware device passthrough. Resources include: hardware IRQs, MMIO regions, x86 I/O ports, and PCI devices; see docs/misc<nowiki>/xsm-flask.tx</nowiki>t for how to label them.
  +
  +
   
 
Access to the legacy PCI configuration space on x86 via port 0xCF8/CFC requires IS_PRIV, even with FLASK. Writes to the BARs are checked as "setup", while other reads/writes are "use"; the target is the PCI device whose configuration space is being modified. Accesses to the MMIO-based PCI express configuration space described by the ACPI MCFG table are controlled as MMIO accesses, and cannot special-case BAR writes.
 
Access to the legacy PCI configuration space on x86 via port 0xCF8/CFC requires IS_PRIV, even with FLASK. Writes to the BARs are checked as "setup", while other reads/writes are "use"; the target is the PCI device whose configuration space is being modified. Accesses to the MMIO-based PCI express configuration space described by the ACPI MCFG table are controlled as MMIO accesses, and cannot special-case BAR writes.
  +
  +
   
 
The {add,remove}_{irq,ioport,iomem,device} permissions use:
 
The {add,remove}_{irq,ioport,iomem,device} permissions use:
  +
 
source = domain making the hypercall
 
source = domain making the hypercall
  +
 
target = resource's security label
 
target = resource's security label
   
   
  +
Description Operation
 
  +
  +
  +
{| class="prettytable"
  +
|-
  +
|
  +
Description
  +
  +
|
  +
Operation
  +
  +
|-
  +
|
 
checked when adding a resource to a domain:
 
checked when adding a resource to a domain:
  +
 
source = domain making the hypercall
 
source = domain making the hypercall
  +
target = domain which will have access to the resource add
 
  +
target = domain which will have access to the resource
  +
  +
|
  +
add
  +
  +
|-
  +
|
 
checked when removing a resource from a domain:
 
checked when removing a resource from a domain:
  +
 
source = domain making the hypercall
 
source = domain making the hypercall
  +
target = domain which will no longer have access to the resource remove
 
  +
target = domain which will no longer have access to the resource
  +
  +
|
  +
remove
  +
  +
|-
  +
|
 
checked when adding a resource to a domain:
 
checked when adding a resource to a domain:
  +
 
source = domain which will have access to the resource
 
source = domain which will have access to the resource
  +
 
target = resource's security label
 
target = resource's security label
  +
also checked when using some core Xen devices (target xen_t) use
 
  +
also checked when using some core Xen devices (target xen_t)
  +
  +
|
  +
use
  +
  +
|-
  +
|
 
PHYSDEVOP_map_pirq and ioapic writes for dom0, when acting on real IRQs
 
PHYSDEVOP_map_pirq and ioapic writes for dom0, when acting on real IRQs
  +
 
For GSI interrupts, the IRQ's label is indexed by the IRQ number
 
For GSI interrupts, the IRQ's label is indexed by the IRQ number
  +
For MSI interrupts, the label of the PCI device is used add_irq
 
  +
For MSI interrupts, the label of the PCI device is used
PHYSDEVOP_unmap_pirq (same as map, and only for real IRQs) remove_irq
 
  +
XEN_DOMCTL_ioport_permission, XEN_DOMCTL_ioport_mapping add_ioport, remove_ioport
 
  +
|
XEN_DOMCTL_iomem_permission, XEN_DOMCTL_memory_mapping add_iomem, remove_iomem
 
  +
add_irq
  +
  +
|-
  +
|
  +
PHYSDEVOP_unmap_pirq (same as map, and only for real IRQs)
  +
  +
|
  +
remove_irq
  +
  +
|-
  +
|
  +
XEN_DOMCTL_ioport_permission, XEN_DOMCTL_ioport_mapping
  +
  +
|
  +
add_ioport, remove_ioport
  +
  +
|-
  +
|
  +
XEN_DOMCTL_iomem_permission, XEN_DOMCTL_memory_mapping
  +
  +
|
  +
add_iomem, remove_iomem
  +
  +
|-
  +
|
 
XEN_DOMCTL_get_device_group, XEN_DOMCTL_test_assign_device:
 
XEN_DOMCTL_get_device_group, XEN_DOMCTL_test_assign_device:
  +
 
source = domain making the hypercall
 
source = domain making the hypercall
  +
 
target = PCI device being queried
 
target = PCI device being queried
  +
stat_device
 
  +
XEN_DOMCTL_assign_device add_device
 
  +
XEN_DOMCTL_deassign_device remove_device
 
  +
|
  +
stat_device
  +
  +
|-
  +
|
  +
XEN_DOMCTL_assign_device
  +
  +
|
  +
add_device
  +
  +
|-
  +
|
  +
XEN_DOMCTL_deassign_device
  +
  +
|
  +
remove_device
  +
  +
|-
  +
|
 
checked for PCI hot and cold-plug hypercalls, with target as the PCI device
 
checked for PCI hot and cold-plug hypercalls, with target as the PCI device
  +
checked for CPU and memory hotplug with xen_t as the target plug
 
  +
checked for CPU and memory hotplug with xen_t as the target
  +
  +
|
  +
plug
  +
  +
|-
  +
|
 
checked for PCI hot-unplug hypercalls, with target as the PCI device
 
checked for PCI hot-unplug hypercalls, with target as the PCI device
  +
 
checked for CPU offlining with xen_t as the target
 
checked for CPU offlining with xen_t as the target
  +
unplug
 
  +
  +
  +
|
  +
unplug
  +
  +
|-
  +
|
 
checked for PHYSDEVOP_restore_msi* (target PCI device)
 
checked for PHYSDEVOP_restore_msi* (target PCI device)
  +
 
checked for PHYSDEVOP_setup_gsi (target IRQ)
 
checked for PHYSDEVOP_setup_gsi (target IRQ)
  +
checked for PHYSDEVOP_pci_mmcfg_reserved (target xen_t) setup
 
  +
checked for PHYSDEVOP_pci_mmcfg_reserved (target xen_t)
  +
  +
|
  +
setup
  +
  +
|}
  +
   
 
class security:
 
class security:
  +
 
Class security describes the FLASK security server itself; these operations are accessed using the xsm_op hypercall. The source is the domain invoking the hypercall, and the target is security_t.
 
Class security describes the FLASK security server itself; these operations are accessed using the xsm_op hypercall. The source is the domain invoking the hypercall, and the target is security_t.
  +
  +
   
 
Any domain with access to load_policy or setenforce must be trusted, since it can bypass the rest of the security policy.
 
Any domain with access to load_policy or setenforce must be trusted, since it can bypass the rest of the security policy.
   
   
Description Operation
 
use the security server to compute an access check compute_av
 
use the security server to compute a type transition compute_create
 
use the security server to compute member selection compute_member
 
sid <-> context string conversions check_context
 
allow loading a new XSM/FLASK policy load_policy
 
use the security server to compute an object relabel compute_relabel
 
use the security server to list the SIDs reachable by a given user compute_user
 
allow switching between enforcing and permissive mode setenforce
 
allow changing policy booleans setbool
 
allow changing security server configuration parmeters setsecparam
 
add ocontext label definitions for resources add_ocontext
 
remove ocontext label definitions for resources del_ocontext
 
   
   
   
  +
{| class="prettytable"
Some of these examples require [[Dom0 Disaggregation]] to be useful, since the domain build process requires the ability to write to the new domain's memory.
 
  +
|-
  +
|
  +
Description
  +
  +
|
  +
Operation
  +
  +
|-
  +
|
  +
use the security server to compute an access check
  +
  +
|
  +
compute_av
  +
  +
|-
  +
|
  +
use the security server to compute a type transition
  +
  +
|
  +
compute_create
  +
  +
|-
  +
|
  +
use the security server to compute member selection
  +
  +
|
  +
compute_member
  +
  +
|-
  +
|
  +
sid &lt;-&gt; context string conversions
  +
  +
|
  +
check_context
  +
  +
|-
  +
|
  +
allow loading a new XSM/FLASK policy
  +
  +
|
  +
load_policy
  +
  +
|-
  +
|
  +
use the security server to compute an object relabel
  +
  +
|
  +
compute_relabel
  +
  +
|-
  +
|
  +
use the security server to list the SIDs reachable by a given user
  +
  +
|
  +
compute_user
  +
  +
|-
  +
|
  +
allow switching between enforcing and permissive mode
  +
  +
|
  +
setenforce
  +
  +
|-
  +
|
  +
allow changing policy booleans
  +
  +
|
  +
setbool
  +
  +
|-
  +
|
  +
allow changing security server configuration parmeters
  +
  +
|
  +
setsecparam
  +
  +
|-
  +
|
  +
add ocontext label definitions for resources
  +
  +
|
  +
add_ocontext
  +
  +
|-
  +
|
  +
remove ocontext label definitions for resources
   
  +
|
More information:
 
  +
del_ocontext
* See [http://xenbits.xen.org/docs/unstable/misc/xsm-flask.txt XSM-FLASK generated docs]
 
   
  +
|}
[[Category:Security]]
 
[[Category:Xen]]
 

Revision as of 03:52, 23 June 2013

XSM Documentation


Overview


This is intended to be a hands-on description of Xen Security Modules (XSM) as well as their structure and operation. This document has been compiled based on docs/misc/xsm-flask.txt, mailing list discussions, Xen source code, and other support material contained within the Xen source-tree.


A reader of this document should be able to:

   1) Build and install Xen with XSM enabled
   2) Create and load a security policy
   3) Tag virtual machines with security labels managed by the security policy
   4) Utilize a simple application making use of privileges permitted by the policy


What is XSM


Xen offers a security framework called Xen Security Modules, or XSM, to enable an administrator or developer to exert fine-grained control over a Xen domain and its capabilities. Specifically, XSM makes it possible to define permissible interactions between domains, the hypervisor itself, and related resources such as memory and devices.


Via XSM, Xen implements a type of mandatory access control via a security architecture called FLASK using a module of the same name. An abbreviation for Flux Advanced Security Kernel, FLASK has its origins in several trusted operating system research projects, managed jointly between the United States’ National Security Agency, the Secure Computing Corporation, and the University of Utah. The specific intent of FLASK is to separate security enforcement from security policy, better isolating logical components of security systems.


As applied to operating system design, FLASK brings about security enhancements that improve auditing of actions and more granular control thereof. Today, it is perhaps best known through its expression in Security Enhanced Linux (SELinux).


In the same sense that SELinux is a collection of Linux security enhancements, auditing and policy mechanisms, so also is the FLASK Xen Security Module to Xen itself. Similarly, each rely upon a set of administration tools to craft security policies and guide their enforcement.








Below are some illustrative examples of what the FLASK Xen Security Module can make possible:

- Prevent two domains from communicating via event channels or grants
- Grant a set of privileged capabilities to otherwise unprivileged domains  
- Control which domains can use device passthrough (and which devices)
- Restrict or audit operations performed by privileged domains
- Prevent a privileged domain from arbitrarily mapping pages from other domains
- Isolation hypervisor support components (such as qemu or xenstore) from each other, and provide assurance that each may only perform its designated actions


Linux and Xen version requirements for use of XSM




Enabling XSM in Xen


XSM is a compile-time option for Xen, and by default it is a disabled feature.

To enable the framework, Xen must be compiled with XSM and FLASK explicitly enabled.


To do so, edit Config.mk or the .config file and set XSM_ENABLE and

FLASK_ENABLE to "y"


NOTE: this change requires a make clean, rebuild, reinstall and reboot.


Compiling the sample FLASK policy


During typical Xen compilation, compilation of the FLASK sample policy is not performed due to the necessary dependency upon the SElinux compiler, otherwise known as ‘checkpolicy.’ This tool must be installed before proceeding:


Installing checkpolicy

  • apt-get install checkpolicy
  • yum install checkpolicy
  • or similar


Next, to build the sample policy itself:

  • cd xen-source-tree/
  • make -C tools/flask/policy


The demonstrtion policy is generated from statements defined in files within the tools/flask/policy path.. After compilation, the resultant policy will be named xenpolicy.24 and reside within the directory tools/flask/policy.


Quoting from its description, this policy illustrates “most of the features of FLASK

that can be used without dom0 disaggregation. The main types for domUs are:


- domU_t is a domain that can communicate with any other domU_t
- isolated_domU_t can only communicate with dom0
- prot_domU_t is a domain type whose creation can be disabled with a boolean
- nomigrate_t is a domain that must be created via the nomigrate_t_building
  type, and whose memory cannot be read by dom0 once created


HVM domains with stubdomain device models use two types (one per domain):

- domHVM_t is an HVM domain that uses a stubdomain device model
- dm_dom_t is the device model for a domain with type domHVM_t”


Booting Xen with FLASK


When Xen is compiled with XSM, the following grub command-line options can be used to set FLASK properties. Using Debian and Ubuntu as examples, these options can be placed in /etc/default/grub within the variable GRUB_CMDLINE_XEN_DEFAULT. Please consult distribution documentation for the recommended method. When package management scripts regenerate the grub configuration (e.g., during a kernel upgrade or at the request of a sysadmin), a system configured in this manner will be guaranteed to properly embed XSM parameters within the grub configuration. For testing purposes, manually editing the grub command line at boot will also suffice.


For example:

  • GRUB_CMDLINE_XEN_DEFAULT="flask_enforcing=1”


Xen XSM command line parameters

  • flask_enforcing
    • The default value for flask_enforcing is '0'. This parameter causes the platform to boot in permissive mode which means that the policy is loaded but not enforced. This mode is often helpful for developing new systems and policies as the policy violations are reported on the xen console and may be viewed in dom0 through 'xl dmesg'.


To boot the platform into enforcing mode, which means that the policy is loaded and enforced, append 'flask_enforcing=1' on the grub line.

    • This parameter may also be changed through the flask hypercall.
    • This parameter may also be changed through the ‘xl setenforce’ command



  • flask_enabled
    • The default value for flask_enabled is '1'. This parameter causes the platform to enable the FLASK security module under the XSM framework. The parameter may be enabled/disabled only once per boot. If the parameter is set to '0', only a reboot can re-enable flask. When flask_enabled is '0' the DUMMY module is enforced; when this module name is encountered in XSM-related documentation and mailing list discussions, it should be interpreted as a “pass through” default XSM policy which matches behavior of a system without XSM enabled at compile-time.
    • This parameter may also be changed through the flask hypercall.
    • This parameter may also be queried through the ‘xl getenforce’ command
    • This parameter may be altered only once per boot.


The compiled policy must be installed into a grub-accessible location (such as /boot where kernels are also stored), as it is loaded during the Xen boot process. Otherwise, FLASK will not be enabled at runtime. It is recommended by the authors of XSM to add an extra subdirectory, such as /boot/flask, to use as a repository for XSM policies.


The policy has to be added to grub as a module after the Xen kernel multiboot line, for example as:


 module /boot/flask/xenpolicy.24


To automatically generate this line when running grub-update, the Xen grub-mkconfig helper script has to be modified in /etc/grub.d/20_linux_xen. This helper scripts are different depending on your grub version (and distribution).


Once Xen is booted with the FLASK policy, the policy (or a new one) can be reloaded using the “xl loadpolicy” command.


Creating domains with security labels


Once FLASK is loaded, domains need to be created using a security label in their configuration. Without this line, the domains will be classified “unlabeled”.


seclabel='system_u:system_r:domU_t'


The label’s three sections are: user, role and type. These will be discussed further in this document.


Monitoring XSM logs

XSM:Flask will emit avc: denied messages when a permission is denied by the

policy, just like SELinux, and can be viewed with xl dmesg:


 xl dmesg | grep avc


An example output looks like:


(XEN) avc: denied { setparam } for domid=0 scontext=system_u:system_r:dom0_t tcontext=system_u:system_r:domU_t tclass=hvm


FLASK


The sample FLASK policy can be found in tools/flask/policy/policy/modules/xen. The two files found here are xen.te, the policy description, and xen.if, a collection of macros to be used in the policy description.


Users, roles, types and attributes


Flask provides multiple levels of categories to abstract away from hypercalls.


On the most basic level, a “type” can be defined to specify the hypercalls that type is allowed to execute and how it is allowed to execute them. When XSM is enforcing the policy, only those hypercalls will be executable that are explicitly allowed in the policy.


The sample XSM policy defines several types, for example: xen_t, dom0_t and domU_t. A new type can be defined with the “type” keyword:


 type new_type_t;


Each type can be assigned into an attribute category, to easily reference each type having the attribute. The sample policy defines several attributes, for example: xen_type, domain_type, resource_type, etc.


A type can be assigned one or multiple attributes, for example


 type xen_t, xen_type, mls_priv;


assigns the xen_t type the attributes xen_type and mls_priv.


Defining which hypercalls are allowed for each type is done using the “allow” keyword. Hypercalls are grouped into security classes (defined in xen/xsm/flask/policy/access_vectors) which will be discussed later. For example the following


 allow dom0_t security_t:security check_context;


enables the dom0_t type to execute the check_context hypercall in the security class targeting a security_t type. The allow line can be generalized as follows:


 allow <source type> <target type>:<security class> <hypercall>;


Multiple hypercalls belonging to the same security class can be defined by wrapping the hypercalls into {}, for example:


 allow dom0_t dom0_t:resource { add remove };


Using the attributes we can quickly allow each type with that attribute access to hypercalls:


 # Allow all domains to use (unprivileged parts of) the tmem hypercall
 allow domain_type xen_t:xen tmem_op;


Roles are the second level above types, where we can define sets of types belonging to a role. While attributes are only accessible internally inside the policy (as a shortcut), a role is part of the security label. A role defines which types belong to that role, therefore it can prevent us from erroneously assigning a type to a VM when it’s role doesn’t have that type.


The sample FLASK policy defines two roles: system_r and vm_r. A role definition is as follows:


 role system_r;
 role system_r types { xen_type domain_type };


The first line declares a new role while the second line assigns the types belonging to that role (using attributes). When we want to include all types with an attribute except some, we can exclude those types by placing “-” in front of them, like


 role vm_r;
 role vm_r types { domain_type -dom0_t };


In the above, the vm_r role is defined as all types with the domain_type attribute, except the dom0_t type.


On the highest level we can define users. Users are not defined in the .te (like roles and types), rather they are defined in tools/flask/policy/policy/users. This allows us to define a generic set of users across multiple security modules. By default the FLASK policy will create three users: system_u, customer_1 and customer_2.


A user can be assigned multiple roles but by default the system_u user is assigned the system_r role, and the customer_* users are assigned the vm_r role.


A new user can be defined in the users file as


 user <user name> roles { <role1> <role2> };


Constraints


Constraints are defined in the file tools/flask/policy/policy/constraints. Constraints are a safety net to specifically disallow undesired operations that the policy may allow otherwise. The sample Flask policy defines two constraints to prevent event channels and grants between different customers. A constraints syntax is as follows:


 constrain <security class> { <hypercall> } ( expression );

For example:


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


The constraint defines that the hypercalls belonging to the security class are only allowed when the expression is true. The expression can contain any user, role and type defined in the policy in the following format:


# expression : ( expression )

# | 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


Macros


Macros are used heavily across the sample Flask policy. For each security module a macro file can be defined as a .if file. The sample macro file (tools/flask/policy/policy/modules/xen/xen.if) contains several commonly used macros, for example for declaring a new domain type and it’s associated sub-types and to setup it’s common allow rules. Macros can call other macros. The macro .if file is required to exist for the policy to compile, even if no macros are defined for a module.


Adding new security modules

New security modules can be easily added by editing tools/flask/policy/policy/modules.conf and adding the new modules name as such:


<module_name> = on


The module has to defined in the folder tools/flask/policy/policy/modules/<module_name> with two files:


 <module_name>.te
 <module_name>.if


When multiple security modules are present the modules can’t contain duplicate role or type declarations.


The sample policy is recommended to be left turned on as it contains several definitions required to boot Xen.


Security classes


Security classes are defined in xen/xsm/flask/policy/access_vectors and categorize each hypercall into one of the classes. Each class can hold a maximum of 32 members.


class xen:

Class xen consists of operations dealing with the hypervisor itself. Unless otherwise specified, the source is the domain executing the hypercall, and the target is the xen initial sid (type xen_t).


Description

Hypercall

XENPF_settime

settime

XEN_SYSCTL_tbuf_op

tbufcontrol

CONSOLEIO_read, XEN_SYSCTL_readconsole

readconsole

XEN_SYSCTL_readconsole with clear=1

clearconsole

XEN_SYSCTL_perfc_op

perfcontrol

XENPF_add_memtype

mtrr_add

XENPF_del_memtype

mtrr_del

XENPF_read_memtype

mtrr_read

XENPF_microcode_update

microcode

XEN_SYSCTL_physinfo, XEN_SYSCTL_topologyinfo, XEN_SYSCTL_numainfo

physinfo

XENPF_platform_quirk

quirk

CONSOLEIO_write

writeconsole

PHYSDEVOP_apic_read, PHYSDEVOP_alloc_irq_vector

readapic

PHYSDEVOP_apic_write

writeapic

Most XENOPROF_*

privprofile

XENOPROF_{init,enable_virq,disable_virq,get_buffer}

nonprivprofile

kexec hypercall

kexec

XENPF_firmware_info, XENPF_efi_runtime_call

firmware

XENPF_enter_acpi_sleep

sleep

XENPF_change_freq

frequency

XENPF_getidletime

getidle

XEN_SYSCTL_debug_keys

debug

XEN_SYSCTL_getcpuinfo, XENPF_get_cpu_version, XENPF_get_cpuinfo

getcpuinfo

XEN_SYSCTL_availheap

heap

XEN_SYSCTL_get_pmstat, XEN_SYSCTL_pm_op, XENPF_set_processor_pminfo,

XENPF_core_parking

pm_op

mca hypercall

mca_op

XEN_SYSCTL_lockprof_op

lockprof

XEN_SYSCTL_cpupool_op

cpupool_op

tmem hypercall (any access)

tmem_op

TMEM_CONTROL command of tmem hypercall

tmem_control

XEN_SYSCTL_scheduler_op with XEN_DOMCTL_SCHEDOP_getinfo, XEN_SYSCTL_sched_id

getscheduler

XEN_SYSCTL_scheduler_op with XEN_DOMCTL_SCHEDOP_putinfo

setscheduler



class domain and class domain2:

Classes domain and domain2 consist of operations that a domain performs on

another domain or on itself. Unless otherwise specified, the source is the

domain executing the hypercall, and the target is the domain being operated on

(which may result in a _self or _target type). Transitions in class domain are used to produce the _self and _target types.


class domain:


Description

Hypercall

XEN_DOMCTL_setvcpucontext

setvcpucontext

XEN_DOMCTL_pausedomain

pause

XEN_DOMCTL_unpausedomain

unpause

XEN_DOMCTL_resumedomain

resume

XEN_DOMCTL_createdomain

create

checked in FLASK_RELABEL_DOMAIN for any relabel operation:

source = the old label of the domain
 target = the new label of the domain

see also the domain2 relabel{from,to,self} permissions

transition

XEN_DOMCTL_max_vcpus

max_vcpus

XEN_DOMCTL_destroydomain

destroy

XEN_DOMCTL_setvcpuaffinity

setvcpuaffinity

XEN_DOMCTL_getvcpuaffinity

getvcpuaffinity

XEN_DOMCTL_scheduler_op with XEN_DOMCTL_SCHEDOP_getinfo

getscheduler

XEN_DOMCTL_getdomaininfo, XEN_SYSCTL_getdomaininfolist

getdomaininfo

XEN_DOMCTL_getvcpuinfo

getvcpuinfo

XEN_DOMCTL_getvcpucontext

getvcpucontext

XEN_DOMCTL_max_mem

setdomainmaxmem

XEN_DOMCTL_setdomainhandle

setdomainhandle

XEN_DOMCTL_setdebugging

setdebugging

XEN_DOMCTL_hypercall_init

hypercall

XEN_DOMCTL_settimeoffset

settime

checked in XEN_DOMCTL_set_target:

source = the new device model domain
target = the new target domain

see also the domain2 make_priv_for and set_as_target checks

set_target

SCHEDOP_remote_shutdown

shutdown

XEN_DOMCTL_set{,_machine}_address_size

setaddrsize

XEN_DOMCTL_get{,_machine}_address_size

getaddrsize

XEN_DOMCTL_sendtrigger

trigger

XEN_DOMCTL_get_ext_vcpucontext

getextvcpucontext

XEN_DOMCTL_set_ext_vcpucontext

setextvcpucontext

XEN_DOMCTL_getvcpuextstate

getvcpuextstate

XEN_DOMCTL_setvcpuextstate

setvcpuextstate

XENMEM_get_pod_target

getpodtarget

XENMEM_set_pod_target

setpodtarget

XEN_DOMCTL_subscribe, XEN_DOMCTL_disable_migrate, XEN_DOMCTL_suppress_spurious_page_faults

set_misc_info

XEN_DOMCTL_set_virq_handler

set_virq_handler


class domain2 (continuation of class domain):


checked in FLASK_RELABEL_DOMAIN with non-DOMID_SELF:

source = the domain making the hypercall
target = the old label of the domain being relabeled

relabelfrom

checked in FLASK_RELABEL_DOMAIN with non-DOMID_SELF:

source = the domain making the hypercall
target = the new label of the domain being relabeled

relabelto

checked in FLASK_RELABEL_DOMAIN, only with DOMID_SELF:

 source = the old label of the domain
 target = the new label of the domain

see also domain__transition

relabelself

checked in XEN_DOMCTL_set_target:

 source = the domain making the hypercall
 target = the new device model domain


make_priv_for

checked in XEN_DOMCTL_set_target:

source = the domain making the hypercall
target = the new target domain

set_as_target

XEN_DOMCTL_set_cpuid

set_cpuid

XEN_DOMCTL_gettscinfo

gettsc

XEN_DOMCTL_settscinfo

settsc

XEN_DOMCTL_scheduler_op with XEN_DOMCTL_SCHEDOP_putinfo

setscheduler


class hvm:

Similar to class domain, but primarily contains domctls related to HVM domains.


XEN_DOMCTL_sethvmcontext

sethvmc

XEN_DOMCTL_gethvmcontext, XEN_DOMCTL_gethvmcontext_partial

gethvmc

HVMOP_set_param

setparam

HVMOP_get_param

getparam

HVMOP_set_pci_intx_level (also needs hvmctl)

pcilevel

HVMOP_set_isa_irq_level

irqlevel

HVMOP_set_pci_link_route

pciroute, bind_irq

XEN_DOMCTL_pin_mem_cacheattr

cacheattr

HVMOP_track_dirty_vram

trackdirtyvram

HVMOP_modified_memory, HVMOP_get_mem_type, HVMOP_set_mem_type,

HVMOP_set_mem_access, HVMOP_get_mem_access, HVMOP_pagetable_dying,

HVMOP_inject_trap

hvmctl

XEN_DOMCTL_set_access_required

mem_event

XEN_DOMCTL_mem_sharing_op and XENMEM_sharing_op_{share,add_physmap} with:

 source = the domain making the hypercall
 target = domain whose memory is being shared

mem_sharing

XEN_DOMCTL_audit_p2m

audit_p2m

HVMOP_inject_msi

send_irq

checked in XENMEM_sharing_op_{share,add_physmap} with:

 source = domain whose memory is being shared
 target = client domain

share_mem


class event:

Class event describes event channels. Interdomain event channels have their own security label which is computed using a type transition between the source and target domains. Each endpoint has its own label, and the permission checks must pass on both endpoints for an event channel to be established.


when creating an interdomain event channel endpoint:

 source = event channel label
 target = remote domain the event channel binds to. This may be a _self or _target label if the endpoints are related as such.

This permission is checked when creating an unbound event channel and when the interdomain event channel is established.

bind

EVTCHNOP_send:

 source = domain sending the event
 target = event channel label

send

EVTCHNOP_status; same as _send

status

when creating an interdomain event channel endpoint:

 source = the domain creating the channel (which might not be an endpoint)
 target = event channel label

create

EVTCHNOP_reset:

 source = domain making the hypercall
 target = domain whose event channels are being reset

reset



class grant:

Class grant describes pages shared by grant mappings. Pages use the security label of their owning domain.


GNTTABOP_map_grant_ref with any access

map_read

GNTTABOP_map_grant_ref with write access

map_write

GNTTABOP_unmap_grant_ref

unmap

GNTTABOP_transfer

transfer

GNTTABOP_setup_table, GNTTABOP_get_status_frames (target is commonly _self)

setup

GNTTABOP_copy

copy

GNTTABOP_query_size, GNTTABOP_get_version

query


class mmu:

Class mmu describes pages of memory not accessed using grants. Permissions are checked using the domain ID used to access the page - the most common case is a domain's own ID (the _self label). Using DOMID_IO in the map command to restrict the mapping to IO memory will result in the target being domio_t, and migration uses read-only mappings with a target of DOMID_XEN (domxen_t).



checked when using mmu_update to map a page readably

 source = domain making the hypercall (which might not own the page table)
 target = domain whose pages are being mapped

map_read

checked when using mmu_update to map a page writably

# source = domain making the hypercall

# target = domain whose pages are being mapped


map_write

XEN_DOMCTL_getpageframeinfo*

pageinfo

XEN_DOMCTL_getmemlist

pagelist

XENMEM_{increase,decrease}_reservation, XENMEM_populate_physmap

adjust

XENMEM_{current,maximum}_reservation, XENMEM_maximum_gpfn

stat

mmu_update MMU_MACHPHYS_UPDATE

updatemp

XENMEM_add_to_physmap, XENMEM_remove_from_physmap

physmap

MMUEXT_PIN_L*_TABLE

pinpage

XENMEM_machine_memory_map (with target xen_t), XENMEM_set_memory_map (with domain target)

memorymap

checked when using mmu_update to update the page tables of another domain

 source = domain making the hypercall
 target = domain whose page tables are being modified


remote_remap

the mmuext_op hypercall acting on the target domain

mmuext_op

XENMEM_exchange:

 source = domain making the hypercall
 target = domain whose pages are being exchanged


exchange


class shadow:

Control of the paging_domctl split by subop


Description

Operation

XEN_DOMCTL_SHADOW_OP_OFF

disable

enable, get/set allocation

enable

enable, read, and clean log

logdirty


class resource:

Class resource is used to describe the resources used in hardware device passthrough. Resources include: hardware IRQs, MMIO regions, x86 I/O ports, and PCI devices; see docs/misc/xsm-flask.txt for how to label them.


Access to the legacy PCI configuration space on x86 via port 0xCF8/CFC requires IS_PRIV, even with FLASK. Writes to the BARs are checked as "setup", while other reads/writes are "use"; the target is the PCI device whose configuration space is being modified. Accesses to the MMIO-based PCI express configuration space described by the ACPI MCFG table are controlled as MMIO accesses, and cannot special-case BAR writes.


The {add,remove}_{irq,ioport,iomem,device} permissions use:

 source = domain making the hypercall
 target = resource's security label



Description

Operation

checked when adding a resource to a domain:

 source = domain making the hypercall
 target = domain which will have access to the resource

add

checked when removing a resource from a domain:

 source = domain making the hypercall
 target = domain which will no longer have access to the resource

remove

checked when adding a resource to a domain:

source = domain which will have access to the resource
 target = resource's security label

also checked when using some core Xen devices (target xen_t)

use

PHYSDEVOP_map_pirq and ioapic writes for dom0, when acting on real IRQs

 For GSI interrupts, the IRQ's label is indexed by the IRQ number
 For MSI interrupts, the label of the PCI device is used

add_irq

PHYSDEVOP_unmap_pirq (same as map, and only for real IRQs)

remove_irq

XEN_DOMCTL_ioport_permission, XEN_DOMCTL_ioport_mapping

add_ioport, remove_ioport

XEN_DOMCTL_iomem_permission, XEN_DOMCTL_memory_mapping

add_iomem, remove_iomem

XEN_DOMCTL_get_device_group, XEN_DOMCTL_test_assign_device:

 source = domain making the hypercall
 target = PCI device being queried


stat_device

XEN_DOMCTL_assign_device

add_device

XEN_DOMCTL_deassign_device

remove_device

checked for PCI hot and cold-plug hypercalls, with target as the PCI device

checked for CPU and memory hotplug with xen_t as the target

plug

checked for PCI hot-unplug hypercalls, with target as the PCI device

checked for CPU offlining with xen_t as the target


unplug

checked for PHYSDEVOP_restore_msi* (target PCI device)

checked for PHYSDEVOP_setup_gsi (target IRQ)

checked for PHYSDEVOP_pci_mmcfg_reserved (target xen_t)

setup


class security:

Class security describes the FLASK security server itself; these operations are accessed using the xsm_op hypercall. The source is the domain invoking the hypercall, and the target is security_t.


Any domain with access to load_policy or setenforce must be trusted, since it can bypass the rest of the security policy.



Description

Operation

use the security server to compute an access check

compute_av

use the security server to compute a type transition

compute_create

use the security server to compute member selection

compute_member

sid <-> context string conversions

check_context

allow loading a new XSM/FLASK policy

load_policy

use the security server to compute an object relabel

compute_relabel

use the security server to list the SIDs reachable by a given user

compute_user

allow switching between enforcing and permissive mode

setenforce

allow changing policy booleans

setbool

allow changing security server configuration parmeters

setsecparam

add ocontext label definitions for resources

add_ocontext

remove ocontext label definitions for resources

del_ocontext