All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3 0/7] xsm: refactoring xsm hooks
@ 2021-08-05 14:06 Daniel P. Smith
  2021-08-05 14:06 ` [PATCH v3 1/7] xen: Implement xen/alternative-call.h for use in common code Daniel P. Smith
                   ` (6 more replies)
  0 siblings, 7 replies; 25+ messages in thread
From: Daniel P. Smith @ 2021-08-05 14:06 UTC (permalink / raw)
  To: xen-devel; +Cc: Daniel P. Smith

Based on feedback from 2021 Xen Developers Summit the xsm-roles RFC patch set
is being split into two separate patch sets. This is the first patch set and is
focused purely on the clean up and refactoring of the XSM hooks.

This patch set refactors the xsm_ops wrapper hooks to use the alternative_call
infrastructure. Then proceeds to move and realign the headers to simplify the
unnecessarily complicated header inclusions, remove the facad of being able to
enable/disable XSM, and simplify the XSM hooks down to a single interface and
implementation. The remainder of the changes are clean up and removing no
longer necessary abstractions.

v2:
 - restructured the patches, breaking them up as needed
 - incorporate Andrew Cooper's alternative call common code
 - change XSM module registration, removing register_xsm
 - incoporate KConfig recommendations
 - reworded commit messages
 - incorporate macro expansion recommendations
 - misc clean-up fallout from recommendations

v3:
 - renamed struct xsm_operations to struct xsm_ops
 - flask and silo ops structs made __initconst
 - fixed misplacement of __init on flask/silo_init
 - lots of coding style alignment
 - further clean up from FLASK_DISABLE removal
 - addressed commit message comments
 - removed missed guard around alternative-call include
 - reworked approach to XSM hooks, merging the two interfaces instead of
   dropping one

Andrew Cooper (1):
  xen: Implement xen/alternative-call.h for use in common code

Daniel P. Smith (6):
  xsm: remove the ability to disable flask
  xsm: refactor xsm_ops handling
  xsm: convert xsm_ops hook calls to alternative call
  xsm: decouple xsm header inclusion selection
  xsm: drop generic event channel labeling exclusion
  xsm: removing facade that XSM can be enabled/disabled

 xen/arch/x86/Kconfig               |    1 +
 xen/common/Kconfig                 |   50 +-
 xen/include/public/xsm/flask_op.h  |    2 +-
 xen/include/xen/alternative-call.h |   63 ++
 xen/include/xen/sched.h            |    4 -
 xen/include/xsm/dummy.h            |  711 +----------------
 xen/include/xsm/xsm-core.h         |  247 ++++++
 xen/include/xsm/xsm.h              | 1145 +++++++++++++++++-----------
 xen/xsm/Makefile                   |    3 +-
 xen/xsm/dummy.c                    |  160 ----
 xen/xsm/flask/flask_op.c           |   30 -
 xen/xsm/flask/hooks.c              |   12 +-
 xen/xsm/silo.c                     |   23 +-
 xen/xsm/xsm_core.c                 |   72 +-
 14 files changed, 1083 insertions(+), 1440 deletions(-)
 create mode 100644 xen/include/xen/alternative-call.h
 create mode 100644 xen/include/xsm/xsm-core.h
 delete mode 100644 xen/xsm/dummy.c

-- 
2.20.1



^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH v3 1/7] xen: Implement xen/alternative-call.h for use in common code
  2021-08-05 14:06 [PATCH v3 0/7] xsm: refactoring xsm hooks Daniel P. Smith
@ 2021-08-05 14:06 ` Daniel P. Smith
  2021-08-05 15:31   ` Jan Beulich
  2021-08-05 14:06 ` [PATCH v3 2/7] xsm: remove the ability to disable flask Daniel P. Smith
                   ` (5 subsequent siblings)
  6 siblings, 1 reply; 25+ messages in thread
From: Daniel P. Smith @ 2021-08-05 14:06 UTC (permalink / raw)
  To: Wei Liu, xen-devel
  Cc: Andrew Cooper, Jan Beulich, Roger Pau Monné,
	Stefano Stabellini, Julien Grall, Volodymyr Babchuk,
	Bob Eshleman, Alistair Francis, Connor Davis, Daniel P . Smith,
	Jan Beulich, George Dunlap, Ian Jackson

From: Andrew Cooper <andrew.cooper3@citrix.com>

The alternative call infrastructure is x86-only for now, but the common iommu
code has a variant and more common code wants to use the infrastructure.

Introduce CONFIG_ALTERNATIVE_CALL and a conditional implemetnation so common
code can use the optimisation when available, without requiring all
architectures to implement no-op stubs.

Write some documentation, which was thus far entirely absent, covering the
requirements for an architecture to implement this optimsiation, and how to
use the infrastructure in general code.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
---
CC: Jan Beulich <JBeulich@suse.com>
CC: Roger Pau Monné <roger.pau@citrix.com>
CC: Wei Liu <wl@xen.org>
CC: Stefano Stabellini <sstabellini@kernel.org>
CC: Julien Grall <julien@xen.org>
CC: Volodymyr Babchuk <Volodymyr_Babchuk@epam.com>
CC: Bob Eshleman <bobbyeshleman@gmail.com>
CC: Alistair Francis <alistair.francis@wdc.com>
CC: Connor Davis <connojdavis@gmail.com>
CC: Daniel P. Smith <dpsmith@apertussolutions.com>

v3:
 * Drop __alt_call_maybe_initconst

This is a pre-requisite to "xsm: refactor xsm_ops handling" to avoid breaking
the ARM build.

