@@ -45,6 +45,7 @@ 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 };
+allow dom0_t nestedxen_t:mmu physmap;
# 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)
@@ -61,6 +61,7 @@ DECLARE_HYPERCALL(kexec_op)
DECLARE_HYPERCALL(argo_op)
DECLARE_HYPERCALL(xenpmu_op)
DECLARE_HYPERCALL(nested_xen_version)
+DECLARE_HYPERCALL(nested_memory_op)
DECLARE_HYPERCALL(arch_0)
DECLARE_HYPERCALL(arch_1)
@@ -22,11 +22,17 @@
#include <xen/lib.h>
#include <xen/sched.h>
+#include <public/memory.h>
#include <public/version.h>
+#include <public/xen.h>
#include <asm/guest/hypercall.h>
#include <asm/guest/xen.h>
+#ifdef CONFIG_COMPAT
+#include <compat/memory.h>
+#endif
+
extern char hypercall_page[];
/* xen_nested: support for nested PV interface enabled */
@@ -80,3 +86,77 @@ long do_nested_xen_version(int cmd, XEN_GUEST_HANDLE_PARAM(void) arg)
return -EOPNOTSUPP;
}
}
+
+static long nested_add_to_physmap(struct xen_add_to_physmap xatp)
+{
+ struct domain *d;
+ long ret;
+
+ if ( !xen_nested )
+ return -ENOSYS;
+
+ if ( (xatp.space != XENMAPSPACE_shared_info) &&
+ (xatp.space != XENMAPSPACE_grant_table) )
+ {
+ gprintk(XENLOG_ERR, "Nested memory op: unknown xatp.space: %u\n",
+ xatp.space);
+ return -EINVAL;
+ }
+
+ if ( xatp.domid != DOMID_SELF )
+ return -EPERM;
+
+ ret = xsm_nested_add_to_physmap(XSM_PRIV, current->domain);
+ if ( ret )
+ return ret;
+
+ gprintk(XENLOG_DEBUG, "Nested XENMEM_add_to_physmap: %d\n", xatp.space);
+
+ d = rcu_lock_current_domain();
+
+ ret = xen_hypercall_memory_op(XENMEM_add_to_physmap, &xatp);
+
+ rcu_unlock_domain(d);
+
+ if ( ret )
+ gprintk(XENLOG_ERR, "Nested memory op failed add_to_physmap"
+ " for %d with %ld\n", xatp.space, ret);
+ return ret;
+}
+
+long do_nested_memory_op(int cmd, XEN_GUEST_HANDLE_PARAM(void) arg)
+{
+ struct xen_add_to_physmap xatp;
+
+ if ( cmd != XENMEM_add_to_physmap )
+ {
+ gprintk(XENLOG_ERR, "Nested memory op %u not implemented.\n", cmd);
+ return -EOPNOTSUPP;
+ }
+
+ if ( copy_from_guest(&xatp, arg, 1) )
+ return -EFAULT;
+
+ return nested_add_to_physmap(xatp);
+}
+
+#ifdef CONFIG_COMPAT
+int compat_nested_memory_op(int cmd, XEN_GUEST_HANDLE_PARAM(void) arg)
+{
+ struct compat_add_to_physmap cmp;
+ struct xen_add_to_physmap *nat = COMPAT_ARG_XLAT_VIRT_BASE;
+
+ if ( cmd != XENMEM_add_to_physmap )
+ {
+ gprintk(XENLOG_ERR, "Nested memory op %u not implemented.\n", cmd);
+ return -EOPNOTSUPP;
+ }
+
+ if ( copy_from_guest(&cmp, arg, 1) )
+ return -EFAULT;
+
+ XLAT_add_to_physmap(nat, &cmp);
+
+ return nested_add_to_physmap(*nat);
+}
+#endif
@@ -75,6 +75,7 @@ const hypercall_args_t hypercall_args_table[NR_hypercalls] =
#endif
#ifdef CONFIG_XEN_NESTED
ARGS(nested_xen_version, 2),
+ COMP(nested_memory_op, 2, 2),
#endif
ARGS(mca, 1),
ARGS(arch_1, 1),
@@ -86,6 +86,7 @@ const hypercall_table_t pv_hypercall_table[] = {
#endif
#ifdef CONFIG_XEN_NESTED
HYPERCALL(nested_xen_version),
+ COMPAT_CALL(nested_memory_op),
#endif
HYPERCALL(mca),
HYPERCALL(arch_1),
@@ -122,6 +122,7 @@ DEFINE_XEN_GUEST_HANDLE(xen_ulong_t);
#define __HYPERVISOR_xenpmu_op 40
#define __HYPERVISOR_dm_op 41
#define __HYPERVISOR_nested_xen_version 42
+#define __HYPERVISOR_nested_memory_op 43
/* Architecture-specific hypercall definitions. */
#define __HYPERVISOR_arch_0 48
@@ -154,6 +154,10 @@ do_dm_op(
extern long do_nested_xen_version(
int cmd,
XEN_GUEST_HANDLE_PARAM(void) arg);
+
+extern long do_nested_memory_op(
+ int cmd,
+ XEN_GUEST_HANDLE_PARAM(void) arg);
#endif
#ifdef CONFIG_COMPAT
@@ -222,6 +226,12 @@ compat_dm_op(
unsigned int nr_bufs,
XEN_GUEST_HANDLE_PARAM(void) bufs);
+#ifdef CONFIG_XEN_NESTED
+extern int compat_nested_memory_op(
+ int cmd,
+ XEN_GUEST_HANDLE_PARAM(void) arg);
+#endif
+
#endif
void arch_get_xen_caps(xen_capabilities_info_t *info);
@@ -747,6 +747,13 @@ static XSM_INLINE int xsm_nested_xen_version(XSM_DEFAULT_ARG
XSM_ASSERT_ACTION(XSM_PRIV);
return xsm_default_action(action, d, NULL);
}
+
+static XSM_INLINE int xsm_nested_add_to_physmap(XSM_DEFAULT_ARG
+ const struct domain *d)
+{
+ XSM_ASSERT_ACTION(XSM_PRIV);
+ return xsm_default_action(action, d, NULL);
+}
#endif
#include <public/version.h>
@@ -189,6 +189,7 @@ struct xsm_operations {
#endif
#ifdef CONFIG_XEN_NESTED
int (*nested_xen_version) (const struct domain *d, unsigned int cmd);
+ int (*nested_add_to_physmap) (const struct domain *d);
#endif
};
@@ -734,6 +735,12 @@ static inline int xsm_nested_xen_version(xsm_default_t def,
return xsm_ops->nested_xen_version(d, cmd);
}
+static inline int xsm_nested_add_to_physmap(xsm_default_t def,
+ const struct domain *d)
+{
+ return xsm_ops->nested_add_to_physmap(d);
+}
+
#endif /* CONFIG_XEN_NESTED */
#endif /* XSM_NO_WRAPPERS */
@@ -159,5 +159,6 @@ void __init xsm_fixup_ops (struct xsm_operations *ops)
#endif
#ifdef CONFIG_XEN_NESTED
set_to_dummy_if_null(ops, nested_xen_version);
+ set_to_dummy_if_null(ops, nested_add_to_physmap);
#endif
}
@@ -1749,6 +1749,20 @@ static int flask_argo_send(const struct domain *d, const struct domain *t)
#endif
#ifdef CONFIG_XEN_NESTED
+static int domain_has_nested_perm(const struct domain *d, u16 class, u32 perm)
+{
+ struct avc_audit_data ad;
+
+ AVC_AUDIT_DATA_INIT(&ad, NONE);
+
+ return avc_has_perm(domain_sid(d), SECINITSID_NESTEDXEN, class, perm, &ad);
+}
+
+static int flask_nested_add_to_physmap(const struct domain *d)
+{
+ return domain_has_nested_perm(d, SECCLASS_MMU, MMU__PHYSMAP);
+}
+
static int flask_nested_xen_version(const struct domain *d, unsigned int op)
{
return domain_has_xen_version(d, SECINITSID_NESTEDXEN, op);
@@ -1897,6 +1911,7 @@ static struct xsm_operations flask_ops = {
#endif
#ifdef CONFIG_XEN_NESTED
.nested_xen_version = flask_nested_xen_version,
+ .nested_add_to_physmap = flask_nested_add_to_physmap,
#endif
};
Provides proxying to the host hypervisor for the XENMEM_add_to_physmap op only for the XENMAPSPACE_shared_info and XENMAPSPACE_grant_table spaces, for DOMID_SELF. Both compat and native entry points. Signed-off-by: Christopher Clark <christopher.clark@starlab.io> --- tools/flask/policy/modules/dom0.te | 1 + xen/arch/x86/guest/hypercall_page.S | 1 + xen/arch/x86/guest/xen-nested.c | 80 +++++++++++++++++++++++++++++ xen/arch/x86/hypercall.c | 1 + xen/arch/x86/pv/hypercall.c | 1 + xen/include/public/xen.h | 1 + xen/include/xen/hypercall.h | 10 ++++ xen/include/xsm/dummy.h | 7 +++ xen/include/xsm/xsm.h | 7 +++ xen/xsm/dummy.c | 1 + xen/xsm/flask/hooks.c | 15 ++++++ 11 files changed, 125 insertions(+)