/* * Default XSM hooks - IS_PRIV and IS_PRIV_FOR checks * * Author: Daniel De Graaf * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2, * as published by the Free Software Foundation. * * * Each XSM hook implementing an access check should have its first parameter * preceded by XSM_DEFAULT_ARG (or use XSM_DEFAULT_VOID if it has no * arguments). The first non-declaration statement shold be XSM_ASSERT_ACTION * with the expected type of the hook, which will either define or check the * value of action. */ #include #include /* Cannot use BUILD_BUG_ON here because the expressions we check are not * considered constant at compile time. Instead, rely on constant propagation to * inline out the calls to this invalid function, which will cause linker errors * if references remain at link time. */ #define LINKER_BUG_ON(x) do { if (x) __xsm_action_mismatch_detected(); } while (0) /* DO NOT implement this function; it is supposed to trigger link errors */ void __xsm_action_mismatch_detected(void); #ifdef XSM_ENABLE /* In XSM_ENABLE builds, this header file is included from xsm/dummy.c, and * contains static (not inline) functions compiled to the dummy XSM module. * There is no xsm_default_t argument available, so the value from the assertion * is used to initialize the variable. */ #define XSM_INLINE /* */ #define XSM_DEFAULT_ARG /* */ #define XSM_DEFAULT_VOID void #define XSM_ASSERT_ACTION(def) xsm_default_t action = def; (void)action #else /* XSM_ENABLE */ /* In !XSM_ENABLE builds, this header file is included from xsm/xsm.h, and * contains inline functions for each XSM hook. These functions also perform * compile-time checks on the xsm_default_t argument to ensure that the behavior * of the dummy XSM module is the same as the behavior with XSM disabled. */ #define XSM_INLINE always_inline #define XSM_DEFAULT_ARG xsm_default_t action, #define XSM_DEFAULT_VOID xsm_default_t action #define XSM_ASSERT_ACTION(def) LINKER_BUG_ON(def != action) #endif /* XSM_ENABLE */ static always_inline int xsm_default_action( xsm_default_t action, struct domain *src, struct domain *target) { switch ( action ) { case XSM_HOOK: return 0; case XSM_DM_PRIV: if ( src->is_privileged ) return 0; if ( target && src->target == target ) return 0; return -EPERM; case XSM_TARGET: if ( src == target ) return 0; if ( src->is_privileged ) return 0; if ( target && src->target == target ) return 0; return -EPERM; case XSM_PRIV: if ( src->is_privileged ) return 0; return -EPERM; default: LINKER_BUG_ON(1); return -EPERM; } } static XSM_INLINE void xsm_security_domaininfo(struct domain *d, struct xen_domctl_getdomaininfo *info) { return; } static XSM_INLINE int xsm_domain_create(XSM_DEFAULT_ARG struct domain *d, u32 ssidref) { XSM_ASSERT_ACTION(XSM_HOOK); return xsm_default_action(action, current->domain, d); } static XSM_INLINE int xsm_getdomaininfo(XSM_DEFAULT_ARG struct domain *d) { XSM_ASSERT_ACTION(XSM_HOOK); return xsm_default_action(action, current->domain, d); } static XSM_INLINE int xsm_domctl_scheduler_op(XSM_DEFAULT_ARG struct domain *d, int cmd) { XSM_ASSERT_ACTION(XSM_HOOK); return xsm_default_action(action, current->domain, d); } static XSM_INLINE int xsm_sysctl_scheduler_op(XSM_DEFAULT_ARG int cmd) { XSM_ASSERT_ACTION(XSM_HOOK); return xsm_default_action(action, current->domain, NULL); } static XSM_INLINE int xsm_set_target(XSM_DEFAULT_ARG struct domain *d, struct domain *e) { XSM_ASSERT_ACTION(XSM_HOOK); return xsm_default_action(action, current->domain, NULL); } static XSM_INLINE int xsm_domctl(XSM_DEFAULT_ARG struct domain *d, int cmd) { XSM_ASSERT_ACTION(XSM_OTHER); switch ( cmd ) { case XEN_DOMCTL_ioport_mapping: case XEN_DOMCTL_memory_mapping: case XEN_DOMCTL_bind_pt_irq: case XEN_DOMCTL_unbind_pt_irq: return xsm_default_action(XSM_DM_PRIV, current->domain, d); default: return xsm_default_action(XSM_PRIV, current->domain, d); } } static XSM_INLINE int xsm_sysctl(XSM_DEFAULT_ARG int cmd) { XSM_ASSERT_ACTION(XSM_PRIV); return xsm_default_action(action, current->domain, NULL); } static XSM_INLINE int xsm_readconsole(XSM_DEFAULT_ARG uint32_t clear) { XSM_ASSERT_ACTION(XSM_HOOK); return xsm_default_action(action, current->domain, NULL); } static XSM_INLINE int xsm_do_mca(XSM_DEFAULT_VOID) { XSM_ASSERT_ACTION(XSM_PRIV); return xsm_default_action(action, current->domain, NULL); } static XSM_INLINE int xsm_alloc_security_domain(struct domain *d) { return 0; } static XSM_INLINE void xsm_free_security_domain(struct domain *d) { return; } static XSM_INLINE int xsm_grant_mapref(XSM_DEFAULT_ARG struct domain *d1, struct domain *d2, uint32_t flags) { XSM_ASSERT_ACTION(XSM_HOOK); return xsm_default_action(action, d1, d2); } static XSM_INLINE int xsm_grant_unmapref(XSM_DEFAULT_ARG struct domain *d1, struct domain *d2) { XSM_ASSERT_ACTION(XSM_HOOK); return xsm_default_action(action, d1, d2); } static XSM_INLINE int xsm_grant_setup(XSM_DEFAULT_ARG struct domain *d1, struct domain *d2) { XSM_ASSERT_ACTION(XSM_TARGET); return xsm_default_action(action, d1, d2); } static XSM_INLINE int xsm_grant_transfer(XSM_DEFAULT_ARG struct domain *d1, struct domain *d2) { XSM_ASSERT_ACTION(XSM_HOOK); return xsm_default_action(action, d1, d2); } static XSM_INLINE int xsm_grant_copy(XSM_DEFAULT_ARG struct domain *d1, struct domain *d2) { XSM_ASSERT_ACTION(XSM_HOOK); return xsm_default_action(action, d1, d2); } static XSM_INLINE int xsm_grant_query_size(XSM_DEFAULT_ARG struct domain *d1, struct domain *d2) { XSM_ASSERT_ACTION(XSM_TARGET); return xsm_default_action(action, d1, d2); } static XSM_INLINE int xsm_memory_exchange(XSM_DEFAULT_ARG struct domain *d) { XSM_ASSERT_ACTION(XSM_TARGET); return xsm_default_action(action, current->domain, d); } static XSM_INLINE int xsm_memory_adjust_reservation(XSM_DEFAULT_ARG struct domain *d1, struct domain *d2) { XSM_ASSERT_ACTION(XSM_TARGET); return xsm_default_action(action, d1, d2); } static XSM_INLINE int xsm_memory_stat_reservation(XSM_DEFAULT_ARG struct domain *d1, struct domain *d2) { XSM_ASSERT_ACTION(XSM_TARGET); return xsm_default_action(action, d1, d2); } static XSM_INLINE int xsm_console_io(XSM_DEFAULT_ARG struct domain *d, int cmd) { XSM_ASSERT_ACTION(XSM_OTHER); #ifdef VERBOSE if ( cmd == CONSOLEIO_write ) return xsm_default_action(XSM_HOOK, d, NULL); #endif return xsm_default_action(XSM_PRIV, d, NULL); } static XSM_INLINE int xsm_profile(XSM_DEFAULT_ARG struct domain *d, int op) { XSM_ASSERT_ACTION(XSM_HOOK); return xsm_default_action(action, d, NULL); } static XSM_INLINE int xsm_kexec(XSM_DEFAULT_VOID) { XSM_ASSERT_ACTION(XSM_PRIV); return xsm_default_action(action, current->domain, NULL); } static XSM_INLINE int xsm_schedop_shutdown(XSM_DEFAULT_ARG struct domain *d1, struct domain *d2) { XSM_ASSERT_ACTION(XSM_DM_PRIV); return xsm_default_action(action, d1, d2); } static XSM_INLINE int xsm_memory_pin_page(XSM_DEFAULT_ARG struct domain *d1, struct domain *d2, struct page_info *page) { XSM_ASSERT_ACTION(XSM_HOOK); return xsm_default_action(action, d1, d2); } static XSM_INLINE int xsm_claim_pages(XSM_DEFAULT_ARG struct domain *d) { XSM_ASSERT_ACTION(XSM_PRIV); return xsm_default_action(action, current->domain, d); } static XSM_INLINE int xsm_evtchn_unbound(XSM_DEFAULT_ARG struct domain *d, struct evtchn *chn, domid_t id2) { XSM_ASSERT_ACTION(XSM_TARGET); return xsm_default_action(action, current->domain, d); } static XSM_INLINE int xsm_evtchn_interdomain(XSM_DEFAULT_ARG struct domain *d1, struct evtchn *chan1, struct domain *d2, struct evtchn *chan2) { XSM_ASSERT_ACTION(XSM_HOOK); return xsm_default_action(action, d1, d2); } static XSM_INLINE void xsm_evtchn_close_post(struct evtchn *chn) { return; } static XSM_INLINE int xsm_evtchn_send(XSM_DEFAULT_ARG struct domain *d, struct evtchn *chn) { XSM_ASSERT_ACTION(XSM_HOOK); return xsm_default_action(action, d, NULL); } static XSM_INLINE int xsm_evtchn_status(XSM_DEFAULT_ARG struct domain *d, struct evtchn *chn) { XSM_ASSERT_ACTION(XSM_TARGET); return xsm_default_action(action, current->domain, d); } static XSM_INLINE int xsm_evtchn_reset(XSM_DEFAULT_ARG struct domain *d1, struct domain *d2) { XSM_ASSERT_ACTION(XSM_TARGET); return xsm_default_action(action, d1, d2); } static XSM_INLINE int xsm_alloc_security_evtchn(struct evtchn *chn) { return 0; } static XSM_INLINE void xsm_free_security_evtchn(struct evtchn *chn) { return; } static XSM_INLINE char *xsm_show_security_evtchn(struct domain *d, const struct evtchn *chn) { return NULL; } static XSM_INLINE int xsm_get_pod_target(XSM_DEFAULT_ARG struct domain *d) { XSM_ASSERT_ACTION(XSM_PRIV); return xsm_default_action(action, current->domain, d); } static XSM_INLINE int xsm_set_pod_target(XSM_DEFAULT_ARG struct domain *d) { XSM_ASSERT_ACTION(XSM_PRIV); return xsm_default_action(action, current->domain, d); } static XSM_INLINE int xsm_get_device_group(XSM_DEFAULT_ARG uint32_t machine_bdf) { XSM_ASSERT_ACTION(XSM_HOOK); return xsm_default_action(action, current->domain, NULL); } static XSM_INLINE int xsm_test_assign_device(XSM_DEFAULT_ARG uint32_t machine_bdf) { XSM_ASSERT_ACTION(XSM_HOOK); return xsm_default_action(action, current->domain, NULL); } static XSM_INLINE int xsm_assign_device(XSM_DEFAULT_ARG struct domain *d, uint32_t machine_bdf) { XSM_ASSERT_ACTION(XSM_HOOK); return xsm_default_action(action, current->domain, d); } static XSM_INLINE int xsm_deassign_device(XSM_DEFAULT_ARG struct domain *d, uint32_t machine_bdf) { XSM_ASSERT_ACTION(XSM_HOOK); return xsm_default_action(action, current->domain, d); } static XSM_INLINE int xsm_resource_plug_core(XSM_DEFAULT_VOID) { XSM_ASSERT_ACTION(XSM_HOOK); return xsm_default_action(action, current->domain, NULL); } static XSM_INLINE int xsm_resource_unplug_core(XSM_DEFAULT_VOID) { XSM_ASSERT_ACTION(XSM_HOOK); return xsm_default_action(action, current->domain, NULL); } static XSM_INLINE int xsm_resource_plug_pci(XSM_DEFAULT_ARG uint32_t machine_bdf) { XSM_ASSERT_ACTION(XSM_PRIV); return xsm_default_action(action, current->domain, NULL); } static XSM_INLINE int xsm_resource_unplug_pci(XSM_DEFAULT_ARG uint32_t machine_bdf) { XSM_ASSERT_ACTION(XSM_PRIV); return xsm_default_action(action, current->domain, NULL); } static XSM_INLINE int xsm_resource_setup_pci(XSM_DEFAULT_ARG uint32_t machine_bdf) { XSM_ASSERT_ACTION(XSM_PRIV); return xsm_default_action(action, current->domain, NULL); } static XSM_INLINE int xsm_resource_setup_gsi(XSM_DEFAULT_ARG int gsi) { XSM_ASSERT_ACTION(XSM_PRIV); return xsm_default_action(action, current->domain, NULL); } static XSM_INLINE int xsm_resource_setup_misc(XSM_DEFAULT_VOID) { XSM_ASSERT_ACTION(XSM_PRIV); return xsm_default_action(action, current->domain, NULL); } static XSM_INLINE int xsm_page_offline(XSM_DEFAULT_ARG uint32_t cmd) { XSM_ASSERT_ACTION(XSM_HOOK); return xsm_default_action(action, current->domain, NULL); } static XSM_INLINE int xsm_tmem_op(XSM_DEFAULT_VOID) { XSM_ASSERT_ACTION(XSM_HOOK); return xsm_default_action(action, current->domain, NULL); } static XSM_INLINE int xsm_tmem_control(XSM_DEFAULT_VOID) { XSM_ASSERT_ACTION(XSM_PRIV); return xsm_default_action(action, current->domain, NULL); } static XSM_INLINE long xsm_do_xsm_op(XEN_GUEST_HANDLE_PARAM(xsm_op_t) op) { return -ENOSYS; } static XSM_INLINE char *xsm_show_irq_sid(int irq) { return NULL; } static XSM_INLINE int xsm_map_domain_pirq(XSM_DEFAULT_ARG struct domain *d) { XSM_ASSERT_ACTION(XSM_TARGET); return xsm_default_action(action, current->domain, d); } static XSM_INLINE int xsm_map_domain_irq(XSM_DEFAULT_ARG struct domain *d, int irq, void *data) { XSM_ASSERT_ACTION(XSM_HOOK); return xsm_default_action(action, current->domain, d); } static XSM_INLINE int xsm_unmap_domain_pirq(XSM_DEFAULT_ARG struct domain *d) { XSM_ASSERT_ACTION(XSM_TARGET); return xsm_default_action(action, current->domain, d); } static XSM_INLINE int xsm_unmap_domain_irq(XSM_DEFAULT_ARG struct domain *d, int irq, void *data) { XSM_ASSERT_ACTION(XSM_HOOK); return xsm_default_action(action, current->domain, d); } static XSM_INLINE int xsm_irq_permission(XSM_DEFAULT_ARG struct domain *d, int pirq, uint8_t allow) { XSM_ASSERT_ACTION(XSM_HOOK); return xsm_default_action(action, current->domain, d); } static XSM_INLINE int xsm_iomem_permission(XSM_DEFAULT_ARG struct domain *d, uint64_t s, uint64_t e, uint8_t allow) { XSM_ASSERT_ACTION(XSM_HOOK); return xsm_default_action(action, current->domain, d); } static XSM_INLINE int xsm_iomem_mapping(XSM_DEFAULT_ARG struct domain *d, uint64_t s, uint64_t e, uint8_t allow) { XSM_ASSERT_ACTION(XSM_HOOK); return xsm_default_action(action, current->domain, d); } static XSM_INLINE int xsm_pci_config_permission(XSM_DEFAULT_ARG struct domain *d, uint32_t machine_bdf, uint16_t start, uint16_t end, uint8_t access) { XSM_ASSERT_ACTION(XSM_HOOK); return xsm_default_action(action, current->domain, d); } static XSM_INLINE int xsm_add_to_physmap(XSM_DEFAULT_ARG struct domain *d1, struct domain *d2) { XSM_ASSERT_ACTION(XSM_TARGET); return xsm_default_action(action, d1, d2); } static XSM_INLINE int xsm_remove_from_physmap(XSM_DEFAULT_ARG struct domain *d1, struct domain *d2) { XSM_ASSERT_ACTION(XSM_TARGET); return xsm_default_action(action, d1, d2); } static XSM_INLINE int xsm_hvm_param(XSM_DEFAULT_ARG struct domain *d, unsigned long op) { XSM_ASSERT_ACTION(XSM_TARGET); return xsm_default_action(action, current->domain, d); } static XSM_INLINE int xsm_hvm_param_nested(XSM_DEFAULT_ARG struct domain *d) { XSM_ASSERT_ACTION(XSM_PRIV); return xsm_default_action(action, current->domain, d); } #ifdef CONFIG_X86 static XSM_INLINE int xsm_shadow_control(XSM_DEFAULT_ARG struct domain *d, uint32_t op) { XSM_ASSERT_ACTION(XSM_HOOK); return xsm_default_action(action, current->domain, d); } static XSM_INLINE int xsm_hvm_set_pci_intx_level(XSM_DEFAULT_ARG struct domain *d) { XSM_ASSERT_ACTION(XSM_DM_PRIV); return xsm_default_action(action, current->domain, d); } static XSM_INLINE int xsm_hvm_set_isa_irq_level(XSM_DEFAULT_ARG struct domain *d) { XSM_ASSERT_ACTION(XSM_DM_PRIV); return xsm_default_action(action, current->domain, d); } static XSM_INLINE int xsm_hvm_set_pci_link_route(XSM_DEFAULT_ARG struct domain *d) { XSM_ASSERT_ACTION(XSM_DM_PRIV); return xsm_default_action(action, current->domain, d); } static XSM_INLINE int xsm_hvm_inject_msi(XSM_DEFAULT_ARG struct domain *d) { XSM_ASSERT_ACTION(XSM_DM_PRIV); return xsm_default_action(action, current->domain, d); } static XSM_INLINE int xsm_mem_event_control(XSM_DEFAULT_ARG struct domain *d, int mode, int op) { XSM_ASSERT_ACTION(XSM_PRIV); return xsm_default_action(action, current->domain, d); } static XSM_INLINE int xsm_mem_event_op(XSM_DEFAULT_ARG struct domain *d, int op) { XSM_ASSERT_ACTION(XSM_TARGET); return xsm_default_action(action, current->domain, d); } static XSM_INLINE int xsm_mem_sharing_op(XSM_DEFAULT_ARG struct domain *d, struct domain *cd, int op) { XSM_ASSERT_ACTION(XSM_TARGET); return xsm_default_action(action, current->domain, cd); } static XSM_INLINE int xsm_apic(XSM_DEFAULT_ARG struct domain *d, int cmd) { XSM_ASSERT_ACTION(XSM_PRIV); return xsm_default_action(action, d, NULL); } static XSM_INLINE int xsm_platform_op(XSM_DEFAULT_ARG uint32_t op) { XSM_ASSERT_ACTION(XSM_PRIV); return xsm_default_action(action, current->domain, NULL); } static XSM_INLINE int xsm_machine_memory_map(XSM_DEFAULT_VOID) { XSM_ASSERT_ACTION(XSM_PRIV); return xsm_default_action(action, current->domain, NULL); } static XSM_INLINE int xsm_domain_memory_map(XSM_DEFAULT_ARG struct domain *d) { XSM_ASSERT_ACTION(XSM_TARGET); return xsm_default_action(action, current->domain, d); } static XSM_INLINE int xsm_mmu_update(XSM_DEFAULT_ARG struct domain *d, struct domain *t, struct domain *f, uint32_t flags) { int rc = 0; XSM_ASSERT_ACTION(XSM_TARGET); if ( f != dom_io ) rc = xsm_default_action(action, d, f); if ( t && !rc ) rc = xsm_default_action(action, d, t); return rc; } static XSM_INLINE int xsm_mmuext_op(XSM_DEFAULT_ARG struct domain *d, struct domain *f) { XSM_ASSERT_ACTION(XSM_TARGET); return xsm_default_action(action, d, f); } static XSM_INLINE int xsm_update_va_mapping(XSM_DEFAULT_ARG struct domain *d, struct domain *f, l1_pgentry_t pte) { XSM_ASSERT_ACTION(XSM_TARGET); return xsm_default_action(action, d, f); } static XSM_INLINE int xsm_priv_mapping(XSM_DEFAULT_ARG struct domain *d, struct domain *t) { XSM_ASSERT_ACTION(XSM_TARGET); return xsm_default_action(action, d, t); } static XSM_INLINE int xsm_bind_pt_irq(XSM_DEFAULT_ARG struct domain *d, struct xen_domctl_bind_pt_irq *bind) { XSM_ASSERT_ACTION(XSM_HOOK); return xsm_default_action(action, current->domain, d); } static XSM_INLINE int xsm_unbind_pt_irq(XSM_DEFAULT_ARG struct domain *d, struct xen_domctl_bind_pt_irq *bind) { XSM_ASSERT_ACTION(XSM_HOOK); return xsm_default_action(action, current->domain, d); } static XSM_INLINE int xsm_ioport_permission(XSM_DEFAULT_ARG struct domain *d, uint32_t s, uint32_t e, uint8_t allow) { XSM_ASSERT_ACTION(XSM_HOOK); return xsm_default_action(action, current->domain, d); } static XSM_INLINE int xsm_ioport_mapping(XSM_DEFAULT_ARG struct domain *d, uint32_t s, uint32_t e, uint8_t allow) { XSM_ASSERT_ACTION(XSM_HOOK); return xsm_default_action(action, current->domain, d); } #endif /* CONFIG_X86 */ #ifdef CONFIG_ARM static XSM_INLINE int xsm_map_gmfn_foreign(XSM_DEFAULT_ARG struct domain *d, struct domain *t) { XSM_ASSERT_ACTION(XSM_TARGET); return xsm_default_action(action, d, t); } #endif