Build test for the XSM code:

  diff --git a/xen/xsm/xsm_core.c b/xen/xsm/xsm_core.c
  index 5eab21e1b168..592074e8f41c 100644
  --- a/xen/xsm/xsm_core.c
  +++ b/xen/xsm/xsm_core.c
  @@ -195,6 +195,16 @@ bool __init has_xsm_magic(paddr_t start)
   }
    #endif

  +#include <xen/alternative-call.h>
  +struct foo {
  +    int (*bar)(void *);
  +} foo __alt_call_maybe_initdata;
  +
  +int test_alternative_call(void)
  +{
  +    return alternative_call(foo.bar, NULL);
  +}
  +
   int __init register_xsm(struct xsm_operations *ops)
    {
         if ( verify(ops) )
---
 xen/arch/x86/Kconfig               |  1 +
 xen/common/Kconfig                 |  3 ++
 xen/include/xen/alternative-call.h | 63 ++++++++++++++++++++++++++++++
 3 files changed, 67 insertions(+)
 create mode 100644 xen/include/xen/alternative-call.h

diff --git a/xen/arch/x86/Kconfig b/xen/arch/x86/Kconfig
index 9b164db641..1f83518ee0 100644
--- a/xen/arch/x86/Kconfig
+++ b/xen/arch/x86/Kconfig
@@ -6,6 +6,7 @@ config X86
 	def_bool y
 	select ACPI
 	select ACPI_LEGACY_TABLES_LOOKUP
+	select ALTERNATIVE_CALL
 	select ARCH_SUPPORTS_INT128
 	select CORE_PARKING
 	select HAS_ALTERNATIVE
diff --git a/xen/common/Kconfig b/xen/common/Kconfig
index 0ddd18e11a..ac5491b1cc 100644
--- a/xen/common/Kconfig
+++ b/xen/common/Kconfig
@@ -22,6 +22,9 @@ config GRANT_TABLE
 
 	  If unsure, say Y.
 
+config ALTERNATIVE_CALL
+	bool
+
 config HAS_ALTERNATIVE
 	bool
 
diff --git a/xen/include/xen/alternative-call.h b/xen/include/xen/alternative-call.h
new file mode 100644
index 0000000000..95ebd66728
--- /dev/null
+++ b/xen/include/xen/alternative-call.h
@@ -0,0 +1,63 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef XEN_ALTERNATIVE_CALL
+#define XEN_ALTERNATIVE_CALL
+
+/*
+ * Some subsystems in Xen may have multiple implementions, which can be
+ * resolved to a single implementation at boot time.  By default, this will
+ * result in the use of function pointers.
+ *
+ * Some architectures may have mechanisms for dynamically modifying .text.
+ * Using this mechnaism, function pointers can be converted to direct calls
+ * which are typically more efficient at runtime.
+ *
+ * For architectures to support:
+ *
+ * - Implement alternative_{,v}call() in asm/alternative.h.  Code generation
+ *   requirements are to emit a function pointer call at build time, and stash
+ *   enough metadata to simplify the call at boot once the implementation has
+ *   been resolved.
+ * - Select ALTERNATIVE_CALL in Kconfig.
+ *
+ * To use:
+ *
+ * Consider the following simplified example.
+ *
+ *  1) struct foo_ops __alt_call_maybe_initdata ops;
+ *
+ *  2) const struct foo_ops __initconst foo_a_ops = { ... };
+ *     const struct foo_ops __initconst foo_b_ops = { ... };
+ *
+ *     void foo_init(void)
+ *     {
+ *         ...
+ *         if ( use_impl_a )
+ *             ops = *foo_a_ops;
+ *         else if ( use_impl_b )
+ *             ops = *foo_b_ops;
+ *         ...
+ *     }
+ *
+ *  3) alternative_call(ops.bar, ...);
+ *
+ * There needs to a single ops object (1) which will eventually contain the
+ * function pointers.  This should be populated in foo's init() function (2)
+ * by one of the available implementations.  To call functions, use
+ * alternative_{,v}call() referencing the main ops object (3).
+ */
+
+#ifdef CONFIG_ALTERNATIVE_CALL
+
+#include <asm/alternative.h>
+
+#define __alt_call_maybe_initdata __initdata
+
+#else
+
+#define alternative_call(func, args...)  (func)(args)
+#define alternative_vcall(func, args...) (func)(args)
+
+#define __alt_call_maybe_initdata
+
+#endif /* !CONFIG_ALTERNATIVE_CALL */
+#endif /* XEN_ALTERNATIVE_CALL */
-- 
2.20.1



^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH v3 2/7] xsm: remove the ability to disable flask
  2021-08-05 14:06 [PATCH v3 0/7] xsm: refactoring xsm hooks Daniel P. Smith
  2021-08-05 14:06 ` [PATCH v3 1/7] xen: Implement xen/alternative-call.h for use in common code Daniel P. Smith
@ 2021-08-05 14:06 ` Daniel P. Smith
  2021-08-25 15:22   ` Jan Beulich
  2021-08-05 14:06 ` [PATCH v3 3/7] xsm: refactor xsm_ops handling Daniel P. Smith
                   ` (4 subsequent siblings)
  6 siblings, 1 reply; 25+ messages in thread
From: Daniel P. Smith @ 2021-08-05 14:06 UTC (permalink / raw)
  To: Daniel P. Smith, xen-devel
  Cc: Andrew Cooper, George Dunlap, Ian Jackson, Jan Beulich,
	Julien Grall, Stefano Stabellini, Wei Liu, Daniel De Graaf

On Linux when SELinux is put into permissive mode the descretionary access
controls are still in place. Whereas for Xen when the enforcing state of flask
is set to permissive, all operations for all domains would succeed, i.e. it
does not fall back to the default access controls. To provide a means to mimic
a similar but not equivalent behavior, a flask op is present to allow a
one-time switch back to the default access controls, aka the "dummy policy".

This patch removes this flask op to enforce a consistent XSM usage model that a
reboot of Xen is required to change the XSM policy module in use.

Signed-off-by: Daniel P. Smith <dpsmith@apertussolutions.com>
---
 xen/include/public/xsm/flask_op.h |  2 +-
 xen/xsm/flask/flask_op.c          | 30 ------------------------------
 2 files changed, 1 insertion(+), 31 deletions(-)

diff --git a/xen/include/public/xsm/flask_op.h b/xen/include/public/xsm/flask_op.h
index 16af7bc22f..b41dd6dac8 100644
--- a/xen/include/public/xsm/flask_op.h
+++ b/xen/include/public/xsm/flask_op.h
@@ -188,7 +188,7 @@ struct xen_flask_op {
 #define FLASK_SETBOOL           12
 #define FLASK_COMMITBOOLS       13
 #define FLASK_MLS               14
-#define FLASK_DISABLE           15
+#define FLASK_DISABLE           15 /* No longer implemented */
 #define FLASK_GETAVC_THRESHOLD  16
 #define FLASK_SETAVC_THRESHOLD  17
 #define FLASK_AVC_HASHSTATS     18
diff --git a/xen/xsm/flask/flask_op.c b/xen/xsm/flask/flask_op.c
index 01e52138a1..f41c025391 100644
--- a/xen/xsm/flask/flask_op.c
+++ b/xen/xsm/flask/flask_op.c
@@ -223,32 +223,6 @@ static int flask_security_sid(struct xen_flask_sid_context *arg)
 
 #ifndef COMPAT
 
-static int flask_disable(void)
-{
-    static int flask_disabled = 0;
-
-    if ( ss_initialized )
-    {
-        /* Not permitted after initial policy load. */
-        return -EINVAL;
-    }
-
-    if ( flask_disabled )
-    {
-        /* Only do this once. */
-        return -EINVAL;
-    }
-
-    printk("Flask:  Disabled at runtime.\n");
-
-    flask_disabled = 1;
-
-    /* Reset xsm_ops to the original module. */
-    xsm_ops = &dummy_xsm_ops;
-
-    return 0;
-}
-
 static int flask_security_setavc_threshold(struct xen_flask_setavc_threshold *arg)
 {
     int rv = 0;
@@ -698,10 +672,6 @@ ret_t do_flask_op(XEN_GUEST_HANDLE_PARAM(xsm_op_t) u_flask_op)
         rv = flask_mls_enabled;
         break;    
 
-    case FLASK_DISABLE:
-        rv = flask_disable();
-        break;
-
     case FLASK_GETAVC_THRESHOLD:
         rv = avc_cache_threshold;
         break;
-- 
2.20.1



^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH v3 3/7] xsm: refactor xsm_ops handling
  2021-08-05 14:06 [PATCH v3 0/7] xsm: refactoring xsm hooks Daniel P. Smith
  2021-08-05 14:06 ` [PATCH v3 1/7] xen: Implement xen/alternative-call.h for use in common code Daniel P. Smith
  2021-08-05 14:06 ` [PATCH v3 2/7] xsm: remove the ability to disable flask Daniel P. Smith
@ 2021-08-05 14:06 ` Daniel P. Smith
  2021-08-25 15:16   ` Jan Beulich
  2021-08-05 14:06 ` [PATCH v3 4/7] xsm: convert xsm_ops hook calls to alternative call Daniel P. Smith
                   ` (3 subsequent siblings)
  6 siblings, 1 reply; 25+ messages in thread
From: Daniel P. Smith @ 2021-08-05 14:06 UTC (permalink / raw)
  To: Daniel P. Smith, xen-devel; +Cc: Daniel De Graaf

This renames the `struct xsm_operations` to the shorter `struct xsm_ops` and
converts the global xsm_ops from being a pointer to an explicit instance. As
part of this conversion, it reworks the XSM modules init function to return
their xsm_ops struct which is copied in to the global xsm_ops instance.

Signed-off-by: Daniel P. Smith <dpsmith@apertussolutions.com>
---
 xen/include/xsm/xsm.h | 221 +++++++++++++++++++++---------------------
 xen/xsm/dummy.c       |   4 +-
 xen/xsm/flask/hooks.c |  12 +--
 xen/xsm/silo.c        |   7 +-
 xen/xsm/xsm_core.c    |  72 +++++++-------
 5 files changed, 161 insertions(+), 155 deletions(-)

diff --git a/xen/include/xsm/xsm.h b/xen/include/xsm/xsm.h
index ad3cddbf7d..aefca46c30 100644
--- a/xen/include/xsm/xsm.h
+++ b/xen/include/xsm/xsm.h
@@ -43,7 +43,7 @@ enum xsm_default {
 };
 typedef enum xsm_default xsm_default_t;
 
-struct xsm_operations {
+struct xsm_ops {
     void (*security_domaininfo) (struct domain *d,
                                         struct xen_domctl_getdomaininfo *info);
     int (*domain_create) (struct domain *d, u32 ssidref);
@@ -191,295 +191,295 @@ struct xsm_operations {
 
 #ifdef CONFIG_XSM
 
-extern struct xsm_operations *xsm_ops;
+extern struct xsm_ops xsm_ops;
 
 #ifndef XSM_NO_WRAPPERS
 
 static inline void xsm_security_domaininfo (struct domain *d,
                                         struct xen_domctl_getdomaininfo *info)
 {
-    xsm_ops->security_domaininfo(d, info);
+    xsm_ops.security_domaininfo(d, info);
 }
 
 static inline int xsm_domain_create (xsm_default_t def, struct domain *d, u32 ssidref)
 {
-    return xsm_ops->domain_create(d, ssidref);
+    return xsm_ops.domain_create(d, ssidref);
 }
 
 static inline int xsm_getdomaininfo (xsm_default_t def, struct domain *d)
 {
-    return xsm_ops->getdomaininfo(d);
+    return xsm_ops.getdomaininfo(d);
 }
 
 static inline int xsm_domctl_scheduler_op (xsm_default_t def, struct domain *d, int cmd)
 {
-    return xsm_ops->domctl_scheduler_op(d, cmd);
+    return xsm_ops.domctl_scheduler_op(d, cmd);
 }
 
 static inline int xsm_sysctl_scheduler_op (xsm_default_t def, int cmd)
 {
-    return xsm_ops->sysctl_scheduler_op(cmd);
+    return xsm_ops.sysctl_scheduler_op(cmd);
 }
 
 static inline int xsm_set_target (xsm_default_t def, struct domain *d, struct domain *e)
 {
-    return xsm_ops->set_target(d, e);
+    return xsm_ops.set_target(d, e);
 }
 
 static inline int xsm_domctl (xsm_default_t def, struct domain *d, int cmd)
 {
-    return xsm_ops->domctl(d, cmd);
+    return xsm_ops.domctl(d, cmd);
 }
 
 static inline int xsm_sysctl (xsm_default_t def, int cmd)
 {
-    return xsm_ops->sysctl(cmd);
+    return xsm_ops.sysctl(cmd);
 }
 
 static inline int xsm_readconsole (xsm_default_t def, uint32_t clear)
 {
-    return xsm_ops->readconsole(clear);
+    return xsm_ops.readconsole(clear);
 }
 
 static inline int xsm_evtchn_unbound (xsm_default_t def, struct domain *d1, struct evtchn *chn,
                                                                     domid_t id2)
 {
-    return xsm_ops->evtchn_unbound(d1, chn, id2);
+    return xsm_ops.evtchn_unbound(d1, chn, id2);
 }
 
 static inline int xsm_evtchn_interdomain (xsm_default_t def, struct domain *d1,
                 struct evtchn *chan1, struct domain *d2, struct evtchn *chan2)
 {
-    return xsm_ops->evtchn_interdomain(d1, chan1, d2, chan2);
+    return xsm_ops.evtchn_interdomain(d1, chan1, d2, chan2);
 }
 
 static inline void xsm_evtchn_close_post (struct evtchn *chn)
 {
-    xsm_ops->evtchn_close_post(chn);
+    xsm_ops.evtchn_close_post(chn);
 }
 
 static inline int xsm_evtchn_send (xsm_default_t def, struct domain *d, struct evtchn *chn)
 {
-    return xsm_ops->evtchn_send(d, chn);
+    return xsm_ops.evtchn_send(d, chn);
 }
 
 static inline int xsm_evtchn_status (xsm_default_t def, struct domain *d, struct evtchn *chn)
 {
-    return xsm_ops->evtchn_status(d, chn);
+    return xsm_ops.evtchn_status(d, chn);
 }
 
 static inline int xsm_evtchn_reset (xsm_default_t def, struct domain *d1, struct domain *d2)
 {
-    return xsm_ops->evtchn_reset(d1, d2);
+    return xsm_ops.evtchn_reset(d1, d2);
 }
 
 static inline int xsm_grant_mapref (xsm_default_t def, struct domain *d1, struct domain *d2,
                                                                 uint32_t flags)
 {
-    return xsm_ops->grant_mapref(d1, d2, flags);
+    return xsm_ops.grant_mapref(d1, d2, flags);
 }
 
 static inline int xsm_grant_unmapref (xsm_default_t def, struct domain *d1, struct domain *d2)
 {
-    return xsm_ops->grant_unmapref(d1, d2);
+    return xsm_ops.grant_unmapref(d1, d2);
 }
 
 static inline int xsm_grant_setup (xsm_default_t def, struct domain *d1, struct domain *d2)
 {
-    return xsm_ops->grant_setup(d1, d2);
+    return xsm_ops.grant_setup(d1, d2);
 }
 
 static inline int xsm_grant_transfer (xsm_default_t def, struct domain *d1, struct domain *d2)
 {
-    return xsm_ops->grant_transfer(d1, d2);
+    return xsm_ops.grant_transfer(d1, d2);
 }
 
 static inline int xsm_grant_copy (xsm_default_t def, struct domain *d1, struct domain *d2)
 {
-    return xsm_ops->grant_copy(d1, d2);
+    return xsm_ops.grant_copy(d1, d2);
 }
 
 static inline int xsm_grant_query_size (xsm_default_t def, struct domain *d1, struct domain *d2)
 {
-    return xsm_ops->grant_query_size(d1, d2);
+    return xsm_ops.grant_query_size(d1, d2);
 }
 
 static inline int xsm_alloc_security_domain (struct domain *d)
 {
-    return xsm_ops->alloc_security_domain(d);
+    return xsm_ops.alloc_security_domain(d);
 }
 
 static inline void xsm_free_security_domain (struct domain *d)
 {
-    xsm_ops->free_security_domain(d);
+    xsm_ops.free_security_domain(d);
 }
 
 static inline int xsm_alloc_security_evtchns(
     struct evtchn chn[], unsigned int nr)
 {
-    return xsm_ops->alloc_security_evtchns(chn, nr);
+    return xsm_ops.alloc_security_evtchns(chn, nr);
 }
 
 static inline void xsm_free_security_evtchns(
     struct evtchn chn[], unsigned int nr)
 {
-    xsm_ops->free_security_evtchns(chn, nr);
+    xsm_ops.free_security_evtchns(chn, nr);
 }
 
 static inline char *xsm_show_security_evtchn (struct domain *d, const struct evtchn *chn)
 {
-    return xsm_ops->show_security_evtchn(d, chn);
+    return xsm_ops.show_security_evtchn(d, chn);
 }
 
 static inline int xsm_init_hardware_domain (xsm_default_t def, struct domain *d)
 {
-    return xsm_ops->init_hardware_domain(d);
+    return xsm_ops.init_hardware_domain(d);
 }
 
 static inline int xsm_get_pod_target (xsm_default_t def, struct domain *d)
 {
-    return xsm_ops->get_pod_target(d);
+    return xsm_ops.get_pod_target(d);
 }
 
 static inline int xsm_set_pod_target (xsm_default_t def, struct domain *d)
 {
-    return xsm_ops->set_pod_target(d);
+    return xsm_ops.set_pod_target(d);
 }
 
 static inline int xsm_memory_exchange (xsm_default_t def, struct domain *d)
 {
-    return xsm_ops->memory_exchange(d);
+    return xsm_ops.memory_exchange(d);
 }
 
 static inline int xsm_memory_adjust_reservation (xsm_default_t def, struct domain *d1, struct
                                                                     domain *d2)
 {
-    return xsm_ops->memory_adjust_reservation(d1, d2);
+    return xsm_ops.memory_adjust_reservation(d1, d2);
 }
 
 static inline int xsm_memory_stat_reservation (xsm_default_t def, struct domain *d1,
                                                             struct domain *d2)
 {
-    return xsm_ops->memory_stat_reservation(d1, d2);
+    return xsm_ops.memory_stat_reservation(d1, d2);
 }
 
 static inline int xsm_memory_pin_page(xsm_default_t def, struct domain *d1, struct domain *d2,
                                       struct page_info *page)
 {
-    return xsm_ops->memory_pin_page(d1, d2, page);
+    return xsm_ops.memory_pin_page(d1, d2, page);
 }
 
 static inline int xsm_add_to_physmap(xsm_default_t def, struct domain *d1, struct domain *d2)
 {
-    return xsm_ops->add_to_physmap(d1, d2);
+    return xsm_ops.add_to_physmap(d1, d2);
 }
 
 static inline int xsm_remove_from_physmap(xsm_default_t def, struct domain *d1, struct domain *d2)
 {
-    return xsm_ops->remove_from_physmap(d1, d2);
+    return xsm_ops.remove_from_physmap(d1, d2);
 }
 
 static inline int xsm_map_gmfn_foreign (xsm_default_t def, struct domain *d, struct domain *t)
 {
-    return xsm_ops->map_gmfn_foreign(d, t);
+    return xsm_ops.map_gmfn_foreign(d, t);
 }
 
 static inline int xsm_claim_pages(xsm_default_t def, struct domain *d)
 {
-    return xsm_ops->claim_pages(d);
+    return xsm_ops.claim_pages(d);
 }
 
 static inline int xsm_console_io (xsm_default_t def, struct domain *d, int cmd)
 {
-    return xsm_ops->console_io(d, cmd);
+    return xsm_ops.console_io(d, cmd);
 }
 
 static inline int xsm_profile (xsm_default_t def, struct domain *d, int op)
 {
-    return xsm_ops->profile(d, op);
+    return xsm_ops.profile(d, op);
 }
 
 static inline int xsm_kexec (xsm_default_t def)
 {
-    return xsm_ops->kexec();
+    return xsm_ops.kexec();
 }
 
 static inline int xsm_schedop_shutdown (xsm_default_t def, struct domain *d1, struct domain *d2)
 {
-    return xsm_ops->schedop_shutdown(d1, d2);
+    return xsm_ops.schedop_shutdown(d1, d2);
 }
 
 static inline char *xsm_show_irq_sid (int irq)
 {
-    return xsm_ops->show_irq_sid(irq);
+    return xsm_ops.show_irq_sid(irq);
 }
 
 static inline int xsm_map_domain_pirq (xsm_default_t def, struct domain *d)
 {
-    return xsm_ops->map_domain_pirq(d);
+    return xsm_ops.map_domain_pirq(d);
 }
 
 static inline int xsm_map_domain_irq (xsm_default_t def, struct domain *d, int irq, void *data)
 {
-    return xsm_ops->map_domain_irq(d, irq, data);
+    return xsm_ops.map_domain_irq(d, irq, data);
 }
 
 static inline int xsm_unmap_domain_pirq (xsm_default_t def, struct domain *d)
 {
-    return xsm_ops->unmap_domain_pirq(d);
+    return xsm_ops.unmap_domain_pirq(d);
 }
 
 static inline int xsm_unmap_domain_irq (xsm_default_t def, struct domain *d, int irq, void *data)
 {
-    return xsm_ops->unmap_domain_irq(d, irq, data);
+    return xsm_ops.unmap_domain_irq(d, irq, data);
 }
 
 static inline int xsm_bind_pt_irq(xsm_default_t def, struct domain *d,
                                   struct xen_domctl_bind_pt_irq *bind)
 {
-    return xsm_ops->bind_pt_irq(d, bind);
+    return xsm_ops.bind_pt_irq(d, bind);
 }
 
 static inline int xsm_unbind_pt_irq(xsm_default_t def, struct domain *d,
                                     struct xen_domctl_bind_pt_irq *bind)
 {
-    return xsm_ops->unbind_pt_irq(d, bind);
+    return xsm_ops.unbind_pt_irq(d, bind);
 }
 
 static inline int xsm_irq_permission (xsm_default_t def, struct domain *d, int pirq, uint8_t allow)
 {
-    return xsm_ops->irq_permission(d, pirq, allow);
+    return xsm_ops.irq_permission(d, pirq, allow);
 }
 
 static inline int xsm_iomem_permission (xsm_default_t def, struct domain *d, uint64_t s, uint64_t e, uint8_t allow)
 {
-    return xsm_ops->iomem_permission(d, s, e, allow);
+    return xsm_ops.iomem_permission(d, s, e, allow);
 }
 
 static inline int xsm_iomem_mapping (xsm_default_t def, struct domain *d, uint64_t s, uint64_t e, uint8_t allow)
 {
-    return xsm_ops->iomem_mapping(d, s, e, allow);
+    return xsm_ops.iomem_mapping(d, s, e, allow);
 }
 
 static inline int xsm_pci_config_permission (xsm_default_t def, struct domain *d, uint32_t machine_bdf, uint16_t start, uint16_t end, uint8_t access)
 {
-    return xsm_ops->pci_config_permission(d, machine_bdf, start, end, access);
+    return xsm_ops.pci_config_permission(d, machine_bdf, start, end, access);
 }
 
 #if defined(CONFIG_HAS_PASSTHROUGH) && defined(CONFIG_HAS_PCI)
 static inline int xsm_get_device_group(xsm_default_t def, uint32_t machine_bdf)
 {
-    return xsm_ops->get_device_group(machine_bdf);
+    return xsm_ops.get_device_group(machine_bdf);
 }
 
 static inline int xsm_assign_device(xsm_default_t def, struct domain *d, uint32_t machine_bdf)
 {
-    return xsm_ops->assign_device(d, machine_bdf);
+    return xsm_ops.assign_device(d, machine_bdf);
 }
 
 static inline int xsm_deassign_device(xsm_default_t def, struct domain *d, uint32_t machine_bdf)
 {
-    return xsm_ops->deassign_device(d, machine_bdf);
+    return xsm_ops.deassign_device(d, machine_bdf);
 }
 #endif /* HAS_PASSTHROUGH && HAS_PCI) */
 
@@ -487,240 +487,240 @@ static inline int xsm_deassign_device(xsm_default_t def, struct domain *d, uint3
 static inline int xsm_assign_dtdevice(xsm_default_t def, struct domain *d,
                                       const char *dtpath)
 {
-    return xsm_ops->assign_dtdevice(d, dtpath);
+    return xsm_ops.assign_dtdevice(d, dtpath);
 }
 
 static inline int xsm_deassign_dtdevice(xsm_default_t def, struct domain *d,
                                         const char *dtpath)
 {
-    return xsm_ops->deassign_dtdevice(d, dtpath);
+    return xsm_ops.deassign_dtdevice(d, dtpath);
 }
 
 #endif /* HAS_PASSTHROUGH && HAS_DEVICE_TREE */
 
 static inline int xsm_resource_plug_pci (xsm_default_t def, uint32_t machine_bdf)
 {
-    return xsm_ops->resource_plug_pci(machine_bdf);
+    return xsm_ops.resource_plug_pci(machine_bdf);
 }
 
 static inline int xsm_resource_unplug_pci (xsm_default_t def, uint32_t machine_bdf)
 {
-    return xsm_ops->resource_unplug_pci(machine_bdf);
+    return xsm_ops.resource_unplug_pci(machine_bdf);
 }
 
 static inline int xsm_resource_plug_core (xsm_default_t def)
 {
-    return xsm_ops->resource_plug_core();
+    return xsm_ops.resource_plug_core();
 }
 
 static inline int xsm_resource_unplug_core (xsm_default_t def)
 {
-    return xsm_ops->resource_unplug_core();
+    return xsm_ops.resource_unplug_core();
 }
 
 static inline int xsm_resource_setup_pci (xsm_default_t def, uint32_t machine_bdf)
 {
-    return xsm_ops->resource_setup_pci(machine_bdf);
+    return xsm_ops.resource_setup_pci(machine_bdf);
 }
 
 static inline int xsm_resource_setup_gsi (xsm_default_t def, int gsi)
 {
-    return xsm_ops->resource_setup_gsi(gsi);
+    return xsm_ops.resource_setup_gsi(gsi);
 }
 
 static inline int xsm_resource_setup_misc (xsm_default_t def)
 {
-    return xsm_ops->resource_setup_misc();
+    return xsm_ops.resource_setup_misc();
 }
 
 static inline int xsm_page_offline(xsm_default_t def, uint32_t cmd)
 {
-    return xsm_ops->page_offline(cmd);
+    return xsm_ops.page_offline(cmd);
 }
 
 static inline int xsm_hypfs_op(xsm_default_t def)
 {
-    return xsm_ops->hypfs_op();
+    return xsm_ops.hypfs_op();
 }
 
 static inline long xsm_do_xsm_op (XEN_GUEST_HANDLE_PARAM(xsm_op_t) op)
 {
-    return xsm_ops->do_xsm_op(op);
+    return xsm_ops.do_xsm_op(op);
 }
 
 #ifdef CONFIG_COMPAT
 static inline int xsm_do_compat_op (XEN_GUEST_HANDLE_PARAM(xsm_op_t) op)
 {
-    return xsm_ops->do_compat_op(op);
+    return xsm_ops.do_compat_op(op);
 }
 #endif
 
 static inline int xsm_hvm_param (xsm_default_t def, struct domain *d, unsigned long op)
 {
-    return xsm_ops->hvm_param(d, op);
+    return xsm_ops.hvm_param(d, op);
 }
 
 static inline int xsm_hvm_control(xsm_default_t def, struct domain *d, unsigned long op)
 {
-    return xsm_ops->hvm_control(d, op);
+    return xsm_ops.hvm_control(d, op);
 }
 
 static inline int xsm_hvm_param_altp2mhvm (xsm_default_t def, struct domain *d)
 {
-    return xsm_ops->hvm_param_altp2mhvm(d);
+    return xsm_ops.hvm_param_altp2mhvm(d);
 }
 
 static inline int xsm_hvm_altp2mhvm_op (xsm_default_t def, struct domain *d, uint64_t mode, uint32_t op)
 {
-    return xsm_ops->hvm_altp2mhvm_op(d, mode, op);
+    return xsm_ops.hvm_altp2mhvm_op(d, mode, op);
 }
 
 static inline int xsm_get_vnumainfo (xsm_default_t def, struct domain *d)
 {
-    return xsm_ops->get_vnumainfo(d);
+    return xsm_ops.get_vnumainfo(d);
 }
 
 static inline int xsm_vm_event_control (xsm_default_t def, struct domain *d, int mode, int op)
 {
-    return xsm_ops->vm_event_control(d, mode, op);
+    return xsm_ops.vm_event_control(d, mode, op);
 }
 
 #ifdef CONFIG_MEM_ACCESS
 static inline int xsm_mem_access (xsm_default_t def, struct domain *d)
 {
-    return xsm_ops->mem_access(d);
+    return xsm_ops.mem_access(d);
 }
 #endif
 
 #ifdef CONFIG_MEM_PAGING
 static inline int xsm_mem_paging (xsm_default_t def, struct domain *d)
 {
-    return xsm_ops->mem_paging(d);
+    return xsm_ops.mem_paging(d);
 }
 #endif
 
 #ifdef CONFIG_MEM_SHARING
 static inline int xsm_mem_sharing (xsm_default_t def, struct domain *d)
 {
-    return xsm_ops->mem_sharing(d);
+    return xsm_ops.mem_sharing(d);
 }
 #endif
 
 static inline int xsm_platform_op (xsm_default_t def, uint32_t op)
 {
-    return xsm_ops->platform_op(op);
+    return xsm_ops.platform_op(op);
 }
 
 #ifdef CONFIG_X86
 static inline int xsm_do_mca(xsm_default_t def)
 {
-    return xsm_ops->do_mca();
+    return xsm_ops.do_mca();
 }
 
 static inline int xsm_shadow_control (xsm_default_t def, struct domain *d, uint32_t op)
 {
-    return xsm_ops->shadow_control(d, op);
+    return xsm_ops.shadow_control(d, op);
 }
 
 static inline int xsm_mem_sharing_op (xsm_default_t def, struct domain *d, struct domain *cd, int op)
 {
-    return xsm_ops->mem_sharing_op(d, cd, op);
+    return xsm_ops.mem_sharing_op(d, cd, op);
 }
 
 static inline int xsm_apic (xsm_default_t def, struct domain *d, int cmd)
 {
-    return xsm_ops->apic(d, cmd);
+    return xsm_ops.apic(d, cmd);
 }
 
 static inline int xsm_memtype (xsm_default_t def, uint32_t access)
 {
-    return xsm_ops->memtype(access);
+    return xsm_ops.memtype(access);
 }
 
 static inline int xsm_machine_memory_map(xsm_default_t def)
 {
-    return xsm_ops->machine_memory_map();
+    return xsm_ops.machine_memory_map();
 }
 
 static inline int xsm_domain_memory_map(xsm_default_t def, struct domain *d)
 {
-    return xsm_ops->domain_memory_map(d);
+    return xsm_ops.domain_memory_map(d);
 }
 
 static inline int xsm_mmu_update (xsm_default_t def, struct domain *d, struct domain *t,
                                   struct domain *f, uint32_t flags)
 {
-    return xsm_ops->mmu_update(d, t, f, flags);
+    return xsm_ops.mmu_update(d, t, f, flags);
 }
 
 static inline int xsm_mmuext_op (xsm_default_t def, struct domain *d, struct domain *f)
 {
-    return xsm_ops->mmuext_op(d, f);
+    return xsm_ops.mmuext_op(d, f);
 }
 
 static inline int xsm_update_va_mapping(xsm_default_t def, struct domain *d, struct domain *f,
                                                             l1_pgentry_t pte)
 {
-    return xsm_ops->update_va_mapping(d, f, pte);
+    return xsm_ops.update_va_mapping(d, f, pte);
 }
 
 static inline int xsm_priv_mapping(xsm_default_t def, struct domain *d, struct domain *t)
 {
-    return xsm_ops->priv_mapping(d, t);
+    return xsm_ops.priv_mapping(d, t);
 }
 
 static inline int xsm_ioport_permission (xsm_default_t def, struct domain *d, uint32_t s, uint32_t e, uint8_t allow)
 {
-    return xsm_ops->ioport_permission(d, s, e, allow);
+    return xsm_ops.ioport_permission(d, s, e, allow);
 }
 
 static inline int xsm_ioport_mapping (xsm_default_t def, struct domain *d, uint32_t s, uint32_t e, uint8_t allow)
 {
-    return xsm_ops->ioport_mapping(d, s, e, allow);
+    return xsm_ops.ioport_mapping(d, s, e, allow);
 }
 
 static inline int xsm_pmu_op (xsm_default_t def, struct domain *d, unsigned int op)
 {
-    return xsm_ops->pmu_op(d, op);
+    return xsm_ops.pmu_op(d, op);
 }
 
 #endif /* CONFIG_X86 */
 
 static inline int xsm_dm_op(xsm_default_t def, struct domain *d)
 {
-    return xsm_ops->dm_op(d);
+    return xsm_ops.dm_op(d);
 }
 
 static inline int xsm_xen_version (xsm_default_t def, uint32_t op)
 {
-    return xsm_ops->xen_version(op);
+    return xsm_ops.xen_version(op);
 }
 
 static inline int xsm_domain_resource_map(xsm_default_t def, struct domain *d)
 {
-    return xsm_ops->domain_resource_map(d);
+    return xsm_ops.domain_resource_map(d);
 }
 
 #ifdef CONFIG_ARGO
 static inline int xsm_argo_enable(const struct domain *d)
 {
-    return xsm_ops->argo_enable(d);
+    return xsm_ops.argo_enable(d);
 }
 
 static inline int xsm_argo_register_single_source(const struct domain *d,
                                                   const struct domain *t)
 {
-    return xsm_ops->argo_register_single_source(d, t);
+    return xsm_ops.argo_register_single_source(d, t);
 }
 
 static inline int xsm_argo_register_any_source(const struct domain *d)
 {
-    return xsm_ops->argo_register_any_source(d);
+    return xsm_ops.argo_register_any_source(d);
 }
 
 static inline int xsm_argo_send(const struct domain *d, const struct domain *t)
 {
-    return xsm_ops->argo_send(d, t);
+    return xsm_ops.argo_send(d, t);
 }
 
 #endif /* CONFIG_ARGO */
@@ -747,16 +747,16 @@ extern int xsm_dt_policy_init(void **policy_buffer, size_t *policy_size);
 extern bool has_xsm_magic(paddr_t);
 #endif
 
-extern int register_xsm(struct xsm_operations *ops);
-
-extern struct xsm_operations dummy_xsm_ops;
-extern void xsm_fixup_ops(struct xsm_operations *ops);
+extern void xsm_fixup_ops(struct xsm_ops *ops);
 
 #ifdef CONFIG_XSM_FLASK
-extern void flask_init(const void *policy_buffer, size_t policy_size);
+extern const struct xsm_ops *flask_init(const void *policy_buffer,
+                                        size_t policy_size);
 #else
-static inline void flask_init(const void *policy_buffer, size_t policy_size)
+static inline struct xsm_ops *flask_init(const void *policy_buffer,
+                                         size_t policy_size)
 {
+    return NULL;
 }
 #endif
 
@@ -766,9 +766,12 @@ extern const unsigned int xsm_flask_init_policy_size;
 #endif
 
 #ifdef CONFIG_XSM_SILO
-extern void silo_init(void);
+extern const struct xsm_ops *silo_init(void);
 #else
-static inline void silo_init(void) {}
+static inline struct xsm_ops *silo_init(void)
+{
+    return NULL;
+}
 #endif
 
 #else /* CONFIG_XSM */
diff --git a/xen/xsm/dummy.c b/xen/xsm/dummy.c
index de44b10130..d8c935328e 100644
--- a/xen/xsm/dummy.c
+++ b/xen/xsm/dummy.c
@@ -13,15 +13,13 @@
 #define XSM_NO_WRAPPERS
 #include <xsm/dummy.h>
 
-struct xsm_operations dummy_xsm_ops;
-
 #define set_to_dummy_if_null(ops, function)                            \
     do {                                                               \
         if ( !ops->function )                                          \
             ops->function = xsm_##function;                            \
     } while (0)
 
-void __init xsm_fixup_ops (struct xsm_operations *ops)
+void __init xsm_fixup_ops (struct xsm_ops *ops)
 {
     set_to_dummy_if_null(ops, security_domaininfo);
     set_to_dummy_if_null(ops, domain_create);
diff --git a/xen/xsm/flask/hooks.c b/xen/xsm/flask/hooks.c
index f1a1217c98..c1f31d8e4a 100644
--- a/xen/xsm/flask/hooks.c
+++ b/xen/xsm/flask/hooks.c
@@ -1745,7 +1745,7 @@ static int flask_argo_send(const struct domain *d, const struct domain *t)
 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);
 
-static struct xsm_operations flask_ops = {
+static const struct xsm_ops __initconst flask_ops = {
     .security_domaininfo = flask_security_domaininfo,
     .domain_create = flask_domain_create,
     .getdomaininfo = flask_getdomaininfo,
@@ -1883,7 +1883,8 @@ static struct xsm_operations flask_ops = {
 #endif
 };
 
-void __init flask_init(const void *policy_buffer, size_t policy_size)
+const struct xsm_ops *__init flask_init(const void *policy_buffer,
+                                        size_t policy_size)
 {
     int ret = -ENOENT;
 
@@ -1891,7 +1892,7 @@ void __init flask_init(const void *policy_buffer, size_t policy_size)
     {
     case FLASK_BOOTPARAM_DISABLED:
         printk(XENLOG_INFO "Flask: Disabled at boot.\n");
-        return;
+        return NULL;
 
     case FLASK_BOOTPARAM_PERMISSIVE:
         flask_enforcing = 0;
@@ -1908,9 +1909,6 @@ void __init flask_init(const void *policy_buffer, size_t policy_size)
 
     avc_init();
 
-    if ( register_xsm(&flask_ops) )
-        panic("Flask: Unable to register with XSM\n");
-
     if ( policy_size && flask_bootparam != FLASK_BOOTPARAM_LATELOAD )
         ret = security_load_policy(policy_buffer, policy_size);
 
@@ -1923,6 +1921,8 @@ void __init flask_init(const void *policy_buffer, size_t policy_size)
         printk(XENLOG_INFO "Flask:  Starting in enforcing mode.\n");
     else
         printk(XENLOG_INFO "Flask:  Starting in permissive mode.\n");
+
+    return &flask_ops;
 }
 
 /*
diff --git a/xen/xsm/silo.c b/xen/xsm/silo.c
index fc2ca5cd2d..3a2dea13fe 100644
--- a/xen/xsm/silo.c
+++ b/xen/xsm/silo.c
@@ -100,7 +100,7 @@ static int silo_argo_send(const struct domain *d1, const struct domain *d2)
 
 #endif
 
-static struct xsm_operations silo_xsm_ops = {
+static const struct xsm_ops __initconst silo_xsm_ops = {
     .evtchn_unbound = silo_evtchn_unbound,
     .evtchn_interdomain = silo_evtchn_interdomain,
     .grant_mapref = silo_grant_mapref,
@@ -112,12 +112,11 @@ static struct xsm_operations silo_xsm_ops = {
 #endif
 };
 
-void __init silo_init(void)
+const struct xsm_ops *__init silo_init(void)
 {
     printk("Initialising XSM SILO mode\n");
 
-    if ( register_xsm(&silo_xsm_ops) )
-        panic("SILO: Unable to register with XSM\n");
+    return &silo_xsm_ops;
 }
 
 /*
diff --git a/xen/xsm/xsm_core.c b/xen/xsm/xsm_core.c
index 5eab21e1b1..b5219dff78 100644
--- a/xen/xsm/xsm_core.c
+++ b/xen/xsm/xsm_core.c
@@ -28,9 +28,17 @@
 #include <asm/setup.h>
 #endif
 
-#define XSM_FRAMEWORK_VERSION    "1.0.0"
+#define XSM_FRAMEWORK_VERSION    "1.0.1"
 
-struct xsm_operations *xsm_ops;
+struct xsm_ops xsm_ops;
+
+enum xsm_ops_state {
+    XSM_OPS_UNREGISTERED,
+    XSM_OPS_REG_FAILED,
+    XSM_OPS_REGISTERED,
+};
+
+static enum xsm_ops_state xsm_ops_registered = XSM_OPS_UNREGISTERED;
 
 enum xsm_bootparam {
     XSM_BOOTPARAM_DUMMY,
@@ -68,17 +76,10 @@ static int __init parse_xsm_param(const char *s)
 }
 custom_param("xsm", parse_xsm_param);
 
-static inline int verify(struct xsm_operations *ops)
-{
-    /* verify the security_operations structure exists */
-    if ( !ops )
-        return -EINVAL;
-    xsm_fixup_ops(ops);
-    return 0;
-}
-
 static int __init xsm_core_init(const void *policy_buffer, size_t policy_size)
 {
+    const struct xsm_ops *ops = NULL;
+
 #ifdef CONFIG_XSM_FLASK_POLICY
     if ( policy_size == 0 )
     {
@@ -87,25 +88,35 @@ static int __init xsm_core_init(const void *policy_buffer, size_t policy_size)
     }
 #endif
 
-    if ( verify(&dummy_xsm_ops) )
+    if ( xsm_ops_registered != XSM_OPS_UNREGISTERED )
     {
-        printk(XENLOG_ERR "Could not verify dummy_xsm_ops structure\n");
+        printk(XENLOG_ERR
+               "Could not init XSM, xsm_ops register already attempted\n");
         return -EIO;
     }
 
-    xsm_ops = &dummy_xsm_ops;
-
     switch ( xsm_bootparam )
     {
     case XSM_BOOTPARAM_DUMMY:
+        xsm_ops_registered = XSM_OPS_REGISTERED;
         break;
 
     case XSM_BOOTPARAM_FLASK:
-        flask_init(policy_buffer, policy_size);
+        ops = flask_init(policy_buffer, policy_size);
+        if ( ops )
+        {
+            xsm_ops_registered = XSM_OPS_REGISTERED;
+            xsm_ops = *ops;
+        }
         break;
 
     case XSM_BOOTPARAM_SILO:
-        silo_init();
+        ops = silo_init();
+        if ( ops )
+        {
+            xsm_ops_registered = XSM_OPS_REGISTERED;
+            xsm_ops = *ops;
+        }
         break;
 
     default:
@@ -113,6 +124,17 @@ static int __init xsm_core_init(const void *policy_buffer, size_t policy_size)
         break;
     }
 
+    /*
+     * This handles three cases,
+     *   - dummy policy module was selected
+     *   - a policy module does not provide all handlers
+     *   - a policy module failed to init
+     */
+    xsm_fixup_ops(&xsm_ops);
+
+    if ( xsm_ops_registered != XSM_OPS_REGISTERED )
+        xsm_ops_registered = XSM_OPS_REG_FAILED;
+
     return 0;
 }
 
@@ -195,22 +217,6 @@ bool __init has_xsm_magic(paddr_t start)
 }
 #endif
 
-int __init register_xsm(struct xsm_operations *ops)
-{
-    if ( verify(ops) )
-    {
-        printk(XENLOG_ERR "Could not verify xsm_operations structure\n");
-        return -EINVAL;
-    }
-
-    if ( xsm_ops != &dummy_xsm_ops )
-        return -EAGAIN;
-
-    xsm_ops = ops;
-
-    return 0;
-}
-
 #endif
 
 long do_xsm_op (XEN_GUEST_HANDLE_PARAM(xsm_op_t) op)
-- 
2.20.1



^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH v3 4/7] xsm: convert xsm_ops hook calls to alternative call
  2021-08-05 14:06 [PATCH v3 0/7] xsm: refactoring xsm hooks Daniel P. Smith
                   ` (2 preceding siblings ...)
  2021-08-05 14:06 ` [PATCH v3 3/7] xsm: refactor xsm_ops handling Daniel P. Smith
@ 2021-08-05 14:06 ` Daniel P. Smith
  2021-08-05 14:06 ` [PATCH v3 5/7] xsm: decouple xsm header inclusion selection Daniel P. Smith
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 25+ messages in thread
From: Daniel P. Smith @ 2021-08-05 14:06 UTC (permalink / raw)
  To: Daniel P. Smith, xen-devel; +Cc: Andrew Cooper, Daniel De Graaf

To reduce retpolines convert all the pointer function calls of the
xsm_ops hooks over to the alternative_call infrastructure.

Signed-off-by: Daniel P. Smith <dpsmith@apertussolutions.com>
Acked-by: Andrew Cooper <andrew.cooper3@citrix.com>
---
 xen/include/xsm/xsm.h | 193 +++++++++++++++++++++---------------------
 1 file changed, 97 insertions(+), 96 deletions(-)

diff --git a/xen/include/xsm/xsm.h b/xen/include/xsm/xsm.h
index aefca46c30..6a54ee883c 100644
--- a/xen/include/xsm/xsm.h
+++ b/xen/include/xsm/xsm.h
@@ -15,6 +15,7 @@
 #ifndef __XSM_H__
 #define __XSM_H__
 
+#include <xen/alternative-call.h>
 #include <xen/sched.h>
 #include <xen/multiboot.h>
 
@@ -198,288 +199,288 @@ extern struct xsm_ops xsm_ops;
 static inline void xsm_security_domaininfo (struct domain *d,
                                         struct xen_domctl_getdomaininfo *info)
 {
-    xsm_ops.security_domaininfo(d, info);
+    alternative_vcall(xsm_ops.security_domaininfo, d, info);
 }
 
 static inline int xsm_domain_create (xsm_default_t def, struct domain *d, u32 ssidref)
 {
-    return xsm_ops.domain_create(d, ssidref);
+    return alternative_call(xsm_ops.domain_create, d, ssidref);
 }
 
 static inline int xsm_getdomaininfo (xsm_default_t def, struct domain *d)
 {
-    return xsm_ops.getdomaininfo(d);
+    return alternative_call(xsm_ops.getdomaininfo, d);
 }
 
 static inline int xsm_domctl_scheduler_op (xsm_default_t def, struct domain *d, int cmd)
 {
-    return xsm_ops.domctl_scheduler_op(d, cmd);
+    return alternative_call(xsm_ops.domctl_scheduler_op, d, cmd);
 }
 
 static inline int xsm_sysctl_scheduler_op (xsm_default_t def, int cmd)
 {
-    return xsm_ops.sysctl_scheduler_op(cmd);
+    return alternative_call(xsm_ops.sysctl_scheduler_op, cmd);
 }
 
 static inline int xsm_set_target (xsm_default_t def, struct domain *d, struct domain *e)
 {
-    return xsm_ops.set_target(d, e);
+    return alternative_call(xsm_ops.set_target, d, e);
 }
 
 static inline int xsm_domctl (xsm_default_t def, struct domain *d, int cmd)
 {
-    return xsm_ops.domctl(d, cmd);
+    return alternative_call(xsm_ops.domctl, d, cmd);
 }
 
 static inline int xsm_sysctl (xsm_default_t def, int cmd)
 {
-    return xsm_ops.sysctl(cmd);
+    return alternative_call(xsm_ops.sysctl, cmd);
 }
 
 static inline int xsm_readconsole (xsm_default_t def, uint32_t clear)
 {
-    return xsm_ops.readconsole(clear);
+    return alternative_call(xsm_ops.readconsole, clear);
 }
 
 static inline int xsm_evtchn_unbound (xsm_default_t def, struct domain *d1, struct evtchn *chn,
                                                                     domid_t id2)
 {
-    return xsm_ops.evtchn_unbound(d1, chn, id2);
+    return alternative_call(xsm_ops.evtchn_unbound, d1, chn, id2);
 }
 
 static inline int xsm_evtchn_interdomain (xsm_default_t def, struct domain *d1,
                 struct evtchn *chan1, struct domain *d2, struct evtchn *chan2)
 {
-    return xsm_ops.evtchn_interdomain(d1, chan1, d2, chan2);
+    return alternative_call(xsm_ops.evtchn_interdomain, d1, chan1, d2, chan2);
 }
 
 static inline void xsm_evtchn_close_post (struct evtchn *chn)
 {
-    xsm_ops.evtchn_close_post(chn);
+    alternative_vcall(xsm_ops.evtchn_close_post, chn);
 }
 
 static inline int xsm_evtchn_send (xsm_default_t def, struct domain *d, struct evtchn *chn)
 {
-    return xsm_ops.evtchn_send(d, chn);
+    return alternative_call(xsm_ops.evtchn_send, d, chn);
 }
 
 static inline int xsm_evtchn_status (xsm_default_t def, struct domain *d, struct evtchn *chn)
 {
-    return xsm_ops.evtchn_status(d, chn);
+    return alternative_call(xsm_ops.evtchn_status, d, chn);
 }
 
 static inline int xsm_evtchn_reset (xsm_default_t def, struct domain *d1, struct domain *d2)
 {
-    return xsm_ops.evtchn_reset(d1, d2);
+    return alternative_call(xsm_ops.evtchn_reset, d1, d2);
 }
 
 static inline int xsm_grant_mapref (xsm_default_t def, struct domain *d1, struct domain *d2,
                                                                 uint32_t flags)
 {
-    return xsm_ops.grant_mapref(d1, d2, flags);
+    return alternative_call(xsm_ops.grant_mapref, d1, d2, flags);
 }
 
 static inline int xsm_grant_unmapref (xsm_default_t def, struct domain *d1, struct domain *d2)
 {
-    return xsm_ops.grant_unmapref(d1, d2);
+    return alternative_call(xsm_ops.grant_unmapref, d1, d2);
 }
 
 static inline int xsm_grant_setup (xsm_default_t def, struct domain *d1, struct domain *d2)
 {
-    return xsm_ops.grant_setup(d1, d2);
+    return alternative_call(xsm_ops.grant_setup, d1, d2);
 }
 
 static inline int xsm_grant_transfer (xsm_default_t def, struct domain *d1, struct domain *d2)
 {
-    return xsm_ops.grant_transfer(d1, d2);
+    return alternative_call(xsm_ops.grant_transfer, d1, d2);
 }
 
 static inline int xsm_grant_copy (xsm_default_t def, struct domain *d1, struct domain *d2)
 {
-    return xsm_ops.grant_copy(d1, d2);
+    return alternative_call(xsm_ops.grant_copy, d1, d2);
 }
 
 static inline int xsm_grant_query_size (xsm_default_t def, struct domain *d1, struct domain *d2)
 {
-    return xsm_ops.grant_query_size(d1, d2);
+    return alternative_call(xsm_ops.grant_query_size, d1, d2);
 }
 
 static inline int xsm_alloc_security_domain (struct domain *d)
 {
-    return xsm_ops.alloc_security_domain(d);
+    return alternative_call(xsm_ops.alloc_security_domain, d);
 }
 
 static inline void xsm_free_security_domain (struct domain *d)
 {
-    xsm_ops.free_security_domain(d);
+    alternative_vcall(xsm_ops.free_security_domain, d);
 }
 
 static inline int xsm_alloc_security_evtchns(
     struct evtchn chn[], unsigned int nr)
 {
-    return xsm_ops.alloc_security_evtchns(chn, nr);
+    return alternative_call(xsm_ops.alloc_security_evtchns, chn, nr);
 }
 
 static inline void xsm_free_security_evtchns(
     struct evtchn chn[], unsigned int nr)
 {
-    xsm_ops.free_security_evtchns(chn, nr);
+    alternative_vcall(xsm_ops.free_security_evtchns, chn, nr);
 }
 
 static inline char *xsm_show_security_evtchn (struct domain *d, const struct evtchn *chn)
 {
-    return xsm_ops.show_security_evtchn(d, chn);
+    return alternative_call(xsm_ops.show_security_evtchn, d, chn);
 }
 
 static inline int xsm_init_hardware_domain (xsm_default_t def, struct domain *d)
 {
-    return xsm_ops.init_hardware_domain(d);
+    return alternative_call(xsm_ops.init_hardware_domain, d);
 }
 
 static inline int xsm_get_pod_target (xsm_default_t def, struct domain *d)
 {
-    return xsm_ops.get_pod_target(d);
+    return alternative_call(xsm_ops.get_pod_target, d);
 }
 
 static inline int xsm_set_pod_target (xsm_default_t def, struct domain *d)
 {
-    return xsm_ops.set_pod_target(d);
+    return alternative_call(xsm_ops.set_pod_target, d);
 }
 
 static inline int xsm_memory_exchange (xsm_default_t def, struct domain *d)
 {
-    return xsm_ops.memory_exchange(d);
+    return alternative_call(xsm_ops.memory_exchange, d);
 }
 
 static inline int xsm_memory_adjust_reservation (xsm_default_t def, struct domain *d1, struct
                                                                     domain *d2)
 {
-    return xsm_ops.memory_adjust_reservation(d1, d2);
+    return alternative_call(xsm_ops.memory_adjust_reservation, d1, d2);
 }
 
 static inline int xsm_memory_stat_reservation (xsm_default_t def, struct domain *d1,
                                                             struct domain *d2)
 {
-    return xsm_ops.memory_stat_reservation(d1, d2);
+    return alternative_call(xsm_ops.memory_stat_reservation, d1, d2);
 }
 
 static inline int xsm_memory_pin_page(xsm_default_t def, struct domain *d1, struct domain *d2,
                                       struct page_info *page)
 {
-    return xsm_ops.memory_pin_page(d1, d2, page);
+    return alternative_call(xsm_ops.memory_pin_page, d1, d2, page);
 }
 
 static inline int xsm_add_to_physmap(xsm_default_t def, struct domain *d1, struct domain *d2)
 {
-    return xsm_ops.add_to_physmap(d1, d2);
+    return alternative_call(xsm_ops.add_to_physmap, d1, d2);
 }
 
 static inline int xsm_remove_from_physmap(xsm_default_t def, struct domain *d1, struct domain *d2)
 {
-    return xsm_ops.remove_from_physmap(d1, d2);
+    return alternative_call(xsm_ops.remove_from_physmap, d1, d2);
 }
 
 static inline int xsm_map_gmfn_foreign (xsm_default_t def, struct domain *d, struct domain *t)
 {
-    return xsm_ops.map_gmfn_foreign(d, t);
+    return alternative_call(xsm_ops.map_gmfn_foreign, d, t);
 }
 
 static inline int xsm_claim_pages(xsm_default_t def, struct domain *d)
 {
-    return xsm_ops.claim_pages(d);
+    return alternative_call(xsm_ops.claim_pages, d);
 }
 
 static inline int xsm_console_io (xsm_default_t def, struct domain *d, int cmd)
 {
-    return xsm_ops.console_io(d, cmd);
+    return alternative_call(xsm_ops.console_io, d, cmd);
 }
 
 static inline int xsm_profile (xsm_default_t def, struct domain *d, int op)
 {
-    return xsm_ops.profile(d, op);
+    return alternative_call(xsm_ops.profile, d, op);
 }
 
 static inline int xsm_kexec (xsm_default_t def)
 {
-    return xsm_ops.kexec();
+    return alternative_call(xsm_ops.kexec);
 }
 
 static inline int xsm_schedop_shutdown (xsm_default_t def, struct domain *d1, struct domain *d2)
 {
-    return xsm_ops.schedop_shutdown(d1, d2);
+    return alternative_call(xsm_ops.schedop_shutdown, d1, d2);
 }
 
 static inline char *xsm_show_irq_sid (int irq)
 {
-    return xsm_ops.show_irq_sid(irq);
+    return alternative_call(xsm_ops.show_irq_sid, irq);
 }
 
 static inline int xsm_map_domain_pirq (xsm_default_t def, struct domain *d)
 {
-    return xsm_ops.map_domain_pirq(d);
+    return alternative_call(xsm_ops.map_domain_pirq, d);
 }
 
 static inline int xsm_map_domain_irq (xsm_default_t def, struct domain *d, int irq, void *data)
 {
-    return xsm_ops.map_domain_irq(d, irq, data);
+    return alternative_call(xsm_ops.map_domain_irq, d, irq, data);
 }
 
 static inline int xsm_unmap_domain_pirq (xsm_default_t def, struct domain *d)
 {
-    return xsm_ops.unmap_domain_pirq(d);
+    return alternative_call(xsm_ops.unmap_domain_pirq, d);
 }
 
 static inline int xsm_unmap_domain_irq (xsm_default_t def, struct domain *d, int irq, void *data)
 {
-    return xsm_ops.unmap_domain_irq(d, irq, data);
+    return alternative_call(xsm_ops.unmap_domain_irq, d, irq, data);
 }
 
 static inline int xsm_bind_pt_irq(xsm_default_t def, struct domain *d,
                                   struct xen_domctl_bind_pt_irq *bind)
 {
-    return xsm_ops.bind_pt_irq(d, bind);
+    return alternative_call(xsm_ops.bind_pt_irq, d, bind);
 }
 
 static inline int xsm_unbind_pt_irq(xsm_default_t def, struct domain *d,
                                     struct xen_domctl_bind_pt_irq *bind)
 {
-    return xsm_ops.unbind_pt_irq(d, bind);
+    return alternative_call(xsm_ops.unbind_pt_irq, d, bind);
 }
 
 static inline int xsm_irq_permission (xsm_default_t def, struct domain *d, int pirq, uint8_t allow)
 {
-    return xsm_ops.irq_permission(d, pirq, allow);
+    return alternative_call(xsm_ops.irq_permission, d, pirq, allow);
 }
 
 static inline int xsm_iomem_permission (xsm_default_t def, struct domain *d, uint64_t s, uint64_t e, uint8_t allow)
 {
-    return xsm_ops.iomem_permission(d, s, e, allow);
+    return alternative_call(xsm_ops.iomem_permission, d, s, e, allow);
 }
 
 static inline int xsm_iomem_mapping (xsm_default_t def, struct domain *d, uint64_t s, uint64_t e, uint8_t allow)
 {
-    return xsm_ops.iomem_mapping(d, s, e, allow);
+    return alternative_call(xsm_ops.iomem_mapping, d, s, e, allow);
 }
 
 static inline int xsm_pci_config_permission (xsm_default_t def, struct domain *d, uint32_t machine_bdf, uint16_t start, uint16_t end, uint8_t access)
 {
-    return xsm_ops.pci_config_permission(d, machine_bdf, start, end, access);
+    return alternative_call(xsm_ops.pci_config_permission, d, machine_bdf, start, end, access);
 }
 
 #if defined(CONFIG_HAS_PASSTHROUGH) && defined(CONFIG_HAS_PCI)
 static inline int xsm_get_device_group(xsm_default_t def, uint32_t machine_bdf)
 {
-    return xsm_ops.get_device_group(machine_bdf);
+    return alternative_call(xsm_ops.get_device_group, machine_bdf);
 }
 
 static inline int xsm_assign_device(xsm_default_t def, struct domain *d, uint32_t machine_bdf)
 {
-    return xsm_ops.assign_device(d, machine_bdf);
+    return alternative_call(xsm_ops.assign_device, d, machine_bdf);
 }
 
 static inline int xsm_deassign_device(xsm_default_t def, struct domain *d, uint32_t machine_bdf)
 {
-    return xsm_ops.deassign_device(d, machine_bdf);
+    return alternative_call(xsm_ops.deassign_device, d, machine_bdf);
 }
 #endif /* HAS_PASSTHROUGH && HAS_PCI) */
 
@@ -487,60 +488,60 @@ static inline int xsm_deassign_device(xsm_default_t def, struct domain *d, uint3
 static inline int xsm_assign_dtdevice(xsm_default_t def, struct domain *d,
                                       const char *dtpath)
 {
-    return xsm_ops.assign_dtdevice(d, dtpath);
+    return alternative_call(xsm_ops.assign_dtdevice, d, dtpath);
 }
 
 static inline int xsm_deassign_dtdevice(xsm_default_t def, struct domain *d,
                                         const char *dtpath)
 {
-    return xsm_ops.deassign_dtdevice(d, dtpath);
+    return alternative_call(xsm_ops.deassign_dtdevice, d, dtpath);
 }
 
 #endif /* HAS_PASSTHROUGH && HAS_DEVICE_TREE */
 
 static inline int xsm_resource_plug_pci (xsm_default_t def, uint32_t machine_bdf)
 {
-    return xsm_ops.resource_plug_pci(machine_bdf);
+    return alternative_call(xsm_ops.resource_plug_pci, machine_bdf);
 }
 
 static inline int xsm_resource_unplug_pci (xsm_default_t def, uint32_t machine_bdf)
 {
-    return xsm_ops.resource_unplug_pci(machine_bdf);
+    return alternative_call(xsm_ops.resource_unplug_pci, machine_bdf);
 }
 
 static inline int xsm_resource_plug_core (xsm_default_t def)
 {
-    return xsm_ops.resource_plug_core();
+    return alternative_call(xsm_ops.resource_plug_core);
 }
 
 static inline int xsm_resource_unplug_core (xsm_default_t def)
 {
-    return xsm_ops.resource_unplug_core();
+    return alternative_call(xsm_ops.resource_unplug_core);
 }
 
 static inline int xsm_resource_setup_pci (xsm_default_t def, uint32_t machine_bdf)
 {
-    return xsm_ops.resource_setup_pci(machine_bdf);
+    return alternative_call(xsm_ops.resource_setup_pci, machine_bdf);
 }
 
 static inline int xsm_resource_setup_gsi (xsm_default_t def, int gsi)
 {
-    return xsm_ops.resource_setup_gsi(gsi);
+    return alternative_call(xsm_ops.resource_setup_gsi, gsi);
 }
 
 static inline int xsm_resource_setup_misc (xsm_default_t def)
 {
-    return xsm_ops.resource_setup_misc();
+    return alternative_call(xsm_ops.resource_setup_misc);
 }
 
 static inline int xsm_page_offline(xsm_default_t def, uint32_t cmd)
 {
-    return xsm_ops.page_offline(cmd);
+    return alternative_call(xsm_ops.page_offline, cmd);
 }
 
 static inline int xsm_hypfs_op(xsm_default_t def)
 {
-    return xsm_ops.hypfs_op();
+    return alternative_call(xsm_ops.hypfs_op);
 }
 
 static inline long xsm_do_xsm_op (XEN_GUEST_HANDLE_PARAM(xsm_op_t) op)
@@ -557,105 +558,105 @@ static inline int xsm_do_compat_op (XEN_GUEST_HANDLE_PARAM(xsm_op_t) op)
 
 static inline int xsm_hvm_param (xsm_default_t def, struct domain *d, unsigned long op)
 {
-    return xsm_ops.hvm_param(d, op);
+    return alternative_call(xsm_ops.hvm_param, d, op);
 }
 
 static inline int xsm_hvm_control(xsm_default_t def, struct domain *d, unsigned long op)
 {
-    return xsm_ops.hvm_control(d, op);
+    return alternative_call(xsm_ops.hvm_control, d, op);
 }
 
 static inline int xsm_hvm_param_altp2mhvm (xsm_default_t def, struct domain *d)
 {
-    return xsm_ops.hvm_param_altp2mhvm(d);
+    return alternative_call(xsm_ops.hvm_param_altp2mhvm, d);
 }
 
 static inline int xsm_hvm_altp2mhvm_op (xsm_default_t def, struct domain *d, uint64_t mode, uint32_t op)
 {
-    return xsm_ops.hvm_altp2mhvm_op(d, mode, op);
+    return alternative_call(xsm_ops.hvm_altp2mhvm_op, d, mode, op);
 }
 
 static inline int xsm_get_vnumainfo (xsm_default_t def, struct domain *d)
 {
-    return xsm_ops.get_vnumainfo(d);
+    return alternative_call(xsm_ops.get_vnumainfo, d);
 }
 
 static inline int xsm_vm_event_control (xsm_default_t def, struct domain *d, int mode, int op)
 {
-    return xsm_ops.vm_event_control(d, mode, op);
+    return alternative_call(xsm_ops.vm_event_control, d, mode, op);
 }
 
 #ifdef CONFIG_MEM_ACCESS
 static inline int xsm_mem_access (xsm_default_t def, struct domain *d)
 {
-    return xsm_ops.mem_access(d);
+    return alternative_call(xsm_ops.mem_access, d);
 }
 #endif
 
 #ifdef CONFIG_MEM_PAGING
 static inline int xsm_mem_paging (xsm_default_t def, struct domain *d)
 {
-    return xsm_ops.mem_paging(d);
+    return alternative_call(xsm_ops.mem_paging, d);
 }
 #endif
 
 #ifdef CONFIG_MEM_SHARING
 static inline int xsm_mem_sharing (xsm_default_t def, struct domain *d)
 {
-    return xsm_ops.mem_sharing(d);
+    return alternative_call(xsm_ops.mem_sharing, d);
 }
 #endif
 
 static inline int xsm_platform_op (xsm_default_t def, uint32_t op)
 {
-    return xsm_ops.platform_op(op);
+    return alternative_call(xsm_ops.platform_op, op);
 }
 
 #ifdef CONFIG_X86
 static inline int xsm_do_mca(xsm_default_t def)
 {
-    return xsm_ops.do_mca();
+    return alternative_call(xsm_ops.do_mca);
 }
 
 static inline int xsm_shadow_control (xsm_default_t def, struct domain *d, uint32_t op)
 {
-    return xsm_ops.shadow_control(d, op);
+    return alternative_call(xsm_ops.shadow_control, d, op);
 }
 
 static inline int xsm_mem_sharing_op (xsm_default_t def, struct domain *d, struct domain *cd, int op)
 {
-    return xsm_ops.mem_sharing_op(d, cd, op);
+    return alternative_call(xsm_ops.mem_sharing_op, d, cd, op);
 }
 
 static inline int xsm_apic (xsm_default_t def, struct domain *d, int cmd)
 {
-    return xsm_ops.apic(d, cmd);
+    return alternative_call(xsm_ops.apic, d, cmd);
 }
 
 static inline int xsm_memtype (xsm_default_t def, uint32_t access)
 {
-    return xsm_ops.memtype(access);
+    return alternative_call(xsm_ops.memtype, access);
 }
 
 static inline int xsm_machine_memory_map(xsm_default_t def)
 {
-    return xsm_ops.machine_memory_map();
+    return alternative_call(xsm_ops.machine_memory_map);
 }
 
 static inline int xsm_domain_memory_map(xsm_default_t def, struct domain *d)
 {
-    return xsm_ops.domain_memory_map(d);
+    return alternative_call(xsm_ops.domain_memory_map, d);
 }
 
 static inline int xsm_mmu_update (xsm_default_t def, struct domain *d, struct domain *t,
                                   struct domain *f, uint32_t flags)
 {
-    return xsm_ops.mmu_update(d, t, f, flags);
+    return alternative_call(xsm_ops.mmu_update, d, t, f, flags);
 }
 
 static inline int xsm_mmuext_op (xsm_default_t def, struct domain *d, struct domain *f)
 {
-    return xsm_ops.mmuext_op(d, f);
+    return alternative_call(xsm_ops.mmuext_op, d, f);
 }
 
 static inline int xsm_update_va_mapping(xsm_default_t def, struct domain *d, struct domain *f,
@@ -666,61 +667,61 @@ static inline int xsm_update_va_mapping(xsm_default_t def, struct domain *d, str
 
 static inline int xsm_priv_mapping(xsm_default_t def, struct domain *d, struct domain *t)
 {
-    return xsm_ops.priv_mapping(d, t);
+    return alternative_call(xsm_ops.priv_mapping, d, t);
 }
 
 static inline int xsm_ioport_permission (xsm_default_t def, struct domain *d, uint32_t s, uint32_t e, uint8_t allow)
 {
-    return xsm_ops.ioport_permission(d, s, e, allow);
+    return alternative_call(xsm_ops.ioport_permission, d, s, e, allow);
 }
 
 static inline int xsm_ioport_mapping (xsm_default_t def, struct domain *d, uint32_t s, uint32_t e, uint8_t allow)
 {
-    return xsm_ops.ioport_mapping(d, s, e, allow);
+    return alternative_call(xsm_ops.ioport_mapping, d, s, e, allow);
 }
 
 static inline int xsm_pmu_op (xsm_default_t def, struct domain *d, unsigned int op)
 {
-    return xsm_ops.pmu_op(d, op);
+    return alternative_call(xsm_ops.pmu_op, d, op);
 }
 
 #endif /* CONFIG_X86 */
 
 static inline int xsm_dm_op(xsm_default_t def, struct domain *d)
 {
-    return xsm_ops.dm_op(d);
+    return alternative_call(xsm_ops.dm_op, d);
 }
 
 static inline int xsm_xen_version (xsm_default_t def, uint32_t op)
 {
-    return xsm_ops.xen_version(op);
+    return alternative_call(xsm_ops.xen_version, op);
 }
 
 static inline int xsm_domain_resource_map(xsm_default_t def, struct domain *d)
 {
-    return xsm_ops.domain_resource_map(d);
+    return alternative_call(xsm_ops.domain_resource_map, d);
 }
 
 #ifdef CONFIG_ARGO
 static inline int xsm_argo_enable(const struct domain *d)
 {
-    return xsm_ops.argo_enable(d);
+    return alternative_call(xsm_ops.argo_enable, d);
 }
 
 static inline int xsm_argo_register_single_source(const struct domain *d,
                                                   const struct domain *t)
 {
-    return xsm_ops.argo_register_single_source(d, t);
+    return alternative_call(xsm_ops.argo_register_single_source, d, t);
 }
 
 static inline int xsm_argo_register_any_source(const struct domain *d)
 {
-    return xsm_ops.argo_register_any_source(d);
+    return alternative_call(xsm_ops.argo_register_any_source, d);
 }
 
 static inline int xsm_argo_send(const struct domain *d, const struct domain *t)
 {
-    return xsm_ops.argo_send(d, t);
+    return alternative_call(xsm_ops.argo_send, d, t);
 }
 
 #endif /* CONFIG_ARGO */
-- 
2.20.1



^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH v3 5/7] xsm: decouple xsm header inclusion selection
  2021-08-05 14:06 [PATCH v3 0/7] xsm: refactoring xsm hooks Daniel P. Smith
                   ` (3 preceding siblings ...)
  2021-08-05 14:06 ` [PATCH v3 4/7] xsm: convert xsm_ops hook calls to alternative call Daniel P. Smith
@ 2021-08-05 14:06 ` Daniel P. Smith
  2021-08-26  8:13   ` Jan Beulich
  2021-08-05 14:06 ` [PATCH v3 6/7] xsm: drop generic event channel labeling exclusion Daniel P. Smith
  2021-08-05 14:06 ` [PATCH v3 7/7] xsm: removing facade that XSM can be enabled/disabled Daniel P. Smith
  6 siblings, 1 reply; 25+ messages in thread
From: Daniel P. Smith @ 2021-08-05 14:06 UTC (permalink / raw)
  To: Daniel P. Smith, xen-devel; +Cc: Daniel De Graaf

Multiple preprocessor defines were used as a mechanism to selective include
parts of the xsm.h header file. This makes it difficult to know which portion
is being included at any one time. This commit works to simplify this by
separating the core structures and functions of XSM into xsm-core.h away from
the wrapper functions which remain in xsm.h and dummy.h.

Signed-off-by: Daniel P. Smith <dpsmith@apertussolutions.com>
---
 xen/include/xsm/dummy.h    |   2 +-
 xen/include/xsm/xsm-core.h | 273 +++++++++++++++++++++++++++++++++++++
 xen/include/xsm/xsm.h      | 243 +--------------------------------
 xen/xsm/dummy.c            |   1 -
 xen/xsm/silo.c             |   1 -
 5 files changed, 275 insertions(+), 245 deletions(-)
 create mode 100644 xen/include/xsm/xsm-core.h

diff --git a/xen/include/xsm/dummy.h b/xen/include/xsm/dummy.h
index 363c6d7798..c445c5681b 100644
--- a/xen/include/xsm/dummy.h
+++ b/xen/include/xsm/dummy.h
@@ -16,7 +16,7 @@
  */
 
 #include <xen/sched.h>
-#include <xsm/xsm.h>
+#include <xsm/xsm-core.h>
 #include <public/hvm/params.h>
 
 /* Cannot use BUILD_BUG_ON here because the expressions we check are not
diff --git a/xen/include/xsm/xsm-core.h b/xen/include/xsm/xsm-core.h
new file mode 100644
index 0000000000..49b00d688c
--- /dev/null
+++ b/xen/include/xsm/xsm-core.h
@@ -0,0 +1,273 @@
+/*
+ *  This file contains the XSM hook definitions for Xen.
+ *
+ *  This work is based on the LSM implementation in Linux 2.6.13.4.
+ *
+ *  Author:  George Coker, <gscoker@alpha.ncsc.mil>
+ *
+ *  Contributors: Michael LeMay, <mdlemay@epoch.ncsc.mil>
+ *
+ *  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.
+ */
+
+#ifndef __XSM_CORE_H__
+#define __XSM_CORE_H__
+
+#include <xen/sched.h>
+#include <xen/multiboot.h>
+
+typedef void xsm_op_t;
+DEFINE_XEN_GUEST_HANDLE(xsm_op_t);
+
+/* policy magic number (defined by XSM_MAGIC) */
+typedef uint32_t xsm_magic_t;
+
+#ifdef CONFIG_XSM_FLASK
+#define XSM_MAGIC 0xf97cff8c
+#else
+#define XSM_MAGIC 0x0
+#endif
+
+/* These annotations are used by callers and in dummy.h to document the
+ * default actions of XSM hooks. They should be compiled out otherwise.
+ */
+enum xsm_default {
+    XSM_HOOK,     /* Guests can normally access the hypercall */
+    XSM_DM_PRIV,  /* Device model can perform on its target domain */
+    XSM_TARGET,   /* Can perform on self or your target domain */
+    XSM_PRIV,     /* Privileged - normally restricted to dom0 */
+    XSM_XS_PRIV,  /* Xenstore domain - can do some privileged operations */
+    XSM_OTHER     /* Something more complex */
+};
+typedef enum xsm_default xsm_default_t;
+
+struct xsm_ops {
+    void (*security_domaininfo) (struct domain *d,
+                                 struct xen_domctl_getdomaininfo *info);
+    int (*domain_create) (struct domain *d, uint32_t ssidref);
+    int (*getdomaininfo) (struct domain *d);
+    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 (*sysctl) (int cmd);
+    int (*readconsole) (uint32_t clear);
+
+    int (*evtchn_unbound) (struct domain *d, struct evtchn *chn, domid_t id2);
+    int (*evtchn_interdomain) (struct domain *d1, struct evtchn *chn1,
+                               struct domain *d2, struct evtchn *chn2);
+    void (*evtchn_close_post) (struct evtchn *chn);
+    int (*evtchn_send) (struct domain *d, struct evtchn *chn);
+    int (*evtchn_status) (struct domain *d, struct evtchn *chn);
+    int (*evtchn_reset) (struct domain *d1, struct domain *d2);
+
+    int (*grant_mapref) (struct domain *d1, struct domain *d2, uint32_t flags);
+    int (*grant_unmapref) (struct domain *d1, struct domain *d2);
+    int (*grant_setup) (struct domain *d1, struct domain *d2);
+    int (*grant_transfer) (struct domain *d1, struct domain *d2);
+    int (*grant_copy) (struct domain *d1, struct domain *d2);
+    int (*grant_query_size) (struct domain *d1, struct domain *d2);
+
+    int (*alloc_security_domain) (struct domain *d);
+    void (*free_security_domain) (struct domain *d);
+    int (*alloc_security_evtchns) (struct evtchn chn[], unsigned int nr);
+    void (*free_security_evtchns) (struct evtchn chn[], unsigned int nr);
+    char *(*show_security_evtchn) (struct domain *d, const struct evtchn *chn);
+    int (*init_hardware_domain) (struct domain *d);
+
+    int (*get_pod_target) (struct domain *d);
+    int (*set_pod_target) (struct domain *d);
+    int (*memory_exchange) (struct domain *d);
+    int (*memory_adjust_reservation) (struct domain *d1, struct domain *d2);
+    int (*memory_stat_reservation) (struct domain *d1, struct domain *d2);
+    int (*memory_pin_page) (struct domain *d1, struct domain *d2,
+                            struct page_info *page);
+    int (*add_to_physmap) (struct domain *d1, struct domain *d2);
+    int (*remove_from_physmap) (struct domain *d1, struct domain *d2);
+    int (*map_gmfn_foreign) (struct domain *d, struct domain *t);
+    int (*claim_pages) (struct domain *d);
+
+    int (*console_io) (struct domain *d, int cmd);
+
+    int (*profile) (struct domain *d, int op);
+
+    int (*kexec) (void);
+    int (*schedop_shutdown) (struct domain *d1, struct domain *d2);
+
+    char *(*show_irq_sid) (int irq);
+    int (*map_domain_pirq) (struct domain *d);
+    int (*map_domain_irq) (struct domain *d, int irq, const void *data);
+    int (*unmap_domain_pirq) (struct domain *d);
+    int (*unmap_domain_irq) (struct domain *d, int irq, const void *data);
+    int (*bind_pt_irq) (struct domain *d, struct xen_domctl_bind_pt_irq *bind);
+    int (*unbind_pt_irq) (struct domain *d,
+                          struct xen_domctl_bind_pt_irq *bind);
+    int (*irq_permission) (struct domain *d, int pirq, uint8_t allow);
+    int (*iomem_permission) (struct domain *d, uint64_t s, uint64_t e,
+                             uint8_t allow);
+    int (*iomem_mapping) (struct domain *d, uint64_t s, uint64_t e,
+                          uint8_t allow);
+    int (*pci_config_permission) (struct domain *d, uint32_t machine_bdf,
+                                  uint16_t start, uint16_t end, uint8_t access);
+
+#if defined(CONFIG_HAS_PASSTHROUGH) && defined(CONFIG_HAS_PCI)
+    int (*get_device_group) (uint32_t machine_bdf);
+    int (*assign_device) (struct domain *d, uint32_t machine_bdf);
+    int (*deassign_device) (struct domain *d, uint32_t machine_bdf);
+#endif
+
+#if defined(CONFIG_HAS_PASSTHROUGH) && defined(CONFIG_HAS_DEVICE_TREE)
+    int (*assign_dtdevice) (struct domain *d, const char *dtpath);
+    int (*deassign_dtdevice) (struct domain *d, const char *dtpath);
+#endif
+
+    int (*resource_plug_core) (void);
+    int (*resource_unplug_core) (void);
+    int (*resource_plug_pci) (uint32_t machine_bdf);
+    int (*resource_unplug_pci) (uint32_t machine_bdf);
+    int (*resource_setup_pci) (uint32_t machine_bdf);
+    int (*resource_setup_gsi) (int gsi);
+    int (*resource_setup_misc) (void);
+
+    int (*page_offline)(uint32_t cmd);
+    int (*hypfs_op)(void);
+
+    long (*do_xsm_op) (XEN_GUEST_HANDLE_PARAM(xsm_op_t) op);
+#ifdef CONFIG_COMPAT
+    int (*do_compat_op) (XEN_GUEST_HANDLE_PARAM(xsm_op_t) op);
+#endif
+
+    int (*hvm_param) (struct domain *d, unsigned long op);
+    int (*hvm_control) (struct domain *d, unsigned long op);
+    int (*hvm_param_altp2mhvm) (struct domain *d);
+    int (*hvm_altp2mhvm_op) (struct domain *d, uint64_t mode, uint32_t op);
+    int (*get_vnumainfo) (struct domain *d);
+
+    int (*vm_event_control) (struct domain *d, int mode, int op);
+
+#ifdef CONFIG_MEM_ACCESS
+    int (*mem_access) (struct domain *d);
+#endif
+
+#ifdef CONFIG_MEM_PAGING
+    int (*mem_paging) (struct domain *d);
+#endif
+
+#ifdef CONFIG_MEM_SHARING
+    int (*mem_sharing) (struct domain *d);
+#endif
+
+    int (*platform_op) (uint32_t cmd);
+
+#ifdef CONFIG_X86
+    int (*do_mca) (void);
+    int (*shadow_control) (struct domain *d, uint32_t op);
+    int (*mem_sharing_op) (struct domain *d, struct domain *cd, int op);
+    int (*apic) (struct domain *d, int cmd);
+    int (*memtype) (uint32_t access);
+    int (*machine_memory_map) (void);
+    int (*domain_memory_map) (struct domain *d);
+#define XSM_MMU_UPDATE_READ      1
+#define XSM_MMU_UPDATE_WRITE     2
+#define XSM_MMU_NORMAL_UPDATE    4
+#define XSM_MMU_MACHPHYS_UPDATE  8
+    int (*mmu_update) (struct domain *d, struct domain *t,
+                       struct domain *f, uint32_t flags);
+    int (*mmuext_op) (struct domain *d, struct domain *f);
+    int (*update_va_mapping) (struct domain *d, struct domain *f,
+                              l1_pgentry_t pte);
+    int (*priv_mapping) (struct domain *d, struct domain *t);
+    int (*ioport_permission) (struct domain *d, uint32_t s, uint32_t e,
+                              uint8_t allow);
+    int (*ioport_mapping) (struct domain *d, uint32_t s, uint32_t e,
+                           uint8_t allow);
+    int (*pmu_op) (struct domain *d, unsigned int op);
+#endif
+    int (*dm_op) (struct domain *d);
+    int (*xen_version) (uint32_t cmd);
+    int (*domain_resource_map) (struct domain *d);
+#ifdef CONFIG_ARGO
+    int (*argo_enable) (const struct domain *d);
+    int (*argo_register_single_source) (const struct domain *d,
+                                        const struct domain *t);
+    int (*argo_register_any_source) (const struct domain *d);
+    int (*argo_send) (const struct domain *d, const struct domain *t);
+#endif
+};
+
+extern void xsm_fixup_ops(struct xsm_ops *ops);
+
+#ifdef CONFIG_XSM
+
+#ifdef CONFIG_MULTIBOOT
+extern int xsm_multiboot_init(unsigned long *module_map,
+                              const multiboot_info_t *mbi);
+extern int xsm_multiboot_policy_init(unsigned long *module_map,
+                                     const multiboot_info_t *mbi,
+                                     void **policy_buffer,
+                                     size_t *policy_size);
+#endif
+
+#ifdef CONFIG_HAS_DEVICE_TREE
+/*
+ * Initialize XSM
+ *
+ * On success, return 1 if using SILO mode else 0.
+ */
+extern int xsm_dt_init(void);
+extern int xsm_dt_policy_init(void **policy_buffer, size_t *policy_size);
+extern bool has_xsm_magic(paddr_t);
+#endif
+
+#ifdef CONFIG_XSM_FLASK
+extern const struct xsm_ops *flask_init(const void *policy_buffer,
+                                        size_t policy_size);
+#else
+static inline const struct xsm_ops *flask_init(const void *policy_buffer,
+                                               size_t policy_size)
+{
+    return NULL;
+}
+#endif
+
+#ifdef CONFIG_XSM_FLASK_POLICY
+extern const unsigned char xsm_flask_init_policy[];
+extern const unsigned int xsm_flask_init_policy_size;
+#endif
+
+#ifdef CONFIG_XSM_SILO
+extern const struct xsm_ops *silo_init(void);
+#else
+static const inline struct xsm_ops *silo_init(void)
+{
+    return NULL;
+}
+#endif
+
+#else /* CONFIG_XSM */
+
+#ifdef CONFIG_MULTIBOOT
+static inline int xsm_multiboot_init (unsigned long *module_map,
+                                      const multiboot_info_t *mbi)
+{
+    return 0;
+}
+#endif
+
+#ifdef CONFIG_HAS_DEVICE_TREE
+static inline int xsm_dt_init(void)
+{
+    return 0;
+}
+
+static inline bool has_xsm_magic(paddr_t start)
+{
+    return false;
+}
+#endif /* CONFIG_HAS_DEVICE_TREE */
+
+#endif /* CONFIG_XSM */
+
+#endif /* __XSM_CORE_H */
diff --git a/xen/include/xsm/xsm.h b/xen/include/xsm/xsm.h
index 6a54ee883c..673b818ac7 100644
--- a/xen/include/xsm/xsm.h
+++ b/xen/include/xsm/xsm.h
@@ -18,184 +18,12 @@
 #include <xen/alternative-call.h>
 #include <xen/sched.h>
 #include <xen/multiboot.h>
-
-typedef void xsm_op_t;
-DEFINE_XEN_GUEST_HANDLE(xsm_op_t);
-
-/* policy magic number (defined by XSM_MAGIC) */
-typedef u32 xsm_magic_t;
-
-#ifdef CONFIG_XSM_FLASK
-#define XSM_MAGIC 0xf97cff8c
-#else
-#define XSM_MAGIC 0x0
-#endif
-
-/* These annotations are used by callers and in dummy.h to document the
- * default actions of XSM hooks. They should be compiled out otherwise.
- */
-enum xsm_default {
-    XSM_HOOK,     /* Guests can normally access the hypercall */
-    XSM_DM_PRIV,  /* Device model can perform on its target domain */
-    XSM_TARGET,   /* Can perform on self or your target domain */
-    XSM_PRIV,     /* Privileged - normally restricted to dom0 */
-    XSM_XS_PRIV,  /* Xenstore domain - can do some privileged operations */
-    XSM_OTHER     /* Something more complex */
-};
-typedef enum xsm_default xsm_default_t;
-
-struct xsm_ops {
-    void (*security_domaininfo) (struct domain *d,
-                                        struct xen_domctl_getdomaininfo *info);
-    int (*domain_create) (struct domain *d, u32 ssidref);
-    int (*getdomaininfo) (struct domain *d);
-    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 (*sysctl) (int cmd);
-    int (*readconsole) (uint32_t clear);
-
-    int (*evtchn_unbound) (struct domain *d, struct evtchn *chn, domid_t id2);
-    int (*evtchn_interdomain) (struct domain *d1, struct evtchn *chn1,
-                                        struct domain *d2, struct evtchn *chn2);
-    void (*evtchn_close_post) (struct evtchn *chn);
-    int (*evtchn_send) (struct domain *d, struct evtchn *chn);
-    int (*evtchn_status) (struct domain *d, struct evtchn *chn);
-    int (*evtchn_reset) (struct domain *d1, struct domain *d2);
-
-    int (*grant_mapref) (struct domain *d1, struct domain *d2, uint32_t flags);
-    int (*grant_unmapref) (struct domain *d1, struct domain *d2);
-    int (*grant_setup) (struct domain *d1, struct domain *d2);
-    int (*grant_transfer) (struct domain *d1, struct domain *d2);
-    int (*grant_copy) (struct domain *d1, struct domain *d2);
-    int (*grant_query_size) (struct domain *d1, struct domain *d2);
-
-    int (*alloc_security_domain) (struct domain *d);
-    void (*free_security_domain) (struct domain *d);
-    int (*alloc_security_evtchns) (struct evtchn chn[], unsigned int nr);
-    void (*free_security_evtchns) (struct evtchn chn[], unsigned int nr);
-    char *(*show_security_evtchn) (struct domain *d, const struct evtchn *chn);
-    int (*init_hardware_domain) (struct domain *d);
-
-    int (*get_pod_target) (struct domain *d);
-    int (*set_pod_target) (struct domain *d);
-    int (*memory_exchange) (struct domain *d);
-    int (*memory_adjust_reservation) (struct domain *d1, struct domain *d2);
-    int (*memory_stat_reservation) (struct domain *d1, struct domain *d2);
-    int (*memory_pin_page) (struct domain *d1, struct domain *d2, struct page_info *page);
-    int (*add_to_physmap) (struct domain *d1, struct domain *d2);
-    int (*remove_from_physmap) (struct domain *d1, struct domain *d2);
-    int (*map_gmfn_foreign) (struct domain *d, struct domain *t);
-    int (*claim_pages) (struct domain *d);
-
-    int (*console_io) (struct domain *d, int cmd);
-
-    int (*profile) (struct domain *d, int op);
-
-    int (*kexec) (void);
-    int (*schedop_shutdown) (struct domain *d1, struct domain *d2);
-
-    char *(*show_irq_sid) (int irq);
-    int (*map_domain_pirq) (struct domain *d);
-    int (*map_domain_irq) (struct domain *d, int irq, const void *data);
-    int (*unmap_domain_pirq) (struct domain *d);
-    int (*unmap_domain_irq) (struct domain *d, int irq, const void *data);
-    int (*bind_pt_irq) (struct domain *d, struct xen_domctl_bind_pt_irq *bind);
-    int (*unbind_pt_irq) (struct domain *d, struct xen_domctl_bind_pt_irq *bind);
-    int (*irq_permission) (struct domain *d, int pirq, uint8_t allow);
-    int (*iomem_permission) (struct domain *d, uint64_t s, uint64_t e, uint8_t allow);
-    int (*iomem_mapping) (struct domain *d, uint64_t s, uint64_t e, uint8_t allow);
-    int (*pci_config_permission) (struct domain *d, uint32_t machine_bdf, uint16_t start, uint16_t end, uint8_t access);
-
-#if defined(CONFIG_HAS_PASSTHROUGH) && defined(CONFIG_HAS_PCI)
-    int (*get_device_group) (uint32_t machine_bdf);
-    int (*assign_device) (struct domain *d, uint32_t machine_bdf);
-    int (*deassign_device) (struct domain *d, uint32_t machine_bdf);
-#endif
-
-#if defined(CONFIG_HAS_PASSTHROUGH) && defined(CONFIG_HAS_DEVICE_TREE)
-    int (*assign_dtdevice) (struct domain *d, const char *dtpath);
-    int (*deassign_dtdevice) (struct domain *d, const char *dtpath);
-#endif
-
-    int (*resource_plug_core) (void);
-    int (*resource_unplug_core) (void);
-    int (*resource_plug_pci) (uint32_t machine_bdf);
-    int (*resource_unplug_pci) (uint32_t machine_bdf);
-    int (*resource_setup_pci) (uint32_t machine_bdf);
-    int (*resource_setup_gsi) (int gsi);
-    int (*resource_setup_misc) (void);
-
-    int (*page_offline)(uint32_t cmd);
-    int (*hypfs_op)(void);
-
-    long (*do_xsm_op) (XEN_GUEST_HANDLE_PARAM(xsm_op_t) op);
-#ifdef CONFIG_COMPAT
-    int (*do_compat_op) (XEN_GUEST_HANDLE_PARAM(xsm_op_t) op);
-#endif
-
-    int (*hvm_param) (struct domain *d, unsigned long op);
-    int (*hvm_control) (struct domain *d, unsigned long op);
-    int (*hvm_param_altp2mhvm) (struct domain *d);
-    int (*hvm_altp2mhvm_op) (struct domain *d, uint64_t mode, uint32_t op);
-    int (*get_vnumainfo) (struct domain *d);
-
-    int (*vm_event_control) (struct domain *d, int mode, int op);
-
-#ifdef CONFIG_MEM_ACCESS
-    int (*mem_access) (struct domain *d);
-#endif
-
-#ifdef CONFIG_MEM_PAGING
-    int (*mem_paging) (struct domain *d);
-#endif
-
-#ifdef CONFIG_MEM_SHARING
-    int (*mem_sharing) (struct domain *d);
-#endif
-
-    int (*platform_op) (uint32_t cmd);
-
-#ifdef CONFIG_X86
-    int (*do_mca) (void);
-    int (*shadow_control) (struct domain *d, uint32_t op);
-    int (*mem_sharing_op) (struct domain *d, struct domain *cd, int op);
-    int (*apic) (struct domain *d, int cmd);
-    int (*memtype) (uint32_t access);
-    int (*machine_memory_map) (void);
-    int (*domain_memory_map) (struct domain *d);
-#define XSM_MMU_UPDATE_READ      1
-#define XSM_MMU_UPDATE_WRITE     2
-#define XSM_MMU_NORMAL_UPDATE    4
-#define XSM_MMU_MACHPHYS_UPDATE  8
-    int (*mmu_update) (struct domain *d, struct domain *t,
-                       struct domain *f, uint32_t flags);
-    int (*mmuext_op) (struct domain *d, struct domain *f);
-    int (*update_va_mapping) (struct domain *d, struct domain *f, l1_pgentry_t pte);
-    int (*priv_mapping) (struct domain *d, struct domain *t);
-    int (*ioport_permission) (struct domain *d, uint32_t s, uint32_t e, uint8_t allow);
-    int (*ioport_mapping) (struct domain *d, uint32_t s, uint32_t e, uint8_t allow);
-    int (*pmu_op) (struct domain *d, unsigned int op);
-#endif
-    int (*dm_op) (struct domain *d);
-    int (*xen_version) (uint32_t cmd);
-    int (*domain_resource_map) (struct domain *d);
-#ifdef CONFIG_ARGO
-    int (*argo_enable) (const struct domain *d);
-    int (*argo_register_single_source) (const struct domain *d,
-                                        const struct domain *t);
-    int (*argo_register_any_source) (const struct domain *d);
-    int (*argo_send) (const struct domain *d, const struct domain *t);
-#endif
-};
+#include <xsm/xsm-core.h>
 
 #ifdef CONFIG_XSM
 
 extern struct xsm_ops xsm_ops;
 
-#ifndef XSM_NO_WRAPPERS
-
 static inline void xsm_security_domaininfo (struct domain *d,
                                         struct xen_domctl_getdomaininfo *info)
 {
@@ -726,79 +554,10 @@ static inline int xsm_argo_send(const struct domain *d, const struct domain *t)
 
 #endif /* CONFIG_ARGO */
 
-#endif /* XSM_NO_WRAPPERS */
-
-#ifdef CONFIG_MULTIBOOT
-extern int xsm_multiboot_init(unsigned long *module_map,
-                              const multiboot_info_t *mbi);
-extern int xsm_multiboot_policy_init(unsigned long *module_map,
-                                     const multiboot_info_t *mbi,
-                                     void **policy_buffer,
-                                     size_t *policy_size);
-#endif
-
-#ifdef CONFIG_HAS_DEVICE_TREE
-/*
- * Initialize XSM
- *
- * On success, return 1 if using SILO mode else 0.
- */
-extern int xsm_dt_init(void);
-extern int xsm_dt_policy_init(void **policy_buffer, size_t *policy_size);
-extern bool has_xsm_magic(paddr_t);
-#endif
-
-extern void xsm_fixup_ops(struct xsm_ops *ops);
-
-#ifdef CONFIG_XSM_FLASK
-extern const struct xsm_ops *flask_init(const void *policy_buffer,
-                                        size_t policy_size);
-#else
-static inline struct xsm_ops *flask_init(const void *policy_buffer,
-                                         size_t policy_size)
-{
-    return NULL;
-}
-#endif
-
-#ifdef CONFIG_XSM_FLASK_POLICY
-extern const unsigned char xsm_flask_init_policy[];
-extern const unsigned int xsm_flask_init_policy_size;
-#endif
-
-#ifdef CONFIG_XSM_SILO
-extern const struct xsm_ops *silo_init(void);
-#else
-static inline struct xsm_ops *silo_init(void)
-{
-    return NULL;
-}
-#endif
-
 #else /* CONFIG_XSM */
 
 #include <xsm/dummy.h>
 
-#ifdef CONFIG_MULTIBOOT
-static inline int xsm_multiboot_init (unsigned long *module_map,
-                                      const multiboot_info_t *mbi)
-{
-    return 0;
-}
-#endif
-
-#ifdef CONFIG_HAS_DEVICE_TREE
-static inline int xsm_dt_init(void)
-{
-    return 0;
-}
-
-static inline bool has_xsm_magic(paddr_t start)
-{
-    return false;
-}
-#endif /* CONFIG_HAS_DEVICE_TREE */
-
 #endif /* CONFIG_XSM */
 
 #endif /* __XSM_H */
diff --git a/xen/xsm/dummy.c b/xen/xsm/dummy.c
index d8c935328e..b848580eaa 100644
--- a/xen/xsm/dummy.c
+++ b/xen/xsm/dummy.c
@@ -10,7 +10,6 @@
  *  as published by the Free Software Foundation.
  */
 
-#define XSM_NO_WRAPPERS
 #include <xsm/dummy.h>
 
 #define set_to_dummy_if_null(ops, function)                            \
diff --git a/xen/xsm/silo.c b/xen/xsm/silo.c
index 3a2dea13fe..4ef40bd712 100644
--- a/xen/xsm/silo.c
+++ b/xen/xsm/silo.c
@@ -17,7 +17,6 @@
  * You should have received a copy of the GNU General Public License along with
  * this program; If not, see <http://www.gnu.org/licenses/>.
  */
-#define XSM_NO_WRAPPERS
 #include <xsm/dummy.h>
 
 /*
-- 
2.20.1



^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH v3 6/7] xsm: drop generic event channel labeling exclusion
  2021-08-05 14:06 [PATCH v3 0/7] xsm: refactoring xsm hooks Daniel P. Smith
                   ` (4 preceding siblings ...)
  2021-08-05 14:06 ` [PATCH v3 5/7] xsm: decouple xsm header inclusion selection Daniel P. Smith
@ 2021-08-05 14:06 ` Daniel P. Smith
  2021-08-25 15:44   ` Jan Beulich
  2021-08-05 14:06 ` [PATCH v3 7/7] xsm: removing facade that XSM can be enabled/disabled Daniel P. Smith
  6 siblings, 1 reply; 25+ messages in thread
