diff --git a/tools/flask/policy/modules/dom0.te b/tools/flask/policy/modules/dom0.te
index 9970f9dc08..9ed7ccb57b 100644
--- a/tools/flask/policy/modules/dom0.te
+++ b/tools/flask/policy/modules/dom0.te
@@ -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
diff --git a/tools/flask/policy/modules/guest_features.te b/tools/flask/policy/modules/guest_features.te
index 2797a22761..baade15f2e 100644
--- a/tools/flask/policy/modules/guest_features.te
+++ b/tools/flask/policy/modules/guest_features.te
@@ -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
diff --git a/tools/flask/policy/modules/xen.te b/tools/flask/policy/modules/xen.te
index 3dbf93d2b8..fbd82334fd 100644
--- a/tools/flask/policy/modules/xen.te
+++ b/tools/flask/policy/modules/xen.te
@@ -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);
 
diff --git a/tools/flask/policy/policy/initial_sids b/tools/flask/policy/policy/initial_sids
index 6b7b7eff21..50b648df3b 100644
--- a/tools/flask/policy/policy/initial_sids
+++ b/tools/flask/policy/policy/initial_sids
@@ -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)
diff --git a/xen/arch/x86/guest/xen-nested.c b/xen/arch/x86/guest/xen-nested.c
index 744592aa0c..fcfa5e1087 100644
--- a/xen/arch/x86/guest/xen-nested.c
+++ b/xen/arch/x86/guest/xen-nested.c
@@ -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);
 
diff --git a/xen/include/xsm/dummy.h b/xen/include/xsm/dummy.h
index 01d2814fed..8011bf2cb4 100644
--- a/xen/include/xsm/dummy.h
+++ b/xen/include/xsm/dummy.h
@@ -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)
 {
diff --git a/xen/include/xsm/xsm.h b/xen/include/xsm/xsm.h
index b6141f6ab1..96044cb55a 100644
--- a/xen/include/xsm/xsm.h
+++ b/xen/include/xsm/xsm.h
@@ -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
diff --git a/xen/xsm/dummy.c b/xen/xsm/dummy.c
index c9a566f2b5..ed0a4b0691 100644
--- a/xen/xsm/dummy.c
+++ b/xen/xsm/dummy.c
@@ -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
 }
diff --git a/xen/xsm/flask/hooks.c b/xen/xsm/flask/hooks.c
index a7d690ac3c..2835279fe7 100644
--- a/xen/xsm/flask/hooks.c
+++ b/xen/xsm/flask/hooks.c
@@ -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)
diff --git a/xen/xsm/flask/policy/access_vectors b/xen/xsm/flask/policy/access_vectors
index 194d743a71..7e0d5aa7bf 100644
--- a/xen/xsm/flask/policy/access_vectors
+++ b/xen/xsm/flask/policy/access_vectors
@@ -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.
diff --git a/xen/xsm/flask/policy/initial_sids b/xen/xsm/flask/policy/initial_sids
index 7eca70d339..c684cda873 100644
--- a/xen/xsm/flask/policy/initial_sids
+++ b/xen/xsm/flask/policy/initial_sids
@@ -15,4 +15,5 @@ sid irq
 sid device
 sid domU
 sid domDM
+sid nestedxen
 # FLASK
