@@ -22,9 +22,9 @@ allow dom0_t xen_t:xen2 {
# Allow dom0 to use all XENVER_ subops that have checks.
# Note that dom0 is part of domain_type so this has duplicates.
allow dom0_t xen_t:version {
- xen_extraversion xen_compile_info xen_capabilities
+ xen_version xen_extraversion xen_compile_info xen_capabilities
xen_changeset xen_pagesize xen_guest_handle xen_commandline
- xen_build_id
+ xen_build_id xen_get_features xen_platform_parameters
};
allow dom0_t xen_t:mmu memorymap;
@@ -43,6 +43,9 @@ allow dom0_t dom0_t:domain2 {
};
allow dom0_t dom0_t:resource { add remove };
+# Allow dom0 to communicate with a nested Xen hypervisor
+allow dom0_t nestedxen_t:version { xen_version xen_get_features };
+
# These permissions allow using the FLASK security server to compute access
# checks locally, which could be used by a domain or service (such as xenstore)
# that does not have its own security server to make access decisions based on
@@ -21,8 +21,9 @@ if (guest_writeconsole) {
# For normal guests, allow all queries except XENVER_commandline.
allow domain_type xen_t:version {
- xen_extraversion xen_compile_info xen_capabilities
- xen_changeset xen_pagesize xen_guest_handle
+ xen_version xen_extraversion xen_compile_info xen_capabilities
+ xen_changeset xen_pagesize xen_guest_handle xen_get_features
+ xen_platform_parameters
};
# Version queries don't need auditing when denied. They can be
@@ -26,6 +26,9 @@ attribute mls_priv;
# The hypervisor itself
type xen_t, xen_type, mls_priv;
+# A nested Xen hypervisor, if any
+type nestedxen_t, xen_type;
+
# Domain 0
declare_singleton_domain(dom0_t, mls_priv);
@@ -16,3 +16,6 @@ sid device gen_context(system_u:object_r:device_t,s0)
# Initial SIDs used by the toolstack for domains without defined labels
sid domU gen_context(system_u:system_r:domU_t,s0)
sid domDM gen_context(system_u:system_r:dm_dom_t,s0)
+
+# Initial SID for nested Xen on Xen
+sid nestedxen gen_context(system_u:system_r:nestedxen_t,s0)
@@ -47,9 +47,9 @@ long do_nested_xen_version(int cmd, XEN_GUEST_HANDLE_PARAM(void) arg)
if ( !xen_nested )
return -ENOSYS;
- /* FIXME: apply XSM check here */
- if ( !is_control_domain(current->domain) )
- return -EPERM;
+ ret = xsm_nested_xen_version(XSM_PRIV, current->domain, cmd);
+ if ( ret )
+ return ret;
gprintk(XENLOG_DEBUG, "Nested xen_version: %d.\n", cmd);
@@ -69,7 +69,7 @@ void __xsm_action_mismatch_detected(void);
#endif /* CONFIG_XSM */
static always_inline int xsm_default_action(
- xsm_default_t action, struct domain *src, struct domain *target)
+ xsm_default_t action, const struct domain *src, const struct domain *target)
{
switch ( action ) {
case XSM_HOOK:
@@ -739,6 +739,16 @@ static XSM_INLINE int xsm_argo_send(const struct domain *d,
#endif /* CONFIG_ARGO */
+#ifdef CONFIG_XEN_NESTED
+static XSM_INLINE int xsm_nested_xen_version(XSM_DEFAULT_ARG
+ const struct domain *d,
+ unsigned int cmd)
+{
+ XSM_ASSERT_ACTION(XSM_PRIV);
+ return xsm_default_action(action, d, NULL);
+}
+#endif
+
#include <public/version.h>
static XSM_INLINE int xsm_xen_version (XSM_DEFAULT_ARG uint32_t op)
{
@@ -187,6 +187,9 @@ struct xsm_operations {
int (*argo_register_any_source) (const struct domain *d);
int (*argo_send) (const struct domain *d, const struct domain *t);
#endif
+#ifdef CONFIG_XEN_NESTED
+ int (*nested_xen_version) (const struct domain *d, unsigned int cmd);
+#endif
};
#ifdef CONFIG_XSM
@@ -723,6 +726,16 @@ static inline int xsm_argo_send(const struct domain *d, const struct domain *t)
#endif /* CONFIG_ARGO */
+#ifdef CONFIG_XEN_NESTED
+static inline int xsm_nested_xen_version(xsm_default_t def,
+ const struct domain *d,
+ unsigned int cmd)
+{
+ return xsm_ops->nested_xen_version(d, cmd);
+}
+
+#endif /* CONFIG_XEN_NESTED */
+
#endif /* XSM_NO_WRAPPERS */
#ifdef CONFIG_MULTIBOOT
@@ -157,4 +157,7 @@ void __init xsm_fixup_ops (struct xsm_operations *ops)
set_to_dummy_if_null(ops, argo_register_any_source);
set_to_dummy_if_null(ops, argo_send);
#endif
+#ifdef CONFIG_XEN_NESTED
+ set_to_dummy_if_null(ops, nested_xen_version);
+#endif
}
@@ -1666,46 +1666,56 @@ static int flask_dm_op(struct domain *d)
#endif /* CONFIG_X86 */
-static int flask_xen_version (uint32_t op)
+static int domain_has_xen_version (const struct domain *d, u32 tsid,
+ uint32_t op)
{
- u32 dsid = domain_sid(current->domain);
+ u32 dsid = domain_sid(d);
switch ( op )
{
case XENVER_version:
- case XENVER_platform_parameters:
- case XENVER_get_features:
- /* These sub-ops ignore the permission checks and return data. */
- return 0;
+ return avc_has_perm(dsid, tsid, SECCLASS_VERSION,
+ VERSION__XEN_VERSION, NULL);
case XENVER_extraversion:
- return avc_has_perm(dsid, SECINITSID_XEN, SECCLASS_VERSION,
+ return avc_has_perm(dsid, tsid, SECCLASS_VERSION,
VERSION__XEN_EXTRAVERSION, NULL);
case XENVER_compile_info:
- return avc_has_perm(dsid, SECINITSID_XEN, SECCLASS_VERSION,
+ return avc_has_perm(dsid, tsid, SECCLASS_VERSION,
VERSION__XEN_COMPILE_INFO, NULL);
case XENVER_capabilities:
- return avc_has_perm(dsid, SECINITSID_XEN, SECCLASS_VERSION,
+ return avc_has_perm(dsid, tsid, SECCLASS_VERSION,
VERSION__XEN_CAPABILITIES, NULL);
case XENVER_changeset:
- return avc_has_perm(dsid, SECINITSID_XEN, SECCLASS_VERSION,
+ return avc_has_perm(dsid, tsid, SECCLASS_VERSION,
VERSION__XEN_CHANGESET, NULL);
+ case XENVER_platform_parameters:
+ return avc_has_perm(dsid, tsid, SECCLASS_VERSION,
+ VERSION__XEN_PLATFORM_PARAMETERS, NULL);
+ case XENVER_get_features:
+ return avc_has_perm(dsid, tsid, SECCLASS_VERSION,
+ VERSION__XEN_GET_FEATURES, NULL);
case XENVER_pagesize:
- return avc_has_perm(dsid, SECINITSID_XEN, SECCLASS_VERSION,
+ return avc_has_perm(dsid, tsid, SECCLASS_VERSION,
VERSION__XEN_PAGESIZE, NULL);
case XENVER_guest_handle:
- return avc_has_perm(dsid, SECINITSID_XEN, SECCLASS_VERSION,
+ return avc_has_perm(dsid, tsid, SECCLASS_VERSION,
VERSION__XEN_GUEST_HANDLE, NULL);
case XENVER_commandline:
- return avc_has_perm(dsid, SECINITSID_XEN, SECCLASS_VERSION,
+ return avc_has_perm(dsid, tsid, SECCLASS_VERSION,
VERSION__XEN_COMMANDLINE, NULL);
case XENVER_build_id:
- return avc_has_perm(dsid, SECINITSID_XEN, SECCLASS_VERSION,
+ return avc_has_perm(dsid, tsid, SECCLASS_VERSION,
VERSION__XEN_BUILD_ID, NULL);
default:
return -EPERM;
}
}
+static int flask_xen_version (uint32_t op)
+{
+ return domain_has_xen_version(current->domain, SECINITSID_XEN, op);
+}
+
static int flask_domain_resource_map(struct domain *d)
{
return current_has_perm(d, SECCLASS_DOMAIN2, DOMAIN2__RESOURCE_MAP);
@@ -1738,6 +1748,14 @@ static int flask_argo_send(const struct domain *d, const struct domain *t)
#endif
+#ifdef CONFIG_XEN_NESTED
+static int flask_nested_xen_version(const struct domain *d, unsigned int op)
+{
+ return domain_has_xen_version(d, SECINITSID_NESTEDXEN, op);
+}
+
+#endif
+
long do_flask_op(XEN_GUEST_HANDLE_PARAM(xsm_op_t) u_flask_op);
int compat_flask_op(XEN_GUEST_HANDLE_PARAM(xsm_op_t) u_flask_op);
@@ -1877,6 +1895,9 @@ static struct xsm_operations flask_ops = {
.argo_register_any_source = flask_argo_register_any_source,
.argo_send = flask_argo_send,
#endif
+#ifdef CONFIG_XEN_NESTED
+ .nested_xen_version = flask_nested_xen_version,
+#endif
};
void __init flask_init(const void *policy_buffer, size_t policy_size)
@@ -510,6 +510,8 @@ class security
#
class version
{
+# Basic information
+ xen_version
# Extra informations (-unstable).
xen_extraversion
# Compile information of the hypervisor.
@@ -518,6 +520,10 @@ class version
xen_capabilities
# Source code changeset.
xen_changeset
+# Hypervisor virt start
+ xen_platform_parameters
+# Query for bitmap of platform features
+ xen_get_features
# Page size the hypervisor uses.
xen_pagesize
# An value that the control stack can choose.
@@ -15,4 +15,5 @@ sid irq
sid device
sid domU
sid domDM
+sid nestedxen
# FLASK
Expand XSM control to the full set of Xen version ops, to allow for granular control over ops a domain is allowed to issue for the nested case. Applies const to args of xsm_default_action. Signed-off-by: Christopher Clark <christopher.clark@starlab.io> --- tools/flask/policy/modules/dom0.te | 7 ++- tools/flask/policy/modules/guest_features.te | 5 +- tools/flask/policy/modules/xen.te | 3 ++ tools/flask/policy/policy/initial_sids | 3 ++ xen/arch/x86/guest/xen-nested.c | 6 +-- xen/include/xsm/dummy.h | 12 ++++- xen/include/xsm/xsm.h | 13 ++++++ xen/xsm/dummy.c | 3 ++ xen/xsm/flask/hooks.c | 49 ++++++++++++++------ xen/xsm/flask/policy/access_vectors | 6 +++ xen/xsm/flask/policy/initial_sids | 1 + 11 files changed, 86 insertions(+), 22 deletions(-)