From: Daniel P. Smith @ 2021-08-05 14:06 UTC (permalink / raw)
  To: xen-devel
  Cc: Daniel P. Smith, Andrew Cooper, George Dunlap, Ian Jackson,
	Jan Beulich, Julien Grall, Stefano Stabellini, Wei Liu

The internal define flag is not used by any XSM module, removing the #ifdef
leaving the generic event channel labeling as always present.

Signed-off-by: Daniel P. Smith <dpsmith@apertussolutions.com>
---
 xen/include/xen/sched.h | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/xen/include/xen/sched.h b/xen/include/xen/sched.h
index 28146ee404..b089324510 100644
--- a/xen/include/xen/sched.h
+++ b/xen/include/xen/sched.h
@@ -120,15 +120,12 @@ struct evtchn
     unsigned short notify_vcpu_id; /* VCPU for local delivery notification */
     uint32_t fifo_lastq;           /* Data for identifying last queue. */
 
-#ifdef CONFIG_XSM
     union {
-#ifdef XSM_NEED_GENERIC_EVTCHN_SSID
         /*
          * If an XSM module needs more space for its event channel context,
          * this pointer stores the necessary data for the security server.
          */
         void *generic;
-#endif
 #ifdef CONFIG_XSM_FLASK
         /*
          * Inlining the contents of the structure for FLASK avoids unneeded
@@ -138,7 +135,6 @@ struct evtchn
         uint32_t flask_sid;
 #endif
     } ssid;
-#endif
 } __attribute__((aligned(64)));
 
 int  evtchn_init(struct domain *d, unsigned int max_port);
-- 
2.20.1



^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH v3 7/7] xsm: removing facade that XSM can be enabled/disabled
  2021-08-05 14:06 [PATCH v3 0/7] xsm: refactoring xsm hooks Daniel P. Smith
                   ` (5 preceding siblings ...)
  2021-08-05 14:06 ` [PATCH v3 6/7] xsm: drop generic event channel labeling exclusion Daniel P. Smith
@ 2021-08-05 14:06 ` Daniel P. Smith
  2021-08-26  9:37   ` Jan Beulich
  6 siblings, 1 reply; 25+ messages in thread
From: Daniel P. Smith @ 2021-08-05 14:06 UTC (permalink / raw)
  To: Daniel P. Smith, xen-devel
  Cc: Andrew Cooper, George Dunlap, Ian Jackson, Jan Beulich,
	Julien Grall, Stefano Stabellini, Wei Liu, Daniel De Graaf

The XSM facilities are always in use by Xen with the facade of being able to
turn XSM on and off. This option is in fact about allowing the selection of
which policies are available and which are used at runtime.  To provide this
facade a complicated serious of #ifdef's are used to selective include
different headers or portions of headers. This series of #ifdef gyrations
switches between two different versions of the XSM hook interfaces and their
respective backing implementation.  All of this is done to provide a minimal
size/performance optimization for when alternative policies are disabled.

To unwind the #ifdef gyrations a series of changes were necessary,
    * replace CONFIG_XSM with XSM_CONFIGURABLE to allow visibility of
      selecting alternate XSM policy modules to those that require it
    * adjusted CONFIG_XSM_SILO, CONFIG_XSM_FLASK, and the default module
      selection to sensible defaults
    * collapsed the "dummy/defualt" XSM interface and implementation with the
      "multiple policy" interface to provide a single inlined implementation
      that attempts to use a registered hook and falls back to the check from
      the dummy implementation
    * the collapse to a single interface broke code relying on the alternate
      interface, specifically SILO, this was reworked to remove the
      indirection/abstraction making SILO explicit in its access control
      decisions
    * with the change of the XSM hooks to fall back to enforcing the dummy
      policy, it is no longer necessary to fill NULL entries in the struct
      xsm_ops returned by an XSM module's init

Signed-off-by: Daniel P. Smith <dpsmith@apertussolutions.com>
---
 xen/common/Kconfig         |  47 +-
 xen/include/xsm/dummy.h    | 709 +----------------------------
 xen/include/xsm/xsm-core.h |  26 --
 xen/include/xsm/xsm.h      | 904 ++++++++++++++++++++++++++++---------
 xen/xsm/Makefile           |   3 +-
 xen/xsm/dummy.c            | 157 -------
 xen/xsm/silo.c             |  15 +-
 xen/xsm/xsm_core.c         |  18 +-
 8 files changed, 726 insertions(+), 1153 deletions(-)
 delete mode 100644 xen/xsm/dummy.c

diff --git a/xen/common/Kconfig b/xen/common/Kconfig
index ac5491b1cc..3c5980a336 100644
--- a/xen/common/Kconfig
+++ b/xen/common/Kconfig
@@ -200,23 +200,15 @@ config XENOPROF
 
 	  If unsure, say Y.
 
-config XSM
-	bool "Xen Security Modules support"
-	default ARM
-	---help---
-	  Enables the security framework known as Xen Security Modules which
-	  allows administrators fine-grained control over a Xen domain and
-	  its capabilities by defining permissible interactions between domains,
-	  the hypervisor itself, and related resources such as memory and
-	  devices.
-
-	  If unsure, say N.
+config XSM_CONFIGURABLE
+    bool "Enable Configuring Xen Security Modules"
 
 config XSM_FLASK
-	def_bool y
-	prompt "FLux Advanced Security Kernel support"
-	depends on XSM
-	---help---
+	bool "FLux Advanced Security Kernel support"
+	default n
+	depends on XSM_CONFIGURABLE
+	select XSM_EVTCHN_LABELING
+	help
 	  Enables FLASK (FLux Advanced Security Kernel) as the access control
 	  mechanism used by the XSM framework.  This provides a mandatory access
 	  control framework by which security enforcement, isolation, and
@@ -226,10 +218,10 @@ config XSM_FLASK
 	  If unsure, say Y.
 
 config XSM_FLASK_AVC_STATS
-	def_bool y
-	prompt "Maintain statistics on the FLASK access vector cache" if EXPERT
+	bool "Maintain statistics on the FLASK access vector cache" if EXPERT
+	default y
 	depends on XSM_FLASK
-	---help---
+	help
 	  Maintain counters on the access vector cache that can be viewed using
 	  the FLASK_AVC_CACHESTATS sub-op of the xsm_op hypercall.  Disabling
 	  this will save a tiny amount of memory and time to update the stats.
@@ -240,7 +232,7 @@ config XSM_FLASK_POLICY
 	bool "Compile Xen with a built-in FLASK security policy"
 	default y if "$(XEN_HAS_CHECKPOLICY)" = "y"
 	depends on XSM_FLASK
-	---help---
+	help
 	  This includes a default XSM policy in the hypervisor so that the
 	  bootloader does not need to load a policy to get sane behavior from an
 	  XSM-enabled hypervisor.  If this is disabled, a policy must be
@@ -253,10 +245,11 @@ config XSM_FLASK_POLICY
 	  If unsure, say Y.
 
 config XSM_SILO
-	def_bool y
-	prompt "SILO support"
-	depends on XSM
-	---help---
+	bool "SILO support"
+	default y if ARM
+	default n
+	depends on XSM_CONFIGURABLE
+	help
 	  Enables SILO as the access control mechanism used by the XSM framework.
 	  This is not the default module, add boot parameter xsm=silo to choose
 	  it. This will deny any unmediated communication channels (grant tables
@@ -265,14 +258,14 @@ config XSM_SILO
 	  If unsure, say Y.
 
 choice
-	prompt "Default XSM implementation"
-	depends on XSM
+	prompt "Default XSM module"
 	default XSM_SILO_DEFAULT if XSM_SILO && ARM
 	default XSM_FLASK_DEFAULT if XSM_FLASK
 	default XSM_SILO_DEFAULT if XSM_SILO
 	default XSM_DUMMY_DEFAULT
+	depends on XSM_CONFIGURABLE
 	config XSM_DUMMY_DEFAULT
-		bool "Match non-XSM behavior"
+		bool "Classic Dom0 behavior"
 	config XSM_FLASK_DEFAULT
 		bool "FLux Advanced Security Kernel" if XSM_FLASK
 	config XSM_SILO_DEFAULT
@@ -282,7 +275,7 @@ endchoice
 config LATE_HWDOM
 	bool "Dedicated hardware domain"
 	default n
-	depends on XSM && X86
+	depends on XSM_FLASK && X86
 	---help---
 	  Allows the creation of a dedicated hardware domain distinct from
 	  domain 0 that manages devices without needing access to other
diff --git a/xen/include/xsm/dummy.h b/xen/include/xsm/dummy.h
index c445c5681b..eb8d61216b 100644
--- a/xen/include/xsm/dummy.h
+++ b/xen/include/xsm/dummy.h
@@ -1,18 +1,11 @@
 /*
- *  Default XSM hooks - IS_PRIV and IS_PRIV_FOR checks
+ *  Default XSM hook check - enforces basic access control decisions
  *
  *  Author: Daniel De Graaf <dgdegra@tyhco.nsa.gov>
  *
  *  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 <xen/sched.h>
@@ -42,33 +35,8 @@ static inline void __xsm_action_mismatch_detected(void)
 void __xsm_action_mismatch_detected(void);
 #endif
 
-#ifdef CONFIG_XSM
-
-/* In CONFIG_XSM 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 __maybe_unused
-
-#define XSM_DEFAULT_ARG /* */
-#define XSM_DEFAULT_VOID void
-#define XSM_ASSERT_ACTION(def) xsm_default_t action = def; (void)action
-
-#else /* CONFIG_XSM */
-
-/* In !CONFIG_XSM 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 /* CONFIG_XSM */
-
 static always_inline int xsm_default_action(
     xsm_default_t action, struct domain *src, struct domain *target)
 {
@@ -97,678 +65,3 @@ static always_inline int xsm_default_action(
         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);
-    case XEN_DOMCTL_getdomaininfo:
-        return xsm_default_action(XSM_XS_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_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);
-    if ( d->is_console )
-        return xsm_default_action(XSM_HOOK, d, NULL);
-#ifdef CONFIG_VERBOSE_DEBUG
-    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_evtchns(
-    struct evtchn chn[], unsigned int nr)
-{
-    return 0;
-}
-
-static XSM_INLINE void xsm_free_security_evtchns(
-    struct evtchn chn[], unsigned int nr)
-{
-    return;
-}
-
-static XSM_INLINE char *xsm_show_security_evtchn(struct domain *d, const struct evtchn *chn)
-{
-    return NULL;
-}
-
-static XSM_INLINE int xsm_init_hardware_domain(XSM_DEFAULT_ARG struct domain *d)
-{
-    XSM_ASSERT_ACTION(XSM_HOOK);
-    return xsm_default_action(action, current->domain, d);
-}
-
-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_vnumainfo(XSM_DEFAULT_ARG struct domain *d)
-{
-    XSM_ASSERT_ACTION(XSM_TARGET);
-    return xsm_default_action(action, current->domain, d);
-}
-
-#if defined(CONFIG_HAS_PASSTHROUGH) && defined(CONFIG_HAS_PCI)
-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_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);
-}
-
-#endif /* HAS_PASSTHROUGH && HAS_PCI */
-
-#if defined(CONFIG_HAS_PASSTHROUGH) && defined(CONFIG_HAS_DEVICE_TREE)
-static XSM_INLINE int xsm_assign_dtdevice(XSM_DEFAULT_ARG struct domain *d,
-                                          const char *dtpath)
-{
-    XSM_ASSERT_ACTION(XSM_HOOK);
-    return xsm_default_action(action, current->domain, d);
-}
-
-static XSM_INLINE int xsm_deassign_dtdevice(XSM_DEFAULT_ARG struct domain *d,
-                                            const char *dtpath)
-{
-    XSM_ASSERT_ACTION(XSM_HOOK);
-    return xsm_default_action(action, current->domain, d);
-}
-
-#endif /* HAS_PASSTHROUGH && HAS_DEVICE_TREE */
-
-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_hypfs_op(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;
-}
-
-#ifdef CONFIG_COMPAT
-static XSM_INLINE int xsm_do_compat_op(XEN_GUEST_HANDLE_PARAM(xsm_op_t) op)
-{
-    return -ENOSYS;
-}
-#endif
-
-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_DM_PRIV);
-    return xsm_default_action(action, current->domain, d);
-}
-
-static XSM_INLINE int xsm_map_domain_irq(XSM_DEFAULT_ARG struct domain *d,
-                                         int irq, const 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_DM_PRIV);
-    return xsm_default_action(action, current->domain, d);
-}
-
-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_unmap_domain_irq(XSM_DEFAULT_ARG struct domain *d,
-                                           int irq, const 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_map_gmfn_foreign(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_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_control(XSM_DEFAULT_ARG struct domain *d, unsigned long op)
-{
-    XSM_ASSERT_ACTION(XSM_DM_PRIV);
-    return xsm_default_action(action, current->domain, d);
-}
-
-static XSM_INLINE int xsm_hvm_param_altp2mhvm(XSM_DEFAULT_ARG struct domain *d)
-{
-    XSM_ASSERT_ACTION(XSM_PRIV);
-    return xsm_default_action(action, current->domain, d);
-}
-
-static XSM_INLINE int xsm_hvm_altp2mhvm_op(XSM_DEFAULT_ARG struct domain *d, uint64_t mode, uint32_t op)
-{
-    XSM_ASSERT_ACTION(XSM_OTHER);
-
-    switch ( mode )
-    {
-    case XEN_ALTP2M_mixed:
-        return xsm_default_action(XSM_TARGET, current->domain, d);
-    case XEN_ALTP2M_external:
-        return xsm_default_action(XSM_DM_PRIV, current->domain, d);
-    case XEN_ALTP2M_limited:
-        if ( HVMOP_altp2m_vcpu_enable_notify == op )
-            return xsm_default_action(XSM_TARGET, current->domain, d);
-        return xsm_default_action(XSM_DM_PRIV, current->domain, d);
-    default:
-        return -EPERM;
-    }
-}
-
-static XSM_INLINE int xsm_vm_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);
-}
-
-#ifdef CONFIG_MEM_ACCESS
-static XSM_INLINE int xsm_mem_access(XSM_DEFAULT_ARG struct domain *d)
-{
-    XSM_ASSERT_ACTION(XSM_DM_PRIV);
-    return xsm_default_action(action, current->domain, d);
-}
-#endif
-
-#ifdef CONFIG_MEM_PAGING
-static XSM_INLINE int xsm_mem_paging(XSM_DEFAULT_ARG struct domain *d)
-{
-    XSM_ASSERT_ACTION(XSM_DM_PRIV);
-    return xsm_default_action(action, current->domain, d);
-}
-#endif
-
-#ifdef CONFIG_MEM_SHARING
-static XSM_INLINE int xsm_mem_sharing(XSM_DEFAULT_ARG struct domain *d)
-{
-    XSM_ASSERT_ACTION(XSM_DM_PRIV);
-    return xsm_default_action(action, current->domain, d);
-}
-#endif
-
-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);
-}
-
-#ifdef CONFIG_X86
-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_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_mem_sharing_op(XSM_DEFAULT_ARG struct domain *d, struct domain *cd, int op)
-{
-    XSM_ASSERT_ACTION(XSM_DM_PRIV);
-    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_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 ( evaluate_nospec(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_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);
-}
-
-static XSM_INLINE int xsm_pmu_op (XSM_DEFAULT_ARG struct domain *d, unsigned int op)
-{
-    XSM_ASSERT_ACTION(XSM_OTHER);
-    switch ( op )
-    {
-    case XENPMU_init:
-    case XENPMU_finish:
-    case XENPMU_lvtpc_set:
-    case XENPMU_flush:
-        return xsm_default_action(XSM_HOOK, d, current->domain);
-    default:
-        return xsm_default_action(XSM_PRIV, d, current->domain);
-    }
-}
-
-#endif /* CONFIG_X86 */
-
-static XSM_INLINE int xsm_dm_op(XSM_DEFAULT_ARG struct domain *d)
-{
-    XSM_ASSERT_ACTION(XSM_DM_PRIV);
-    return xsm_default_action(action, current->domain, d);
-}
-
-#ifdef CONFIG_ARGO
-static XSM_INLINE int xsm_argo_enable(const struct domain *d)
-{
-    return 0;
-}
-
-static XSM_INLINE int xsm_argo_register_single_source(const struct domain *d,
-                                                      const struct domain *t)
-{
-    return 0;
-}
-
-static XSM_INLINE int xsm_argo_register_any_source(const struct domain *d)
-{
-    return 0;
-}
-
-static XSM_INLINE int xsm_argo_send(const struct domain *d,
-                                    const struct domain *t)
-{
-    return 0;
-}
-
-#endif /* CONFIG_ARGO */
-
-#include <public/version.h>
-static XSM_INLINE int xsm_xen_version (XSM_DEFAULT_ARG uint32_t op)
-{
-    XSM_ASSERT_ACTION(XSM_OTHER);
-    switch ( op )
-    {
-    case XENVER_version:
-    case XENVER_platform_parameters:
-    case XENVER_get_features:
-        /* These sub-ops ignore the permission checks and return data. */
-        block_speculation();
-        return 0;
-    case XENVER_extraversion:
-    case XENVER_compile_info:
-    case XENVER_capabilities:
-    case XENVER_changeset:
-    case XENVER_pagesize:
-    case XENVER_guest_handle:
-        /* These MUST always be accessible to any guest by default. */
-        return xsm_default_action(XSM_HOOK, current->domain, NULL);
-    default:
-        return xsm_default_action(XSM_PRIV, current->domain, NULL);
-    }
-}
-
-static XSM_INLINE int xsm_domain_resource_map(XSM_DEFAULT_ARG struct domain *d)
-{
-    XSM_ASSERT_ACTION(XSM_DM_PRIV);
-    return xsm_default_action(action, current->domain, d);
-}
diff --git a/xen/include/xsm/xsm-core.h b/xen/include/xsm/xsm-core.h
index 49b00d688c..dfe9378cb2 100644
--- a/xen/include/xsm/xsm-core.h
+++ b/xen/include/xsm/xsm-core.h
@@ -199,8 +199,6 @@ struct xsm_ops {
 
 extern void xsm_fixup_ops(struct xsm_ops *ops);
 
-#ifdef CONFIG_XSM
-
 #ifdef CONFIG_MULTIBOOT
 extern int xsm_multiboot_init(unsigned long *module_map,
                               const multiboot_info_t *mbi);
@@ -246,28 +244,4 @@ static const inline struct xsm_ops *silo_init(void)
 }
 #endif
 
-#else /* CONFIG_XSM */
-
-#ifdef CONFIG_MULTIBOOT
-static inline int xsm_multiboot_init (unsigned long *module_map,
-                                      const multiboot_info_t *mbi)
-{
-    return 0;
-}
-#endif
-
-#ifdef CONFIG_HAS_DEVICE_TREE
-static inline int xsm_dt_init(void)
-{
-    return 0;
-}
-
-static inline bool has_xsm_magic(paddr_t start)
-{
-    return false;
-}
-#endif /* CONFIG_HAS_DEVICE_TREE */
-
-#endif /* CONFIG_XSM */
-
 #endif /* __XSM_CORE_H */
diff --git a/xen/include/xsm/xsm.h b/xen/include/xsm/xsm.h
index 673b818ac7..deb3a39062 100644
--- a/xen/include/xsm/xsm.h
+++ b/xen/include/xsm/xsm.h
@@ -19,545 +19,1023 @@
 #include <xen/sched.h>
 #include <xen/multiboot.h>
 #include <xsm/xsm-core.h>
-
-#ifdef CONFIG_XSM
+#include <xsm/dummy.h>
+#include <public/version.h>
 
 extern struct xsm_ops xsm_ops;
 
-static inline void xsm_security_domaininfo (struct domain *d,
-                                        struct xen_domctl_getdomaininfo *info)
+static inline void xsm_security_domaininfo(
+    struct domain *d,
+    struct xen_domctl_getdomaininfo *info)
 {
-    alternative_vcall(xsm_ops.security_domaininfo, d, info);
+    if ( xsm_ops.security_domaininfo )
+        alternative_vcall(xsm_ops.security_domaininfo, d, info);
 }
 
-static inline int xsm_domain_create (xsm_default_t def, struct domain *d, u32 ssidref)
+static inline int xsm_domain_create(xsm_default_t action, struct domain *d,
+                                    u32 ssidref)
 {
-    return alternative_call(xsm_ops.domain_create, d, ssidref);
+    if ( xsm_ops.domain_create )
+        return alternative_call(xsm_ops.domain_create, d, ssidref);
+
+    XSM_ASSERT_ACTION(XSM_HOOK);
+    return xsm_default_action(action, current->domain, d);
 }
 
-static inline int xsm_getdomaininfo (xsm_default_t def, struct domain *d)
+static inline int xsm_getdomaininfo(xsm_default_t action, struct domain *d)
 {
-    return alternative_call(xsm_ops.getdomaininfo, d);
+    if ( xsm_ops.getdomaininfo )
+        return alternative_call(xsm_ops.getdomaininfo, d);
+
+    XSM_ASSERT_ACTION(XSM_HOOK);
+    return xsm_default_action(action, current->domain, d);
 }
 
-static inline int xsm_domctl_scheduler_op (xsm_default_t def, struct domain *d, int cmd)
+static inline int xsm_domctl_scheduler_op(xsm_default_t action, struct domain *d,
+                                          int cmd)
 {
-    return alternative_call(xsm_ops.domctl_scheduler_op, d, cmd);
+    if ( xsm_ops.domctl_scheduler_op )
+        return alternative_call(xsm_ops.domctl_scheduler_op, d, cmd);
+
+    XSM_ASSERT_ACTION(XSM_HOOK);
+    return xsm_default_action(action, current->domain, d);
 }
 
-static inline int xsm_sysctl_scheduler_op (xsm_default_t def, int cmd)
+static inline int xsm_sysctl_scheduler_op(xsm_default_t action, int cmd)
 {
-    return alternative_call(xsm_ops.sysctl_scheduler_op, cmd);
+    if ( xsm_ops.sysctl_scheduler_op )
+        return alternative_call(xsm_ops.sysctl_scheduler_op, cmd);
+
+    XSM_ASSERT_ACTION(XSM_HOOK);
+    return xsm_default_action(action, current->domain, NULL);
 }
 
-static inline int xsm_set_target (xsm_default_t def, struct domain *d, struct domain *e)
+static inline int xsm_set_target(xsm_default_t action, struct domain *d,
+                                 struct domain *e)
 {
-    return alternative_call(xsm_ops.set_target, d, e);
+    if ( xsm_ops.set_target )
+        return alternative_call(xsm_ops.set_target, d, e);
+
+    XSM_ASSERT_ACTION(XSM_HOOK);
+    return xsm_default_action(action, current->domain, NULL);
 }
 
-static inline int xsm_domctl (xsm_default_t def, struct domain *d, int cmd)
+static inline int xsm_domctl(xsm_default_t action, struct domain *d, int cmd)
 {
-    return alternative_call(xsm_ops.domctl, d, cmd);
+    if ( xsm_ops.domctl )
+        return alternative_call(xsm_ops.domctl, d, 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);
+    case XEN_DOMCTL_getdomaininfo:
+        return xsm_default_action(XSM_XS_PRIV, current->domain, d);
+    default:
+        return xsm_default_action(XSM_PRIV, current->domain, d);
+    }
 }
 
-static inline int xsm_sysctl (xsm_default_t def, int cmd)
+static inline int xsm_sysctl(xsm_default_t action, int cmd)
 {
-    return alternative_call(xsm_ops.sysctl, cmd);
+    if ( xsm_ops.sysctl )
+        return alternative_call(xsm_ops.sysctl, cmd);
+
+    XSM_ASSERT_ACTION(XSM_PRIV);
+    return xsm_default_action(action, current->domain, NULL);
 }
 
-static inline int xsm_readconsole (xsm_default_t def, uint32_t clear)
+static inline int xsm_readconsole(xsm_default_t action, uint32_t clear)
 {
-    return alternative_call(xsm_ops.readconsole, clear);
+    if ( xsm_ops.readconsole )
+        return alternative_call(xsm_ops.readconsole, clear);
+
+    XSM_ASSERT_ACTION(XSM_HOOK);
+    return xsm_default_action(action, current->domain, NULL);
 }
 
-static inline int xsm_evtchn_unbound (xsm_default_t def, struct domain *d1, struct evtchn *chn,
-                                                                    domid_t id2)
+static inline int xsm_evtchn_unbound(xsm_default_t action, struct domain *d1,
+                                     struct evtchn *chn, domid_t id2)
 {
-    return alternative_call(xsm_ops.evtchn_unbound, d1, chn, id2);
+    if ( xsm_ops.evtchn_unbound )
+        return alternative_call(xsm_ops.evtchn_unbound, d1, chn, id2);
+
+    XSM_ASSERT_ACTION(XSM_TARGET);
+    return xsm_default_action(action, current->domain, d1);
 }
 
-static inline int xsm_evtchn_interdomain (xsm_default_t def, struct domain *d1,
-                struct evtchn *chan1, struct domain *d2, struct evtchn *chan2)
+static inline int xsm_evtchn_interdomain(xsm_default_t action,
+                                         struct domain *d1,
+                                         struct evtchn *chan1,
+                                         struct domain *d2,
+                                         struct evtchn *chan2)
 {
-    return alternative_call(xsm_ops.evtchn_interdomain, d1, chan1, d2, chan2);
+    if ( xsm_ops.evtchn_interdomain )
+        return alternative_call(xsm_ops.evtchn_interdomain, d1, chan1, d2,
+                                chan2);
+
+    XSM_ASSERT_ACTION(XSM_HOOK);
+    return xsm_default_action(action, d1, d2);
 }
 
-static inline void xsm_evtchn_close_post (struct evtchn *chn)
+static inline void xsm_evtchn_close_post(struct evtchn *chn)
 {
-    alternative_vcall(xsm_ops.evtchn_close_post, chn);
+    if ( xsm_ops.evtchn_close_post )
+        alternative_vcall(xsm_ops.evtchn_close_post, chn);
 }
 
-static inline int xsm_evtchn_send (xsm_default_t def, struct domain *d, struct evtchn *chn)
+static inline int xsm_evtchn_send(xsm_default_t action, struct domain *d,
+                                  struct evtchn *chn)
 {
-    return alternative_call(xsm_ops.evtchn_send, d, chn);
+    if ( xsm_ops.evtchn_send )
+        return alternative_call(xsm_ops.evtchn_send, d, chn);
+
+    XSM_ASSERT_ACTION(XSM_HOOK);
+    return xsm_default_action(action, d, NULL);
 }
 
-static inline int xsm_evtchn_status (xsm_default_t def, struct domain *d, struct evtchn *chn)
+static inline int xsm_evtchn_status(xsm_default_t action, struct domain *d,
+                                    struct evtchn *chn)
 {
-    return alternative_call(xsm_ops.evtchn_status, d, chn);
+    if ( xsm_ops.evtchn_status )
+        return alternative_call(xsm_ops.evtchn_status, d, chn);
+
+    XSM_ASSERT_ACTION(XSM_TARGET);
+    return xsm_default_action(action, current->domain, d);
 }
 
-static inline int xsm_evtchn_reset (xsm_default_t def, struct domain *d1, struct domain *d2)
+static inline int xsm_evtchn_reset(xsm_default_t action, struct domain *d1,
+                                   struct domain *d2)
 {
-    return alternative_call(xsm_ops.evtchn_reset, d1, d2);
+    if ( xsm_ops.evtchn_reset )
+        return alternative_call(xsm_ops.evtchn_reset, d1, d2);
+
+    XSM_ASSERT_ACTION(XSM_TARGET);
+    return xsm_default_action(action, d1, d2);
 }
 
-static inline int xsm_grant_mapref (xsm_default_t def, struct domain *d1, struct domain *d2,
-                                                                uint32_t flags)
+static inline int xsm_grant_mapref(xsm_default_t action, struct domain *d1,
+                                   struct domain *d2, uint32_t flags)
 {
-    return alternative_call(xsm_ops.grant_mapref, d1, d2, flags);
+    if ( xsm_ops.grant_mapref )
+        return alternative_call(xsm_ops.grant_mapref, d1, d2, flags);
+
+    XSM_ASSERT_ACTION(XSM_HOOK);
+    return xsm_default_action(action, d1, d2);
 }
 
-static inline int xsm_grant_unmapref (xsm_default_t def, struct domain *d1, struct domain *d2)
+static inline int xsm_grant_unmapref(xsm_default_t action, struct domain *d1,
+                                     struct domain *d2)
 {
-    return alternative_call(xsm_ops.grant_unmapref, d1, d2);
+    if ( xsm_ops.grant_unmapref )
+        return alternative_call(xsm_ops.grant_unmapref, d1, d2);
+
+    XSM_ASSERT_ACTION(XSM_HOOK);
+    return xsm_default_action(action, d1, d2);
 }
 
-static inline int xsm_grant_setup (xsm_default_t def, struct domain *d1, struct domain *d2)
+static inline int xsm_grant_setup(xsm_default_t action, struct domain *d1,
+                                  struct domain *d2)
 {
-    return alternative_call(xsm_ops.grant_setup, d1, d2);
+    if ( xsm_ops.grant_setup )
+        return alternative_call(xsm_ops.grant_setup, d1, d2);
+
+    XSM_ASSERT_ACTION(XSM_TARGET);
+    return xsm_default_action(action, d1, d2);
 }
 
-static inline int xsm_grant_transfer (xsm_default_t def, struct domain *d1, struct domain *d2)
+static inline int xsm_grant_transfer(xsm_default_t action, struct domain *d1,
+                                     struct domain *d2)
 {
-    return alternative_call(xsm_ops.grant_transfer, d1, d2);
+    if ( xsm_ops.grant_transfer )
+        return alternative_call(xsm_ops.grant_transfer, d1, d2);
+
+    XSM_ASSERT_ACTION(XSM_HOOK);
+    return xsm_default_action(action, d1, d2);
 }
 
-static inline int xsm_grant_copy (xsm_default_t def, struct domain *d1, struct domain *d2)
+static inline int xsm_grant_copy(xsm_default_t action, struct domain *d1,
+                                 struct domain *d2)
 {
-    return alternative_call(xsm_ops.grant_copy, d1, d2);
+    if ( xsm_ops.grant_copy )
+        return alternative_call(xsm_ops.grant_copy, d1, d2);
+
+    XSM_ASSERT_ACTION(XSM_HOOK);
+    return xsm_default_action(action, d1, d2);
 }
 
-static inline int xsm_grant_query_size (xsm_default_t def, struct domain *d1, struct domain *d2)
+static inline int xsm_grant_query_size(xsm_default_t action, struct domain *d1,
+                                       struct domain *d2)
 {
-    return alternative_call(xsm_ops.grant_query_size, d1, d2);
+    if ( xsm_ops.grant_query_size )
+        return alternative_call(xsm_ops.grant_query_size, d1, d2);
+
+    XSM_ASSERT_ACTION(XSM_TARGET);
+    return xsm_default_action(action, d1, d2);
 }
 
-static inline int xsm_alloc_security_domain (struct domain *d)
+static inline int xsm_alloc_security_domain(struct domain *d)
 {
-    return alternative_call(xsm_ops.alloc_security_domain, d);
+    if ( xsm_ops.alloc_security_domain )
+        return alternative_call(xsm_ops.alloc_security_domain, d);
+
+    return 0;
 }
 
-static inline void xsm_free_security_domain (struct domain *d)
+static inline void xsm_free_security_domain(struct domain *d)
 {
-    alternative_vcall(xsm_ops.free_security_domain, d);
+    if ( xsm_ops.free_security_domain )
+        alternative_vcall(xsm_ops.free_security_domain, d);
 }
 
-static inline int xsm_alloc_security_evtchns(
-    struct evtchn chn[], unsigned int nr)
+static inline int xsm_alloc_security_evtchns(struct evtchn chn[],
+                                             unsigned int nr)
 {
-    return alternative_call(xsm_ops.alloc_security_evtchns, chn, nr);
+    if ( xsm_ops.alloc_security_evtchns )
+        return alternative_call(xsm_ops.alloc_security_evtchns, chn, nr);
+
+    return 0;
 }
 
-static inline void xsm_free_security_evtchns(
-    struct evtchn chn[], unsigned int nr)
+static inline void xsm_free_security_evtchns(struct evtchn chn[],
+                                             unsigned int nr)
 {
-    alternative_vcall(xsm_ops.free_security_evtchns, chn, nr);
+    if ( xsm_ops.free_security_evtchns )
+        alternative_vcall(xsm_ops.free_security_evtchns, chn, nr);
 }
 
-static inline char *xsm_show_security_evtchn (struct domain *d, const struct evtchn *chn)
+static inline char *xsm_show_security_evtchn(struct domain *d,
+                                             const struct evtchn *chn)
 {
-    return alternative_call(xsm_ops.show_security_evtchn, d, chn);
+    if ( xsm_ops.show_security_evtchn )
+        return alternative_call(xsm_ops.show_security_evtchn, d, chn);
+
+    return NULL;
 }
 
-static inline int xsm_init_hardware_domain (xsm_default_t def, struct domain *d)
+static inline int xsm_init_hardware_domain(xsm_default_t action, struct domain *d)
 {
-    return alternative_call(xsm_ops.init_hardware_domain, d);
+    if ( xsm_ops.init_hardware_domain )
+        return alternative_call(xsm_ops.init_hardware_domain, d);
+
+    XSM_ASSERT_ACTION(XSM_HOOK);
+    return xsm_default_action(action, current->domain, d);
 }
 
-static inline int xsm_get_pod_target (xsm_default_t def, struct domain *d)
+static inline int xsm_get_pod_target(xsm_default_t action, struct domain *d)
 {
-    return alternative_call(xsm_ops.get_pod_target, d);
+    if ( xsm_ops.get_pod_target )
+        return alternative_call(xsm_ops.get_pod_target, d);
+
+    XSM_ASSERT_ACTION(XSM_PRIV);
+    return xsm_default_action(action, current->domain, d);
 }
 
-static inline int xsm_set_pod_target (xsm_default_t def, struct domain *d)
+static inline int xsm_set_pod_target(xsm_default_t action, struct domain *d)
 {
-    return alternative_call(xsm_ops.set_pod_target, d);
+    if ( xsm_ops.set_pod_target )
+        return alternative_call(xsm_ops.set_pod_target, d);
+
+    XSM_ASSERT_ACTION(XSM_PRIV);
+    return xsm_default_action(action, current->domain, d);
 }
 
-static inline int xsm_memory_exchange (xsm_default_t def, struct domain *d)
+static inline int xsm_memory_exchange(xsm_default_t action, struct domain *d)
 {
-    return alternative_call(xsm_ops.memory_exchange, d);
+    if ( xsm_ops.memory_exchange )
+        return alternative_call(xsm_ops.memory_exchange, d);
+
+    XSM_ASSERT_ACTION(XSM_TARGET);
+    return xsm_default_action(action, current->domain, d);
 }
 
-static inline int xsm_memory_adjust_reservation (xsm_default_t def, struct domain *d1, struct
-                                                                    domain *d2)
+static inline int xsm_memory_adjust_reservation(xsm_default_t action,
+                                                struct domain *d1,
+                                                struct domain *d2)
 {
-    return alternative_call(xsm_ops.memory_adjust_reservation, d1, d2);
+    if ( xsm_ops.memory_adjust_reservation )
+        return alternative_call(xsm_ops.memory_adjust_reservation, d1, d2);
+
+    XSM_ASSERT_ACTION(XSM_TARGET);
+    return xsm_default_action(action, d1, d2);
 }
 
-static inline int xsm_memory_stat_reservation (xsm_default_t def, struct domain *d1,
-                                                            struct domain *d2)
+static inline int xsm_memory_stat_reservation(xsm_default_t action,
+                                              struct domain *d1,
+                                              struct domain *d2)
 {
-    return alternative_call(xsm_ops.memory_stat_reservation, d1, d2);
+    if ( xsm_ops.memory_stat_reservation )
+        return alternative_call(xsm_ops.memory_stat_reservation, d1, d2);
+
+    XSM_ASSERT_ACTION(XSM_TARGET);
+    return xsm_default_action(action, d1, d2);
 }
 
-static inline int xsm_memory_pin_page(xsm_default_t def, struct domain *d1, struct domain *d2,
-                                      struct page_info *page)
+static inline int xsm_memory_pin_page(xsm_default_t action, struct domain *d1,
+                                      struct domain *d2, struct page_info *page)
 {
-    return alternative_call(xsm_ops.memory_pin_page, d1, d2, page);
+    if ( xsm_ops.memory_pin_page )
+        return alternative_call(xsm_ops.memory_pin_page, d1, d2, page);
+
+    XSM_ASSERT_ACTION(XSM_HOOK);
+    return xsm_default_action(action, d1, d2);
 }
 
-static inline int xsm_add_to_physmap(xsm_default_t def, struct domain *d1, struct domain *d2)
+static inline int xsm_add_to_physmap(xsm_default_t action, struct domain *d1,
+                                     struct domain *d2)
 {
-    return alternative_call(xsm_ops.add_to_physmap, d1, d2);
+    if ( xsm_ops.add_to_physmap )
+        return alternative_call(xsm_ops.add_to_physmap, d1, d2);
+
+    XSM_ASSERT_ACTION(XSM_TARGET);
+    return xsm_default_action(action, d1, d2);
 }
 
-static inline int xsm_remove_from_physmap(xsm_default_t def, struct domain *d1, struct domain *d2)
+static inline int xsm_remove_from_physmap(xsm_default_t action, struct domain *d1,
+                                          struct domain *d2)
 {
-    return alternative_call(xsm_ops.remove_from_physmap, d1, d2);
+    if ( xsm_ops.remove_from_physmap )
+        return alternative_call(xsm_ops.remove_from_physmap, d1, d2);
+
+    XSM_ASSERT_ACTION(XSM_TARGET);
+    return xsm_default_action(action, d1, d2);
 }
 
-static inline int xsm_map_gmfn_foreign (xsm_default_t def, struct domain *d, struct domain *t)
+static inline int xsm_map_gmfn_foreign(xsm_default_t action, struct domain *d,
+                                       struct domain *t)
 {
-    return alternative_call(xsm_ops.map_gmfn_foreign, d, t);
+    if ( xsm_ops.map_gmfn_foreign )
+        return alternative_call(xsm_ops.map_gmfn_foreign, d, t);
+
+    XSM_ASSERT_ACTION(XSM_TARGET);
+    return xsm_default_action(action, d, t);
 }
 
-static inline int xsm_claim_pages(xsm_default_t def, struct domain *d)
+static inline int xsm_claim_pages(xsm_default_t action, struct domain *d)
 {
-    return alternative_call(xsm_ops.claim_pages, d);
+    if ( xsm_ops.claim_pages )
+        return alternative_call(xsm_ops.claim_pages, d);
+
+    XSM_ASSERT_ACTION(XSM_PRIV);
+    return xsm_default_action(action, current->domain, d);
 }
 
-static inline int xsm_console_io (xsm_default_t def, struct domain *d, int cmd)
+static inline int xsm_console_io(xsm_default_t action, struct domain *d, int cmd)
 {
-    return alternative_call(xsm_ops.console_io, d, cmd);
+    if ( xsm_ops.console_io )
+        return alternative_call(xsm_ops.console_io, d, cmd);
+
+    XSM_ASSERT_ACTION(XSM_OTHER);
+    if ( d->is_console )
+        return xsm_default_action(XSM_HOOK, d, NULL);
+#ifdef CONFIG_VERBOSE_DEBUG
+    if ( cmd == CONSOLEIO_write )
+        return xsm_default_action(XSM_HOOK, d, NULL);
+#endif
+    return xsm_default_action(XSM_PRIV, d, NULL);
 }
 
-static inline int xsm_profile (xsm_default_t def, struct domain *d, int op)
+static inline int xsm_profile(xsm_default_t action, struct domain *d, int op)
 {
-    return alternative_call(xsm_ops.profile, d, op);
+    if ( xsm_ops.profile )
+        return alternative_call(xsm_ops.profile, d, op);
+
+    XSM_ASSERT_ACTION(XSM_HOOK);
+    return xsm_default_action(action, d, NULL);
 }
 
-static inline int xsm_kexec (xsm_default_t def)
+static inline int xsm_kexec (xsm_default_t action)
 {
-    return alternative_call(xsm_ops.kexec);
+    if ( xsm_ops.kexec )
+        return alternative_call(xsm_ops.kexec);
+
+    XSM_ASSERT_ACTION(XSM_PRIV);
+    return xsm_default_action(action, current->domain, NULL);
 }
 
-static inline int xsm_schedop_shutdown (xsm_default_t def, struct domain *d1, struct domain *d2)
+static inline int xsm_schedop_shutdown(xsm_default_t action, struct domain *d1,
+                                       struct domain *d2)
 {
-    return alternative_call(xsm_ops.schedop_shutdown, d1, d2);
+    if ( xsm_ops.schedop_shutdown )
+        return alternative_call(xsm_ops.schedop_shutdown, d1, d2);
+
+    XSM_ASSERT_ACTION(XSM_DM_PRIV);
+    return xsm_default_action(action, d1, d2);
 }
 
-static inline char *xsm_show_irq_sid (int irq)
+static inline char *xsm_show_irq_sid(int irq)
 {
-    return alternative_call(xsm_ops.show_irq_sid, irq);
+    if ( xsm_ops.show_irq_sid )
+        return alternative_call(xsm_ops.show_irq_sid, irq);
+
+    return NULL;
 }
 
-static inline int xsm_map_domain_pirq (xsm_default_t def, struct domain *d)
+static inline int xsm_map_domain_pirq(xsm_default_t action, struct domain *d)
 {
-    return alternative_call(xsm_ops.map_domain_pirq, d);
+    if ( xsm_ops.map_domain_pirq )
+        return alternative_call(xsm_ops.map_domain_pirq, d);
+
+    XSM_ASSERT_ACTION(XSM_DM_PRIV);
+    return xsm_default_action(action, current->domain, d);
 }
 
-static inline int xsm_map_domain_irq (xsm_default_t def, struct domain *d, int irq, void *data)
+static inline int xsm_map_domain_irq(xsm_default_t action, struct domain *d,
+                                     int irq, void *data)
 {
-    return alternative_call(xsm_ops.map_domain_irq, d, irq, data);
+    if ( xsm_ops.map_domain_irq )
+        return alternative_call(xsm_ops.map_domain_irq, d, irq, data);
+
+    XSM_ASSERT_ACTION(XSM_HOOK);
+    return xsm_default_action(action, current->domain, d);
 }
 
-static inline int xsm_unmap_domain_pirq (xsm_default_t def, struct domain *d)
+static inline int xsm_unmap_domain_pirq(xsm_default_t action, struct domain *d)
 {
-    return alternative_call(xsm_ops.unmap_domain_pirq, d);
+    if ( xsm_ops.unmap_domain_pirq )
+        return alternative_call(xsm_ops.unmap_domain_pirq, d);
+
+    XSM_ASSERT_ACTION(XSM_DM_PRIV);
+    return xsm_default_action(action, current->domain, d);
 }
 
-static inline int xsm_unmap_domain_irq (xsm_default_t def, struct domain *d, int irq, void *data)
+static inline int xsm_unmap_domain_irq(xsm_default_t action, struct domain *d,
+                                       int irq, void *data)
 {
-    return alternative_call(xsm_ops.unmap_domain_irq, d, irq, data);
+    if ( xsm_ops.unmap_domain_irq )
+        return alternative_call(xsm_ops.unmap_domain_irq, d, irq, data);
+
+    XSM_ASSERT_ACTION(XSM_HOOK);
+    return xsm_default_action(action, current->domain, d);
 }
 
-static inline int xsm_bind_pt_irq(xsm_default_t def, struct domain *d,
+static inline int xsm_bind_pt_irq(xsm_default_t action, struct domain *d,
                                   struct xen_domctl_bind_pt_irq *bind)
 {
-    return alternative_call(xsm_ops.bind_pt_irq, d, bind);
+    if ( xsm_ops.bind_pt_irq )
+        return alternative_call(xsm_ops.bind_pt_irq, d, bind);
+
+    XSM_ASSERT_ACTION(XSM_HOOK);
+    return xsm_default_action(action, current->domain, d);
 }
 
-static inline int xsm_unbind_pt_irq(xsm_default_t def, struct domain *d,
+static inline int xsm_unbind_pt_irq(xsm_default_t action, struct domain *d,
                                     struct xen_domctl_bind_pt_irq *bind)
 {
-    return alternative_call(xsm_ops.unbind_pt_irq, d, bind);
+    if ( xsm_ops.unbind_pt_irq )
+        return alternative_call(xsm_ops.unbind_pt_irq, d, bind);
+
+    XSM_ASSERT_ACTION(XSM_HOOK);
+    return xsm_default_action(action, current->domain, d);
 }
 
-static inline int xsm_irq_permission (xsm_default_t def, struct domain *d, int pirq, uint8_t allow)
+static inline int xsm_irq_permission(xsm_default_t action, struct domain *d,
+                                     int pirq, uint8_t allow)
 {
-    return alternative_call(xsm_ops.irq_permission, d, pirq, allow);
+    if ( xsm_ops.irq_permission )
+        return alternative_call(xsm_ops.irq_permission, d, pirq, allow);
+
+    XSM_ASSERT_ACTION(XSM_HOOK);
+    return xsm_default_action(action, current->domain, d);
 }
 
-static inline int xsm_iomem_permission (xsm_default_t def, struct domain *d, uint64_t s, uint64_t e, uint8_t allow)
+static inline int xsm_iomem_permission(xsm_default_t action, struct domain *d,
+                                       uint64_t s, uint64_t e, uint8_t allow)
 {
-    return alternative_call(xsm_ops.iomem_permission, d, s, e, allow);
+    if ( xsm_ops.iomem_permission )
+        return alternative_call(xsm_ops.iomem_permission, d, s, e, allow);
+
+    XSM_ASSERT_ACTION(XSM_HOOK);
+    return xsm_default_action(action, current->domain, d);
 }
 
-static inline int xsm_iomem_mapping (xsm_default_t def, struct domain *d, uint64_t s, uint64_t e, uint8_t allow)
+static inline int xsm_iomem_mapping(xsm_default_t action, struct domain *d,
+                                    uint64_t s, uint64_t e, uint8_t allow)
 {
-    return alternative_call(xsm_ops.iomem_mapping, d, s, e, allow);
+    if ( xsm_ops.iomem_mapping )
+        return alternative_call(xsm_ops.iomem_mapping, d, s, e, allow);
+
+    XSM_ASSERT_ACTION(XSM_HOOK);
+    return xsm_default_action(action, current->domain, d);
 }
 
-static inline int xsm_pci_config_permission (xsm_default_t def, struct domain *d, uint32_t machine_bdf, uint16_t start, uint16_t end, uint8_t access)
+static inline int xsm_pci_config_permission(xsm_default_t action,
+                                            struct domain *d,
+                                            uint32_t machine_bdf,
+                                            uint16_t start,
+                                            uint16_t end,
+                                            uint8_t access)
 {
-    return alternative_call(xsm_ops.pci_config_permission, d, machine_bdf, start, end, access);
+    if ( xsm_ops.pci_config_permission )
+        return alternative_call(xsm_ops.pci_config_permission, d, machine_bdf, start, end, access);
+
+    XSM_ASSERT_ACTION(XSM_HOOK);
+    return xsm_default_action(action, current->domain, d);
 }
 
 #if defined(CONFIG_HAS_PASSTHROUGH) && defined(CONFIG_HAS_PCI)
-static inline int xsm_get_device_group(xsm_default_t def, uint32_t machine_bdf)
+static inline int xsm_get_device_group(xsm_default_t action, uint32_t machine_bdf)
 {
-    return alternative_call(xsm_ops.get_device_group, machine_bdf);
+    if ( xsm_ops.get_device_group )
+        return alternative_call(xsm_ops.get_device_group, machine_bdf);
+
+    XSM_ASSERT_ACTION(XSM_HOOK);
+    return xsm_default_action(action, current->domain, NULL);
 }
 
-static inline int xsm_assign_device(xsm_default_t def, struct domain *d, uint32_t machine_bdf)
+static inline int xsm_assign_device(xsm_default_t action, struct domain *d,
+                                    uint32_t machine_bdf)
 {
-    return alternative_call(xsm_ops.assign_device, d, machine_bdf);
+    if ( xsm_ops.assign_device )
+        return alternative_call(xsm_ops.assign_device, d, machine_bdf);
+
+    XSM_ASSERT_ACTION(XSM_HOOK);
+    return xsm_default_action(action, current->domain, d);
 }
 
-static inline int xsm_deassign_device(xsm_default_t def, struct domain *d, uint32_t machine_bdf)
+static inline int xsm_deassign_device(xsm_default_t action, struct domain *d,
+                                      uint32_t machine_bdf)
 {
-    return alternative_call(xsm_ops.deassign_device, d, machine_bdf);
+    if ( xsm_ops.deassign_device )
+        return alternative_call(xsm_ops.deassign_device, d, machine_bdf);
+
+    XSM_ASSERT_ACTION(XSM_HOOK);
+    return xsm_default_action(action, current->domain, d);
 }
 #endif /* HAS_PASSTHROUGH && HAS_PCI) */
 
 #if defined(CONFIG_HAS_PASSTHROUGH) && defined(CONFIG_HAS_DEVICE_TREE)
-static inline int xsm_assign_dtdevice(xsm_default_t def, struct domain *d,
+static inline int xsm_assign_dtdevice(xsm_default_t action, struct domain *d,
                                       const char *dtpath)
 {
-    return alternative_call(xsm_ops.assign_dtdevice, d, dtpath);
+    if ( xsm_ops.assign_dtdevice )
+        return alternative_call(xsm_ops.assign_dtdevice, d, dtpath);
+
+    XSM_ASSERT_ACTION(XSM_HOOK);
+    return xsm_default_action(action, current->domain, d);
 }
 
-static inline int xsm_deassign_dtdevice(xsm_default_t def, struct domain *d,
+static inline int xsm_deassign_dtdevice(xsm_default_t action, struct domain *d,
                                         const char *dtpath)
 {
-    return alternative_call(xsm_ops.deassign_dtdevice, d, dtpath);
+    if ( xsm_ops.deassign_dtdevice )
+        return alternative_call(xsm_ops.deassign_dtdevice, d, dtpath);
+
+    XSM_ASSERT_ACTION(XSM_HOOK);
+    return xsm_default_action(action, current->domain, d);
 }
 
 #endif /* HAS_PASSTHROUGH && HAS_DEVICE_TREE */
 
-static inline int xsm_resource_plug_pci (xsm_default_t def, uint32_t machine_bdf)
+static inline int xsm_resource_plug_pci(xsm_default_t action, uint32_t machine_bdf)
 {
-    return alternative_call(xsm_ops.resource_plug_pci, machine_bdf);
+    if ( xsm_ops.resource_plug_pci )
+        return alternative_call(xsm_ops.resource_plug_pci, machine_bdf);
+
+    XSM_ASSERT_ACTION(XSM_PRIV);
+    return xsm_default_action(action, current->domain, NULL);
 }
 
-static inline int xsm_resource_unplug_pci (xsm_default_t def, uint32_t machine_bdf)
+static inline int xsm_resource_unplug_pci(xsm_default_t action,
+                                           uint32_t machine_bdf)
 {
-    return alternative_call(xsm_ops.resource_unplug_pci, machine_bdf);
+    if ( xsm_ops.resource_unplug_pci )
+        return alternative_call(xsm_ops.resource_unplug_pci, machine_bdf);
+
+    XSM_ASSERT_ACTION(XSM_PRIV);
+    return xsm_default_action(action, current->domain, NULL);
 }
 
-static inline int xsm_resource_plug_core (xsm_default_t def)
+static inline int xsm_resource_plug_core(xsm_default_t action)
 {
-    return alternative_call(xsm_ops.resource_plug_core);
+    if ( xsm_ops.resource_plug_core )
+        return alternative_call(xsm_ops.resource_plug_core);
+
+    XSM_ASSERT_ACTION(XSM_HOOK);
+    return xsm_default_action(action, current->domain, NULL);
 }
 
-static inline int xsm_resource_unplug_core (xsm_default_t def)
+static inline int xsm_resource_unplug_core(xsm_default_t action)
 {
-    return alternative_call(xsm_ops.resource_unplug_core);
+    if ( xsm_ops.resource_unplug_core )
+        return alternative_call(xsm_ops.resource_unplug_core);
+
+    XSM_ASSERT_ACTION(XSM_HOOK);
+    return xsm_default_action(action, current->domain, NULL);
 }
 
-static inline int xsm_resource_setup_pci (xsm_default_t def, uint32_t machine_bdf)
+static inline int xsm_resource_setup_pci(xsm_default_t action,
+                                         uint32_t machine_bdf)
 {
-    return alternative_call(xsm_ops.resource_setup_pci, machine_bdf);
+    if ( xsm_ops.resource_setup_pci )
+        return alternative_call(xsm_ops.resource_setup_pci, machine_bdf);
+
+    XSM_ASSERT_ACTION(XSM_PRIV);
+    return xsm_default_action(action, current->domain, NULL);
 }
 
-static inline int xsm_resource_setup_gsi (xsm_default_t def, int gsi)
+static inline int xsm_resource_setup_gsi(xsm_default_t action, int gsi)
 {
-    return alternative_call(xsm_ops.resource_setup_gsi, gsi);
+    if ( xsm_ops.resource_setup_gsi )
+        return alternative_call(xsm_ops.resource_setup_gsi, gsi);
+
+    XSM_ASSERT_ACTION(XSM_PRIV);
+    return xsm_default_action(action, current->domain, NULL);
 }
 
-static inline int xsm_resource_setup_misc (xsm_default_t def)
+static inline int xsm_resource_setup_misc (xsm_default_t action)
 {
-    return alternative_call(xsm_ops.resource_setup_misc);
+    if ( xsm_ops.resource_setup_misc )
+        return alternative_call(xsm_ops.resource_setup_misc);
+
+    XSM_ASSERT_ACTION(XSM_PRIV);
+    return xsm_default_action(action, current->domain, NULL);
 }
 
-static inline int xsm_page_offline(xsm_default_t def, uint32_t cmd)
+static inline int xsm_page_offline(xsm_default_t action, uint32_t cmd)
 {
-    return alternative_call(xsm_ops.page_offline, cmd);
+    if ( xsm_ops.page_offline )
+        return alternative_call(xsm_ops.page_offline, cmd);
+
+    XSM_ASSERT_ACTION(XSM_HOOK);
+    return xsm_default_action(action, current->domain, NULL);
 }
 
-static inline int xsm_hypfs_op(xsm_default_t def)
+static inline int xsm_hypfs_op(xsm_default_t action)
 {
-    return alternative_call(xsm_ops.hypfs_op);
+    if ( xsm_ops.hypfs_op )
+        return alternative_call(xsm_ops.hypfs_op);
+
+    XSM_ASSERT_ACTION(XSM_PRIV);
+    return xsm_default_action(action, current->domain, NULL);
 }
 
-static inline long xsm_do_xsm_op (XEN_GUEST_HANDLE_PARAM(xsm_op_t) op)
+static inline long xsm_do_xsm_op(XEN_GUEST_HANDLE_PARAM(xsm_op_t) op)
 {
-    return xsm_ops.do_xsm_op(op);
+    if ( xsm_ops.do_xsm_op )
+        return xsm_ops.do_xsm_op(op);
+
+    return -ENOSYS;
 }
 
 #ifdef CONFIG_COMPAT
-static inline int xsm_do_compat_op (XEN_GUEST_HANDLE_PARAM(xsm_op_t) op)
+static inline int xsm_do_compat_op(XEN_GUEST_HANDLE_PARAM(xsm_op_t) op)
 {
-    return xsm_ops.do_compat_op(op);
+    if ( xsm_ops.do_compat_op )
+        return xsm_ops.do_compat_op(op);
+
+    return -ENOSYS;
 }
 #endif
 
-static inline int xsm_hvm_param (xsm_default_t def, struct domain *d, unsigned long op)
+static inline int xsm_hvm_param(xsm_default_t action, struct domain *d,
+                                unsigned long op)
 {
-    return alternative_call(xsm_ops.hvm_param, d, op);
+    if ( xsm_ops.hvm_param )
+        return alternative_call(xsm_ops.hvm_param, d, op);
+
+    XSM_ASSERT_ACTION(XSM_TARGET);
+    return xsm_default_action(action, current->domain, d);
 }
 
-static inline int xsm_hvm_control(xsm_default_t def, struct domain *d, unsigned long op)
+static inline int xsm_hvm_control(xsm_default_t action, struct domain *d,
+                                  unsigned long op)
 {
-    return alternative_call(xsm_ops.hvm_control, d, op);
+    if ( xsm_ops.hvm_control )
+        return alternative_call(xsm_ops.hvm_control, d, op);
+
+    XSM_ASSERT_ACTION(XSM_DM_PRIV);
+    return xsm_default_action(action, current->domain, d);
 }
 
-static inline int xsm_hvm_param_altp2mhvm (xsm_default_t def, struct domain *d)
+static inline int xsm_hvm_param_altp2mhvm(xsm_default_t action, struct domain *d)
 {
-    return alternative_call(xsm_ops.hvm_param_altp2mhvm, d);
+    if ( xsm_ops.hvm_param_altp2mhvm )
+        return alternative_call(xsm_ops.hvm_param_altp2mhvm, d);
+
+    XSM_ASSERT_ACTION(XSM_PRIV);
+    return xsm_default_action(action, current->domain, d);
 }
 
-static inline int xsm_hvm_altp2mhvm_op (xsm_default_t def, struct domain *d, uint64_t mode, uint32_t op)
+static inline int xsm_hvm_altp2mhvm_op(xsm_default_t action, struct domain *d,
+                                       uint64_t mode, uint32_t op)
 {
-    return alternative_call(xsm_ops.hvm_altp2mhvm_op, d, mode, op);
+    if ( xsm_ops.hvm_altp2mhvm_op )
+        return alternative_call(xsm_ops.hvm_altp2mhvm_op, d, mode, op);
+
+    XSM_ASSERT_ACTION(XSM_OTHER);
+
+    switch ( mode )
+    {
+    case XEN_ALTP2M_mixed:
+        return xsm_default_action(XSM_TARGET, current->domain, d);
+    case XEN_ALTP2M_external:
+        return xsm_default_action(XSM_DM_PRIV, current->domain, d);
+    case XEN_ALTP2M_limited:
+        if ( HVMOP_altp2m_vcpu_enable_notify == op )
+            return xsm_default_action(XSM_TARGET, current->domain, d);
+        return xsm_default_action(XSM_DM_PRIV, current->domain, d);
+    default:
+        return -EPERM;
+    }
 }
 
-static inline int xsm_get_vnumainfo (xsm_default_t def, struct domain *d)
+static inline int xsm_get_vnumainfo(xsm_default_t action, struct domain *d)
 {
-    return alternative_call(xsm_ops.get_vnumainfo, d);
+    if ( xsm_ops.get_vnumainfo )
+        return alternative_call(xsm_ops.get_vnumainfo, d);
+
+    XSM_ASSERT_ACTION(XSM_TARGET);
+    return xsm_default_action(action, current->domain, d);
 }
 
-static inline int xsm_vm_event_control (xsm_default_t def, struct domain *d, int mode, int op)
+static inline int xsm_vm_event_control(xsm_default_t action, struct domain *d,
+                                       int mode, int op)
 {
-    return alternative_call(xsm_ops.vm_event_control, d, mode, op);
+    if ( xsm_ops.vm_event_control )
+        return alternative_call(xsm_ops.vm_event_control, d, mode, op);
+
+    XSM_ASSERT_ACTION(XSM_PRIV);
+    return xsm_default_action(action, current->domain, d);
 }
 
 #ifdef CONFIG_MEM_ACCESS
-static inline int xsm_mem_access (xsm_default_t def, struct domain *d)
+static inline int xsm_mem_access(xsm_default_t action, struct domain *d)
 {
-    return alternative_call(xsm_ops.mem_access, d);
+    if ( xsm_ops.mem_access )
+        return alternative_call(xsm_ops.mem_access, d);
+
+    XSM_ASSERT_ACTION(XSM_DM_PRIV);
+    return xsm_default_action(action, current->domain, d);
 }
 #endif
 
 #ifdef CONFIG_MEM_PAGING
-static inline int xsm_mem_paging (xsm_default_t def, struct domain *d)
+static inline int xsm_mem_paging(xsm_default_t action, struct domain *d)
 {
-    return alternative_call(xsm_ops.mem_paging, d);
+    if ( xsm_ops.mem_paging )
+        return alternative_call(xsm_ops.mem_paging, d);
+
+    XSM_ASSERT_ACTION(XSM_DM_PRIV);
+    return xsm_default_action(action, current->domain, d);
 }
 #endif
 
 #ifdef CONFIG_MEM_SHARING
-static inline int xsm_mem_sharing (xsm_default_t def, struct domain *d)
+static inline int xsm_mem_sharing(xsm_default_t action, struct domain *d)
 {
-    return alternative_call(xsm_ops.mem_sharing, d);
+    if ( xsm_ops.mem_sharing )
+        return alternative_call(xsm_ops.mem_sharing, d);
+
+    XSM_ASSERT_ACTION(XSM_DM_PRIV);
+    return xsm_default_action(action, current->domain, d);
 }
 #endif
 
-static inline int xsm_platform_op (xsm_default_t def, uint32_t op)
+static inline int xsm_platform_op(xsm_default_t action, uint32_t op)
 {
-    return alternative_call(xsm_ops.platform_op, op);
+    if ( xsm_ops.platform_op )
+        return alternative_call(xsm_ops.platform_op, op);
+
+    XSM_ASSERT_ACTION(XSM_PRIV);
+    return xsm_default_action(action, current->domain, NULL);
 }
 
 #ifdef CONFIG_X86
-static inline int xsm_do_mca(xsm_default_t def)
+static inline int xsm_do_mca(xsm_default_t action)
 {
-    return alternative_call(xsm_ops.do_mca);
+    if ( xsm_ops.do_mca )
+        return alternative_call(xsm_ops.do_mca);
+
+    XSM_ASSERT_ACTION(XSM_PRIV);
+    return xsm_default_action(action, current->domain, NULL);
 }
 
-static inline int xsm_shadow_control (xsm_default_t def, struct domain *d, uint32_t op)
+static inline int xsm_shadow_control(xsm_default_t action, struct domain *d,
+                                     uint32_t op)
 {
-    return alternative_call(xsm_ops.shadow_control, d, op);
+    if ( xsm_ops.shadow_control )
+        return alternative_call(xsm_ops.shadow_control, d, op);
+
+    XSM_ASSERT_ACTION(XSM_HOOK);
+    return xsm_default_action(action, current->domain, d);
 }
 
-static inline int xsm_mem_sharing_op (xsm_default_t def, struct domain *d, struct domain *cd, int op)
+static inline int xsm_mem_sharing_op(xsm_default_t action, struct domain *d,
+                                     struct domain *cd, int op)
 {
-    return alternative_call(xsm_ops.mem_sharing_op, d, cd, op);
+    if ( xsm_ops.mem_sharing_op )
+        return alternative_call(xsm_ops.mem_sharing_op, d, cd, op);
+
+    XSM_ASSERT_ACTION(XSM_DM_PRIV);
+    return xsm_default_action(action, current->domain, cd);
 }
 
-static inline int xsm_apic (xsm_default_t def, struct domain *d, int cmd)
+static inline int xsm_apic(xsm_default_t action, struct domain *d, int cmd)
 {
-    return alternative_call(xsm_ops.apic, d, cmd);
+    if ( xsm_ops.apic )
+        return alternative_call(xsm_ops.apic, d, cmd);
+
+    XSM_ASSERT_ACTION(XSM_PRIV);
+    return xsm_default_action(action, d, NULL);
 }
 
-static inline int xsm_memtype (xsm_default_t def, uint32_t access)
+/* No longer called */
+static inline int xsm_memtype(xsm_default_t action, uint32_t access)
 {
-    return alternative_call(xsm_ops.memtype, access);
+    if ( xsm_ops.memtype )
+        return alternative_call(xsm_ops.memtype, access);
 }
 
-static inline int xsm_machine_memory_map(xsm_default_t def)
+static inline int xsm_machine_memory_map(xsm_default_t action)
 {
-    return alternative_call(xsm_ops.machine_memory_map);
+    if ( xsm_ops.machine_memory_map )
+        return alternative_call(xsm_ops.machine_memory_map);
+
+    XSM_ASSERT_ACTION(XSM_PRIV);
+    return xsm_default_action(action, current->domain, NULL);
 }
 
-static inline int xsm_domain_memory_map(xsm_default_t def, struct domain *d)
+static inline int xsm_domain_memory_map(xsm_default_t action, struct domain *d)
 {
-    return alternative_call(xsm_ops.domain_memory_map, d);
+    if ( xsm_ops.domain_memory_map )
+        return alternative_call(xsm_ops.domain_memory_map, d);
+
+    XSM_ASSERT_ACTION(XSM_TARGET);
+    return xsm_default_action(action, current->domain, d);
 }
 
-static inline int xsm_mmu_update (xsm_default_t def, struct domain *d, struct domain *t,
-                                  struct domain *f, uint32_t flags)
+static inline int xsm_mmu_update(xsm_default_t action, struct domain *d,
+                                 struct domain *t, struct domain *f,
+                                 uint32_t flags)
 {
-    return alternative_call(xsm_ops.mmu_update, d, t, f, flags);
+    int rc = 0;
+
+    if ( xsm_ops.mmu_update )
+        return alternative_call(xsm_ops.mmu_update, d, t, f, flags);
+
+    XSM_ASSERT_ACTION(XSM_TARGET);
+    if ( f != dom_io )
+        rc = xsm_default_action(action, d, f);
+    if ( evaluate_nospec(t) && !rc )
+        rc = xsm_default_action(action, d, t);
+    return rc;
 }
 
-static inline int xsm_mmuext_op (xsm_default_t def, struct domain *d, struct domain *f)
+static inline int xsm_mmuext_op(xsm_default_t action, struct domain *d,
+                                struct domain *f)
 {
-    return alternative_call(xsm_ops.mmuext_op, d, f);
+    if ( xsm_ops.mmuext_op )
+        return alternative_call(xsm_ops.mmuext_op, d, f);
+
+    XSM_ASSERT_ACTION(XSM_TARGET);
+    return xsm_default_action(action, d, f);
 }
 
-static inline int xsm_update_va_mapping(xsm_default_t def, struct domain *d, struct domain *f,
-                                                            l1_pgentry_t pte)
+static inline int xsm_update_va_mapping(xsm_default_t action, struct domain *d,
+                                        struct domain *f, l1_pgentry_t pte)
 {
-    return xsm_ops.update_va_mapping(d, f, pte);
+    if ( xsm_ops.update_va_mapping )
+        return xsm_ops.update_va_mapping(d, f, pte);
+
+    XSM_ASSERT_ACTION(XSM_TARGET);
+    return xsm_default_action(action, d, f);
 }
 
-static inline int xsm_priv_mapping(xsm_default_t def, struct domain *d, struct domain *t)
+static inline int xsm_priv_mapping(xsm_default_t action, struct domain *d,
+                                   struct domain *t)
 {
-    return alternative_call(xsm_ops.priv_mapping, d, t);
+    if ( xsm_ops.priv_mapping )
+        return alternative_call(xsm_ops.priv_mapping, d, t);
+
+    XSM_ASSERT_ACTION(XSM_TARGET);
+    return xsm_default_action(action, d, t);
 }
 
-static inline int xsm_ioport_permission (xsm_default_t def, struct domain *d, uint32_t s, uint32_t e, uint8_t allow)
+static inline int xsm_ioport_permission(xsm_default_t action, struct domain *d,
+                                        uint32_t s, uint32_t e, uint8_t allow)
 {
-    return alternative_call(xsm_ops.ioport_permission, d, s, e, allow);
+    if ( xsm_ops.ioport_permission )
+        return alternative_call(xsm_ops.ioport_permission, d, s, e, allow);
+
+    XSM_ASSERT_ACTION(XSM_HOOK);
+    return xsm_default_action(action, current->domain, d);
 }
 
-static inline int xsm_ioport_mapping (xsm_default_t def, struct domain *d, uint32_t s, uint32_t e, uint8_t allow)
+static inline int xsm_ioport_mapping(xsm_default_t action, struct domain *d,
+                                     uint32_t s, uint32_t e, uint8_t allow)
 {
-    return alternative_call(xsm_ops.ioport_mapping, d, s, e, allow);
+    if ( xsm_ops.ioport_mapping )
+        return alternative_call(xsm_ops.ioport_mapping, d, s, e, allow);
+
+    XSM_ASSERT_ACTION(XSM_HOOK);
+    return xsm_default_action(action, current->domain, d);
 }
 
-static inline int xsm_pmu_op (xsm_default_t def, struct domain *d, unsigned int op)
+static inline int xsm_pmu_op(xsm_default_t action, struct domain *d,
+                             unsigned int op)
 {
-    return alternative_call(xsm_ops.pmu_op, d, op);
+    if ( xsm_ops.pmu_op )
+        return alternative_call(xsm_ops.pmu_op, d, op);
+
+    XSM_ASSERT_ACTION(XSM_OTHER);
+    switch ( op )
+    {
+    case XENPMU_init:
+    case XENPMU_finish:
+    case XENPMU_lvtpc_set:
+    case XENPMU_flush:
+        return xsm_default_action(XSM_HOOK, d, current->domain);
+    default:
+        return xsm_default_action(XSM_PRIV, d, current->domain);
+    }
 }
 
 #endif /* CONFIG_X86 */
 
-static inline int xsm_dm_op(xsm_default_t def, struct domain *d)
+static inline int xsm_dm_op(xsm_default_t action, struct domain *d)
 {
-    return alternative_call(xsm_ops.dm_op, d);
+    if ( xsm_ops.dm_op )
+        return alternative_call(xsm_ops.dm_op, d);
+
+    XSM_ASSERT_ACTION(XSM_DM_PRIV);
+    return xsm_default_action(action, current->domain, d);
 }
 
-static inline int xsm_xen_version (xsm_default_t def, uint32_t op)
+static inline int xsm_xen_version(xsm_default_t action, uint32_t op)
 {
-    return alternative_call(xsm_ops.xen_version, op);
+    if ( xsm_ops.xen_version )
+        return alternative_call(xsm_ops.xen_version, op);
+
+    XSM_ASSERT_ACTION(XSM_OTHER);
+    switch ( op )
+    {
+    case XENVER_version:
+    case XENVER_platform_parameters:
+    case XENVER_get_features:
+        /* These sub-ops ignore the permission checks and return data. */
+        block_speculation();
+        return 0;
+    case XENVER_extraversion:
+    case XENVER_compile_info:
+    case XENVER_capabilities:
+    case XENVER_changeset:
+    case XENVER_pagesize:
+    case XENVER_guest_handle:
+        /* These MUST always be accessible to any guest by default. */
+        return xsm_default_action(XSM_HOOK, current->domain, NULL);
+    default:
+        return xsm_default_action(XSM_PRIV, current->domain, NULL);
+    }
 }
 
-static inline int xsm_domain_resource_map(xsm_default_t def, struct domain *d)
+static inline int xsm_domain_resource_map(xsm_default_t action, struct domain *d)
 {
-    return alternative_call(xsm_ops.domain_resource_map, d);
+    if ( xsm_ops.domain_resource_map )
+        return alternative_call(xsm_ops.domain_resource_map, d);
+
+    XSM_ASSERT_ACTION(XSM_DM_PRIV);
+    return xsm_default_action(action, current->domain, d);
 }
 
 #ifdef CONFIG_ARGO
 static inline int xsm_argo_enable(const struct domain *d)
 {
-    return alternative_call(xsm_ops.argo_enable, d);
+    if ( xsm_ops.argo_enable )
+        return alternative_call(xsm_ops.argo_enable, d);
+
+    return 0;
 }
 
 static inline int xsm_argo_register_single_source(const struct domain *d,
                                                   const struct domain *t)
 {
-    return alternative_call(xsm_ops.argo_register_single_source, d, t);
+    if ( xsm_ops.argo_register_single_source )
+        return alternative_call(xsm_ops.argo_register_single_source, d, t);
+
+    return 0;
 }
 
 static inline int xsm_argo_register_any_source(const struct domain *d)
 {
-    return alternative_call(xsm_ops.argo_register_any_source, d);
+    if ( xsm_ops.argo_register_any_source )
+        return alternative_call(xsm_ops.argo_register_any_source, d);
+
+    return 0;
 }
 
 static inline int xsm_argo_send(const struct domain *d, const struct domain *t)
 {
-    return alternative_call(xsm_ops.argo_send, d, t);
+    if ( xsm_ops.argo_send )
+        return alternative_call(xsm_ops.argo_send, d, t);
+
+    return 0;
 }
 
 #endif /* CONFIG_ARGO */
 
-#else /* CONFIG_XSM */
-
-#include <xsm/dummy.h>
-
-#endif /* CONFIG_XSM */
-
 #endif /* __XSM_H */
diff --git a/xen/xsm/Makefile b/xen/xsm/Makefile
index cf0a728f1c..ab1fb74edc 100644
--- a/xen/xsm/Makefile
+++ b/xen/xsm/Makefile
@@ -1,6 +1,5 @@
 obj-y += xsm_core.o
-obj-$(CONFIG_XSM) += xsm_policy.o
-obj-$(CONFIG_XSM) += dummy.o
+obj-y += xsm_policy.o
 obj-$(CONFIG_XSM_SILO) += silo.o
 
 obj-$(CONFIG_XSM_FLASK) += flask/
diff --git a/xen/xsm/dummy.c b/xen/xsm/dummy.c
deleted file mode 100644
index b848580eaa..0000000000
--- a/xen/xsm/dummy.c
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- *  This work is based on the LSM implementation in Linux 2.6.13.4.
- *
- *  Author:  George Coker, <gscoker@alpha.ncsc.mil>
- *
- *  Contributors: Michael LeMay, <mdlemay@epoch.ncsc.mil>
- *
- *  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.
- */
-
-#include <xsm/dummy.h>
-
-#define set_to_dummy_if_null(ops, function)                            \
-    do {                                                               \
-        if ( !ops->function )                                          \
-            ops->function = xsm_##function;                            \
-    } while (0)
-
-void __init xsm_fixup_ops (struct xsm_ops *ops)
-{
-    set_to_dummy_if_null(ops, security_domaininfo);
-    set_to_dummy_if_null(ops, domain_create);
-    set_to_dummy_if_null(ops, getdomaininfo);
-    set_to_dummy_if_null(ops, domctl_scheduler_op);
-    set_to_dummy_if_null(ops, sysctl_scheduler_op);
-    set_to_dummy_if_null(ops, set_target);
-    set_to_dummy_if_null(ops, domctl);
-    set_to_dummy_if_null(ops, sysctl);
-    set_to_dummy_if_null(ops, readconsole);
-
-    set_to_dummy_if_null(ops, evtchn_unbound);
-    set_to_dummy_if_null(ops, evtchn_interdomain);
-    set_to_dummy_if_null(ops, evtchn_close_post);
-    set_to_dummy_if_null(ops, evtchn_send);
-    set_to_dummy_if_null(ops, evtchn_status);
-    set_to_dummy_if_null(ops, evtchn_reset);
-
-    set_to_dummy_if_null(ops, grant_mapref);
-    set_to_dummy_if_null(ops, grant_unmapref);
-    set_to_dummy_if_null(ops, grant_setup);
-    set_to_dummy_if_null(ops, grant_transfer);
-    set_to_dummy_if_null(ops, grant_copy);
-    set_to_dummy_if_null(ops, grant_query_size);
-
-    set_to_dummy_if_null(ops, alloc_security_domain);
-    set_to_dummy_if_null(ops, free_security_domain);
-    set_to_dummy_if_null(ops, alloc_security_evtchns);
-    set_to_dummy_if_null(ops, free_security_evtchns);
-    set_to_dummy_if_null(ops, show_security_evtchn);
-    set_to_dummy_if_null(ops, init_hardware_domain);
-
-    set_to_dummy_if_null(ops, get_pod_target);
-    set_to_dummy_if_null(ops, set_pod_target);
-
-    set_to_dummy_if_null(ops, memory_exchange);
-    set_to_dummy_if_null(ops, memory_adjust_reservation);
-    set_to_dummy_if_null(ops, memory_stat_reservation);
-    set_to_dummy_if_null(ops, memory_pin_page);
-    set_to_dummy_if_null(ops, claim_pages);
-
-    set_to_dummy_if_null(ops, console_io);
-
-    set_to_dummy_if_null(ops, profile);
-
-    set_to_dummy_if_null(ops, kexec);
-    set_to_dummy_if_null(ops, schedop_shutdown);
-
-    set_to_dummy_if_null(ops, show_irq_sid);
-    set_to_dummy_if_null(ops, map_domain_pirq);
-    set_to_dummy_if_null(ops, map_domain_irq);
-    set_to_dummy_if_null(ops, unmap_domain_pirq);
-    set_to_dummy_if_null(ops, unmap_domain_irq);
-    set_to_dummy_if_null(ops, bind_pt_irq);
-    set_to_dummy_if_null(ops, unbind_pt_irq);
-    set_to_dummy_if_null(ops, irq_permission);
-    set_to_dummy_if_null(ops, iomem_permission);
-    set_to_dummy_if_null(ops, iomem_mapping);
-    set_to_dummy_if_null(ops, pci_config_permission);
-    set_to_dummy_if_null(ops, get_vnumainfo);
-
-#if defined(CONFIG_HAS_PASSTHROUGH) && defined(CONFIG_HAS_PCI)
-    set_to_dummy_if_null(ops, get_device_group);
-    set_to_dummy_if_null(ops, assign_device);
-    set_to_dummy_if_null(ops, deassign_device);
-#endif
-
-#if defined(CONFIG_HAS_PASSTHROUGH) && defined(CONFIG_HAS_DEVICE_TREE)
-    set_to_dummy_if_null(ops, assign_dtdevice);
-    set_to_dummy_if_null(ops, deassign_dtdevice);
-#endif
-
-    set_to_dummy_if_null(ops, resource_plug_core);
-    set_to_dummy_if_null(ops, resource_unplug_core);
-    set_to_dummy_if_null(ops, resource_plug_pci);
-    set_to_dummy_if_null(ops, resource_unplug_pci);
-    set_to_dummy_if_null(ops, resource_setup_pci);
-    set_to_dummy_if_null(ops, resource_setup_gsi);
-    set_to_dummy_if_null(ops, resource_setup_misc);
-
-    set_to_dummy_if_null(ops, page_offline);
-    set_to_dummy_if_null(ops, hypfs_op);
-    set_to_dummy_if_null(ops, hvm_param);
-    set_to_dummy_if_null(ops, hvm_control);
-    set_to_dummy_if_null(ops, hvm_param_altp2mhvm);
-    set_to_dummy_if_null(ops, hvm_altp2mhvm_op);
-
-    set_to_dummy_if_null(ops, do_xsm_op);
-#ifdef CONFIG_COMPAT
-    set_to_dummy_if_null(ops, do_compat_op);
-#endif
-
-    set_to_dummy_if_null(ops, add_to_physmap);
-    set_to_dummy_if_null(ops, remove_from_physmap);
-    set_to_dummy_if_null(ops, map_gmfn_foreign);
-
-    set_to_dummy_if_null(ops, vm_event_control);
-
-#ifdef CONFIG_MEM_ACCESS
-    set_to_dummy_if_null(ops, mem_access);
-#endif
-
-#ifdef CONFIG_MEM_PAGING
-    set_to_dummy_if_null(ops, mem_paging);
-#endif
-
-#ifdef CONFIG_MEM_SHARING
-    set_to_dummy_if_null(ops, mem_sharing);
-#endif
-
-    set_to_dummy_if_null(ops, platform_op);
-#ifdef CONFIG_X86
-    set_to_dummy_if_null(ops, do_mca);
-    set_to_dummy_if_null(ops, shadow_control);
-    set_to_dummy_if_null(ops, mem_sharing_op);
-    set_to_dummy_if_null(ops, apic);
-    set_to_dummy_if_null(ops, machine_memory_map);
-    set_to_dummy_if_null(ops, domain_memory_map);
-    set_to_dummy_if_null(ops, mmu_update);
-    set_to_dummy_if_null(ops, mmuext_op);
-    set_to_dummy_if_null(ops, update_va_mapping);
-    set_to_dummy_if_null(ops, priv_mapping);
-    set_to_dummy_if_null(ops, ioport_permission);
-    set_to_dummy_if_null(ops, ioport_mapping);
-    set_to_dummy_if_null(ops, pmu_op);
-#endif
-    set_to_dummy_if_null(ops, dm_op);
-    set_to_dummy_if_null(ops, xen_version);
-    set_to_dummy_if_null(ops, domain_resource_map);
-#ifdef CONFIG_ARGO
-    set_to_dummy_if_null(ops, argo_enable);
-    set_to_dummy_if_null(ops, argo_register_single_source);
-    set_to_dummy_if_null(ops, argo_register_any_source);
-    set_to_dummy_if_null(ops, argo_send);
-#endif
-}
diff --git a/xen/xsm/silo.c b/xen/xsm/silo.c
index 4ef40bd712..0455e1eb4b 100644
--- a/xen/xsm/silo.c
+++ b/xen/xsm/silo.c
@@ -17,6 +17,7 @@
  * You should have received a copy of the GNU General Public License along with
  * this program; If not, see <http://www.gnu.org/licenses/>.
  */
+#include <xsm/xsm-core.h>
 #include <xsm/dummy.h>
 
 /*
@@ -43,7 +44,7 @@ static int silo_evtchn_unbound(struct domain *d1, struct evtchn *chn,
     else
     {
         if ( silo_mode_dom_check(d1, d2) )
-            rc = xsm_evtchn_unbound(d1, chn, id2);
+            rc = xsm_default_action(XSM_TARGET, current->domain, d1);
         rcu_unlock_domain(d2);
     }
 
@@ -54,7 +55,7 @@ static int silo_evtchn_interdomain(struct domain *d1, struct evtchn *chan1,
                                    struct domain *d2, struct evtchn *chan2)
 {
     if ( silo_mode_dom_check(d1, d2) )
-        return xsm_evtchn_interdomain(d1, chan1, d2, chan2);
+        return xsm_default_action(XSM_HOOK, d1, d2);
     return -EPERM;
 }
 
@@ -62,21 +63,21 @@ static int silo_grant_mapref(struct domain *d1, struct domain *d2,
                              uint32_t flags)
 {
     if ( silo_mode_dom_check(d1, d2) )
-        return xsm_grant_mapref(d1, d2, flags);
+        return xsm_default_action(XSM_HOOK, d1, d2);
     return -EPERM;
 }
 
 static int silo_grant_transfer(struct domain *d1, struct domain *d2)
 {
     if ( silo_mode_dom_check(d1, d2) )
-        return xsm_grant_transfer(d1, d2);
+        return xsm_default_action(XSM_HOOK, d1, d2);
     return -EPERM;
 }
 
 static int silo_grant_copy(struct domain *d1, struct domain *d2)
 {
     if ( silo_mode_dom_check(d1, d2) )
-        return xsm_grant_copy(d1, d2);
+        return xsm_default_action(XSM_HOOK, d1, d2);
     return -EPERM;
 }
 
@@ -86,14 +87,14 @@ static int silo_argo_register_single_source(const struct domain *d1,
                                             const struct domain *d2)
 {
     if ( silo_mode_dom_check(d1, d2) )
-        return xsm_argo_register_single_source(d1, d2);
+        return 0;
     return -EPERM;
 }
 
 static int silo_argo_send(const struct domain *d1, const struct domain *d2)
 {
     if ( silo_mode_dom_check(d1, d2) )
-        return xsm_argo_send(d1, d2);
+        return 0;
     return -EPERM;
 }
 
diff --git a/xen/xsm/xsm_core.c b/xen/xsm/xsm_core.c
index b5219dff78..75bd2678ef 100644
--- a/xen/xsm/xsm_core.c
+++ b/xen/xsm/xsm_core.c
@@ -18,8 +18,6 @@
 #include <xen/hypercall.h>
 #include <xsm/xsm.h>
 
-#ifdef CONFIG_XSM
-
 #ifdef CONFIG_MULTIBOOT
 #include <asm/setup.h>
 #endif
@@ -124,16 +122,12 @@ static int __init xsm_core_init(const void *policy_buffer, size_t policy_size)
         break;
     }
 
-    /*
-     * This handles three cases,
-     *   - dummy policy module was selected
-     *   - a policy module does not provide all handlers
-     *   - a policy module failed to init
-     */
-    xsm_fixup_ops(&xsm_ops);
-
-    if ( xsm_ops_registered != XSM_OPS_REGISTERED )
+    if ( xsm_ops_registered != XSM_OPS_REGISTERED ) {
         xsm_ops_registered = XSM_OPS_REG_FAILED;
+        printk(XENLOG_ERR
+               "Could not init XSM, xsm_ops register failed\n");
+        return -EFAULT;
+    }
 
     return 0;
 }
@@ -217,8 +211,6 @@ bool __init has_xsm_magic(paddr_t start)
 }
 #endif
 
-#endif
-
 long do_xsm_op (XEN_GUEST_HANDLE_PARAM(xsm_op_t) op)
 {
     return xsm_do_xsm_op(op);
-- 
2.20.1



^ permalink raw reply related	[flat|nested] 25+ messages in thread

* Re: [PATCH v3 1/7] xen: Implement xen/alternative-call.h for use in common code
  2021-08-05 14:06 ` [PATCH v3 1/7] xen: Implement xen/alternative-call.h for use in common code Daniel P. Smith
@ 2021-08-05 15:31   ` Jan Beulich
  0 siblings, 0 replies; 25+ messages in thread
From: Jan Beulich @ 2021-08-05 15:31 UTC (permalink / raw)
  To: Daniel P. Smith, Andrew Cooper
  Cc: Roger Pau Monné,
	Stefano Stabellini, Julien Grall, Volodymyr Babchuk,
	Bob Eshleman, Alistair Francis, Connor Davis, George Dunlap,
	Ian Jackson, Wei Liu, xen-devel

On 05.08.2021 16:06, Daniel P. Smith wrote:
> --- /dev/null
> +++ b/xen/include/xen/alternative-call.h
> @@ -0,0 +1,63 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +#ifndef XEN_ALTERNATIVE_CALL
> +#define XEN_ALTERNATIVE_CALL
> +
> +/*
> + * Some subsystems in Xen may have multiple implementions, which can be
> + * resolved to a single implementation at boot time.  By default, this will
> + * result in the use of function pointers.
> + *
> + * Some architectures may have mechanisms for dynamically modifying .text.
> + * Using this mechnaism, function pointers can be converted to direct calls
> + * which are typically more efficient at runtime.
> + *
> + * For architectures to support:
> + *
> + * - Implement alternative_{,v}call() in asm/alternative.h.  Code generation
> + *   requirements are to emit a function pointer call at build time, and stash
> + *   enough metadata to simplify the call at boot once the implementation has
> + *   been resolved.
> + * - Select ALTERNATIVE_CALL in Kconfig.
> + *
> + * To use:
> + *
> + * Consider the following simplified example.
> + *
> + *  1) struct foo_ops __alt_call_maybe_initdata ops;
> + *
> + *  2) const struct foo_ops __initconst foo_a_ops = { ... };
> + *     const struct foo_ops __initconst foo_b_ops = { ... };
> + *
> + *     void foo_init(void)
> + *     {
> + *         ...
> + *         if ( use_impl_a )
> + *             ops = *foo_a_ops;
> + *         else if ( use_impl_b )
> + *             ops = *foo_b_ops;
> + *         ...
> + *     }
> + *
> + *  3) alternative_call(ops.bar, ...);
> + *
> + * There needs to a single ops object (1) which will eventually contain the
> + * function pointers.  This should be populated in foo's init() function (2)
> + * by one of the available implementations.  To call functions, use
> + * alternative_{,v}call() referencing the main ops object (3).
> + */
> +
> +#ifdef CONFIG_ALTERNATIVE_CALL
> +
> +#include <asm/alternative.h>
> +
> +#define __alt_call_maybe_initdata __initdata

I think it wants (needs) clarifying that this may only be used if
the ops object is used exclusively in alternative_{,v}call()
instances (besides the original assignments to it, of course).

> +#else
> +
> +#define alternative_call(func, args...)  (func)(args)
> +#define alternative_vcall(func, args...) (func)(args)
> +
> +#define __alt_call_maybe_initdata

Wouldn't this want to resolve to __read_mostly?

Jan



^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH v3 3/7] xsm: refactor xsm_ops handling
  2021-08-05 14:06 ` [PATCH v3 3/7] xsm: refactor xsm_ops handling Daniel P. Smith
@ 2021-08-25 15:16   ` Jan Beulich
  2021-08-27 13:44     ` Daniel P. Smith
  0 siblings, 1 reply; 25+ messages in thread
From: Jan Beulich @ 2021-08-25 15:16 UTC (permalink / raw)
  To: Daniel P. Smith; +Cc: Daniel De Graaf, xen-devel

On 05.08.2021 16:06, Daniel P. Smith wrote:
> @@ -747,16 +747,16 @@ extern int xsm_dt_policy_init(void **policy_buffer, size_t *policy_size);
>  extern bool has_xsm_magic(paddr_t);
>  #endif
>  
> -extern int register_xsm(struct xsm_operations *ops);
> -
> -extern struct xsm_operations dummy_xsm_ops;
> -extern void xsm_fixup_ops(struct xsm_operations *ops);
> +extern void xsm_fixup_ops(struct xsm_ops *ops);
>  
>  #ifdef CONFIG_XSM_FLASK
> -extern void flask_init(const void *policy_buffer, size_t policy_size);
> +extern const struct xsm_ops *flask_init(const void *policy_buffer,
> +                                        size_t policy_size);
>  #else
> -static inline void flask_init(const void *policy_buffer, size_t policy_size)
> +static inline struct xsm_ops *flask_init(const void *policy_buffer,

Please use const consistently between real function and stub.

> @@ -766,9 +766,12 @@ extern const unsigned int xsm_flask_init_policy_size;
>  #endif
>  
>  #ifdef CONFIG_XSM_SILO
> -extern void silo_init(void);
> +extern const struct xsm_ops *silo_init(void);
>  #else
> -static inline void silo_init(void) {}
> +static inline struct xsm_ops *silo_init(void)

Same here.

> --- a/xen/xsm/flask/hooks.c
> +++ b/xen/xsm/flask/hooks.c
> @@ -1745,7 +1745,7 @@ static int flask_argo_send(const struct domain *d, const struct domain *t)
>  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);
>  
> -static struct xsm_operations flask_ops = {
> +static const struct xsm_ops __initconst flask_ops = {

__initconstrel please (I thought I had pointed out the difference
already during earlier discussion). Same for SILO then of course.

> --- a/xen/xsm/xsm_core.c
> +++ b/xen/xsm/xsm_core.c
> @@ -28,9 +28,17 @@
>  #include <asm/setup.h>
>  #endif
>  
> -#define XSM_FRAMEWORK_VERSION    "1.0.0"
> +#define XSM_FRAMEWORK_VERSION    "1.0.1"
>  
> -struct xsm_operations *xsm_ops;
> +struct xsm_ops xsm_ops;

__read_mostly?

Jan



^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH v3 2/7] xsm: remove the ability to disable flask
  2021-08-05 14:06 ` [PATCH v3 2/7] xsm: remove the ability to disable flask Daniel P. Smith
@ 2021-08-25 15:22   ` Jan Beulich
  2021-08-27 13:42     ` Daniel P. Smith
  0 siblings, 1 reply; 25+ messages in thread
From: Jan Beulich @ 2021-08-25 15:22 UTC (permalink / raw)
  To: Daniel P. Smith
  Cc: Andrew Cooper, George Dunlap, Ian Jackson, Julien Grall,
	Stefano Stabellini, Wei Liu, Daniel De Graaf, xen-devel

On 05.08.2021 16:06, Daniel P. Smith wrote:
> On Linux when SELinux is put into permissive mode the descretionary access
> controls are still in place. Whereas for Xen when the enforcing state of flask
> is set to permissive, all operations for all domains would succeed, i.e. it
> does not fall back to the default access controls. To provide a means to mimic
> a similar but not equivalent behavior, a flask op is present to allow a
> one-time switch back to the default access controls, aka the "dummy policy".
> 
> This patch removes this flask op to enforce a consistent XSM usage model that a
> reboot of Xen is required to change the XSM policy module in use.
> 
> Signed-off-by: Daniel P. Smith <dpsmith@apertussolutions.com>

The primary reason you remove this is - aiui - that with alternatives
patching there's technically not really a way back (would need to re-
patch every patched location, or every hook would need to check whether
state changed to disabled and if so chain on to the dummy function).
This became sufficiently clear to me only when looking at the next
patch. It would be nice if description also said why the change is
needed. As it stands to me the description reads at best like something
that people could have different views on (and initially I didn't mean
to reply here, for not being convinced of the removal of functionality
in the common case).

Jan



^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH v3 6/7] xsm: drop generic event channel labeling exclusion
  2021-08-05 14:06 ` [PATCH v3 6/7] xsm: drop generic event channel labeling exclusion Daniel P. Smith
@ 2021-08-25 15:44   ` Jan Beulich
  2021-08-27 14:16     ` Daniel P. Smith
  0 siblings, 1 reply; 25+ messages in thread
From: Jan Beulich @ 2021-08-25 15:44 UTC (permalink / raw)
  To: Daniel P. Smith
  Cc: Andrew Cooper, George Dunlap, Ian Jackson, Julien Grall,
	Stefano Stabellini, Wei Liu, xen-devel

On 05.08.2021 16:06, Daniel P. Smith wrote:
> The internal define flag is not used by any XSM module, removing the #ifdef
> leaving the generic event channel labeling as always present.

With this description ...

> --- a/xen/include/xen/sched.h
> +++ b/xen/include/xen/sched.h
> @@ -120,15 +120,12 @@ struct evtchn
>      unsigned short notify_vcpu_id; /* VCPU for local delivery notification */
>      uint32_t fifo_lastq;           /* Data for identifying last queue. */
>  
> -#ifdef CONFIG_XSM
>      union {
> -#ifdef XSM_NEED_GENERIC_EVTCHN_SSID
>          /*
>           * If an XSM module needs more space for its event channel context,
>           * this pointer stores the necessary data for the security server.
>           */
>          void *generic;
> -#endif
>  #ifdef CONFIG_XSM_FLASK
>          /*
>           * Inlining the contents of the structure for FLASK avoids unneeded
> @@ -138,7 +135,6 @@ struct evtchn
>          uint32_t flask_sid;
>  #endif
>      } ssid;
> -#endif
>  } __attribute__((aligned(64)));

... I can see the inner #ifdef go away, but not the outer one. While
the (imo bogus) attribute means you don't alter the size of the
struct, I'm afraid that's not obvious at all without counting bits
and bytes, and hence this may also want saying explicitly in the
description.

Jan



^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH v3 5/7] xsm: decouple xsm header inclusion selection
  2021-08-05 14:06 ` [PATCH v3 5/7] xsm: decouple xsm header inclusion selection Daniel P. Smith
@ 2021-08-26  8:13   ` Jan Beulich
  2021-08-27 14:06     ` Daniel P. Smith
  0 siblings, 1 reply; 25+ messages in thread
From: Jan Beulich @ 2021-08-26  8:13 UTC (permalink / raw)
  To: Daniel P. Smith; +Cc: Daniel De Graaf, xen-devel

On 05.08.2021 16:06, Daniel P. Smith wrote:
> --- /dev/null
> +++ b/xen/include/xsm/xsm-core.h
> @@ -0,0 +1,273 @@
> +/*
> + *  This file contains the XSM hook definitions for Xen.
> + *
> + *  This work is based on the LSM implementation in Linux 2.6.13.4.
> + *
> + *  Author:  George Coker, <gscoker@alpha.ncsc.mil>
> + *
> + *  Contributors: Michael LeMay, <mdlemay@epoch.ncsc.mil>
> + *
> + *  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.
> + */
> +
> +#ifndef __XSM_CORE_H__
> +#define __XSM_CORE_H__
> +
> +#include <xen/sched.h>
> +#include <xen/multiboot.h>

I was going to ask to invert the order (as we try to arrange #include-s
alphabetically), but it looks like multiboot.h isn't fit for this.

> +typedef void xsm_op_t;
> +DEFINE_XEN_GUEST_HANDLE(xsm_op_t);

Just FTR - I consider this dubious. If void is meant, I don't see why
a void handle can't be used.

> +/* policy magic number (defined by XSM_MAGIC) */
> +typedef uint32_t xsm_magic_t;
> +
> +#ifdef CONFIG_XSM_FLASK
> +#define XSM_MAGIC 0xf97cff8c
> +#else
> +#define XSM_MAGIC 0x0
> +#endif
> +
> +/* These annotations are used by callers and in dummy.h to document the
> + * default actions of XSM hooks. They should be compiled out otherwise.
> + */

I realize you only move code, but like e.g. the u32 -> uint32_t change
in context above I'd like to encourage you to also address other style
issues in the newly introduced file. Here I'm talking about comment
style, requiring /* to be on its own line.

> +enum xsm_default {
> +    XSM_HOOK,     /* Guests can normally access the hypercall */
> +    XSM_DM_PRIV,  /* Device model can perform on its target domain */
> +    XSM_TARGET,   /* Can perform on self or your target domain */
> +    XSM_PRIV,     /* Privileged - normally restricted to dom0 */
> +    XSM_XS_PRIV,  /* Xenstore domain - can do some privileged operations */
> +    XSM_OTHER     /* Something more complex */
> +};
> +typedef enum xsm_default xsm_default_t;
> +
> +struct xsm_ops {
> +    void (*security_domaininfo) (struct domain *d,

Similarly here (and below) - we don't normally put a blank between
the closing and opening parentheses in function pointer declarations.
The majority does so here, but ...

>[...]
> +    int (*page_offline)(uint32_t cmd);
> +    int (*hypfs_op)(void);

... there are exceptions.

>[...]
> +    int (*platform_op) (uint32_t cmd);
> +
> +#ifdef CONFIG_X86
> +    int (*do_mca) (void);
> +    int (*shadow_control) (struct domain *d, uint32_t op);
> +    int (*mem_sharing_op) (struct domain *d, struct domain *cd, int op);
> +    int (*apic) (struct domain *d, int cmd);
> +    int (*memtype) (uint32_t access);
> +    int (*machine_memory_map) (void);
> +    int (*domain_memory_map) (struct domain *d);
> +#define XSM_MMU_UPDATE_READ      1
> +#define XSM_MMU_UPDATE_WRITE     2
> +#define XSM_MMU_NORMAL_UPDATE    4
> +#define XSM_MMU_MACHPHYS_UPDATE  8
> +    int (*mmu_update) (struct domain *d, struct domain *t,
> +                       struct domain *f, uint32_t flags);
> +    int (*mmuext_op) (struct domain *d, struct domain *f);
> +    int (*update_va_mapping) (struct domain *d, struct domain *f,
> +                              l1_pgentry_t pte);
> +    int (*priv_mapping) (struct domain *d, struct domain *t);
> +    int (*ioport_permission) (struct domain *d, uint32_t s, uint32_t e,
> +                              uint8_t allow);
> +    int (*ioport_mapping) (struct domain *d, uint32_t s, uint32_t e,
> +                           uint8_t allow);
> +    int (*pmu_op) (struct domain *d, unsigned int op);
> +#endif
> +    int (*dm_op) (struct domain *d);

To match grouping elsewhere, a blank line above here, ...

> +    int (*xen_version) (uint32_t cmd);
> +    int (*domain_resource_map) (struct domain *d);
> +#ifdef CONFIG_ARGO

... and here would be nice.

> +    int (*argo_enable) (const struct domain *d);
> +    int (*argo_register_single_source) (const struct domain *d,
> +                                        const struct domain *t);
> +    int (*argo_register_any_source) (const struct domain *d);
> +    int (*argo_send) (const struct domain *d, const struct domain *t);
> +#endif
> +};
> +
> +extern void xsm_fixup_ops(struct xsm_ops *ops);
> +
> +#ifdef CONFIG_XSM
> +
> +#ifdef CONFIG_MULTIBOOT
> +extern int xsm_multiboot_init(unsigned long *module_map,
> +                              const multiboot_info_t *mbi);
> +extern int xsm_multiboot_policy_init(unsigned long *module_map,
> +                                     const multiboot_info_t *mbi,
> +                                     void **policy_buffer,
> +                                     size_t *policy_size);
> +#endif
> +
> +#ifdef CONFIG_HAS_DEVICE_TREE
> +/*
> + * Initialize XSM
> + *
> + * On success, return 1 if using SILO mode else 0.
> + */
> +extern int xsm_dt_init(void);
> +extern int xsm_dt_policy_init(void **policy_buffer, size_t *policy_size);
> +extern bool has_xsm_magic(paddr_t);
> +#endif
> +
> +#ifdef CONFIG_XSM_FLASK
> +extern const struct xsm_ops *flask_init(const void *policy_buffer,
> +                                        size_t policy_size);
> +#else
> +static inline const struct xsm_ops *flask_init(const void *policy_buffer,
> +                                               size_t policy_size)
> +{
> +    return NULL;
> +}
> +#endif
> +
> +#ifdef CONFIG_XSM_FLASK_POLICY
> +extern const unsigned char xsm_flask_init_policy[];
> +extern const unsigned int xsm_flask_init_policy_size;
> +#endif

To be honest, I don't think this belongs in any header. This interfaces
with a generated assembly file. In such a case I would always suggest
to limit visibility of the symbols as much as possible, i.e. put the
declarations in the sole file referencing them.

> +#ifdef CONFIG_XSM_SILO
> +extern const struct xsm_ops *silo_init(void);
> +#else
> +static const inline struct xsm_ops *silo_init(void)
> +{
> +    return NULL;
> +}
> +#endif
> +
> +#else /* CONFIG_XSM */
> +
> +#ifdef CONFIG_MULTIBOOT
> +static inline int xsm_multiboot_init (unsigned long *module_map,

Nit: Stray blank ahead of the opening parenthesis.

Looking back there's also the question of "extern" on function
declarations. In new code I don't think we put the redundant
storage class specifier there; they're only needed on data
declarations. I'm inclined to suggest to drop all of them while
moving the code.

Preferably with these adjustments
Acked-by: Jan Beulich <jbeulich@suse.com>

Jan



^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH v3 7/7] xsm: removing facade that XSM can be enabled/disabled
  2021-08-05 14:06 ` [PATCH v3 7/7] xsm: removing facade that XSM can be enabled/disabled Daniel P. Smith
@ 2021-08-26  9:37   ` Jan Beulich
  2021-08-30 12:11     ` Daniel P. Smith
  0 siblings, 1 reply; 25+ messages in thread
From: Jan Beulich @ 2021-08-26  9:37 UTC (permalink / raw)
  To: Daniel P. Smith
  Cc: Andrew Cooper, George Dunlap, Ian Jackson, Julien Grall,
	Stefano Stabellini, Wei Liu, Daniel De Graaf, xen-devel

On 05.08.2021 16:06, Daniel P. Smith wrote:
> The XSM facilities are always in use by Xen with the facade of being able to
> turn XSM on and off. This option is in fact about allowing the selection of
> which policies are available and which are used at runtime.  To provide this
> facade a complicated serious of #ifdef's are used to selective include

Nit: It took me a moment to realize that the sentence reads oddly because
you likely mean "series", not "serious".

> different headers or portions of headers. This series of #ifdef gyrations
> switches between two different versions of the XSM hook interfaces and their
> respective backing implementation.  All of this is done to provide a minimal
> size/performance optimization for when alternative policies are disabled.
> 
> To unwind the #ifdef gyrations a series of changes were necessary,
>     * replace CONFIG_XSM with XSM_CONFIGURABLE to allow visibility of
>       selecting alternate XSM policy modules to those that require it
>     * adjusted CONFIG_XSM_SILO, CONFIG_XSM_FLASK, and the default module
>       selection to sensible defaults
>     * collapsed the "dummy/defualt" XSM interface and implementation with the
>       "multiple policy" interface to provide a single inlined implementation
>       that attempts to use a registered hook and falls back to the check from
>       the dummy implementation
>     * the collapse to a single interface broke code relying on the alternate
>       interface, specifically SILO, this was reworked to remove the
>       indirection/abstraction making SILO explicit in its access control
>       decisions
>     * with the change of the XSM hooks to fall back to enforcing the dummy
>       policy, it is no longer necessary to fill NULL entries in the struct
>       xsm_ops returned by an XSM module's init

It would be nice if some of this could be split. Is this really close to
impossible?

> --- a/xen/common/Kconfig
> +++ b/xen/common/Kconfig
> @@ -200,23 +200,15 @@ config XENOPROF
>  
>  	  If unsure, say Y.
>  
> -config XSM
> -	bool "Xen Security Modules support"
> -	default ARM
> -	---help---
> -	  Enables the security framework known as Xen Security Modules which
> -	  allows administrators fine-grained control over a Xen domain and
> -	  its capabilities by defining permissible interactions between domains,
> -	  the hypervisor itself, and related resources such as memory and
> -	  devices.
> -
> -	  If unsure, say N.
> +config XSM_CONFIGURABLE
> +    bool "Enable Configuring Xen Security Modules"

Is there a reason to change not only the prompt, but also the name of
the Kconfig setting? This alone is the reason for some otherwise
unnecessary code churn.

Also please correct indentation here.

>  config XSM_FLASK
> -	def_bool y
> -	prompt "FLux Advanced Security Kernel support"
> -	depends on XSM
> -	---help---
> +	bool "FLux Advanced Security Kernel support"
> +	default n

I don't understand this change in default (and as an aside, a default
of "n" doesn't need spelling out): In the description you say "adjusted
CONFIG_XSM_SILO, CONFIG_XSM_FLASK, and the default module selection to
sensible defaults". If that's to describe this change, then I'm afraid
I don't see why defaulting to "n" is more sensible once the person
configuring Xen has chosen the configure XSM's (or XSM_CONFIGURABLE's)
sub-options. If that's unrelated to the change here, then I'm afraid
I'm missing justification altogether. (Same for SILO then.)

> +	depends on XSM_CONFIGURABLE
> +	select XSM_EVTCHN_LABELING

Neither this nor any prior patch introduces an option of this name,
and there's also none in the present tree. All afaics; I may have
overlooked something or typo-ed a "grep" command.

> @@ -265,14 +258,14 @@ config XSM_SILO
>  	  If unsure, say Y.
>  
>  choice
> -	prompt "Default XSM implementation"
> -	depends on XSM
> +	prompt "Default XSM module"
>  	default XSM_SILO_DEFAULT if XSM_SILO && ARM
>  	default XSM_FLASK_DEFAULT if XSM_FLASK
>  	default XSM_SILO_DEFAULT if XSM_SILO
>  	default XSM_DUMMY_DEFAULT
> +	depends on XSM_CONFIGURABLE

With the larger set of "default" lines I'd like to suggest to keep
"depends on" ahead of them.

> @@ -282,7 +275,7 @@ endchoice
>  config LATE_HWDOM
>  	bool "Dedicated hardware domain"
>  	default n
> -	depends on XSM && X86
> +	depends on XSM_FLASK && X86

This change is not mentioned or justified in the description. In fact
I think it is unrelated to the change here and hence would want breaking
out.

>  	---help---

As you're changing these elsewhere, any chance of you also changing
this one to just "help"?

> --- a/xen/include/xsm/xsm.h
> +++ b/xen/include/xsm/xsm.h
> @@ -19,545 +19,1023 @@
>  #include <xen/sched.h>
>  #include <xen/multiboot.h>
>  #include <xsm/xsm-core.h>
> -
> -#ifdef CONFIG_XSM
> +#include <xsm/dummy.h>
> +#include <public/version.h>
>  
>  extern struct xsm_ops xsm_ops;
>  
> -static inline void xsm_security_domaininfo (struct domain *d,
> -                                        struct xen_domctl_getdomaininfo *info)
> +static inline void xsm_security_domaininfo(
> +    struct domain *d,
> +    struct xen_domctl_getdomaininfo *info)
>  {
> -    alternative_vcall(xsm_ops.security_domaininfo, d, info);
> +    if ( xsm_ops.security_domaininfo )
> +        alternative_vcall(xsm_ops.security_domaininfo, d, info);

Here and everywhere else, when !XSM_CONFIGURABLE you now needlessly
force NULL checks to occur which are never going to be true. There's
then also the dead indirect call and the associated patching data. I
think this wants hiding in another pair of wrappers, which simply
expand to nothing when !XSM_CONFIGURABLE - perhaps xsm_vcall() and
xsm_call().

>  }
>  
> -static inline int xsm_domain_create (xsm_default_t def, struct domain *d, u32 ssidref)
> +static inline int xsm_domain_create(xsm_default_t action, struct domain *d,
> +                                    u32 ssidref)

It would be nice if you kept on converting u32 -> uint32_t as you did
in earlier patches.

>  {
> -    return alternative_call(xsm_ops.domain_create, d, ssidref);
> +    if ( xsm_ops.domain_create )
> +        return alternative_call(xsm_ops.domain_create, d, ssidref);
> +
> +    XSM_ASSERT_ACTION(XSM_HOOK);

Any reason not to put these assertions first in the functions?

> +    return xsm_default_action(action, current->domain, d);
>  }

Since

static inline int xsm_domain_create(xsm_default_t action, struct domain *d,
                                    uint32_t ssidref)
{
    XSM_ASSERT_ACTION(XSM_HOOK);
    return xsm_call(xsm_ops.domain_create, d, ssidref);
    return xsm_default_action(action, current->domain, d);
}

won't work, and since integrating "return" into xsm_call() also would't
yield a sufficiently clear result:

static inline int xsm_domain_create(xsm_default_t action, struct domain *d,
                                    uint32_t ssidref)
{
    XSM_ASSERT_ACTION(XSM_HOOK);
    xsm_call(xsm_ops.domain_create, d, ssidref);
    return xsm_default_action(action, current->domain, d);
}

(as control flow would be unobvious), the xsm_default_action() invocation
likely would also need integrating into xsm_call() then.

Unless there's some obstacle, this would eliminate a whole lot of code
redundancy.

> -static inline int xsm_set_target (xsm_default_t def, struct domain *d, struct domain *e)
> +static inline int xsm_set_target(xsm_default_t action, struct domain *d,
> +                                 struct domain *e)
>  {
> -    return alternative_call(xsm_ops.set_target, d, e);
> +    if ( xsm_ops.set_target )
> +        return alternative_call(xsm_ops.set_target, d, e);
> +
> +    XSM_ASSERT_ACTION(XSM_HOOK);
> +    return xsm_default_action(action, current->domain, NULL);
>  }

While benign because xsm_default_action() does nothing for XSM_HOOK, I
think there's an inconsistency here which rather wants correcting (in
a prereq patch): The default hook should have been passed consistent
arguments, no matter whether used because of !XSM or because of the
module in use left the hook unset.

Of course such anomalies are much easier to notice (outside of review
of patches introducing such) with you now placing both invocations
next to each other.

> -static inline int xsm_evtchn_interdomain (xsm_default_t def, struct domain *d1,
> -                struct evtchn *chan1, struct domain *d2, struct evtchn *chan2)
> +static inline int xsm_evtchn_interdomain(xsm_default_t action,
> +                                         struct domain *d1,
> +                                         struct evtchn *chan1,
> +                                         struct domain *d2,
> +                                         struct evtchn *chan2)
>  {
> -    return alternative_call(xsm_ops.evtchn_interdomain, d1, chan1, d2, chan2);
> +    if ( xsm_ops.evtchn_interdomain )
> +        return alternative_call(xsm_ops.evtchn_interdomain, d1, chan1, d2,
> +                                chan2);
> +
> +    XSM_ASSERT_ACTION(XSM_HOOK);
> +    return xsm_default_action(action, d1, d2);
>  }

There's another anomaly here: The first argument to xsm_default_action()
typically is current->domain in similar functions. Here d1 gets passed in
despite always being current->domain. I think the unnecessary parameter
wants dropping (again in a prereq patch)) from the wrapper and hook, to
avoid giving the wrong impression of both domains potentially being remote
ones.

> -static inline int xsm_evtchn_send (xsm_default_t def, struct domain *d, struct evtchn *chn)
> +static inline int xsm_evtchn_send(xsm_default_t action, struct domain *d,
> +                                  struct evtchn *chn)
>  {
> -    return alternative_call(xsm_ops.evtchn_send, d, chn);
> +    if ( xsm_ops.evtchn_send )
> +        return alternative_call(xsm_ops.evtchn_send, d, chn);
> +
> +    XSM_ASSERT_ACTION(XSM_HOOK);
> +    return xsm_default_action(action, d, NULL);

This again looks wrong (and again is benign only because XSM_HOOK means
xsm_default_action() ignores the other function parameters), wanting to
follow the usual

    return xsm_default_action(action, current->domain, d);

pattern instead.

> -static inline int xsm_evtchn_reset (xsm_default_t def, struct domain *d1, struct domain *d2)
> +static inline int xsm_evtchn_reset(xsm_default_t action, struct domain *d1,
> +                                   struct domain *d2)
>  {
> -    return alternative_call(xsm_ops.evtchn_reset, d1, d2);
> +    if ( xsm_ops.evtchn_reset )
> +        return alternative_call(xsm_ops.evtchn_reset, d1, d2);
> +
> +    XSM_ASSERT_ACTION(XSM_TARGET);
> +    return xsm_default_action(action, d1, d2);

See xsm_evtchn_interdomain() above.

> -static inline int xsm_grant_mapref (xsm_default_t def, struct domain *d1, struct domain *d2,
> -                                                                uint32_t flags)
> +static inline int xsm_grant_mapref(xsm_default_t action, struct domain *d1,
> +                                   struct domain *d2, uint32_t flags)
>  {
> -    return alternative_call(xsm_ops.grant_mapref, d1, d2, flags);
> +    if ( xsm_ops.grant_mapref )
> +        return alternative_call(xsm_ops.grant_mapref, d1, d2, flags);
> +
> +    XSM_ASSERT_ACTION(XSM_HOOK);
> +    return xsm_default_action(action, d1, d2);

Again (more similar grant ones follow).

> -static inline int xsm_memory_adjust_reservation (xsm_default_t def, struct domain *d1, struct
> -                                                                    domain *d2)
> +static inline int xsm_memory_adjust_reservation(xsm_default_t action,
> +                                                struct domain *d1,
> +                                                struct domain *d2)
>  {
> -    return alternative_call(xsm_ops.memory_adjust_reservation, d1, d2);
> +    if ( xsm_ops.memory_adjust_reservation )
> +        return alternative_call(xsm_ops.memory_adjust_reservation, d1, d2);
> +
> +    XSM_ASSERT_ACTION(XSM_TARGET);
> +    return xsm_default_action(action, d1, d2);

Again (more similar memory ones follow).

> -static inline int xsm_memory_pin_page(xsm_default_t def, struct domain *d1, struct domain *d2,
> -                                      struct page_info *page)
> +static inline int xsm_memory_pin_page(xsm_default_t action, struct domain *d1,
> +                                      struct domain *d2, struct page_info *page)
>  {
> -    return alternative_call(xsm_ops.memory_pin_page, d1, d2, page);
> +    if ( xsm_ops.memory_pin_page )
> +        return alternative_call(xsm_ops.memory_pin_page, d1, d2, page);
> +
> +    XSM_ASSERT_ACTION(XSM_HOOK);
> +    return xsm_default_action(action, d1, d2);

This one has the same issue, but is more interesting: There's no
similar hook/check for unpinning a page (nor does the same check
get re-used there). Plus it's x86 (more precisely PV) specific.

> -static inline int xsm_map_gmfn_foreign (xsm_default_t def, struct domain *d, struct domain *t)
> +static inline int xsm_map_gmfn_foreign(xsm_default_t action, struct domain *d,
> +                                       struct domain *t)
>  {
> -    return alternative_call(xsm_ops.map_gmfn_foreign, d, t);
> +    if ( xsm_ops.map_gmfn_foreign )
> +        return alternative_call(xsm_ops.map_gmfn_foreign, d, t);
> +
> +    XSM_ASSERT_ACTION(XSM_TARGET);
> +    return xsm_default_action(action, d, t);

This one is also interesting: There's no check at all here that
current->domain has any permissions towards d or t. Interestingly
even flask_map_gmfn_foreign() doesn't check this.

> -static inline int xsm_console_io (xsm_default_t def, struct domain *d, int cmd)
> +static inline int xsm_console_io(xsm_default_t action, struct domain *d, int cmd)
>  {
> -    return alternative_call(xsm_ops.console_io, d, cmd);
> +    if ( xsm_ops.console_io )
> +        return alternative_call(xsm_ops.console_io, d, cmd);
> +
> +    XSM_ASSERT_ACTION(XSM_OTHER);
> +    if ( d->is_console )
> +        return xsm_default_action(XSM_HOOK, d, NULL);
> +#ifdef CONFIG_VERBOSE_DEBUG
> +    if ( cmd == CONSOLEIO_write )
> +        return xsm_default_action(XSM_HOOK, d, NULL);
> +#endif
> +    return xsm_default_action(XSM_PRIV, d, NULL);

Same implication of d == current->domain here again. I guess I'll
stop enumerating further ones.

> -static inline int xsm_pci_config_permission (xsm_default_t def, struct domain *d, uint32_t machine_bdf, uint16_t start, uint16_t end, uint8_t access)
> +static inline int xsm_pci_config_permission(xsm_default_t action,
> +                                            struct domain *d,
> +                                            uint32_t machine_bdf,
> +                                            uint16_t start,
> +                                            uint16_t end,
> +                                            uint8_t access)
>  {
> -    return alternative_call(xsm_ops.pci_config_permission, d, machine_bdf, start, end, access);
> +    if ( xsm_ops.pci_config_permission )
> +        return alternative_call(xsm_ops.pci_config_permission, d, machine_bdf, start, end, access);

Nit: Line length.

> -static inline int xsm_pmu_op (xsm_default_t def, struct domain *d, unsigned int op)
> +static inline int xsm_pmu_op(xsm_default_t action, struct domain *d,
> +                             unsigned int op)
>  {
> -    return alternative_call(xsm_ops.pmu_op, d, op);
> +    if ( xsm_ops.pmu_op )
> +        return alternative_call(xsm_ops.pmu_op, d, op);
> +
> +    XSM_ASSERT_ACTION(XSM_OTHER);
> +    switch ( op )
> +    {
> +    case XENPMU_init:
> +    case XENPMU_finish:
> +    case XENPMU_lvtpc_set:
> +    case XENPMU_flush:
> +        return xsm_default_action(XSM_HOOK, d, current->domain);
> +    default:
> +        return xsm_default_action(XSM_PRIV, d, current->domain);

Urgh - isn't this the wrong way round? (Luckily vPMU isn't security
supported, so no XSA would be needed.)

> --- a/xen/xsm/Makefile
> +++ b/xen/xsm/Makefile
> @@ -1,6 +1,5 @@
>  obj-y += xsm_core.o
> -obj-$(CONFIG_XSM) += xsm_policy.o
> -obj-$(CONFIG_XSM) += dummy.o
> +obj-y += xsm_policy.o

Why would this now need compiling in all cases?

> --- a/xen/xsm/silo.c
> +++ b/xen/xsm/silo.c
> @@ -17,6 +17,7 @@
>   * You should have received a copy of the GNU General Public License along with
>   * this program; If not, see <http://www.gnu.org/licenses/>.
>   */
> +#include <xsm/xsm-core.h>
>  #include <xsm/dummy.h>

As already mentioned elsewhere - where possible please arrange #include-s
alphabetically.

> @@ -124,16 +122,12 @@ static int __init xsm_core_init(const void *policy_buffer, size_t policy_size)
>          break;
>      }
>  
> -    /*
> -     * This handles three cases,
> -     *   - dummy policy module was selected
> -     *   - a policy module does not provide all handlers
> -     *   - a policy module failed to init
> -     */
> -    xsm_fixup_ops(&xsm_ops);
> -
> -    if ( xsm_ops_registered != XSM_OPS_REGISTERED )
> +    if ( xsm_ops_registered != XSM_OPS_REGISTERED ) {

Nit (style): Brace goes on its own line.

Jan



^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH v3 2/7] xsm: remove the ability to disable flask
  2021-08-25 15:22   ` Jan Beulich
@ 2021-08-27 13:42     ` Daniel P. Smith
  0 siblings, 0 replies; 25+ messages in thread
From: Daniel P. Smith @ 2021-08-27 13:42 UTC (permalink / raw)
  To: Jan Beulich
  Cc: Andrew Cooper, George Dunlap, Ian Jackson, Julien Grall,
	Stefano Stabellini, Wei Liu, Daniel De Graaf, xen-devel

On 8/25/21 11:22 AM, Jan Beulich wrote:
> On 05.08.2021 16:06, Daniel P. Smith wrote:
>> On Linux when SELinux is put into permissive mode the descretionary access
>> controls are still in place. Whereas for Xen when the enforcing state of flask
>> is set to permissive, all operations for all domains would succeed, i.e. it
>> does not fall back to the default access controls. To provide a means to mimic
>> a similar but not equivalent behavior, a flask op is present to allow a
>> one-time switch back to the default access controls, aka the "dummy policy".
>>
>> This patch removes this flask op to enforce a consistent XSM usage model that a
>> reboot of Xen is required to change the XSM policy module in use.
>>
>> Signed-off-by: Daniel P. Smith <dpsmith@apertussolutions.com>
> 
> The primary reason you remove this is - aiui - that with alternatives
> patching there's technically not really a way back (would need to re-
> patch every patched location, or every hook would need to check whether
> state changed to disabled and if so chain on to the dummy function).
> This became sufficiently clear to me only when looking at the next
> patch. It would be nice if description also said why the change is
> needed. As it stands to me the description reads at best like something
> that people could have different views on (and initially I didn't mean
> to reply here, for not being convinced of the removal of functionality
> in the common case).
> 
> Jan
> 

Ack, I can expand further.

v/r,
dps


^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH v3 3/7] xsm: refactor xsm_ops handling
  2021-08-25 15:16   ` Jan Beulich
@ 2021-08-27 13:44     ` Daniel P. Smith
  0 siblings, 0 replies; 25+ messages in thread
From: Daniel P. Smith @ 2021-08-27 13:44 UTC (permalink / raw)
  To: Jan Beulich; +Cc: Daniel De Graaf, xen-devel

On 8/25/21 11:16 AM, Jan Beulich wrote:
> On 05.08.2021 16:06, Daniel P. Smith wrote:
>> @@ -747,16 +747,16 @@ extern int xsm_dt_policy_init(void **policy_buffer, size_t *policy_size);
>>  extern bool has_xsm_magic(paddr_t);
>>  #endif
>>  
>> -extern int register_xsm(struct xsm_operations *ops);
>> -
>> -extern struct xsm_operations dummy_xsm_ops;
>> -extern void xsm_fixup_ops(struct xsm_operations *ops);
>> +extern void xsm_fixup_ops(struct xsm_ops *ops);
>>  
>>  #ifdef CONFIG_XSM_FLASK
>> -extern void flask_init(const void *policy_buffer, size_t policy_size);
>> +extern const struct xsm_ops *flask_init(const void *policy_buffer,
>> +                                        size_t policy_size);
>>  #else
>> -static inline void flask_init(const void *policy_buffer, size_t policy_size)
>> +static inline struct xsm_ops *flask_init(const void *policy_buffer,
> 
> Please use const consistently between real function and stub.

Ack.

>> @@ -766,9 +766,12 @@ extern const unsigned int xsm_flask_init_policy_size;
>>  #endif
>>  
>>  #ifdef CONFIG_XSM_SILO
>> -extern void silo_init(void);
>> +extern const struct xsm_ops *silo_init(void);
>>  #else
>> -static inline void silo_init(void) {}
>> +static inline struct xsm_ops *silo_init(void)
> 
> Same here.

Ack.

>> --- a/xen/xsm/flask/hooks.c
>> +++ b/xen/xsm/flask/hooks.c
>> @@ -1745,7 +1745,7 @@ static int flask_argo_send(const struct domain *d, const struct domain *t)
>>  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);
>>  
>> -static struct xsm_operations flask_ops = {
>> +static const struct xsm_ops __initconst flask_ops = {
> 
> __initconstrel please (I thought I had pointed out the difference
> already during earlier discussion). Same for SILO then of course.

Apologies, yes you did and that is my fault as I had only recorded the
__initconst suggestion in my checklist and did not update with your
__initconstrel suggestion.

>> --- a/xen/xsm/xsm_core.c
>> +++ b/xen/xsm/xsm_core.c
>> @@ -28,9 +28,17 @@
>>  #include <asm/setup.h>
>>  #endif
>>  
>> -#define XSM_FRAMEWORK_VERSION    "1.0.0"
>> +#define XSM_FRAMEWORK_VERSION    "1.0.1"
>>  
>> -struct xsm_operations *xsm_ops;
>> +struct xsm_ops xsm_ops;
> 
> __read_mostly?

Ack.

v/r,
dps



^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH v3 5/7] xsm: decouple xsm header inclusion selection
  2021-08-26  8:13   ` Jan Beulich
@ 2021-08-27 14:06     ` Daniel P. Smith
  2021-08-30 13:24       ` Jan Beulich
  0 siblings, 1 reply; 25+ messages in thread
From: Daniel P. Smith @ 2021-08-27 14:06 UTC (permalink / raw)
  To: Jan Beulich; +Cc: Daniel De Graaf, xen-devel

On 8/26/21 4:13 AM, Jan Beulich wrote:
> On 05.08.2021 16:06, Daniel P. Smith wrote:
>> --- /dev/null
>> +++ b/xen/include/xsm/xsm-core.h
>> @@ -0,0 +1,273 @@
>> +/*
>> + *  This file contains the XSM hook definitions for Xen.
>> + *
>> + *  This work is based on the LSM implementation in Linux 2.6.13.4.
>> + *
>> + *  Author:  George Coker, <gscoker@alpha.ncsc.mil>
>> + *
>> + *  Contributors: Michael LeMay, <mdlemay@epoch.ncsc.mil>
>> + *
>> + *  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.
>> + */
>> +
>> +#ifndef __XSM_CORE_H__
>> +#define __XSM_CORE_H__
>> +
>> +#include <xen/sched.h>
>> +#include <xen/multiboot.h>
> 
> I was going to ask to invert the order (as we try to arrange #include-s
> alphabetically), but it looks like multiboot.h isn't fit for this.

So my understanding is to leave this as is.

>> +typedef void xsm_op_t;
>> +DEFINE_XEN_GUEST_HANDLE(xsm_op_t);
> 
> Just FTR - I consider this dubious. If void is meant, I don't see why
> a void handle can't be used.

Unless I am misunderstanding what you are calling for, I am afraid this
will trickle further that what intended to be addressed in this patch
set. If disagree and would like to provide me a suggest that stays
bounded, I would gladly incorporate.

>> +/* policy magic number (defined by XSM_MAGIC) */
>> +typedef uint32_t xsm_magic_t;
>> +
>> +#ifdef CONFIG_XSM_FLASK
>> +#define XSM_MAGIC 0xf97cff8c
>> +#else
>> +#define XSM_MAGIC 0x0
>> +#endif
>> +
>> +/* These annotations are used by callers and in dummy.h to document the
>> + * default actions of XSM hooks. They should be compiled out otherwise.
>> + */
> 
> I realize you only move code, but like e.g. the u32 -> uint32_t change
> in context above I'd like to encourage you to also address other style
> issues in the newly introduced file. Here I'm talking about comment
> style, requiring /* to be on its own line.

Ack.

>> +enum xsm_default {
>> +    XSM_HOOK,     /* Guests can normally access the hypercall */
>> +    XSM_DM_PRIV,  /* Device model can perform on its target domain */
>> +    XSM_TARGET,   /* Can perform on self or your target domain */
>> +    XSM_PRIV,     /* Privileged - normally restricted to dom0 */
>> +    XSM_XS_PRIV,  /* Xenstore domain - can do some privileged operations */
>> +    XSM_OTHER     /* Something more complex */
>> +};
>> +typedef enum xsm_default xsm_default_t;
>> +
>> +struct xsm_ops {
>> +    void (*security_domaininfo) (struct domain *d,
> 
> Similarly here (and below) - we don't normally put a blank between
> the closing and opening parentheses in function pointer declarations.
> The majority does so here, but ...

Ack.

>> [...]
>> +    int (*page_offline)(uint32_t cmd);
>> +    int (*hypfs_op)(void);
> 
> ... there are exceptions.
> 
>> [...]
>> +    int (*platform_op) (uint32_t cmd);
>> +
>> +#ifdef CONFIG_X86
>> +    int (*do_mca) (void);
>> +    int (*shadow_control) (struct domain *d, uint32_t op);
>> +    int (*mem_sharing_op) (struct domain *d, struct domain *cd, int op);
>> +    int (*apic) (struct domain *d, int cmd);
>> +    int (*memtype) (uint32_t access);
>> +    int (*machine_memory_map) (void);
>> +    int (*domain_memory_map) (struct domain *d);
>> +#define XSM_MMU_UPDATE_READ      1
>> +#define XSM_MMU_UPDATE_WRITE     2
>> +#define XSM_MMU_NORMAL_UPDATE    4
>> +#define XSM_MMU_MACHPHYS_UPDATE  8
>> +    int (*mmu_update) (struct domain *d, struct domain *t,
>> +                       struct domain *f, uint32_t flags);
>> +    int (*mmuext_op) (struct domain *d, struct domain *f);
>> +    int (*update_va_mapping) (struct domain *d, struct domain *f,
>> +                              l1_pgentry_t pte);
>> +    int (*priv_mapping) (struct domain *d, struct domain *t);
>> +    int (*ioport_permission) (struct domain *d, uint32_t s, uint32_t e,
>> +                              uint8_t allow);
>> +    int (*ioport_mapping) (struct domain *d, uint32_t s, uint32_t e,
>> +                           uint8_t allow);
>> +    int (*pmu_op) (struct domain *d, unsigned int op);
>> +#endif
>> +    int (*dm_op) (struct domain *d);
> 
> To match grouping elsewhere, a blank line above here, ...

Ack.

>> +    int (*xen_version) (uint32_t cmd);
>> +    int (*domain_resource_map) (struct domain *d);
>> +#ifdef CONFIG_ARGO
> 
> ... and here would be nice.

Ack.

>> +    int (*argo_enable) (const struct domain *d);
>> +    int (*argo_register_single_source) (const struct domain *d,
>> +                                        const struct domain *t);
>> +    int (*argo_register_any_source) (const struct domain *d);
>> +    int (*argo_send) (const struct domain *d, const struct domain *t);
>> +#endif
>> +};
>> +
>> +extern void xsm_fixup_ops(struct xsm_ops *ops);
>> +
>> +#ifdef CONFIG_XSM
>> +
>> +#ifdef CONFIG_MULTIBOOT
>> +extern int xsm_multiboot_init(unsigned long *module_map,
>> +                              const multiboot_info_t *mbi);
>> +extern int xsm_multiboot_policy_init(unsigned long *module_map,
>> +                                     const multiboot_info_t *mbi,
>> +                                     void **policy_buffer,
>> +                                     size_t *policy_size);
>> +#endif
>> +
>> +#ifdef CONFIG_HAS_DEVICE_TREE
>> +/*
>> + * Initialize XSM
>> + *
>> + * On success, return 1 if using SILO mode else 0.
>> + */
>> +extern int xsm_dt_init(void);
>> +extern int xsm_dt_policy_init(void **policy_buffer, size_t *policy_size);
>> +extern bool has_xsm_magic(paddr_t);
>> +#endif
>> +
>> +#ifdef CONFIG_XSM_FLASK
>> +extern const struct xsm_ops *flask_init(const void *policy_buffer,
>> +                                        size_t policy_size);
>> +#else
>> +static inline const struct xsm_ops *flask_init(const void *policy_buffer,
>> +                                               size_t policy_size)
>> +{
>> +    return NULL;
>> +}
>> +#endif
>> +
>> +#ifdef CONFIG_XSM_FLASK_POLICY
>> +extern const unsigned char xsm_flask_init_policy[];
>> +extern const unsigned int xsm_flask_init_policy_size;
>> +#endif
> 
> To be honest, I don't think this belongs in any header. This interfaces
> with a generated assembly file. In such a case I would always suggest
> to limit visibility of the symbols as much as possible, i.e. put the
> declarations in the sole file referencing them.

Confirmed only used in xsm_core.c, so will move there.

>> +#ifdef CONFIG_XSM_SILO
>> +extern const struct xsm_ops *silo_init(void);
>> +#else
>> +static const inline struct xsm_ops *silo_init(void)
>> +{
>> +    return NULL;
>> +}
>> +#endif
>> +
>> +#else /* CONFIG_XSM */
>> +
>> +#ifdef CONFIG_MULTIBOOT
>> +static inline int xsm_multiboot_init (unsigned long *module_map,
> 
> Nit: Stray blank ahead of the opening parenthesis.

Ack.

> Looking back there's also the question of "extern" on function
> declarations. In new code I don't think we put the redundant
> storage class specifier there; they're only needed on data
> declarations. I'm inclined to suggest to drop all of them while
> moving the code.
> 
> Preferably with these adjustments
> Acked-by: Jan Beulich <jbeulich@suse.com>

I believe I have pretty much incorporated all your adjustments. Will
include your Acked-by unless you feel I have not.

v/r,
dps


^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH v3 6/7] xsm: drop generic event channel labeling exclusion
  2021-08-25 15:44   ` Jan Beulich
@ 2021-08-27 14:16     ` Daniel P. Smith
  2021-08-30 13:25       ` Jan Beulich
  0 siblings, 1 reply; 25+ messages in thread
From: Daniel P. Smith @ 2021-08-27 14:16 UTC (permalink / raw)
  To: Jan Beulich
  Cc: Andrew Cooper, George Dunlap, Ian Jackson, Julien Grall,
	Stefano Stabellini, Wei Liu, xen-devel

On 8/25/21 11:44 AM, Jan Beulich wrote:
> On 05.08.2021 16:06, Daniel P. Smith wrote:
>> The internal define flag is not used by any XSM module, removing the #ifdef
>> leaving the generic event channel labeling as always present.
> 
> With this description ...
> 
>> --- a/xen/include/xen/sched.h
>> +++ b/xen/include/xen/sched.h
>> @@ -120,15 +120,12 @@ struct evtchn
>>      unsigned short notify_vcpu_id; /* VCPU for local delivery notification */
>>      uint32_t fifo_lastq;           /* Data for identifying last queue. */
>>  
>> -#ifdef CONFIG_XSM
>>      union {
>> -#ifdef XSM_NEED_GENERIC_EVTCHN_SSID
>>          /*
>>           * If an XSM module needs more space for its event channel context,
>>           * this pointer stores the necessary data for the security server.
>>           */
>>          void *generic;
>> -#endif
>>  #ifdef CONFIG_XSM_FLASK
>>          /*
>>           * Inlining the contents of the structure for FLASK avoids unneeded
>> @@ -138,7 +135,6 @@ struct evtchn
>>          uint32_t flask_sid;
>>  #endif
>>      } ssid;
>> -#endif
>>  } __attribute__((aligned(64)));
> 
> ... I can see the inner #ifdef go away, but not the outer one. While
> the (imo bogus) attribute means you don't alter the size of the
> struct, I'm afraid that's not obvious at all without counting bits
> and bytes, and hence this may also want saying explicitly in the
> description.

I can put the #ifdef CONFIG_XSM back and in the subsequent patch change
it to CONFIG_XSM_CONFIGURABLE, making this the only difference between
being able to select the XSM policy in effect or not.

v/r,
dps



^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH v3 7/7] xsm: removing facade that XSM can be enabled/disabled
  2021-08-26  9:37   ` Jan Beulich
@ 2021-08-30 12:11     ` Daniel P. Smith
  2021-08-30 13:34       ` Jan Beulich
  0 siblings, 1 reply; 25+ messages in thread
From: Daniel P. Smith @ 2021-08-30 12:11 UTC (permalink / raw)
  To: Jan Beulich
  Cc: Andrew Cooper, Ian Jackson, George Dunlap, Julien Grall,
	Stefano Stabellini, Wei Liu, Daniel De Graaf, xen-devel

On 8/26/21 5:37 AM, Jan Beulich wrote:
> On 05.08.2021 16:06, Daniel P. Smith wrote:
>> The XSM facilities are always in use by Xen with the facade of being able to
>> turn XSM on and off. This option is in fact about allowing the selection of
>> which policies are available and which are used at runtime.  To provide this
>> facade a complicated serious of #ifdef's are used to selective include
> 
> Nit: It took me a moment to realize that the sentence reads oddly because
> you likely mean "series", not "serious".
> 
>> different headers or portions of headers. This series of #ifdef gyrations
>> switches between two different versions of the XSM hook interfaces and their
>> respective backing implementation.  All of this is done to provide a minimal
>> size/performance optimization for when alternative policies are disabled.
>>
>> To unwind the #ifdef gyrations a series of changes were necessary,
>>     * replace CONFIG_XSM with XSM_CONFIGURABLE to allow visibility of
>>       selecting alternate XSM policy modules to those that require it
>>     * adjusted CONFIG_XSM_SILO, CONFIG_XSM_FLASK, and the default module
>>       selection to sensible defaults
>>     * collapsed the "dummy/defualt" XSM interface and implementation with the
>>       "multiple policy" interface to provide a single inlined implementation
>>       that attempts to use a registered hook and falls back to the check from
>>       the dummy implementation
>>     * the collapse to a single interface broke code relying on the alternate
>>       interface, specifically SILO, this was reworked to remove the
>>       indirection/abstraction making SILO explicit in its access control
>>       decisions
>>     * with the change of the XSM hooks to fall back to enforcing the dummy
>>       policy, it is no longer necessary to fill NULL entries in the struct
>>       xsm_ops returned by an XSM module's init
> 
> It would be nice if some of this could be split. Is this really close to
> impossible?

I am looking into that now, especially after my points below.

>> --- a/xen/common/Kconfig
>> +++ b/xen/common/Kconfig
>> @@ -200,23 +200,15 @@ config XENOPROF
>>  
>>  	  If unsure, say Y.
>>  
>> -config XSM
>> -	bool "Xen Security Modules support"
>> -	default ARM
>> -	---help---
>> -	  Enables the security framework known as Xen Security Modules which
>> -	  allows administrators fine-grained control over a Xen domain and
>> -	  its capabilities by defining permissible interactions between domains,
>> -	  the hypervisor itself, and related resources such as memory and
>> -	  devices.
>> -
>> -	  If unsure, say N.
>> +config XSM_CONFIGURABLE
>> +    bool "Enable Configuring Xen Security Modules"
> 
> Is there a reason to change not only the prompt, but also the name of
> the Kconfig setting? This alone is the reason for some otherwise
> unnecessary code churn.

Yes, because this idea of "turning off" XSM needs to end externally and
internally. The XSM framework is always being used, it's just that it is
possible to build a configuration with support only for the
default/dummy policy, regardless of how the functions implementing the
default/dummy policy are being invoked.

> Also please correct indentation here.

Ack.

>>  config XSM_FLASK
>> -	def_bool y
>> -	prompt "FLux Advanced Security Kernel support"
>> -	depends on XSM
>> -	---help---
>> +	bool "FLux Advanced Security Kernel support"
>> +	default n
> 
> I don't understand this change in default (and as an aside, a default
> of "n" doesn't need spelling out): In the description you say "adjusted
> CONFIG_XSM_SILO, CONFIG_XSM_FLASK, and the default module selection to
> sensible defaults". If that's to describe this change, then I'm afraid
> I don't see why defaulting to "n" is more sensible once the person
> configuring Xen has chosen the configure XSM's (or XSM_CONFIGURABLE's)
> sub-options. If that's unrelated to the change here, then I'm afraid
> I'm missing justification altogether. (Same for SILO then.)

When an individual selects to be able to be to configure/select
alternative policy modules, they should be the ones to decide which
one(s) should be enabled and not have presumptuous selections provided
to them. IOW, the sensible default is to have no modules selected and
allow the user to enable the one(s) they want.

>> +	depends on XSM_CONFIGURABLE
>> +	select XSM_EVTCHN_LABELING
> 
> Neither this nor any prior patch introduces an option of this name,
> and there's also none in the present tree. All afaics; I may have
> overlooked something or typo-ed a "grep" command.

Ack, missed this in the previous patch. will clean it up there.

>> @@ -265,14 +258,14 @@ config XSM_SILO
>>  	  If unsure, say Y.
>>  
>>  choice
>> -	prompt "Default XSM implementation"
>> -	depends on XSM
>> +	prompt "Default XSM module"
>>  	default XSM_SILO_DEFAULT if XSM_SILO && ARM
>>  	default XSM_FLASK_DEFAULT if XSM_FLASK
>>  	default XSM_SILO_DEFAULT if XSM_SILO
>>  	default XSM_DUMMY_DEFAULT
>> +	depends on XSM_CONFIGURABLE
> 
> With the larger set of "default" lines I'd like to suggest to keep

Ack.

>> @@ -282,7 +275,7 @@ endchoice
>>  config LATE_HWDOM
>>  	bool "Dedicated hardware domain"
>>  	default n
>> -	depends on XSM && X86
>> +	depends on XSM_FLASK && X86
> 
> This change is not mentioned or justified in the description. In fact
> I think it is unrelated to the change here and hence would want breaking
> out.

Actually, if you read the help just below it specifically says to use
this feature requires having an XSM policy (legacy wording for XSM Flask
policy) to be able to do the proper fine grained delegation of the
permissions/accesses necessary for a hardware domain to work. This
should have been made XSM_FLASK when that KConfig option was added.
Dropping the XSM KConfig option just exposed this oversight. Ack that I
should have mentioned this in the commit message.

>>  	---help---
> 
> As you're changing these elsewhere, any chance of you also changing
> this one to just "help"?

Ack.

>> --- a/xen/include/xsm/xsm.h
>> +++ b/xen/include/xsm/xsm.h
>> @@ -19,545 +19,1023 @@
>>  #include <xen/sched.h>
>>  #include <xen/multiboot.h>
>>  #include <xsm/xsm-core.h>
>> -
>> -#ifdef CONFIG_XSM
>> +#include <xsm/dummy.h>
>> +#include <public/version.h>
>>  
>>  extern struct xsm_ops xsm_ops;
>>  
>> -static inline void xsm_security_domaininfo (struct domain *d,
>> -                                        struct xen_domctl_getdomaininfo *info)
>> +static inline void xsm_security_domaininfo(
>> +    struct domain *d,
>> +    struct xen_domctl_getdomaininfo *info)
>>  {
>> -    alternative_vcall(xsm_ops.security_domaininfo, d, info);
>> +    if ( xsm_ops.security_domaininfo )
>> +        alternative_vcall(xsm_ops.security_domaininfo, d, info);
> 
> Here and everywhere else, when !XSM_CONFIGURABLE you now needlessly
> force NULL checks to occur which are never going to be true. There's
> then also the dead indirect call and the associated patching data. I
> think this wants hiding in another pair of wrappers, which simply
> expand to nothing when !XSM_CONFIGURABLE - perhaps xsm_vcall() and
> xsm_call().


This has now come back full circle to the attempts made in v1 at
addressing the RFC comments collected at the developer's summit. The
calls xsm_vcall and xsm_call will not be simple since the different xsm
hooks take a different number of arguments. Therefore these calls will
have to become a series of macros to handle the varying number of
arguments, similar to alternative_call and elsewhere but instead of
being general purpose for use throughout the hypervisor they will create
a complication in the code that is dedicated to a single file under XSM.
Outside of a demonstrable significant performance impact that can be
measured, the goal for security relevant code should be simplicity and
ability to reason about correctness. Therefore without a demonstration
that there is an actual performance impact simplicity should be the goal
here, especially considering this effort has unmasked potential bugs
noted below that were masked by this kind of complication.

With that I would like to withdraw this patch and spin a v4 of this
patch set with that revives the dropping of the inlines done similar to
v1/v2. As requested above, I will look to see if any of the changes that
still applies could be split into dedicated commits.

<snip>

>> -static inline int xsm_set_target (xsm_default_t def, struct domain *d, struct domain *e)
>> +static inline int xsm_set_target(xsm_default_t action, struct domain *d,
>> +                                 struct domain *e)
>>  {
>> -    return alternative_call(xsm_ops.set_target, d, e);
>> +    if ( xsm_ops.set_target )
>> +        return alternative_call(xsm_ops.set_target, d, e);
>> +
>> +    XSM_ASSERT_ACTION(XSM_HOOK);
>> +    return xsm_default_action(action, current->domain, NULL);
>>  }
> 
> While benign because xsm_default_action() does nothing for XSM_HOOK, I
> think there's an inconsistency here which rather wants correcting (in
> a prereq patch): The default hook should have been passed consistent
> arguments, no matter whether used because of !XSM or because of the
> module in use left the hook unset.
> 
> Of course such anomalies are much easier to notice (outside of review
> of patches introducing such) with you now placing both invocations
> next to each other.

This series assumes the logic is correct and is only focused on trying
to make XSM more maintainable. I would be glad to consider looking at
what the right security decisions should be in a subsequent patch set
but will be consider out of scope for this patch set.

>> -static inline int xsm_evtchn_interdomain (xsm_default_t def, struct domain *d1,
>> -                struct evtchn *chan1, struct domain *d2, struct evtchn *chan2)
>> +static inline int xsm_evtchn_interdomain(xsm_default_t action,
>> +                                         struct domain *d1,
>> +                                         struct evtchn *chan1,
>> +                                         struct domain *d2,
>> +                                         struct evtchn *chan2)
>>  {
>> -    return alternative_call(xsm_ops.evtchn_interdomain, d1, chan1, d2, chan2);
>> +    if ( xsm_ops.evtchn_interdomain )
>> +        return alternative_call(xsm_ops.evtchn_interdomain, d1, chan1, d2,
>> +                                chan2);
>> +
>> +    XSM_ASSERT_ACTION(XSM_HOOK);
>> +    return xsm_default_action(action, d1, d2);
>>  }
> 
> There's another anomaly here: The first argument to xsm_default_action()
> typically is current->domain in similar functions. Here d1 gets passed in
> despite always being current->domain. I think the unnecessary parameter
> wants dropping (again in a prereq patch)) from the wrapper and hook, to
> avoid giving the wrong impression of both domains potentially being remote
> ones.

out of scope

>> -static inline int xsm_evtchn_send (xsm_default_t def, struct domain *d, struct evtchn *chn)
>> +static inline int xsm_evtchn_send(xsm_default_t action, struct domain *d,
>> +                                  struct evtchn *chn)
>>  {
>> -    return alternative_call(xsm_ops.evtchn_send, d, chn);
>> +    if ( xsm_ops.evtchn_send )
>> +        return alternative_call(xsm_ops.evtchn_send, d, chn);
>> +
>> +    XSM_ASSERT_ACTION(XSM_HOOK);
>> +    return xsm_default_action(action, d, NULL);
> 
> This again looks wrong (and again is benign only because XSM_HOOK means
> xsm_default_action() ignores the other function parameters), wanting to
> follow the usual
> 
>     return xsm_default_action(action, current->domain, d);
> 
> pattern instead.

out of scope

>> -static inline int xsm_evtchn_reset (xsm_default_t def, struct domain *d1, struct domain *d2)
>> +static inline int xsm_evtchn_reset(xsm_default_t action, struct domain *d1,
>> +                                   struct domain *d2)
>>  {
>> -    return alternative_call(xsm_ops.evtchn_reset, d1, d2);
>> +    if ( xsm_ops.evtchn_reset )
>> +        return alternative_call(xsm_ops.evtchn_reset, d1, d2);
>> +
>> +    XSM_ASSERT_ACTION(XSM_TARGET);
>> +    return xsm_default_action(action, d1, d2);
> 
> See xsm_evtchn_interdomain() above.

out of scope

>> -static inline int xsm_grant_mapref (xsm_default_t def, struct domain *d1, struct domain *d2,
>> -                                                                uint32_t flags)
>> +static inline int xsm_grant_mapref(xsm_default_t action, struct domain *d1,
>> +                                   struct domain *d2, uint32_t flags)
>>  {
>> -    return alternative_call(xsm_ops.grant_mapref, d1, d2, flags);
>> +    if ( xsm_ops.grant_mapref )
>> +        return alternative_call(xsm_ops.grant_mapref, d1, d2, flags);
>> +
>> +    XSM_ASSERT_ACTION(XSM_HOOK);
>> +    return xsm_default_action(action, d1, d2);
> 
> Again (more similar grant ones follow).

out of scope

>> -static inline int xsm_memory_adjust_reservation (xsm_default_t def, struct domain *d1, struct
>> -                                                                    domain *d2)
>> +static inline int xsm_memory_adjust_reservation(xsm_default_t action,
>> +                                                struct domain *d1,
>> +                                                struct domain *d2)
>>  {
>> -    return alternative_call(xsm_ops.memory_adjust_reservation, d1, d2);
>> +    if ( xsm_ops.memory_adjust_reservation )
>> +        return alternative_call(xsm_ops.memory_adjust_reservation, d1, d2);
>> +
>> +    XSM_ASSERT_ACTION(XSM_TARGET);
>> +    return xsm_default_action(action, d1, d2);
> 
> Again (more similar memory ones follow).

out of scope

>> -static inline int xsm_memory_pin_page(xsm_default_t def, struct domain *d1, struct domain *d2,
>> -                                      struct page_info *page)
>> +static inline int xsm_memory_pin_page(xsm_default_t action, struct domain *d1,
>> +                                      struct domain *d2, struct page_info *page)
>>  {
>> -    return alternative_call(xsm_ops.memory_pin_page, d1, d2, page);
>> +    if ( xsm_ops.memory_pin_page )
>> +        return alternative_call(xsm_ops.memory_pin_page, d1, d2, page);
>> +
>> +    XSM_ASSERT_ACTION(XSM_HOOK);
>> +    return xsm_default_action(action, d1, d2);
> 
> This one has the same issue, but is more interesting: There's no
> similar hook/check for unpinning a page (nor does the same check
> get re-used there). Plus it's x86 (more precisely PV) specific.

out of scope

>> -static inline int xsm_map_gmfn_foreign (xsm_default_t def, struct domain *d, struct domain *t)
>> +static inline int xsm_map_gmfn_foreign(xsm_default_t action, struct domain *d,
>> +                                       struct domain *t)
>>  {
>> -    return alternative_call(xsm_ops.map_gmfn_foreign, d, t);
>> +    if ( xsm_ops.map_gmfn_foreign )
>> +        return alternative_call(xsm_ops.map_gmfn_foreign, d, t);
>> +
>> +    XSM_ASSERT_ACTION(XSM_TARGET);
>> +    return xsm_default_action(action, d, t);
> 
> This one is also interesting: There's no check at all here that
> current->domain has any permissions towards d or t. Interestingly
> even flask_map_gmfn_foreign() doesn't check this.

out of scope

>> -static inline int xsm_console_io (xsm_default_t def, struct domain *d, int cmd)
>> +static inline int xsm_console_io(xsm_default_t action, struct domain *d, int cmd)
>>  {
>> -    return alternative_call(xsm_ops.console_io, d, cmd);
>> +    if ( xsm_ops.console_io )
>> +        return alternative_call(xsm_ops.console_io, d, cmd);
>> +
>> +    XSM_ASSERT_ACTION(XSM_OTHER);
>> +    if ( d->is_console )
>> +        return xsm_default_action(XSM_HOOK, d, NULL);
>> +#ifdef CONFIG_VERBOSE_DEBUG
>> +    if ( cmd == CONSOLEIO_write )
>> +        return xsm_default_action(XSM_HOOK, d, NULL);
>> +#endif
>> +    return xsm_default_action(XSM_PRIV, d, NULL);
> 
> Same implication of d == current->domain here again. I guess I'll
> stop enumerating further ones.

out of scope

<snip>

>> -static inline int xsm_pmu_op (xsm_default_t def, struct domain *d, unsigned int op)
>> +static inline int xsm_pmu_op(xsm_default_t action, struct domain *d,
>> +                             unsigned int op)
>>  {
>> -    return alternative_call(xsm_ops.pmu_op, d, op);
>> +    if ( xsm_ops.pmu_op )
>> +        return alternative_call(xsm_ops.pmu_op, d, op);
>> +
>> +    XSM_ASSERT_ACTION(XSM_OTHER);
>> +    switch ( op )
>> +    {
>> +    case XENPMU_init:
>> +    case XENPMU_finish:
>> +    case XENPMU_lvtpc_set:
>> +    case XENPMU_flush:
>> +        return xsm_default_action(XSM_HOOK, d, current->domain);
>> +    default:
>> +        return xsm_default_action(XSM_PRIV, d, current->domain);
> 
> Urgh - isn't this the wrong way round? (Luckily vPMU isn't security
> supported, so no XSA would be needed.)

out of scope

<snip>

>> --- a/xen/xsm/silo.c
>> +++ b/xen/xsm/silo.c
>> @@ -17,6 +17,7 @@
>>   * You should have received a copy of the GNU General Public License along with
>>   * this program; If not, see <http://www.gnu.org/licenses/>.
>>   */
>> +#include <xsm/xsm-core.h>
>>  #include <xsm/dummy.h>
> 
> As already mentioned elsewhere - where possible please arrange #include-s
> alphabetically.

Ack.

>> @@ -124,16 +122,12 @@ static int __init xsm_core_init(const void *policy_buffer, size_t policy_size)
>>          break;
>>      }
>>  
>> -    /*
>> -     * This handles three cases,
>> -     *   - dummy policy module was selected
>> -     *   - a policy module does not provide all handlers
>> -     *   - a policy module failed to init
>> -     */
>> -    xsm_fixup_ops(&xsm_ops);
>> -
>> -    if ( xsm_ops_registered != XSM_OPS_REGISTERED )
>> +    if ( xsm_ops_registered != XSM_OPS_REGISTERED ) {
> 
> Nit (style): Brace goes on its own line.

Ack

v/r,
dps



^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH v3 5/7] xsm: decouple xsm header inclusion selection
  2021-08-27 14:06     ` Daniel P. Smith
@ 2021-08-30 13:24       ` Jan Beulich
  2021-08-30 13:41         ` Daniel P. Smith
  0 siblings, 1 reply; 25+ messages in thread
From: Jan Beulich @ 2021-08-30 13:24 UTC (permalink / raw)
  To: Daniel P. Smith; +Cc: Daniel De Graaf, xen-devel

On 27.08.2021 16:06, Daniel P. Smith wrote:
> On 8/26/21 4:13 AM, Jan Beulich wrote:
>> On 05.08.2021 16:06, Daniel P. Smith wrote:
>>> --- /dev/null
>>> +++ b/xen/include/xsm/xsm-core.h
>>> @@ -0,0 +1,273 @@
>>> +/*
>>> + *  This file contains the XSM hook definitions for Xen.
>>> + *
>>> + *  This work is based on the LSM implementation in Linux 2.6.13.4.
>>> + *
>>> + *  Author:  George Coker, <gscoker@alpha.ncsc.mil>
>>> + *
>>> + *  Contributors: Michael LeMay, <mdlemay@epoch.ncsc.mil>
>>> + *
>>> + *  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.
>>> + */
>>> +
>>> +#ifndef __XSM_CORE_H__
>>> +#define __XSM_CORE_H__
>>> +
>>> +#include <xen/sched.h>
>>> +#include <xen/multiboot.h>
>>
>> I was going to ask to invert the order (as we try to arrange #include-s
>> alphabetically), but it looks like multiboot.h isn't fit for this.
> 
> So my understanding is to leave this as is.

Yes, unfortunately.

>>> +typedef void xsm_op_t;
>>> +DEFINE_XEN_GUEST_HANDLE(xsm_op_t);
>>
>> Just FTR - I consider this dubious. If void is meant, I don't see why
>> a void handle can't be used.
> 
> Unless I am misunderstanding what you are calling for, I am afraid this
> will trickle further that what intended to be addressed in this patch
> set. If disagree and would like to provide me a suggest that stays
> bounded, I would gladly incorporate.

All I'm asking is to remove this pointless typedef and handle definition,
seeing that you're doing a major rework anyway. I'm afraid I don't see
how this would collide with the purpose of the overall series (albeit I
may also have misunderstood your reply, as the 2nd half of the first
sentence makes me struggle some with trying to parse it).

Jan



^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH v3 6/7] xsm: drop generic event channel labeling exclusion
  2021-08-27 14:16     ` Daniel P. Smith
@ 2021-08-30 13:25       ` Jan Beulich
  0 siblings, 0 replies; 25+ messages in thread
From: Jan Beulich @ 2021-08-30 13:25 UTC (permalink / raw)
  To: Daniel P. Smith
  Cc: Andrew Cooper, George Dunlap, Ian Jackson, Julien Grall,
	Stefano Stabellini, Wei Liu, xen-devel

On 27.08.2021 16:16, Daniel P. Smith wrote:
> On 8/25/21 11:44 AM, Jan Beulich wrote:
>> On 05.08.2021 16:06, Daniel P. Smith wrote:
>>> The internal define flag is not used by any XSM module, removing the #ifdef
>>> leaving the generic event channel labeling as always present.
>>
>> With this description ...
>>
>>> --- a/xen/include/xen/sched.h
>>> +++ b/xen/include/xen/sched.h
>>> @@ -120,15 +120,12 @@ struct evtchn
>>>      unsigned short notify_vcpu_id; /* VCPU for local delivery notification */
>>>      uint32_t fifo_lastq;           /* Data for identifying last queue. */
>>>  
>>> -#ifdef CONFIG_XSM
>>>      union {
>>> -#ifdef XSM_NEED_GENERIC_EVTCHN_SSID
>>>          /*
>>>           * If an XSM module needs more space for its event channel context,
>>>           * this pointer stores the necessary data for the security server.
>>>           */
>>>          void *generic;
>>> -#endif
>>>  #ifdef CONFIG_XSM_FLASK
>>>          /*
>>>           * Inlining the contents of the structure for FLASK avoids unneeded
>>> @@ -138,7 +135,6 @@ struct evtchn
>>>          uint32_t flask_sid;
>>>  #endif
>>>      } ssid;
>>> -#endif
>>>  } __attribute__((aligned(64)));
>>
>> ... I can see the inner #ifdef go away, but not the outer one. While
>> the (imo bogus) attribute means you don't alter the size of the
>> struct, I'm afraid that's not obvious at all without counting bits
>> and bytes, and hence this may also want saying explicitly in the
>> description.
> 
> I can put the #ifdef CONFIG_XSM back and in the subsequent patch change
> it to CONFIG_XSM_CONFIGURABLE, making this the only difference between
> being able to select the XSM policy in effect or not.

Well, yes, that's one way of addressing my comment. Another would be to
actually justify the removal. (Personally I'm in favor of the former.)

Jan



^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH v3 7/7] xsm: removing facade that XSM can be enabled/disabled
  2021-08-30 12:11     ` Daniel P. Smith
@ 2021-08-30 13:34       ` Jan Beulich
  0 siblings, 0 replies; 25+ messages in thread
From: Jan Beulich @ 2021-08-30 13:34 UTC (permalink / raw)
  To: Daniel P. Smith
  Cc: Andrew Cooper, Ian Jackson, George Dunlap, Julien Grall,
	Stefano Stabellini, Wei Liu, Daniel De Graaf, xen-devel

On 30.08.2021 14:11, Daniel P. Smith wrote:
> On 8/26/21 5:37 AM, Jan Beulich wrote:
>> On 05.08.2021 16:06, Daniel P. Smith wrote:
>>>  config XSM_FLASK
>>> -	def_bool y
>>> -	prompt "FLux Advanced Security Kernel support"
>>> -	depends on XSM
>>> -	---help---
>>> +	bool "FLux Advanced Security Kernel support"
>>> +	default n
>>
>> I don't understand this change in default (and as an aside, a default
>> of "n" doesn't need spelling out): In the description you say "adjusted
>> CONFIG_XSM_SILO, CONFIG_XSM_FLASK, and the default module selection to
>> sensible defaults". If that's to describe this change, then I'm afraid
>> I don't see why defaulting to "n" is more sensible once the person
>> configuring Xen has chosen the configure XSM's (or XSM_CONFIGURABLE's)
>> sub-options. If that's unrelated to the change here, then I'm afraid
>> I'm missing justification altogether. (Same for SILO then.)
> 
> When an individual selects to be able to be to configure/select
> alternative policy modules, they should be the ones to decide which
> one(s) should be enabled and not have presumptuous selections provided
> to them. IOW, the sensible default is to have no modules selected and
> allow the user to enable the one(s) they want.

Just FTR - I disagree. Defaults should be such that a majority would
not need to alter the respective settings.

>>> @@ -282,7 +275,7 @@ endchoice
>>>  config LATE_HWDOM
>>>  	bool "Dedicated hardware domain"
>>>  	default n
>>> -	depends on XSM && X86
>>> +	depends on XSM_FLASK && X86
>>
>> This change is not mentioned or justified in the description. In fact
>> I think it is unrelated to the change here and hence would want breaking
>> out.
> 
> Actually, if you read the help just below it specifically says to use
> this feature requires having an XSM policy (legacy wording for XSM Flask
> policy) to be able to do the proper fine grained delegation of the
> permissions/accesses necessary for a hardware domain to work. This
> should have been made XSM_FLASK when that KConfig option was added.
> Dropping the XSM KConfig option just exposed this oversight. Ack that I
> should have mentioned this in the commit message.

I'm getting the impression that you mistook "breaking out" for "dropping".
I can see the point of the change; it merely shouldn't be hidden in this
otherwise unrelated much larger change.

>>> -static inline int xsm_set_target (xsm_default_t def, struct domain *d, struct domain *e)
>>> +static inline int xsm_set_target(xsm_default_t action, struct domain *d,
>>> +                                 struct domain *e)
>>>  {
>>> -    return alternative_call(xsm_ops.set_target, d, e);
>>> +    if ( xsm_ops.set_target )
>>> +        return alternative_call(xsm_ops.set_target, d, e);
>>> +
>>> +    XSM_ASSERT_ACTION(XSM_HOOK);
>>> +    return xsm_default_action(action, current->domain, NULL);
>>>  }
>>
>> While benign because xsm_default_action() does nothing for XSM_HOOK, I
>> think there's an inconsistency here which rather wants correcting (in
>> a prereq patch): The default hook should have been passed consistent
>> arguments, no matter whether used because of !XSM or because of the
>> module in use left the hook unset.
>>
>> Of course such anomalies are much easier to notice (outside of review
>> of patches introducing such) with you now placing both invocations
>> next to each other.
> 
> This series assumes the logic is correct and is only focused on trying
> to make XSM more maintainable. I would be glad to consider looking at
> what the right security decisions should be in a subsequent patch set
> but will be consider out of scope for this patch set.

Well, I came to make these comments because these anomalies look to
stand in the way of producing a sufficiently small set of wrapper /
helper macros. But since you want to go back to an older version's
approach, the need to correct these as a (series of) prereq(s) may
indeed vanish.

Jan



^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH v3 5/7] xsm: decouple xsm header inclusion selection
  2021-08-30 13:24       ` Jan Beulich
@ 2021-08-30 13:41         ` Daniel P. Smith
  2021-08-30 13:46           ` Jan Beulich
  0 siblings, 1 reply; 25+ messages in thread
From: Daniel P. Smith @ 2021-08-30 13:41 UTC (permalink / raw)
  To: Jan Beulich; +Cc: Daniel De Graaf, xen-devel

On 8/30/21 9:24 AM, Jan Beulich wrote:
> On 27.08.2021 16:06, Daniel P. Smith wrote:
>> On 8/26/21 4:13 AM, Jan Beulich wrote:
>>> On 05.08.2021 16:06, Daniel P. Smith wrote:
>>>> --- /dev/null
>>>> +++ b/xen/include/xsm/xsm-core.h
>>>> @@ -0,0 +1,273 @@
>>>> +/*
>>>> + *  This file contains the XSM hook definitions for Xen.
>>>> + *
>>>> + *  This work is based on the LSM implementation in Linux 2.6.13.4.
>>>> + *
>>>> + *  Author:  George Coker, <gscoker@alpha.ncsc.mil>
>>>> + *
>>>> + *  Contributors: Michael LeMay, <mdlemay@epoch.ncsc.mil>
>>>> + *
>>>> + *  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.
>>>> + */
>>>> +
>>>> +#ifndef __XSM_CORE_H__
>>>> +#define __XSM_CORE_H__
>>>> +
>>>> +#include <xen/sched.h>
>>>> +#include <xen/multiboot.h>
>>>
>>> I was going to ask to invert the order (as we try to arrange #include-s
>>> alphabetically), but it looks like multiboot.h isn't fit for this.
>>
>> So my understanding is to leave this as is.
> 
> Yes, unfortunately.
> 
>>>> +typedef void xsm_op_t;
>>>> +DEFINE_XEN_GUEST_HANDLE(xsm_op_t);
>>>
>>> Just FTR - I consider this dubious. If void is meant, I don't see why
>>> a void handle can't be used.
>>
>> Unless I am misunderstanding what you are calling for, I am afraid this
>> will trickle further that what intended to be addressed in this patch
>> set. If disagree and would like to provide me a suggest that stays
>> bounded, I would gladly incorporate.
> 
> All I'm asking is to remove this pointless typedef and handle definition,
> seeing that you're doing a major rework anyway. I'm afraid I don't see
> how this would collide with the purpose of the overall series (albeit I
> may also have misunderstood your reply, as the 2nd half of the first
> sentence makes me struggle some with trying to parse it).
> 
> Jan
> 

If I drop the typedef and start changing everywhere xsm_op_t is
referenced to void, this now adds hypercall.h to the files I am now
touching.

In the end it is not about whether the change is big or small, but that
more and more unrelated small changes/clean ups keep getting requested.
There has to be a cut-off point to limit the scope of changes down to
the purpose of the patch set, which is to unravel and simplify the XSM
hooks. And this is being done so, so that the the XSM-Roles work can be
introduced to bring a more solid definition to the the default access
control system, which itself is needed to bring in hyperlaunch.

v/r,
dps


^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH v3 5/7] xsm: decouple xsm header inclusion selection
  2021-08-30 13:41         ` Daniel P. Smith
@ 2021-08-30 13:46           ` Jan Beulich
  2021-08-30 13:55             ` Daniel P. Smith
  0 siblings, 1 reply; 25+ messages in thread
From: Jan Beulich @ 2021-08-30 13:46 UTC (permalink / raw)
  To: Daniel P. Smith; +Cc: Daniel De Graaf, xen-devel

On 30.08.2021 15:41, Daniel P. Smith wrote:
> On 8/30/21 9:24 AM, Jan Beulich wrote:
>> On 27.08.2021 16:06, Daniel P. Smith wrote:
>>> On 8/26/21 4:13 AM, Jan Beulich wrote:
>>>> On 05.08.2021 16:06, Daniel P. Smith wrote:
>>>>> --- /dev/null
>>>>> +++ b/xen/include/xsm/xsm-core.h
>>>>> @@ -0,0 +1,273 @@
>>>>> +/*
>>>>> + *  This file contains the XSM hook definitions for Xen.
>>>>> + *
>>>>> + *  This work is based on the LSM implementation in Linux 2.6.13.4.
>>>>> + *
>>>>> + *  Author:  George Coker, <gscoker@alpha.ncsc.mil>
>>>>> + *
>>>>> + *  Contributors: Michael LeMay, <mdlemay@epoch.ncsc.mil>
>>>>> + *
>>>>> + *  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.
>>>>> + */
>>>>> +
>>>>> +#ifndef __XSM_CORE_H__
>>>>> +#define __XSM_CORE_H__
>>>>> +
>>>>> +#include <xen/sched.h>
>>>>> +#include <xen/multiboot.h>
>>>>
>>>> I was going to ask to invert the order (as we try to arrange #include-s
>>>> alphabetically), but it looks like multiboot.h isn't fit for this.
>>>
>>> So my understanding is to leave this as is.
>>
>> Yes, unfortunately.
>>
>>>>> +typedef void xsm_op_t;
>>>>> +DEFINE_XEN_GUEST_HANDLE(xsm_op_t);
>>>>
>>>> Just FTR - I consider this dubious. If void is meant, I don't see why
>>>> a void handle can't be used.
>>>
>>> Unless I am misunderstanding what you are calling for, I am afraid this
>>> will trickle further that what intended to be addressed in this patch
>>> set. If disagree and would like to provide me a suggest that stays
>>> bounded, I would gladly incorporate.
>>
>> All I'm asking is to remove this pointless typedef and handle definition,
>> seeing that you're doing a major rework anyway. I'm afraid I don't see
>> how this would collide with the purpose of the overall series (albeit I
>> may also have misunderstood your reply, as the 2nd half of the first
>> sentence makes me struggle some with trying to parse it).
> 
> If I drop the typedef and start changing everywhere xsm_op_t is
> referenced to void, this now adds hypercall.h to the files I am now
> touching.
> 
> In the end it is not about whether the change is big or small, but that
> more and more unrelated small changes/clean ups keep getting requested.
> There has to be a cut-off point to limit the scope of changes down to
> the purpose of the patch set, which is to unravel and simplify the XSM
> hooks. And this is being done so, so that the the XSM-Roles work can be
> introduced to bring a more solid definition to the the default access
> control system, which itself is needed to bring in hyperlaunch.

Well, yes, you effectively suffer from XSM not having been actively
maintained for a number of years. As said in the original reply, I'd
prefer my ack to cover all the suggested changes, but I didn't mean
to insist. If this particular one goes too far for your taste, so be
it.

Jan



^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH v3 5/7] xsm: decouple xsm header inclusion selection
  2021-08-30 13:46           ` Jan Beulich
@ 2021-08-30 13:55             ` Daniel P. Smith
  0 siblings, 0 replies; 25+ messages in thread
From: Daniel P. Smith @ 2021-08-30 13:55 UTC (permalink / raw)
  To: Jan Beulich; +Cc: Daniel De Graaf, xen-devel

On 8/30/21 9:46 AM, Jan Beulich wrote:
> On 30.08.2021 15:41, Daniel P. Smith wrote:
>> On 8/30/21 9:24 AM, Jan Beulich wrote:
>>> On 27.08.2021 16:06, Daniel P. Smith wrote:
>>>> On 8/26/21 4:13 AM, Jan Beulich wrote:
>>>>> On 05.08.2021 16:06, Daniel P. Smith wrote:
>>>>>> --- /dev/null
>>>>>> +++ b/xen/include/xsm/xsm-core.h
>>>>>> @@ -0,0 +1,273 @@
>>>>>> +/*
>>>>>> + *  This file contains the XSM hook definitions for Xen.
>>>>>> + *
>>>>>> + *  This work is based on the LSM implementation in Linux 2.6.13.4.
>>>>>> + *
>>>>>> + *  Author:  George Coker, <gscoker@alpha.ncsc.mil>
>>>>>> + *
>>>>>> + *  Contributors: Michael LeMay, <mdlemay@epoch.ncsc.mil>
>>>>>> + *
>>>>>> + *  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.
>>>>>> + */
>>>>>> +
>>>>>> +#ifndef __XSM_CORE_H__
>>>>>> +#define __XSM_CORE_H__
>>>>>> +
>>>>>> +#include <xen/sched.h>
>>>>>> +#include <xen/multiboot.h>
>>>>>
>>>>> I was going to ask to invert the order (as we try to arrange #include-s
>>>>> alphabetically), but it looks like multiboot.h isn't fit for this.
>>>>
>>>> So my understanding is to leave this as is.
>>>
>>> Yes, unfortunately.
>>>
>>>>>> +typedef void xsm_op_t;
>>>>>> +DEFINE_XEN_GUEST_HANDLE(xsm_op_t);
>>>>>
>>>>> Just FTR - I consider this dubious. If void is meant, I don't see why
>>>>> a void handle can't be used.
>>>>
>>>> Unless I am misunderstanding what you are calling for, I am afraid this
>>>> will trickle further that what intended to be addressed in this patch
>>>> set. If disagree and would like to provide me a suggest that stays
>>>> bounded, I would gladly incorporate.
>>>
>>> All I'm asking is to remove this pointless typedef and handle definition,
>>> seeing that you're doing a major rework anyway. I'm afraid I don't see
>>> how this would collide with the purpose of the overall series (albeit I
>>> may also have misunderstood your reply, as the 2nd half of the first
>>> sentence makes me struggle some with trying to parse it).
>>
>> If I drop the typedef and start changing everywhere xsm_op_t is
>> referenced to void, this now adds hypercall.h to the files I am now
>> touching.
>>
>> In the end it is not about whether the change is big or small, but that
>> more and more unrelated small changes/clean ups keep getting requested.
>> There has to be a cut-off point to limit the scope of changes down to
>> the purpose of the patch set, which is to unravel and simplify the XSM
>> hooks. And this is being done so, so that the the XSM-Roles work can be
>> introduced to bring a more solid definition to the the default access
>> control system, which itself is needed to bring in hyperlaunch.
> 
> Well, yes, you effectively suffer from XSM not having been actively
> maintained for a number of years. As said in the original reply, I'd
> prefer my ack to cover all the suggested changes, but I didn't mean
> to insist. If this particular one goes too far for your taste, so be
> it.
> 
> Jan
> 

I think we can agree that XSM has not been receiving appropriate care
and maintenance. It can't all be fixed in one go and I am trying to step
up to get it back into shape. Since this is really undoing a masking of
void, I can add this and the risk is very low of breaking something
else. Which this is my biggest concern as I see new files getting
brought in with each cleanup requested.

v/r,
dps


^ permalink raw reply	[flat|nested] 25+ messages in thread

end of thread, other threads:[~2021-08-30 13:55 UTC | newest]

Thread overview: 25+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-08-05 14:06 [PATCH v3 0/7] xsm: refactoring xsm hooks Daniel P. Smith
2021-08-05 14:06 ` [PATCH v3 1/7] xen: Implement xen/alternative-call.h for use in common code Daniel P. Smith
2021-08-05 15:31   ` Jan Beulich
2021-08-05 14:06 ` [PATCH v3 2/7] xsm: remove the ability to disable flask Daniel P. Smith
2021-08-25 15:22   ` Jan Beulich
2021-08-27 13:42     ` Daniel P. Smith
2021-08-05 14:06 ` [PATCH v3 3/7] xsm: refactor xsm_ops handling Daniel P. Smith
2021-08-25 15:16   ` Jan Beulich
2021-08-27 13:44     ` Daniel P. Smith
2021-08-05 14:06 ` [PATCH v3 4/7] xsm: convert xsm_ops hook calls to alternative call Daniel P. Smith
2021-08-05 14:06 ` [PATCH v3 5/7] xsm: decouple xsm header inclusion selection Daniel P. Smith
2021-08-26  8:13   ` Jan Beulich
2021-08-27 14:06     ` Daniel P. Smith
2021-08-30 13:24       ` Jan Beulich
2021-08-30 13:41         ` Daniel P. Smith
2021-08-30 13:46           ` Jan Beulich
2021-08-30 13:55             ` Daniel P. Smith
2021-08-05 14:06 ` [PATCH v3 6/7] xsm: drop generic event channel labeling exclusion Daniel P. Smith
2021-08-25 15:44   ` Jan Beulich
2021-08-27 14:16     ` Daniel P. Smith
2021-08-30 13:25       ` Jan Beulich
2021-08-05 14:06 ` [PATCH v3 7/7] xsm: removing facade that XSM can be enabled/disabled Daniel P. Smith
2021-08-26  9:37   ` Jan Beulich
2021-08-30 12:11     ` Daniel P. Smith
2021-08-30 13:34       ` Jan Beulich

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.