diff --git a/xen/arch/x86/mm/paging.c b/xen/arch/x86/mm/paging.c index 34d833251b..3a309bc74b 100644 --- a/xen/arch/x86/mm/paging.c +++ b/xen/arch/x86/mm/paging.c @@ -767,7 +767,7 @@ long do_paging_domctl_cont( if ( d == NULL ) return -ESRCH; - ret = xsm_domctl(XSM_OTHER, d, op.cmd); + ret = xsm_domctl(XSM_OTHER, d, op.cmd, 0 /* SSIDref not applicable */); if ( !ret ) { if ( domctl_lock_acquire() ) diff --git a/xen/common/domctl.c b/xen/common/domctl.c index 505e29c0dc..6cf78d4975 100644 --- a/xen/common/domctl.c +++ b/xen/common/domctl.c @@ -318,7 +318,9 @@ long do_domctl(XEN_GUEST_HANDLE_PARAM(xen_domctl_t) u_domctl) return -ESRCH; } - ret = xsm_domctl(XSM_OTHER, d, op->cmd); + ret = xsm_domctl(XSM_OTHER, d, op->cmd, + /* SSIDRef only applicable for cmd == createdomain */ + op->u.createdomain.ssidref); if ( ret ) goto domctl_out_unlock_domonly; diff --git a/xen/include/xsm/dummy.h b/xen/include/xsm/dummy.h index 8671af1ba4..3286befeca 100644 --- a/xen/include/xsm/dummy.h +++ b/xen/include/xsm/dummy.h @@ -162,7 +162,7 @@ static XSM_INLINE int cf_check xsm_set_target( } static XSM_INLINE int cf_check xsm_domctl( - XSM_DEFAULT_ARG struct domain *d, int cmd) + XSM_DEFAULT_ARG struct domain *d, unsigned int cmd, uint32_t ssidref) { XSM_ASSERT_ACTION(XSM_OTHER); switch ( cmd ) diff --git a/xen/include/xsm/xsm.h b/xen/include/xsm/xsm.h index 8dad03fd3d..627c0d2731 100644 --- a/xen/include/xsm/xsm.h +++ b/xen/include/xsm/xsm.h @@ -60,7 +60,7 @@ struct xsm_ops { int (*domctl_scheduler_op)(struct domain *d, int op); int (*sysctl_scheduler_op)(int op); int (*set_target)(struct domain *d, struct domain *e); - int (*domctl)(struct domain *d, int cmd); + int (*domctl)(struct domain *d, unsigned int cmd, uint32_t ssidref); int (*sysctl)(int cmd); int (*readconsole)(uint32_t clear); @@ -248,9 +248,10 @@ static inline int xsm_set_target( return alternative_call(xsm_ops.set_target, d, e); } -static inline int xsm_domctl(xsm_default_t def, struct domain *d, int cmd) +static inline int xsm_domctl(xsm_default_t def, struct domain *d, + unsigned int cmd, uint32_t ssidref) { - return alternative_call(xsm_ops.domctl, d, cmd); + return alternative_call(xsm_ops.domctl, d, cmd, ssidref); } static inline int xsm_sysctl(xsm_default_t def, int cmd) diff --git a/xen/xsm/flask/hooks.c b/xen/xsm/flask/hooks.c index 5e88c71b8e..278ad38c2a 100644 --- a/xen/xsm/flask/hooks.c +++ b/xen/xsm/flask/hooks.c @@ -663,12 +663,22 @@ static int cf_check flask_set_target(struct domain *d, struct domain *t) return rc; } -static int cf_check flask_domctl(struct domain *d, int cmd) +static int cf_check flask_domctl(struct domain *d, unsigned int cmd, + uint32_t ssidref) { switch ( cmd ) { - /* These have individual XSM hooks (common/domctl.c) */ case XEN_DOMCTL_createdomain: + /* + * There is a later hook too, but at this early point simply check + * that the calling domain is privileged enough to create a domain. + * + * Note that d is NULL because we haven't even allocated memory for it + * this early in XEN_DOMCTL_createdomain. + */ + return avc_current_has_perm(ssidref, SECCLASS_DOMAIN, DOMAIN__CREATE, NULL); + + /* These have individual XSM hooks (common/domctl.c) */ case XEN_DOMCTL_getdomaininfo: case XEN_DOMCTL_scheduler_op: case XEN_DOMCTL_irq_permission: