All of lore.kernel.org
 help / color / mirror / Atom feed
* [PULL 00/14] QOM security status patches
@ 2026-09-17 16:05 Daniel P. Berrangé
  2026-09-17 16:05 ` [PULL 01/14] qom: add tracking of security state of object types Daniel P. Berrangé
                   ` (14 more replies)
  0 siblings, 15 replies; 19+ messages in thread
From: Daniel P. Berrangé @ 2026-09-17 16:05 UTC (permalink / raw)
  To: qemu-devel; +Cc: Daniel P. Berrangé

The following changes since commit f8296b816fabd370307cd22b0270b610fc0fa279:

  Merge tag 'pull-loongarch-20260917' of https://github.com/bibo-mao/qemu into staging (2026-09-16 18:24:08 -1000)

are available in the Git repository at:

  https://gitlab.com/berrange/qemu tags/misc-fixes-pull-request

for you to fetch changes up to f49f267664ac9a681ab19c1790cc3d75a1723790:

  machine: add helpers for declaring secure/insecure machine types (2026-09-17 17:00:44 +0100)

----------------------------------------------------------------
Merge support for recording & reporting object security status

* '-compat' gains a new option 'insecure-types=reject|warn|accept'
* '-device help', '-accel help' and '-machine help' report
  security status of their objects
* 'qom-list-types' can filter and report on security status of types
* 'query-machines' can report on security status of machines
* Adding macros for defining secure machine types

----------------------------------------------------------------

Daniel P. Berrangé (14):
  qom: add tracking of security state of object types
  qapi: add 'insecure-types' option for -compat argument
  qom: add helper API for checking object class security policy
    compliance
  system: check security for accelerator types
  system: report acclerator security status in help output
  system: check security for machine types
  system: report machine security status in help output
  system: check security of device types
  system: report device security status in help output
  hw/core: report security status in query-machines
  qom: refactor data passing for QOM list filtering
  qom: report & filter on security status in qom-list-types
  docs: expand security docs with info about security status
  machine: add helpers for declaring secure/insecure machine types

 docs/system/security.rst     | 36 ++++++++++++++++++++++++++++++++++++
 hw/arm/bananapi_m2u.c        |  2 +-
 hw/arm/cubieboard.c          |  2 +-
 hw/arm/imx8mm-evk.c          |  2 +-
 hw/arm/integratorcp.c        |  2 +-
 hw/arm/mcimx7d-sabre.c       |  2 +-
 hw/arm/orangepi.c            |  2 +-
 hw/core/machine-qmp-cmds.c   |  1 +
 hw/ppc/pegasos.c             |  3 ++-
 include/hw/core/boards.h     | 25 ++++++++++++++++++++-----
 include/hw/i386/pc.h         | 11 ++++++++++-
 include/qapi/compat-policy.h |  5 +++++
 include/qom/object.h         | 26 ++++++++++++++++++++++++++
 qapi/compat.json             | 23 ++++++++++++++++++++++-
 qapi/machine.json            |  8 +++++++-
 qapi/qapi-util.c             | 30 ++++++++++++++++++++++++++++++
 qapi/qom.json                | 13 +++++++++++--
 qom/object.c                 | 16 ++++++++++++++++
 qom/qom-qmp-cmds.c           | 35 +++++++++++++++++++++++++++++------
 rust/qom/src/qom.rs          |  4 ++++
 system/qdev-monitor.c        |  7 +++++++
 system/vl.c                  | 30 +++++++++++++++++++++++++-----
 tests/qtest/fuzz/qos_fuzz.c  |  3 ++-
 23 files changed, 259 insertions(+), 29 deletions(-)

-- 
2.55.0



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

* [PULL 01/14] qom: add tracking of security state of object types
  2026-09-17 16:05 [PULL 00/14] QOM security status patches Daniel P. Berrangé
@ 2026-09-17 16:05 ` Daniel P. Berrangé
  2026-09-17 16:05 ` [PULL 02/14] qapi: add 'insecure-types' option for -compat argument Daniel P. Berrangé
                   ` (13 subsequent siblings)
  14 siblings, 0 replies; 19+ messages in thread
From: Daniel P. Berrangé @ 2026-09-17 16:05 UTC (permalink / raw)
  To: qemu-devel
  Cc: Daniel P. Berrangé, Marc-André Lureau,
	Richard Henderson

This introduces a new flag "secure" against the Type/TypeInfo
structs, and helpers to check this against the ObjectClass
struct.

If an object is considered to provide a security boundary to
protect against untrusted code, the "secure" flag must be
explicitly set to true.

If it is set to false, or left unset, this indicates that
the object does not intend to provide a security boundary.
Bugs related to this object class will be ineligible for
CVE assignment.

Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
---
 include/qom/object.h | 13 +++++++++++++
 qom/object.c         |  7 +++++++
 rust/qom/src/qom.rs  |  4 ++++
 3 files changed, 24 insertions(+)

diff --git a/include/qom/object.h b/include/qom/object.h
index 7ecd0f210fb..687ceb6bba0 100644
--- a/include/qom/object.h
+++ b/include/qom/object.h
@@ -453,6 +453,10 @@ struct Object
  *   function.
  * @abstract: If this field is true, then the class is considered abstract and
  *   cannot be directly instantiated.
+ * @secure: If this field is initialized to true, then the class is considered
+ *   to provide a security boundary. If initialized to false, the class does
+ *   not provide a security boundary. If uninitialized (and thus implicitly
+ *   false) its status is not yet defined.
  * @class_size: The size of the class object (derivative of #ObjectClass)
  *   for this object.  If @class_size is 0, then the size of the class will be
  *   assumed to be the size of the parent class.  This allows a type to avoid
@@ -487,6 +491,7 @@ struct TypeInfo
     void (*instance_finalize)(Object *obj);
 
     bool abstract;
+    bool secure;
     size_t class_size;
 
     void (*class_init)(ObjectClass *klass, const void *data);
@@ -1074,6 +1079,14 @@ const char *object_class_get_name(ObjectClass *klass);
  */
 bool object_class_is_abstract(ObjectClass *klass);
 
+/**
+ * object_class_is_secure:
+ * @klass: The class to check security of
+ *
+ * Returns: %true if @klass is declared to be secure, %false if not declared
+ */
+bool object_class_is_secure(ObjectClass *klass);
+
 /**
  * object_class_by_name:
  * @typename: The QOM typename to obtain the class for.
diff --git a/qom/object.c b/qom/object.c
index b1834a57cc9..32736a01114 100644
--- a/qom/object.c
+++ b/qom/object.c
@@ -67,6 +67,7 @@ struct TypeImpl
     void (*instance_finalize)(Object *obj);
 
     bool abstract;
+    bool secure;
 
     const char *parent;
     TypeImpl *parent_type;
@@ -122,6 +123,7 @@ static TypeImpl *type_new(const TypeInfo *info)
     ti->instance_finalize = info->instance_finalize;
 
     ti->abstract = info->abstract;
+    ti->secure = info->secure;
 
     for (i = 0; info->interfaces && info->interfaces[i].type; i++) {
         ti->interfaces[i].typename = g_strdup(info->interfaces[i].type);
@@ -1144,6 +1146,11 @@ bool object_class_is_abstract(ObjectClass *klass)
     return klass->type->abstract;
 }
 
+bool object_class_is_secure(ObjectClass *klass)
+{
+    return klass->type->secure;
+}
+
 const char *object_class_get_name(ObjectClass *klass)
 {
     return klass->type->name;
diff --git a/rust/qom/src/qom.rs b/rust/qom/src/qom.rs
index bbb485e2cfd..81449eeefad 100644
--- a/rust/qom/src/qom.rs
+++ b/rust/qom/src/qom.rs
@@ -651,6 +651,9 @@ pub trait ObjectImpl: ObjectType + IsA<Object> {
     /// Whether the object can be instantiated
     const ABSTRACT: bool = false;
 
+    /// Whether the object provides a security boundary for untrusted access
+    const SECURE: bool = false;
+
     /// Function that is called to initialize an object.  The parent class will
     /// have already been initialized so the type is only responsible for
     /// initializing its own members.
@@ -687,6 +690,7 @@ pub trait ObjectImpl: ObjectType + IsA<Object> {
         },
         instance_finalize: Some(drop_object::<Self>),
         abstract_: Self::ABSTRACT,
+        secure: Self::SECURE,
         class_size: core::mem::size_of::<Self::Class>(),
         class_init: Some(rust_class_init::<Self>),
         class_base_init: Self::CLASS_BASE_INIT,
-- 
2.55.0



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

* [PULL 02/14] qapi: add 'insecure-types' option for -compat argument
  2026-09-17 16:05 [PULL 00/14] QOM security status patches Daniel P. Berrangé
  2026-09-17 16:05 ` [PULL 01/14] qom: add tracking of security state of object types Daniel P. Berrangé
@ 2026-09-17 16:05 ` Daniel P. Berrangé
  2026-10-27  9:46   ` Markus Armbruster
  2026-09-17 16:05 ` [PULL 03/14] qom: add helper API for checking object class security policy compliance Daniel P. Berrangé
                   ` (12 subsequent siblings)
  14 siblings, 1 reply; 19+ messages in thread
From: Daniel P. Berrangé @ 2026-09-17 16:05 UTC (permalink / raw)
  To: qemu-devel
  Cc: Daniel P. Berrangé, Marc-André Lureau,
	Richard Henderson

This introduces a new 'insecure-types' option for the 'compat'
argument that accepts three values

 * accept: Allow any usage
 * reject: Reject with an error reported
 * warn: Allow any usage, with a warning reported

For historical compatibility it defaults to 'accept'.

The 'reject' and 'warn' values will take effect for any type
that has been explicitly marked insecure, or is lacking an
explicit declaration of its security status.

This new command line option is currently a no-op, but will
become functional as following patches enable the checks.

Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
---
 include/qapi/compat-policy.h |  5 +++++
 qapi/compat.json             | 23 ++++++++++++++++++++++-
 qapi/qapi-util.c             | 30 ++++++++++++++++++++++++++++++
 3 files changed, 57 insertions(+), 1 deletion(-)

diff --git a/include/qapi/compat-policy.h b/include/qapi/compat-policy.h
index ea65e10744a..f5af2090692 100644
--- a/include/qapi/compat-policy.h
+++ b/include/qapi/compat-policy.h
@@ -24,6 +24,11 @@ bool compat_policy_input_ok(uint64_t features,
                             const char *kind, const char *name,
                             Error **errp);
 
+bool compat_policy_check_security(const CompatPolicy *policy,
+                                  const char *typename,
+                                  bool is_secure,
+                                  Error **errp);
+
 /*
  * Create a QObject input visitor for @obj for use with QMP
  *
diff --git a/qapi/compat.json b/qapi/compat.json
index 90b8d51cf27..b54f8eb3713 100644
--- a/qapi/compat.json
+++ b/qapi/compat.json
@@ -37,6 +37,23 @@
 { 'enum': 'CompatPolicyOutput',
   'data': [ 'accept', 'hide' ] }
 
+##
+# @CompatPolicySecurity:
+#
+# Policy for handling any devices or backends which do not provide a
+# security boundary to protect against untrusted environments
+#
+# @accept: Allow any usage
+#
+# @reject: Reject with an error reported
+#
+# @warn: Allow any usage, with a warning reported
+#
+# Since: 11.2
+##
+{ 'enum': 'CompatPolicySecurity',
+  'data': [ 'accept', 'reject', 'warn' ] }
+
 ##
 # @CompatPolicy:
 #
@@ -62,10 +79,14 @@
 # @unstable-output: how to handle unstable output (default 'accept')
 #     (since 6.2)
 #
+# @insecure-types: how to handle types that are not declared secure
+#     (default 'accept') (since 11.2)
+#
 # Since: 6.0
 ##
 { 'struct': 'CompatPolicy',
   'data': { '*deprecated-input': 'CompatPolicyInput',
             '*deprecated-output': 'CompatPolicyOutput',
             '*unstable-input': 'CompatPolicyInput',
-            '*unstable-output': 'CompatPolicyOutput' } }
+            '*unstable-output': 'CompatPolicyOutput',
+            '*insecure-types': 'CompatPolicySecurity' } }
diff --git a/qapi/qapi-util.c b/qapi/qapi-util.c
index 3d849fe0347..38b1cec7a41 100644
--- a/qapi/qapi-util.c
+++ b/qapi/qapi-util.c
@@ -14,6 +14,7 @@
 #include "qapi/compat-policy.h"
 #include "qapi/error.h"
 #include "qemu/ctype.h"
+#include "qemu/error-report.h"
 #include "qapi/qmp/qerror.h"
 
 CompatPolicy compat_policy;
@@ -58,6 +59,35 @@ bool compat_policy_input_ok(uint64_t features,
     return true;
 }
 
+bool compat_policy_check_security(const CompatPolicy *policy,
+                                  const char *typename,
+                                  bool is_secure,
+                                  Error **errp)
+{
+    if (is_secure) {
+        return true;
+    }
+
+    switch (policy->insecure_types) {
+    case COMPAT_POLICY_SECURITY_ACCEPT:
+        return true;
+
+    case COMPAT_POLICY_SECURITY_REJECT:
+        error_setg(errp, "Type '%s' does not provide a security boundary "
+                   "to protect against untrusted data or actions", typename);
+        return false;
+
+    case COMPAT_POLICY_SECURITY_WARN:
+        warn_report("Type '%s' does not provide a security boundary "
+                    "to protect against untrusted data or actions", typename);
+        return true;
+
+    default:
+        g_assert_not_reached();
+    }
+}
+
+
 const char *qapi_enum_lookup(const QEnumLookup *lookup, int val)
 {
     assert(val >= 0 && val < lookup->size);
-- 
2.55.0



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

* [PULL 03/14] qom: add helper API for checking object class security policy compliance
  2026-09-17 16:05 [PULL 00/14] QOM security status patches Daniel P. Berrangé
  2026-09-17 16:05 ` [PULL 01/14] qom: add tracking of security state of object types Daniel P. Berrangé
  2026-09-17 16:05 ` [PULL 02/14] qapi: add 'insecure-types' option for -compat argument Daniel P. Berrangé
@ 2026-09-17 16:05 ` Daniel P. Berrangé
  2026-09-17 16:05 ` [PULL 04/14] system: check security for accelerator types Daniel P. Berrangé
                   ` (11 subsequent siblings)
  14 siblings, 0 replies; 19+ messages in thread
From: Daniel P. Berrangé @ 2026-09-17 16:05 UTC (permalink / raw)
  To: qemu-devel
  Cc: Daniel P. Berrangé, Marc-André Lureau,
	Richard Henderson

This helper simply avoids a verbose code pattern being repeated for
many callers.

Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
---
 include/qom/object.h | 13 +++++++++++++
 qom/object.c         |  9 +++++++++
 2 files changed, 22 insertions(+)

diff --git a/include/qom/object.h b/include/qom/object.h
index 687ceb6bba0..32852186646 100644
--- a/include/qom/object.h
+++ b/include/qom/object.h
@@ -2405,6 +2405,19 @@ Object *object_property_add_new_container(Object *obj, const char *name);
 char *object_property_help(const char *name, const char *type,
                            QObject *defval, const char *description);
 
+/**
+ * object_class_check_security:
+ * @klass: the object class to check
+ * @errp: a pointer to an Error that is filled if not compliant
+ *
+ * Check whether the object class @klass complies with the
+ * currently requested security policy. Reports an error
+ * in @errp if not compliant.
+ *
+ * Returns: true if compliant, false if an error was raised
+ */
+bool object_class_check_security(ObjectClass *klass, Error **errp);
+
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(Object, object_unref)
 
 #endif
diff --git a/qom/object.c b/qom/object.c
index 32736a01114..41b1ec81d4e 100644
--- a/qom/object.c
+++ b/qom/object.c
@@ -23,6 +23,7 @@
 #include "qapi/qobject-input-visitor.h"
 #include "qapi/forward-visitor.h"
 #include "qapi/qapi-builtin-visit.h"
+#include "qapi/compat-policy.h"
 #include "qobject/qdict.h"
 #include "qobject/qjson.h"
 #include "qemu/id.h"
@@ -3149,6 +3150,14 @@ void object_class_property_set_description(ObjectClass *klass,
     op->description = g_strdup(description);
 }
 
+bool object_class_check_security(ObjectClass *klass, Error **errp)
+{
+    return compat_policy_check_security(&compat_policy,
+                                        object_class_get_name(klass),
+                                        object_class_is_secure(klass),
+                                        errp);
+}
+
 static void object_class_init(ObjectClass *klass, const void *data)
 {
     object_class_property_add_str(klass, "type", object_get_type,
-- 
2.55.0



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

* [PULL 04/14] system: check security for accelerator types
  2026-09-17 16:05 [PULL 00/14] QOM security status patches Daniel P. Berrangé
                   ` (2 preceding siblings ...)
  2026-09-17 16:05 ` [PULL 03/14] qom: add helper API for checking object class security policy compliance Daniel P. Berrangé
@ 2026-09-17 16:05 ` Daniel P. Berrangé
  2026-09-17 16:05 ` [PULL 05/14] system: report acclerator security status in help output Daniel P. Berrangé
                   ` (10 subsequent siblings)
  14 siblings, 0 replies; 19+ messages in thread
From: Daniel P. Berrangé @ 2026-09-17 16:05 UTC (permalink / raw)
  To: qemu-devel
  Cc: Daniel P. Berrangé, Marc-André Lureau,
	Richard Henderson

This wires up the accelerator creation code to apply the compat policy
security check. When multiple -accel options are given, normal fallback
logic applies. IOW, if one is rejected by the security check, it will
carry on to try the next accelerator until one passes the security
check.

Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
---
 system/vl.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/system/vl.c b/system/vl.c
index 9bd7664b85c..0c6e44f21cc 100644
--- a/system/vl.c
+++ b/system/vl.c
@@ -2412,6 +2412,11 @@ static int do_configure_accelerator(void *opaque, QemuOpts *opts, Error **errp)
         }
         goto bad;
     }
+
+    if (!object_class_check_security(OBJECT_CLASS(ac), errp)) {
+        goto bad;
+    }
+
     accel = ACCEL(object_new_with_class(OBJECT_CLASS(ac)));
     object_apply_compat_props(OBJECT(accel));
     qemu_opt_foreach(opts, accelerator_set_property,
-- 
2.55.0



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

* [PULL 05/14] system: report acclerator security status in help output
  2026-09-17 16:05 [PULL 00/14] QOM security status patches Daniel P. Berrangé
                   ` (3 preceding siblings ...)
  2026-09-17 16:05 ` [PULL 04/14] system: check security for accelerator types Daniel P. Berrangé
@ 2026-09-17 16:05 ` Daniel P. Berrangé
  2026-09-17 16:05 ` [PULL 06/14] system: check security for machine types Daniel P. Berrangé
                   ` (9 subsequent siblings)
  14 siblings, 0 replies; 19+ messages in thread
From: Daniel P. Berrangé @ 2026-09-17 16:05 UTC (permalink / raw)
  To: qemu-devel
  Cc: Daniel P. Berrangé, Marc-André Lureau,
	Richard Henderson

When '-accel help' is given, report the security status of each
accelerator.

Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
---
 system/vl.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/system/vl.c b/system/vl.c
index 0c6e44f21cc..ca54da26c54 100644
--- a/system/vl.c
+++ b/system/vl.c
@@ -3451,7 +3451,10 @@ void qemu_init(int argc, char **argv)
                             g_str_has_suffix(typename, ACCEL_CLASS_SUFFIX)) {
                             gchar **optname = g_strsplit(typename,
                                                          ACCEL_CLASS_SUFFIX, 0);
-                            printf("%s\n", optname[0]);
+                            printf("%s%s\n", optname[0],
+                                   object_class_is_secure(
+                                       OBJECT_CLASS(el->data)) ?
+                                   " (secure)" : "");
                             g_strfreev(optname);
                         }
                         g_free(typename);
-- 
2.55.0



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

* [PULL 06/14] system: check security for machine types
  2026-09-17 16:05 [PULL 00/14] QOM security status patches Daniel P. Berrangé
                   ` (4 preceding siblings ...)
  2026-09-17 16:05 ` [PULL 05/14] system: report acclerator security status in help output Daniel P. Berrangé
@ 2026-09-17 16:05 ` Daniel P. Berrangé
  2026-09-17 16:05 ` [PULL 07/14] system: report machine security status in help output Daniel P. Berrangé
                   ` (8 subsequent siblings)
  14 siblings, 0 replies; 19+ messages in thread
From: Daniel P. Berrangé @ 2026-09-17 16:05 UTC (permalink / raw)
  To: qemu-devel
  Cc: Daniel P. Berrangé, Marc-André Lureau,
	Richard Henderson

This wires up the machine creation code to apply the compat policy
security check.

Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
---
 system/vl.c | 15 +++++++++++++--
 1 file changed, 13 insertions(+), 2 deletions(-)

diff --git a/system/vl.c b/system/vl.c
index ca54da26c54..f54449b43e7 100644
--- a/system/vl.c
+++ b/system/vl.c
@@ -2201,11 +2201,18 @@ static void qemu_create_machine_containers(Object *machine)
     }
 }
 
-static void qemu_create_machine(QDict *qdict)
+static bool qemu_create_machine(QDict *qdict)
 {
+    Error *local_err = NULL;
     MachineClass *machine_class = select_machine(qdict, &error_fatal);
     object_set_machine_compat_props(machine_class->compat_props);
 
+    if (!object_class_check_security(OBJECT_CLASS(machine_class),
+                                     &local_err)) {
+        error_report_err(local_err);
+        return false;
+    }
+
     current_machine = MACHINE(object_new_with_class(OBJECT_CLASS(machine_class)));
     object_property_add_child(object_get_root(), "machine",
                               OBJECT(current_machine));
@@ -2237,6 +2244,8 @@ static void qemu_create_machine(QDict *qdict)
                                      false, &error_abort);
         qobject_unref(default_opts);
     }
+
+    return true;
 }
 
 static int global_init_func(void *opaque, QemuOpts *opts, Error **errp)
@@ -3790,7 +3799,9 @@ void qemu_init(int argc, char **argv)
     /* Transfer QemuOpts options into machine options */
     parse_memory_options();
 
-    qemu_create_machine(machine_opts_dict);
+    if (!qemu_create_machine(machine_opts_dict)) {
+        exit(1);
+    }
 
     /*
      * Load incoming CPR state before any devices are created, because it
-- 
2.55.0



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

* [PULL 07/14] system: report machine security status in help output
  2026-09-17 16:05 [PULL 00/14] QOM security status patches Daniel P. Berrangé
                   ` (5 preceding siblings ...)
  2026-09-17 16:05 ` [PULL 06/14] system: check security for machine types Daniel P. Berrangé
@ 2026-09-17 16:05 ` Daniel P. Berrangé
  2026-09-17 16:05 ` [PULL 08/14] system: check security of device types Daniel P. Berrangé
                   ` (7 subsequent siblings)
  14 siblings, 0 replies; 19+ messages in thread
From: Daniel P. Berrangé @ 2026-09-17 16:05 UTC (permalink / raw)
  To: qemu-devel
  Cc: Daniel P. Berrangé, Marc-André Lureau,
	Richard Henderson

When '-machine help' is given, report the security status of each
machine.

Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
---
 system/vl.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/system/vl.c b/system/vl.c
index f54449b43e7..468a9fc247a 100644
--- a/system/vl.c
+++ b/system/vl.c
@@ -1586,9 +1586,10 @@ static void machine_help_func(const QDict *qdict)
         if (mc->alias) {
             printf("%-20s %s (alias of %s)\n", mc->alias, mc->desc, mc->name);
         }
-        printf("%-20s %s%s%s\n", mc->name, mc->desc,
+        printf("%-20s %s%s%s%s\n", mc->name, mc->desc,
                mc->is_default ? " (default)" : "",
-               mc->deprecation_reason ? " (deprecated)" : "");
+               mc->deprecation_reason ? " (deprecated)" : "",
+               object_class_is_secure(OBJECT_CLASS(mc)) ? " (secure)" : "");
     }
 }
 
-- 
2.55.0



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

* [PULL 08/14] system: check security of device types
  2026-09-17 16:05 [PULL 00/14] QOM security status patches Daniel P. Berrangé
                   ` (6 preceding siblings ...)
  2026-09-17 16:05 ` [PULL 07/14] system: report machine security status in help output Daniel P. Berrangé
@ 2026-09-17 16:05 ` Daniel P. Berrangé
  2026-09-17 16:05 ` [PULL 09/14] system: report device security status in help output Daniel P. Berrangé
                   ` (6 subsequent siblings)
  14 siblings, 0 replies; 19+ messages in thread
From: Daniel P. Berrangé @ 2026-09-17 16:05 UTC (permalink / raw)
  To: qemu-devel
  Cc: Daniel P. Berrangé, Marc-André Lureau,
	Richard Henderson

This wires up the DeviceClass types to have their
security checked when devices are created.

Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
---
 system/qdev-monitor.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/system/qdev-monitor.c b/system/qdev-monitor.c
index a62ad23ecf0..c483b4e6281 100644
--- a/system/qdev-monitor.c
+++ b/system/qdev-monitor.c
@@ -672,6 +672,10 @@ DeviceState *qdev_device_add_from_qdict(const QDict *opts,
         return NULL;
     }
 
+    if (!object_class_check_security(OBJECT_CLASS(dc), errp)) {
+        return NULL;
+    }
+
     /* find bus */
     path = qdict_get_try_str(opts, "bus");
     if (path != NULL) {
-- 
2.55.0



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

* [PULL 09/14] system: report device security status in help output
  2026-09-17 16:05 [PULL 00/14] QOM security status patches Daniel P. Berrangé
                   ` (7 preceding siblings ...)
  2026-09-17 16:05 ` [PULL 08/14] system: check security of device types Daniel P. Berrangé
@ 2026-09-17 16:05 ` Daniel P. Berrangé
  2026-09-17 16:05 ` [PULL 10/14] hw/core: report security status in query-machines Daniel P. Berrangé
                   ` (5 subsequent siblings)
  14 siblings, 0 replies; 19+ messages in thread
From: Daniel P. Berrangé @ 2026-09-17 16:05 UTC (permalink / raw)
  To: qemu-devel
  Cc: Daniel P. Berrangé, Marc-André Lureau,
	Richard Henderson

When '-device help', 'device_add help' and 'info qdm' are used, report
the security status of each device.

Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
---
 system/qdev-monitor.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/system/qdev-monitor.c b/system/qdev-monitor.c
index c483b4e6281..8185822daa7 100644
--- a/system/qdev-monitor.c
+++ b/system/qdev-monitor.c
@@ -166,6 +166,9 @@ static void qdev_print_devinfo(DeviceClass *dc)
     if (!dc->user_creatable) {
         qemu_printf(", no-user");
     }
+    if (object_class_is_secure(OBJECT_CLASS(dc))) {
+        qemu_printf(", secure");
+    }
     qemu_printf("\n");
 }
 
-- 
2.55.0



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

* [PULL 10/14] hw/core: report security status in query-machines
  2026-09-17 16:05 [PULL 00/14] QOM security status patches Daniel P. Berrangé
                   ` (8 preceding siblings ...)
  2026-09-17 16:05 ` [PULL 09/14] system: report device security status in help output Daniel P. Berrangé
@ 2026-09-17 16:05 ` Daniel P. Berrangé
  2026-09-17 16:05 ` [PULL 11/14] qom: refactor data passing for QOM list filtering Daniel P. Berrangé
                   ` (4 subsequent siblings)
  14 siblings, 0 replies; 19+ messages in thread
From: Daniel P. Berrangé @ 2026-09-17 16:05 UTC (permalink / raw)
  To: qemu-devel
  Cc: Daniel P. Berrangé, Marc-André Lureau,
	Richard Henderson

Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
---
 hw/core/machine-qmp-cmds.c | 1 +
 qapi/machine.json          | 8 +++++++-
 2 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/hw/core/machine-qmp-cmds.c b/hw/core/machine-qmp-cmds.c
index 543dd3201b5..9c08b17510a 100644
--- a/hw/core/machine-qmp-cmds.c
+++ b/hw/core/machine-qmp-cmds.c
@@ -127,6 +127,7 @@ MachineInfoList *qmp_query_machines(bool has_compat_props, bool compat_props,
         if (mc->default_ram_id) {
             info->default_ram_id = g_strdup(mc->default_ram_id);
         }
+        info->secure = object_class_is_secure(OBJECT_CLASS(mc));
 
         if (compat_props && mc->compat_props) {
             int i;
diff --git a/qapi/machine.json b/qapi/machine.json
index de6460f091c..b1be5608b61 100644
--- a/qapi/machine.json
+++ b/qapi/machine.json
@@ -196,6 +196,11 @@
 #     present when `query-machines` argument @compat-props is true.
 #     (since 9.1)
 #
+# @secure: If true, the machine is declared to provide a security
+#     boundary from the guest; if false the machine is either
+#     not providing a security boundary, or its status is undefined.
+#     (since 11.2)
+#
 # Features:
 #
 # @unstable: Member @compat-props is experimental.
@@ -209,7 +214,8 @@
             'deprecated': 'bool', '*default-cpu-type': 'str',
             '*default-ram-id': 'str', 'acpi': 'bool',
             '*compat-props': { 'type': ['CompatProperty'],
-                               'features': ['unstable'] } } }
+                               'features': ['unstable'] },
+            'secure': 'bool' } }
 
 ##
 # @query-machines:
-- 
2.55.0



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

* [PULL 11/14] qom: refactor data passing for QOM list filtering
  2026-09-17 16:05 [PULL 00/14] QOM security status patches Daniel P. Berrangé
                   ` (9 preceding siblings ...)
  2026-09-17 16:05 ` [PULL 10/14] hw/core: report security status in query-machines Daniel P. Berrangé
@ 2026-09-17 16:05 ` Daniel P. Berrangé
  2026-09-17 16:05 ` [PULL 12/14] qom: report & filter on security status in qom-list-types Daniel P. Berrangé
                   ` (3 subsequent siblings)
  14 siblings, 0 replies; 19+ messages in thread
From: Daniel P. Berrangé @ 2026-09-17 16:05 UTC (permalink / raw)
  To: qemu-devel; +Cc: Daniel P. Berrangé, Marc-André Lureau

Currently the QOM list method can filter on the abstract flag,
but extending the filtering to more variables requires a way
to pass in extra data items. This requires a refactoring of the
iterator to take a full struct as its opaque data item.

Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
---
 qom/qom-qmp-cmds.c | 18 ++++++++++++------
 1 file changed, 12 insertions(+), 6 deletions(-)

diff --git a/qom/qom-qmp-cmds.c b/qom/qom-qmp-cmds.c
index 330895361d4..b999e9f7238 100644
--- a/qom/qom-qmp-cmds.c
+++ b/qom/qom-qmp-cmds.c
@@ -151,9 +151,13 @@ QObject *qmp_qom_get(const char *path, const char *property, Error **errp)
     return object_property_get_qobject(obj, property, errp);
 }
 
-static void qom_list_types_tramp(ObjectClass *klass, void *data)
+typedef struct {
+    ObjectTypeInfoList *list;
+} ObjectTypeInfoData;
+
+static void qom_list_types_tramp(ObjectClass *klass, void *opaque)
 {
-    ObjectTypeInfoList **pret = data;
+    ObjectTypeInfoData *data = opaque;
     ObjectTypeInfo *info;
     ObjectClass *parent = object_class_get_parent(klass);
 
@@ -164,7 +168,7 @@ static void qom_list_types_tramp(ObjectClass *klass, void *data)
         info->parent = g_strdup(object_class_get_name(parent));
     }
 
-    QAPI_LIST_PREPEND(*pret, info);
+    QAPI_LIST_PREPEND(data->list, info);
 }
 
 ObjectTypeInfoList *qmp_qom_list_types(const char *implements,
@@ -172,12 +176,14 @@ ObjectTypeInfoList *qmp_qom_list_types(const char *implements,
                                        bool abstract,
                                        Error **errp)
 {
-    ObjectTypeInfoList *ret = NULL;
+    ObjectTypeInfoData data = {
+        .list = NULL,
+    };
 
     module_load_qom_all();
-    object_class_foreach(qom_list_types_tramp, implements, abstract, &ret);
+    object_class_foreach(qom_list_types_tramp, implements, abstract, &data);
 
-    return ret;
+    return data.list;
 }
 
 ObjectPropertyInfoList *qmp_device_list_properties(const char *typename,
-- 
2.55.0



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

* [PULL 12/14] qom: report & filter on security status in qom-list-types
  2026-09-17 16:05 [PULL 00/14] QOM security status patches Daniel P. Berrangé
                   ` (10 preceding siblings ...)
  2026-09-17 16:05 ` [PULL 11/14] qom: refactor data passing for QOM list filtering Daniel P. Berrangé
@ 2026-09-17 16:05 ` Daniel P. Berrangé
  2026-09-17 16:05 ` [PULL 13/14] docs: expand security docs with info about security status Daniel P. Berrangé
                   ` (2 subsequent siblings)
  14 siblings, 0 replies; 19+ messages in thread
From: Daniel P. Berrangé @ 2026-09-17 16:05 UTC (permalink / raw)
  To: qemu-devel
  Cc: Daniel P. Berrangé, Marc-André Lureau,
	Richard Henderson

This adds:

 * a new boolean 'secure' field to the type info returned by
   qom-list-types, which will be set if the type provides a
   security boundary

 * a new boolean 'secure' parameter to the arguments of
   qom-list-types, which can be used to filter types based
   on their security status

Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
---
 qapi/qom.json               | 13 +++++++++++--
 qom/qom-qmp-cmds.c          | 17 +++++++++++++++++
 tests/qtest/fuzz/qos_fuzz.c |  3 ++-
 3 files changed, 30 insertions(+), 3 deletions(-)

diff --git a/qapi/qom.json b/qapi/qom.json
index 4a9b7f90884..5895c977503 100644
--- a/qapi/qom.json
+++ b/qapi/qom.json
@@ -210,12 +210,18 @@
 # @abstract: the type is abstract and can't be directly instantiated.
 #     Omitted if false.  (since 2.10)
 #
+# @secure: the type provides a security boundary.  Omitted if false.
+#     (since 11.2)
+#
 # @parent: Name of parent type, if any (since 2.10)
 #
 # Since: 1.1
 ##
 { 'struct': 'ObjectTypeInfo',
-  'data': { 'name': 'str', '*abstract': 'bool', '*parent': 'str' } }
+  'data': { 'name': 'str',
+            '*abstract': 'bool',
+            '*parent': 'str',
+            '*secure': 'bool' } }
 
 ##
 # @qom-list-types:
@@ -227,12 +233,15 @@
 #
 # @abstract: if true, include abstract types in the results
 #
+# @secure: if set, filter to only include types with matching security
+#     status (since 11.2)
+#
 # Returns: a list of types, or an empty list if no results are found
 #
 # Since: 1.1
 ##
 { 'command': 'qom-list-types',
-  'data': { '*implements': 'str', '*abstract': 'bool' },
+  'data': { '*implements': 'str', '*abstract': 'bool', '*secure': 'bool' },
   'returns': [ 'ObjectTypeInfo' ],
   'allow-preconfig': true }
 
diff --git a/qom/qom-qmp-cmds.c b/qom/qom-qmp-cmds.c
index b999e9f7238..f17389c7305 100644
--- a/qom/qom-qmp-cmds.c
+++ b/qom/qom-qmp-cmds.c
@@ -153,6 +153,8 @@ QObject *qmp_qom_get(const char *path, const char *property, Error **errp)
 
 typedef struct {
     ObjectTypeInfoList *list;
+    bool has_secure;
+    bool secure;
 } ObjectTypeInfoData;
 
 static void qom_list_types_tramp(ObjectClass *klass, void *opaque)
@@ -160,10 +162,21 @@ static void qom_list_types_tramp(ObjectClass *klass, void *opaque)
     ObjectTypeInfoData *data = opaque;
     ObjectTypeInfo *info;
     ObjectClass *parent = object_class_get_parent(klass);
+    bool secure = object_class_is_secure(klass);
+
+    if (data->has_secure &&
+        data->secure != secure) {
+        return;
+    }
 
     info = g_malloc0(sizeof(*info));
     info->name = g_strdup(object_class_get_name(klass));
     info->has_abstract = info->abstract = object_class_is_abstract(klass);
+    /*
+     * Set has_secure such that we omit the 'secure' attribute
+     * from the QMP response for insecure types
+     */
+    info->has_secure = info->secure = secure;
     if (parent) {
         info->parent = g_strdup(object_class_get_name(parent));
     }
@@ -174,10 +187,14 @@ static void qom_list_types_tramp(ObjectClass *klass, void *opaque)
 ObjectTypeInfoList *qmp_qom_list_types(const char *implements,
                                        bool has_abstract,
                                        bool abstract,
+                                       bool has_secure,
+                                       bool secure,
                                        Error **errp)
 {
     ObjectTypeInfoData data = {
         .list = NULL,
+        .has_secure = has_secure,
+        .secure = secure,
     };
 
     module_load_qom_all();
diff --git a/tests/qtest/fuzz/qos_fuzz.c b/tests/qtest/fuzz/qos_fuzz.c
index 9afe8bf6d8b..9ea6b1aef09 100644
--- a/tests/qtest/fuzz/qos_fuzz.c
+++ b/tests/qtest/fuzz/qos_fuzz.c
@@ -50,7 +50,8 @@ static void qos_set_machines_devices_available(void)
     machines_apply_to_node(mach_info);
     qapi_free_MachineInfoList(mach_info);
 
-    type_info = qmp_qom_list_types("device", true, true, &error_abort);
+    type_info = qmp_qom_list_types("device", true, true,
+                                   false, false, &error_abort);
     types_apply_to_node(type_info);
     qapi_free_ObjectTypeInfoList(type_info);
 }
-- 
2.55.0



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

* [PULL 13/14] docs: expand security docs with info about security status
  2026-09-17 16:05 [PULL 00/14] QOM security status patches Daniel P. Berrangé
                   ` (11 preceding siblings ...)
  2026-09-17 16:05 ` [PULL 12/14] qom: report & filter on security status in qom-list-types Daniel P. Berrangé
@ 2026-09-17 16:05 ` Daniel P. Berrangé
  2026-09-17 16:05 ` [PULL 14/14] machine: add helpers for declaring secure/insecure machine types Daniel P. Berrangé
  2026-09-17 21:50 ` [PULL 00/14] QOM security status patches Richard Henderson
  14 siblings, 0 replies; 19+ messages in thread
From: Daniel P. Berrangé @ 2026-09-17 16:05 UTC (permalink / raw)
  To: qemu-devel
  Cc: Daniel P. Berrangé, Marc-André Lureau,
	Richard Henderson

The description of virtualization vs non-virtualization use
cases is a crude approximation of the security characteristics
of QEMU devices.

Document how QEMU can be probed to obtain information on the
security status of type classes, and how policies can be set
to inform or control their usage.

Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
---
 docs/system/security.rst | 36 ++++++++++++++++++++++++++++++++++++
 1 file changed, 36 insertions(+)

diff --git a/docs/system/security.rst b/docs/system/security.rst
index 8c42d1a6d83..75e39caedea 100644
--- a/docs/system/security.rst
+++ b/docs/system/security.rst
@@ -158,6 +158,42 @@ an issue as a normal bug.
   usually not justify handling as security bugs, nor assignment
   of CVEs. They will be fixed as routine bugs when time allows.
 
+Security status reporting
+'''''''''''''''''''''''''
+
+The QEMU project annotates types to explicitly state whether they are
+considered to provide a security boundary or not. For machine, accelerator
+and device types, only those annotated with the "secure" flag will be
+eligible for CVE assignment. Annotations will be extended to other backend
+and object types over time, to make their security status explicit.
+
+It is possible to control or identify the usage of types that do not offer
+an explicit security boundary using the ``insecure-types`` parameter to the
+``-compat`` argument, which accepts three values:
+
+ * accept: usage of any type will be permitted. This is the current
+   and historical default behaviour
+ * warn: usage of types not explicitly declared secure will result
+   in a warning message, but still be permitted.
+ * reject: usage of types not explicitly declared secure will result
+   in an error message, and will not be permitted.
+
+The compatibility policy will be honoured both at initial startup of
+QEMU and during any runtime alterations made with monitor commands.
+
+The status of any type class can be queried at runtime using the
+``qom-list-types`` command, whose returned information will flag any
+types declared as secure. The ``query-machines`` command will also
+reflect this same information for machine types.
+
+Machine type, accelerator and device security status can be queried
+using ``-machine help``, ``-accel help`` and ``-device help`` command
+line options respectively.
+
+Setting the ``.secure`` field to ``true`` in the ``TypeInfo``
+instance for an Object class, declares that the type aims to provide
+a security boundary.
+
 Architecture
 ------------
 
-- 
2.55.0



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

* [PULL 14/14] machine: add helpers for declaring secure/insecure machine types
  2026-09-17 16:05 [PULL 00/14] QOM security status patches Daniel P. Berrangé
                   ` (12 preceding siblings ...)
  2026-09-17 16:05 ` [PULL 13/14] docs: expand security docs with info about security status Daniel P. Berrangé
@ 2026-09-17 16:05 ` Daniel P. Berrangé
  2026-09-17 21:50 ` [PULL 00/14] QOM security status patches Richard Henderson
  14 siblings, 0 replies; 19+ messages in thread
From: Daniel P. Berrangé @ 2026-09-17 16:05 UTC (permalink / raw)
  To: qemu-devel; +Cc: Daniel P. Berrangé, Marc-André Lureau

The current DEFINE_MACHINE macro will declare machine type without any
explicit statement about the security status. As such the machine type
will be treated as implicitly insecure at runtime.

Introduce a new DEFINE_SECURE_MACHINE macro (with variants) that
allow code to make an explicit statement that the machine is treated
as secure. This should primarily be used for versioned machine types
that are intended to be used with KVM, though some others may warrant
a security declaration.

Use of the existing macros marks a machine as insecure, which is the
desired default for most machines servicing emulation use cases.

The same is done for the specialized i386 PC related macros.

Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
---
 hw/arm/bananapi_m2u.c    |  2 +-
 hw/arm/cubieboard.c      |  2 +-
 hw/arm/imx8mm-evk.c      |  2 +-
 hw/arm/integratorcp.c    |  2 +-
 hw/arm/mcimx7d-sabre.c   |  2 +-
 hw/arm/orangepi.c        |  2 +-
 hw/ppc/pegasos.c         |  3 ++-
 include/hw/core/boards.h | 25 ++++++++++++++++++++-----
 include/hw/i386/pc.h     | 11 ++++++++++-
 9 files changed, 38 insertions(+), 13 deletions(-)

diff --git a/hw/arm/bananapi_m2u.c b/hw/arm/bananapi_m2u.c
index 8f59111fd4e..ccf60ba2955 100644
--- a/hw/arm/bananapi_m2u.c
+++ b/hw/arm/bananapi_m2u.c
@@ -153,4 +153,4 @@ static void bpim2u_machine_init(MachineClass *mc)
 }
 
 DEFINE_MACHINE_EXTENDED("bpim2u", MACHINE, Bpim2uMachineState,
-                        bpim2u_machine_init, false, NULL)
+                        bpim2u_machine_init, false, false, NULL)
diff --git a/hw/arm/cubieboard.c b/hw/arm/cubieboard.c
index ae27056938f..e4fef9cd76b 100644
--- a/hw/arm/cubieboard.c
+++ b/hw/arm/cubieboard.c
@@ -133,5 +133,5 @@ static void cubieboard_machine_init(MachineClass *mc)
 }
 
 DEFINE_MACHINE_EXTENDED("cubieboard", MACHINE, CubieboardMachineState,
-                        cubieboard_machine_init, false,
+                        cubieboard_machine_init, false, false,
                         NULL)
diff --git a/hw/arm/imx8mm-evk.c b/hw/arm/imx8mm-evk.c
index 8a5737502fd..c3215b11cb9 100644
--- a/hw/arm/imx8mm-evk.c
+++ b/hw/arm/imx8mm-evk.c
@@ -134,5 +134,5 @@ static void imx8mm_evk_machine_init(MachineClass *mc)
 }
 
 DEFINE_MACHINE_EXTENDED("imx8mm-evk", MACHINE, Imx8mmEvkMachineState,
-                        imx8mm_evk_machine_init, false,
+                        imx8mm_evk_machine_init, false, false,
                         NULL)
diff --git a/hw/arm/integratorcp.c b/hw/arm/integratorcp.c
index 382ea7850d8..b766edeeee1 100644
--- a/hw/arm/integratorcp.c
+++ b/hw/arm/integratorcp.c
@@ -704,7 +704,7 @@ static void integratorcp_machine_init(MachineClass *mc)
 }
 
 DEFINE_MACHINE_EXTENDED("integratorcp", MACHINE, IntegratorcpMachineState,
-                        integratorcp_machine_init, false,
+                        integratorcp_machine_init, false, false,
                         NULL)
 
 static const Property core_properties[] = {
diff --git a/hw/arm/mcimx7d-sabre.c b/hw/arm/mcimx7d-sabre.c
index db8a62e5f6c..65fdb19c06f 100644
--- a/hw/arm/mcimx7d-sabre.c
+++ b/hw/arm/mcimx7d-sabre.c
@@ -86,5 +86,5 @@ static void mcimx7d_sabre_machine_init(MachineClass *mc)
 }
 
 DEFINE_MACHINE_EXTENDED("mcimx7d-sabre", MACHINE, Mcimx7dSabreMachineState,
-                        mcimx7d_sabre_machine_init, false,
+                        mcimx7d_sabre_machine_init, false, false,
                         NULL)
diff --git a/hw/arm/orangepi.c b/hw/arm/orangepi.c
index 7a19732f5df..18ed174032b 100644
--- a/hw/arm/orangepi.c
+++ b/hw/arm/orangepi.c
@@ -133,5 +133,5 @@ static void orangepi_machine_init(MachineClass *mc)
 }
 
 DEFINE_MACHINE_EXTENDED("orangepi-pc", MACHINE, OrangePiMachineState,
-                        orangepi_machine_init, false,
+                        orangepi_machine_init, false, false,
                         NULL)
diff --git a/hw/ppc/pegasos.c b/hw/ppc/pegasos.c
index 9d7e279123b..fba2a558905 100644
--- a/hw/ppc/pegasos.c
+++ b/hw/ppc/pegasos.c
@@ -788,7 +788,8 @@ static void pegasos2_machine_class_init(ObjectClass *oc, const void *data)
 }
 
 DEFINE_MACHINE_EXTENDED("pegasos", MACHINE, PegasosMachineState,
-                        pegasos_machine_init, true, (const InterfaceInfo[]) {
+                        pegasos_machine_init, true, false,
+                        (const InterfaceInfo[]) {
                         { TYPE_PPC_VIRTUAL_HYPERVISOR },
                         { TYPE_VOF_MACHINE_IF }, { } })
 
diff --git a/include/hw/core/boards.h b/include/hw/core/boards.h
index dba465efc2c..3b86724cf00 100644
--- a/include/hw/core/boards.h
+++ b/include/hw/core/boards.h
@@ -514,7 +514,7 @@ struct MachineState {
  */
 
 #define DEFINE_MACHINE_EXTENDED(namestr, PARENT_NAME, InstanceName, \
-                                machine_initfn, ABSTRACT, ifaces...) \
+                                machine_initfn, ABSTRACT, SECURE, ifaces...) \
     static void machine_initfn##_class_init(ObjectClass *oc, const void *data) \
     { \
         MachineClass *mc = MACHINE_CLASS(oc); \
@@ -526,6 +526,7 @@ struct MachineState {
         .class_init = machine_initfn##_class_init, \
         .instance_size = sizeof(InstanceName), \
         .abstract = ABSTRACT, \
+        .secure     = SECURE, \
         .interfaces = ifaces, \
     }; \
     static void machine_initfn##_register_types(void) \
@@ -534,18 +535,32 @@ struct MachineState {
     } \
     type_init(machine_initfn##_register_types)
 
+/* Implicitly insecure */
 #define DEFINE_MACHINE(namestr, machine_initfn) \
     DEFINE_MACHINE_EXTENDED(namestr, MACHINE, MachineState, machine_initfn, \
-                            false, NULL)
+                            false, false, NULL)
 
-#define DEFINE_MACHINE_WITH_INTERFACE_ARRAY(namestr, machine_initfn, ifaces...)\
+#define DEFINE_MACHINE_WITH_INTERFACE_ARRAY(namestr, machine_initfn, ifaces...) \
     DEFINE_MACHINE_EXTENDED(namestr, MACHINE, MachineState, machine_initfn, \
-                            false, ifaces)
+                            false, false, ifaces)
 
-#define DEFINE_MACHINE_WITH_INTERFACES(namestr, machine_initfn, ...) \
+#define DEFINE_MACHINE_WITH_INTERFACES(namestr, machine_initfn, ...)    \
     DEFINE_MACHINE_WITH_INTERFACE_ARRAY(namestr, machine_initfn, \
                                         (const InterfaceInfo[]) { __VA_ARGS__ })
 
+
+#define DEFINE_SECURE_MACHINE(namestr, machine_initfn) \
+    DEFINE_MACHINE_EXTENDED(namestr, MACHINE, MachineState, machine_initfn, \
+                            false, true, NULL)
+
+#define DEFINE_SECURE_MACHINE_WITH_INTERFACE_ARRAY(namestr, machine_initfn, ifaces...) \
+    DEFINE_MACHINE_EXTENDED(namestr, MACHINE, MachineState, machine_initfn, \
+                            false, true, ifaces)
+
+#define DEFINE_SECURE_MACHINE_WITH_INTERFACES(namestr, machine_initfn, ...) \
+    DEFINE_SECURE_MACHINE_WITH_INTERFACE_ARRAY(namestr, machine_initfn, \
+                                               (const InterfaceInfo[]) { __VA_ARGS__ })
+
 /*
  * Helper for dispatching different macros based on how
  * many __VA_ARGS__ are passed. Supports 1 to 5 variadic
diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
index ac03da97b64..d5dc79df178 100644
--- a/include/hw/i386/pc.h
+++ b/include/hw/i386/pc.h
@@ -275,7 +275,7 @@ extern const size_t pc_compat_4_2_len;
 extern GlobalProperty pc_compat_4_1[];
 extern const size_t pc_compat_4_1_len;
 
-#define DEFINE_PC_MACHINE(suffix, namestr, initfn, optsfn) \
+#define DEFINE_PC_MACHINE_EXTENDED(suffix, namestr, initfn, optsfn, issecure) \
     static void pc_machine_##suffix##_class_init(ObjectClass *oc, \
                                                  const void *data) \
     { \
@@ -287,6 +287,7 @@ extern const size_t pc_compat_4_1_len;
         .name       = namestr TYPE_MACHINE_SUFFIX, \
         .parent     = TYPE_PC_MACHINE, \
         .class_init = pc_machine_##suffix##_class_init, \
+        .secure     = issecure, \
     }; \
     static void pc_machine_init_##suffix(void) \
     { \
@@ -294,6 +295,14 @@ extern const size_t pc_compat_4_1_len;
     } \
     type_init(pc_machine_init_##suffix)
 
+/* Implicitly insecure */
+#define DEFINE_PC_MACHINE(suffix, namestr, initfn, optsfn) \
+    DEFINE_PC_MACHINE_EXTENDED(suffix, namestr, initfn, optsfn, false)
+
+#define DEFINE_SECURE_PC_MACHINE(suffix, namestr, initfn, optsfn) \
+    DEFINE_PC_MACHINE_EXTENDED(suffix, namestr, initfn, optsfn, true)
+
+
 #define DEFINE_PC_VER_MACHINE(namesym, namestr, initfn, isdefault, malias, ...) \
     static void MACHINE_VER_SYM(init, namesym, __VA_ARGS__)( \
         MachineState *machine) \
-- 
2.55.0



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

* Re: [PULL 00/14] QOM security status patches
  2026-09-17 16:05 [PULL 00/14] QOM security status patches Daniel P. Berrangé
                   ` (13 preceding siblings ...)
  2026-09-17 16:05 ` [PULL 14/14] machine: add helpers for declaring secure/insecure machine types Daniel P. Berrangé
@ 2026-09-17 21:50 ` Richard Henderson
  14 siblings, 0 replies; 19+ messages in thread
From: Richard Henderson @ 2026-09-17 21:50 UTC (permalink / raw)
  To: Daniel P. Berrangé, qemu-devel

On 9/17/26 06:05, Daniel P. Berrangé wrote:
> The following changes since commit f8296b816fabd370307cd22b0270b610fc0fa279:
> 
>    Merge tag 'pull-loongarch-20260917' ofhttps://github.com/bibo-mao/qemu into staging (2026-09-16 18:24:08 -1000)
> 
> are available in the Git repository at:
> 
>    https://gitlab.com/berrange/qemu tags/misc-fixes-pull-request
> 
> for you to fetch changes up to f49f267664ac9a681ab19c1790cc3d75a1723790:
> 
>    machine: add helpers for declaring secure/insecure machine types (2026-09-17 17:00:44 +0100)
> 
> ----------------------------------------------------------------
> Merge support for recording & reporting object security status
> 
> * '-compat' gains a new option 'insecure-types=reject|warn|accept'
> * '-device help', '-accel help' and '-machine help' report
>    security status of their objects
> * 'qom-list-types' can filter and report on security status of types
> * 'query-machines' can report on security status of machines
> * Adding macros for defining secure machine types

Applied, thanks.

r~


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

* Re: [PULL 02/14] qapi: add 'insecure-types' option for -compat argument
  2026-09-17 16:05 ` [PULL 02/14] qapi: add 'insecure-types' option for -compat argument Daniel P. Berrangé
@ 2026-10-27  9:46   ` Markus Armbruster
  2026-10-27 14:47     ` Daniel P. Berrangé
  0 siblings, 1 reply; 19+ messages in thread
From: Markus Armbruster @ 2026-10-27  9:46 UTC (permalink / raw)
  To: Daniel P. Berrangé
  Cc: qemu-devel, Marc-André Lureau, Richard Henderson, Eric Blake,
	John Snow

This has long been merged.  I couldn't review it at the time, and
merging it without my review was clearly appropriate.

I have questions / doubts about the external interface I'd like to
discuss now.

Daniel P. Berrangé <berrange@redhat.com> writes:

> This introduces a new 'insecure-types' option for the 'compat'
> argument that accepts three values
>
>  * accept: Allow any usage
>  * reject: Reject with an error reported
>  * warn: Allow any usage, with a warning reported
>
> For historical compatibility it defaults to 'accept'.
>
> The 'reject' and 'warn' values will take effect for any type
> that has been explicitly marked insecure, or is lacking an
> explicit declaration of its security status.
>
> This new command line option is currently a no-op, but will
> become functional as following patches enable the checks.
>
> Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
> Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
> ---
>  include/qapi/compat-policy.h |  5 +++++
>  qapi/compat.json             | 23 ++++++++++++++++++++++-
>  qapi/qapi-util.c             | 30 ++++++++++++++++++++++++++++++
>  3 files changed, 57 insertions(+), 1 deletion(-)
>
> diff --git a/include/qapi/compat-policy.h b/include/qapi/compat-policy.h
> index ea65e10744a..f5af2090692 100644
> --- a/include/qapi/compat-policy.h
> +++ b/include/qapi/compat-policy.h
> @@ -24,6 +24,11 @@ bool compat_policy_input_ok(uint64_t features,
>                              const char *kind, const char *name,
>                              Error **errp);
>  
> +bool compat_policy_check_security(const CompatPolicy *policy,
> +                                  const char *typename,
> +                                  bool is_secure,
> +                                  Error **errp);
> +
>  /*
>   * Create a QObject input visitor for @obj for use with QMP
>   *
> diff --git a/qapi/compat.json b/qapi/compat.json
> index 90b8d51cf27..b54f8eb3713 100644
> --- a/qapi/compat.json
> +++ b/qapi/compat.json
> @@ -37,6 +37,23 @@
>  { 'enum': 'CompatPolicyOutput',
>    'data': [ 'accept', 'hide' ] }
>  
> +##
> +# @CompatPolicySecurity:
> +#
> +# Policy for handling any devices or backends which do not provide a
> +# security boundary to protect against untrusted environments
> +#
> +# @accept: Allow any usage
> +#
> +# @reject: Reject with an error reported
> +#
> +# @warn: Allow any usage, with a warning reported
> +#
> +# Since: 11.2
> +##
> +{ 'enum': 'CompatPolicySecurity',
> +  'data': [ 'accept', 'reject', 'warn' ] }
> +
>  ##
>  # @CompatPolicy:
>  #
> @@ -62,10 +79,14 @@
   # Policy for handling deprecated management interfaces.
   #
   # This is intended for testing users of the management interfaces.
   #
   # Limitation: covers only syntactic aspects of QMP, i.e. stuff tagged
   # with feature 'deprecated' or 'unstable'.  We may want to extend it
   # to cover semantic aspects and CLI.
   #
   # Limitation: deprecated-output policy @hide is not implemented for
   # enumeration values.  They behave the same as with policy @accept.
   #
   # @deprecated-input: how to handle deprecated input (default 'accept')
   #
   # @deprecated-output: how to handle deprecated output (default
   #     'accept')
   #
   # @unstable-input: how to handle unstable input (default 'accept')
   #     (since 6.2)
   #
>  # @unstable-output: how to handle unstable output (default 'accept')
>  #     (since 6.2)
>  #
> +# @insecure-types: how to handle types that are not declared secure
> +#     (default 'accept') (since 11.2)

Minor issue: "types" is ambiguous without context.  We call lots of
things "types" in our external interfaces.  It's actually QOM types
here.  Let's say so.  I can take care of it.

Similar confusion exists elsewhere[*], but let's not digress.

> +#
>  # Since: 6.0
>  ##
>  { 'struct': 'CompatPolicy',
>    'data': { '*deprecated-input': 'CompatPolicyInput',
>              '*deprecated-output': 'CompatPolicyOutput',
>              '*unstable-input': 'CompatPolicyInput',
> -            '*unstable-output': 'CompatPolicyOutput' } }
> +            '*unstable-output': 'CompatPolicyOutput',
> +            '*insecure-types': 'CompatPolicySecurity' } }

The existing members are all named "wide", and the documentation narrows
them.  For instance, the name @deprecated-input could cover *any* input,
but its documentation narrows it to "only syntactic aspects of QMP".  I
did it this way to let us extend coverage without having to change the
external interface.

New member @insecure-types is named "narrow".  Why different?  Why not
@insecure-input?

The existing @FOO-input support CompatPolicyInput: "accept", "reject",
"crash".  New insecure-types supports CompatPolicySecurity: "accept",
"reject", "warn".  Why different?

My rationale for "crash" is in commit dbb675c19aa (qapi: New -compat
deprecated-input=crash):

    Bugs in integration tests may mask the error from policy "reject".
    Provide a larger hammer: crash outright.  Masking that seems unlikely.

If "crash" can be useful for testing a management application's non-use
of deprecated and unstable interfaces, surely it's just as useful for
insecure ones.

Likewise, "warn".  I didn't provide "warn" at the time, because QMP
lacks support for warnings.  Do management applications find warnings on
stderr in response to QMP commands useful?

-util.c b/qapi/qapi-util.c
> index 3d849fe0347..38b1cec7a41 100644
> --- a/qapi/qapi-util.c
> +++ b/qapi/qapi-util.c
> @@ -14,6 +14,7 @@
>  #include "qapi/compat-policy.h"
>  #include "qapi/error.h"
>  #include "qemu/ctype.h"
> +#include "qemu/error-report.h"
>  #include "qapi/qmp/qerror.h"
>  
>  CompatPolicy compat_policy;
> @@ -58,6 +59,35 @@ bool compat_policy_input_ok(uint64_t features,
>      return true;
>  }
>  
> +bool compat_policy_check_security(const CompatPolicy *policy,
> +                                  const char *typename,
> +                                  bool is_secure,
> +                                  Error **errp)

More minor issues.

The policy functions are named compat_policy_FOO_ok().  Why different?

Their arguments are "relevant facts" (@features), @policy, "stuff for
error message" (@error_class, @kind, @name), @errp.  This one has the
same things in different order.  Why?

> +{
> +    if (is_secure) {
> +        return true;
> +    }
> +
> +    switch (policy->insecure_types) {
> +    case COMPAT_POLICY_SECURITY_ACCEPT:
> +        return true;
> +
> +    case COMPAT_POLICY_SECURITY_REJECT:
> +        error_setg(errp, "Type '%s' does not provide a security boundary "
> +                   "to protect against untrusted data or actions", typename);
> +        return false;
> +
> +    case COMPAT_POLICY_SECURITY_WARN:
> +        warn_report("Type '%s' does not provide a security boundary "
> +                    "to protect against untrusted data or actions", typename);
> +        return true;
> +
> +    default:
> +        g_assert_not_reached();
> +    }
> +}
> +
> +
>  const char *qapi_enum_lookup(const QEnumLookup *lookup, int val)
>  {
>      assert(val >= 0 && val < lookup->size);


[*] So I digress in a footnote.  Sue me ;)

While examining the QAPI schema, I found near object-add:

    ##
    # @qom-list-properties:
    #     List properties associated with a QOM object.
    #
    # @typename: the type name of an object
    [...]
    ##
    # @object-add:
    #     Create a QOM object.
    #
    # Errors:
    #     - If @qom-type is not a valid class name
    [...]
    ##
    # @ObjectOptions:
    #     Describes the options of a user creatable QOM object.
    #
    # @qom-type: the class name for the object to be created

We use "QOM type" and "QOM class".  This is pretty bad; we should pick
one and stick with it.

And near device_add:

    ##
    # @device-list-properties:
    #     List properties associated with a device.
    #
    # @typename: the type name of a device
    [...]
    ##
    # @device_add:
    #     Add a device.
    #
    # @driver: the name of the new device's driver

We use "driver" and "device type".  Similarly bad.

Not today.



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

* Re: [PULL 02/14] qapi: add 'insecure-types' option for -compat argument
  2026-10-27  9:46   ` Markus Armbruster
@ 2026-10-27 14:47     ` Daniel P. Berrangé
  2026-10-28  9:23       ` Markus Armbruster
  0 siblings, 1 reply; 19+ messages in thread
From: Daniel P. Berrangé @ 2026-10-27 14:47 UTC (permalink / raw)
  To: Markus Armbruster
  Cc: qemu-devel, Marc-André Lureau, Richard Henderson, Eric Blake,
	John Snow

On Tue, Oct 27, 2026 at 10:46:00AM +0100, Markus Armbruster wrote:
> This has long been merged.  I couldn't review it at the time, and
> merging it without my review was clearly appropriate.
> 
> I have questions / doubts about the external interface I'd like to
> discuss now.

... just in time for freeze if we need any urgent changes
before this gets into a release.

> Daniel P. Berrangé <berrange@redhat.com> writes:
> 
> > This introduces a new 'insecure-types' option for the 'compat'
> > argument that accepts three values
> >
> >  * accept: Allow any usage
> >  * reject: Reject with an error reported
> >  * warn: Allow any usage, with a warning reported
> >
> > For historical compatibility it defaults to 'accept'.
> >
> > The 'reject' and 'warn' values will take effect for any type
> > that has been explicitly marked insecure, or is lacking an
> > explicit declaration of its security status.
> >
> > This new command line option is currently a no-op, but will
> > become functional as following patches enable the checks.
> >
> > Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> > Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
> > Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>

snip

> > diff --git a/qapi/compat.json b/qapi/compat.json
> > index 90b8d51cf27..b54f8eb3713 100644
> > --- a/qapi/compat.json
> > +++ b/qapi/compat.json
> > @@ -37,6 +37,23 @@
> >  { 'enum': 'CompatPolicyOutput',
> >    'data': [ 'accept', 'hide' ] }
> >  
> > +##
> > +# @CompatPolicySecurity:
> > +#
> > +# Policy for handling any devices or backends which do not provide a
> > +# security boundary to protect against untrusted environments
> > +#
> > +# @accept: Allow any usage
> > +#
> > +# @reject: Reject with an error reported
> > +#
> > +# @warn: Allow any usage, with a warning reported
> > +#
> > +# Since: 11.2
> > +##
> > +{ 'enum': 'CompatPolicySecurity',
> > +  'data': [ 'accept', 'reject', 'warn' ] }
> > +
> >  ##
> >  # @CompatPolicy:
> >  #
> > @@ -62,10 +79,14 @@
>    # Policy for handling deprecated management interfaces.
>    #
>    # This is intended for testing users of the management interfaces.
>    #
>    # Limitation: covers only syntactic aspects of QMP, i.e. stuff tagged
>    # with feature 'deprecated' or 'unstable'.  We may want to extend it
>    # to cover semantic aspects and CLI.
>    #
>    # Limitation: deprecated-output policy @hide is not implemented for
>    # enumeration values.  They behave the same as with policy @accept.
>    #
>    # @deprecated-input: how to handle deprecated input (default 'accept')
>    #
>    # @deprecated-output: how to handle deprecated output (default
>    #     'accept')
>    #
>    # @unstable-input: how to handle unstable input (default 'accept')
>    #     (since 6.2)
>    #
> >  # @unstable-output: how to handle unstable output (default 'accept')
> >  #     (since 6.2)
> >  #
> > +# @insecure-types: how to handle types that are not declared secure
> > +#     (default 'accept') (since 11.2)
> 
> Minor issue: "types" is ambiguous without context.  We call lots of
> things "types" in our external interfaces.  It's actually QOM types
> here.  Let's say so.  I can take care of it.
> 
> Similar confusion exists elsewhere[*], but let's not digress.

It is currently  QOM types. It might even stay exclusively QOM types,
but not guaranteed.

The initial focus is mostly on guest visible pieces (-device, -machine)
with '-object' as an easy extra win that's more backend oriented.

In theory it might be extended to other backend types, which are probably
modelled in QAPI, but are not neccessarily implemented with QOM. So I
somewhat intentionally left it fuzzy what 'types' we refer to.

> >  # Since: 6.0
> >  ##
> >  { 'struct': 'CompatPolicy',
> >    'data': { '*deprecated-input': 'CompatPolicyInput',
> >              '*deprecated-output': 'CompatPolicyOutput',
> >              '*unstable-input': 'CompatPolicyInput',
> > -            '*unstable-output': 'CompatPolicyOutput' } }
> > +            '*unstable-output': 'CompatPolicyOutput',
> > +            '*insecure-types': 'CompatPolicySecurity' } }
> 
> The existing members are all named "wide", and the documentation narrows
> them.  For instance, the name @deprecated-input could cover *any* input,
> but its documentation narrows it to "only syntactic aspects of QMP".  I
> did it this way to let us extend coverage without having to change the
> external interface.
> 
> New member @insecure-types is named "narrow".  Why different?  Why not
> @insecure-input?

In those existing examples, we're directly refering to data streams,
whether they're command line / QMP parameters or QMP response, so
input/output are reasonable terms.

In the security status, we specifically focused on types, regardless
of whether they're requested explicitly via -device (& friends) or
arrive implicitly via built-in command line defaults and/or hardcoded
type relationships (ie built devices in a machine type).  I don't
find 'input' to be a desired term in that respect.

What is being determined is whether the VM as a whole can be classed
as secure or not.

> The existing @FOO-input support CompatPolicyInput: "accept", "reject",
> "crash".  New insecure-types supports CompatPolicySecurity: "accept",
> "reject", "warn".  Why different?

With deprecations, there is often (but not always) a warning message
printed unconditioally. eg even if you have 'accept' as policy, you
are liable to see a deprecation warning message on stderr. This is
good because even if you want to carry on using it for now, and
never give a -compat flag, actioning the deprecation warning is
still essential.


With security checks, it is valid to launch QEMU in an insecure
configuration and use it that way forever, with no action required
to change anything. As such we must never report any warnings by
default for insecure types, any warning messages must be strictly
opt-in.  So "accept" is the default behaviour which is totally
silent, "warn" lets you know something is bad but does not
enforce it, and "reject' lets you know something is bad and
refuses to let it be used. So overall, I think "warn" is justified
for security checks, while not required for deprecations.

> My rationale for "crash" is in commit dbb675c19aa (qapi: New -compat
> deprecated-input=crash):
> 
>     Bugs in integration tests may mask the error from policy "reject".
>     Provide a larger hammer: crash outright.  Masking that seems unlikely.
> 
> If "crash" can be useful for testing a management application's non-use
> of deprecated and unstable interfaces, surely it's just as useful for
> insecure ones.

I'm happy to add 'crash' as an extra option.

> Likewise, "warn".  I didn't provide "warn" at the time, because QMP
> lacks support for warnings.  Do management applications find warnings on
> stderr in response to QMP commands useful?

Many deprecations none the less report warnings on stderr - we just
haven't automated that process from QAPI schema.

I've seen plenty of scenarios where people have paid attention to
the deprecation warnings in libvirt logs capturing QEMU's stderr.
It is likely the main way that non-developers find out about the
deprecations, as few people proactively read the QEMU docs to
see deprecations, and similarly few use a -compat arg.


For the security compat arg, my expectation was that distros which
wish to restrict what their ship & support (ie RHEL) could use
the -compat insecure-types arg to validate their configs, and
could even set libvirt in their distro to pass 'warn' (or even
'reject') as a safety net against mistakes.

I think it would also be interesting for virt-install (and similar
tools) to request secure types only by default, at least if KVM
is used.

> -util.c b/qapi/qapi-util.c
> > index 3d849fe0347..38b1cec7a41 100644
> > --- a/qapi/qapi-util.c
> > +++ b/qapi/qapi-util.c
> > @@ -14,6 +14,7 @@
> >  #include "qapi/compat-policy.h"
> >  #include "qapi/error.h"
> >  #include "qemu/ctype.h"
> > +#include "qemu/error-report.h"
> >  #include "qapi/qmp/qerror.h"
> >  
> >  CompatPolicy compat_policy;
> > @@ -58,6 +59,35 @@ bool compat_policy_input_ok(uint64_t features,
> >      return true;
> >  }
> >  
> > +bool compat_policy_check_security(const CompatPolicy *policy,
> > +                                  const char *typename,
> > +                                  bool is_secure,
> > +                                  Error **errp)
> 
> More minor issues.
> 
> The policy functions are named compat_policy_FOO_ok().  Why different?

I wasn't paying close enough attention to the naming convention.

> Their arguments are "relevant facts" (@features), @policy, "stuff for
> error message" (@error_class, @kind, @name), @errp.  This one has the
> same things in different order.  Why?

Same lack of close attention as above.

Though I would say I think the 'const CompatPolicy *policy' arg should
be the first one in all the existing methods, as it is typical convention
for the first arg type to be associated with the method name.

> 
> > +{
> > +    if (is_secure) {
> > +        return true;
> > +    }
> > +
> > +    switch (policy->insecure_types) {
> > +    case COMPAT_POLICY_SECURITY_ACCEPT:
> > +        return true;
> > +
> > +    case COMPAT_POLICY_SECURITY_REJECT:
> > +        error_setg(errp, "Type '%s' does not provide a security boundary "
> > +                   "to protect against untrusted data or actions", typename);
> > +        return false;
> > +
> > +    case COMPAT_POLICY_SECURITY_WARN:
> > +        warn_report("Type '%s' does not provide a security boundary "
> > +                    "to protect against untrusted data or actions", typename);
> > +        return true;
> > +
> > +    default:
> > +        g_assert_not_reached();
> > +    }
> > +}
> > +
> > +
> >  const char *qapi_enum_lookup(const QEnumLookup *lookup, int val)
> >  {
> >      assert(val >= 0 && val < lookup->size);
> 
> 
> [*] So I digress in a footnote.  Sue me ;)
> 
> While examining the QAPI schema, I found near object-add:
> 
>     ##
>     # @qom-list-properties:
>     #     List properties associated with a QOM object.
>     #
>     # @typename: the type name of an object
>     [...]
>     ##
>     # @object-add:
>     #     Create a QOM object.
>     #
>     # Errors:
>     #     - If @qom-type is not a valid class name
>     [...]
>     ##
>     # @ObjectOptions:
>     #     Describes the options of a user creatable QOM object.
>     #
>     # @qom-type: the class name for the object to be created
> 
> We use "QOM type" and "QOM class".  This is pretty bad; we should pick
> one and stick with it.

Probably "type" since there is no concept of a "class" in QAPI,
it is just a schema for describing types and their relationships.

The 'class' is an internal QOM implementation detail of the
public QAPI 'type'.

> And near device_add:
> 
>     ##
>     # @device-list-properties:
>     #     List properties associated with a device.
>     #
>     # @typename: the type name of a device
>     [...]
>     ##
>     # @device_add:
>     #     Add a device.
>     #
>     # @driver: the name of the new device's driver
> 
> We use "driver" and "device type".  Similarly bad.

Kind of wish we just used a plain 'type' in both -object and -device,
but changing that is not worth the disruption. At least the docs
could refer to 'QOM type' generally.


With regards,
Daniel
-- 
|: https://berrange.com       ~~        https://hachyderm.io/@berrange :|
|: https://libvirt.org          ~~          https://entangle-photo.org :|
|: https://pixelfed.art/berrange   ~~    https://fstop138.berrange.com :|



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

* Re: [PULL 02/14] qapi: add 'insecure-types' option for -compat argument
  2026-10-27 14:47     ` Daniel P. Berrangé
@ 2026-10-28  9:23       ` Markus Armbruster
  0 siblings, 0 replies; 19+ messages in thread
From: Markus Armbruster @ 2026-10-28  9:23 UTC (permalink / raw)
  To: Daniel P. Berrangé
  Cc: qemu-devel, Marc-André Lureau, Richard Henderson, Eric Blake,
	John Snow

Daniel P. Berrangé <berrange@redhat.com> writes:

> On Tue, Oct 27, 2026 at 10:46:00AM +0100, Markus Armbruster wrote:
>> This has long been merged.  I couldn't review it at the time, and
>> merging it without my review was clearly appropriate.
>> 
>> I have questions / doubts about the external interface I'd like to
>> discuss now.
>
> ... just in time for freeze if we need any urgent changes
> before this gets into a release.

Basically last minute :)

>> Daniel P. Berrangé <berrange@redhat.com> writes:
>> 
>> > This introduces a new 'insecure-types' option for the 'compat'
>> > argument that accepts three values
>> >
>> >  * accept: Allow any usage
>> >  * reject: Reject with an error reported
>> >  * warn: Allow any usage, with a warning reported
>> >
>> > For historical compatibility it defaults to 'accept'.
>> >
>> > The 'reject' and 'warn' values will take effect for any type
>> > that has been explicitly marked insecure, or is lacking an
>> > explicit declaration of its security status.
>> >
>> > This new command line option is currently a no-op, but will
>> > become functional as following patches enable the checks.
>> >
>> > Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
>> > Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
>> > Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
>
> snip
>
>> > diff --git a/qapi/compat.json b/qapi/compat.json
>> > index 90b8d51cf27..b54f8eb3713 100644
>> > --- a/qapi/compat.json
>> > +++ b/qapi/compat.json
>> > @@ -37,6 +37,23 @@
>> >  { 'enum': 'CompatPolicyOutput',
>> >    'data': [ 'accept', 'hide' ] }
>> >  
>> > +##
>> > +# @CompatPolicySecurity:
>> > +#
>> > +# Policy for handling any devices or backends which do not provide a
>> > +# security boundary to protect against untrusted environments
>> > +#
>> > +# @accept: Allow any usage
>> > +#
>> > +# @reject: Reject with an error reported
>> > +#
>> > +# @warn: Allow any usage, with a warning reported
>> > +#
>> > +# Since: 11.2
>> > +##
>> > +{ 'enum': 'CompatPolicySecurity',
>> > +  'data': [ 'accept', 'reject', 'warn' ] }
>> > +
>> >  ##
>> >  # @CompatPolicy:
>> >  #
>> > @@ -62,10 +79,14 @@
>>    # Policy for handling deprecated management interfaces.
>>    #
>>    # This is intended for testing users of the management interfaces.
>>    #
>>    # Limitation: covers only syntactic aspects of QMP, i.e. stuff tagged
>>    # with feature 'deprecated' or 'unstable'.  We may want to extend it
>>    # to cover semantic aspects and CLI.
>>    #
>>    # Limitation: deprecated-output policy @hide is not implemented for
>>    # enumeration values.  They behave the same as with policy @accept.
>>    #
>>    # @deprecated-input: how to handle deprecated input (default 'accept')
>>    #
>>    # @deprecated-output: how to handle deprecated output (default
>>    #     'accept')
>>    #
>>    # @unstable-input: how to handle unstable input (default 'accept')
>>    #     (since 6.2)
>>    #
>> >  # @unstable-output: how to handle unstable output (default 'accept')
>> >  #     (since 6.2)
>> >  #
>> > +# @insecure-types: how to handle types that are not declared secure
>> > +#     (default 'accept') (since 11.2)
>> 
>> Minor issue: "types" is ambiguous without context.  We call lots of
>> things "types" in our external interfaces.  It's actually QOM types
>> here.  Let's say so.  I can take care of it.
>> 
>> Similar confusion exists elsewhere[*], but let's not digress.
>
> It is currently  QOM types. It might even stay exclusively QOM types,
> but not guaranteed.
>
> The initial focus is mostly on guest visible pieces (-device, -machine)
> with '-object' as an easy extra win that's more backend oriented.
>
> In theory it might be extended to other backend types, which are probably
> modelled in QAPI, but are not neccessarily implemented with QOM. So I
> somewhat intentionally left it fuzzy what 'types' we refer to.

If we named it @insecure-fuzz, users would get about the same
information ("it's about *something*") with less risk of confusion ("it
must be about device types, right?").

I'm not actually proposing to name it this way, I'm merely arguing that
the current name is problematic.

>> >  # Since: 6.0
>> >  ##
>> >  { 'struct': 'CompatPolicy',
>> >    'data': { '*deprecated-input': 'CompatPolicyInput',
>> >              '*deprecated-output': 'CompatPolicyOutput',
>> >              '*unstable-input': 'CompatPolicyInput',
>> > -            '*unstable-output': 'CompatPolicyOutput' } }
>> > +            '*unstable-output': 'CompatPolicyOutput',
>> > +            '*insecure-types': 'CompatPolicySecurity' } }
>> 
>> The existing members are all named "wide", and the documentation narrows
>> them.  For instance, the name @deprecated-input could cover *any* input,
>> but its documentation narrows it to "only syntactic aspects of QMP".  I
>> did it this way to let us extend coverage without having to change the
>> external interface.
>> 
>> New member @insecure-types is named "narrow".  Why different?  Why not
>> @insecure-input?
>
> In those existing examples, we're directly refering to data streams,
> whether they're command line / QMP parameters or QMP response, so
> input/output are reasonable terms.

To avoid misunderstandings: @deprecated-input is strictly QMP (all four
policies predating yours are strictly QMP in fact).  For instance,
chardev kind "memory" is deprecated.  Creating one with QMP is caught by
policy:

    $ qemu-system-x86_64 -S -nodefaults -display none -compat deprecated-input=reject -qmp stdio
    {"QMP": {"version": {"qemu": {"micro": 50, "minor": 1, "major": 11}, "package": "v11.1.0-2787-g288458be66-dirty"}, "capabilities": ["oob"]}}
    {"execute": "qmp_capabilities", "arguments": {"enable": ["oob"]}}
    {"return": {}}
    {"execute":"chardev-add", "arguments": {"id":"chr0", "backend": {"type": "memory", "data": {}}}}
    {"error": {"class": "GenericError", "desc": "Deprecated value memory disabled by policy"}}
    {"execute": "quit"}
    {"timestamp": {"seconds": 1793173931, "microseconds": 999776}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
    {"return": {}}

Creating one with CLI is not:

    $ qemu-system-x86_64 -S -nodefaults -display none -compat deprecated-input=reject -chardev memory,id=chr0 -qmp stdio
    {"QMP": {"version": {"qemu": {"micro": 50, "minor": 1, "major": 11}, "package": "v11.1.0-2787-g288458be66-dirty"}, "capabilities": ["oob"]}}
    {"execute": "qmp_capabilities", "arguments": {"enable": ["oob"]}}
    {"return": {}}
    {"execute": "query-chardev"}
    {"return": [{"frontend-open": false, "filename": "memory", "label": "chr0"}, {"frontend-open": true, "filename": "stdio", "label": "compat_monitor0"}]}
    {"execute": "quit"}
    {"timestamp": {"seconds": 1793174007, "microseconds": 270419}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
    {"return": {}}

Works as intended, and matches documentation.  Yes, applying the policy
more widely would be more useful, and applying it everywhere would
likely be most useful, but this better than nothing, and it's what I
could actually implement.  New CompatPolicy members, such as yours, need
not have this limitation.  The may have others.

> In the security status, we specifically focused on types, regardless
> of whether they're requested explicitly via -device (& friends) or
> arrive implicitly via built-in command line defaults and/or hardcoded
> type relationships (ie built devices in a machine type).  I don't
> find 'input' to be a desired term in that respect.
>
> What is being determined is whether the VM as a whole can be classed
> as secure or not.

1. You picked a different limitation for @insecure-types: it covers only
QOM types.  Again, a different limitation is *fine*.  "Only QOM types"
is obviously more useful than "only QOM types and only QMP" would be.

2. I do think the policy is about input.  What else could be accepted
(@accept), accepted with a warning (@warn), or rejected (@reject)?  The
connection from QOM object creation to input can be less obvious than it
is for @deprecated-input and @unstable-input.  But it surely exists,
don't you think?  Consider how a QOM object of type T could be created:

* The user asked for it with -device T,..., -object T,..., or similar.
  Obvious.

* The user asked for it with -machine M, -cpu C, or similar.  Same,
  except we use machine names / CPU names, ... instead of QOM type
  names, mostly for historical reasons, which makes it slightly less
  obvious.

* The user asked for another type that contains T as a component.  This
  can be unobvious, e.g. when a machine contains some obscure onboard
  device the user doesn't know or care about.  It's still the user's
  input that triggers its creation.

* We create T by default, i.e. we can't pin it on any particular piece
  of user input.  It's still triggered by user input, though.

  Example: the user elects not to pass -machine, and the default machine
  contains an insecure onboard device.  The user still asked for that
  machine, if only by not asking for another one.

  Hypothetical example: qemu-system-insecure provides just one machine
  type, which contains an insecure onboard device.  The user still asked
  for that machine, if only by running qemu-system-insecure.

* Did I miss ways to create T?

>> The existing @FOO-input support CompatPolicyInput: "accept", "reject",
>> "crash".  New insecure-types supports CompatPolicySecurity: "accept",
>> "reject", "warn".  Why different?
>
> With deprecations, there is often (but not always) a warning message
> printed unconditioally.

Yes, we do this manually when we remember to.

We do *not* do this automatically for QAPI schema feature @deprecated.
There is no warning then for QMP input.  CLI and HMP wrapping around QMP
warn only if someone added code for it manually.  Rare to never, I'd
guess.  So, @deprecated-input policy @accept does what it says on the
tin: accept silently.  Possibly with rare exceptions.

>                         eg even if you have 'accept' as policy, you
> are liable to see a deprecation warning message on stderr.

Uh, what's the difference between policy @accept and policy @warn then?

>                                                            This is
> good because even if you want to carry on using it for now, and
> never give a -compat flag, actioning the deprecation warning is
> still essential.
>
> With security checks, it is valid to launch QEMU in an insecure
> configuration and use it that way forever, with no action required
> to change anything. As such we must never report any warnings by
> default for insecure types, any warning messages must be strictly
> opt-in.  So "accept" is the default behaviour which is totally
> silent, "warn" lets you know something is bad but does not
> enforce it, and "reject' lets you know something is bad and
> refuses to let it be used. So overall, I think "warn" is justified
> for security checks, while not required for deprecations.

If I understand you correctly, you're arguing for "accept insecure
silently" by default, and for "accept deprecated with a warning" by
default.  Correct?

I feel the sane way to do this would be a choice of accept/warn/reject
in both cases, but with different default, @warn for deprecated, @accept
for insecure.

>> My rationale for "crash" is in commit dbb675c19aa (qapi: New -compat
>> deprecated-input=crash):
>> 
>>     Bugs in integration tests may mask the error from policy "reject".
>>     Provide a larger hammer: crash outright.  Masking that seems unlikely.
>> 
>> If "crash" can be useful for testing a management application's non-use
>> of deprecated and unstable interfaces, surely it's just as useful for
>> insecure ones.
>
> I'm happy to add 'crash' as an extra option.

One-liner, almost :)

>> Likewise, "warn".  I didn't provide "warn" at the time, because QMP
>> lacks support for warnings.

I just remembered another reason.  We generally want to emit a
deprecation warning at most once, to not annoy users.
warn_report_once() makes that easy.  Doesn't work when all the QAPI
deprecation warnings are detected by a single piece of code.  Using
warn_report_once() there would go silent after the first QAPI
deprecation warning, which is not what we'd want.

>>                              Do management applications find warnings on
>> stderr in response to QMP commands useful?
>
> Many deprecations none the less report warnings on stderr - we just
> haven't automated that process from QAPI schema.
>
> I've seen plenty of scenarios where people have paid attention to
> the deprecation warnings in libvirt logs capturing QEMU's stderr.
> It is likely the main way that non-developers find out about the
> deprecations, as few people proactively read the QEMU docs to
> see deprecations, and similarly few use a -compat arg.

I am open to adding policy @warn to deprecated-input and unstable-input,
with deprecated-input's default changing to @warn.

However, I'd much prefer to warn at most once per deprecated thing.  I
can't say offhand how that could be done, though.

> For the security compat arg, my expectation was that distros which
> wish to restrict what their ship & support (ie RHEL) could use
> the -compat insecure-types arg to validate their configs, and
> could even set libvirt in their distro to pass 'warn' (or even
> 'reject') as a safety net against mistakes.
>
> I think it would also be interesting for virt-install (and similar
> tools) to request secure types only by default, at least if KVM
> is used.
>
>> > diff --git a/qapi/qapi-util.c b/qapi/qapi-util.c
>> > index 3d849fe0347..38b1cec7a41 100644
>> > --- a/qapi/qapi-util.c
>> > +++ b/qapi/qapi-util.c
>> > @@ -14,6 +14,7 @@
>> >  #include "qapi/compat-policy.h"
>> >  #include "qapi/error.h"
>> >  #include "qemu/ctype.h"
>> > +#include "qemu/error-report.h"
>> >  #include "qapi/qmp/qerror.h"
>> >  
>> >  CompatPolicy compat_policy;
>> > @@ -58,6 +59,35 @@ bool compat_policy_input_ok(uint64_t features,
>> >      return true;
>> >  }
>> >  
>> > +bool compat_policy_check_security(const CompatPolicy *policy,
>> > +                                  const char *typename,
>> > +                                  bool is_secure,
>> > +                                  Error **errp)
>> 
>> More minor issues.
>> 
>> The policy functions are named compat_policy_FOO_ok().  Why different?
>
> I wasn't paying close enough attention to the naming convention.

Happens :)  Easy enough to tidy up.

>> Their arguments are "relevant facts" (@features), @policy, "stuff for
>> error message" (@error_class, @kind, @name), @errp.  This one has the
>> same things in different order.  Why?
>
> Same lack of close attention as above.
>
> Though I would say I think the 'const CompatPolicy *policy' arg should
> be the first one in all the existing methods, as it is typical convention
> for the first arg type to be associated with the method name.

Fair point.

>> > +{
>> > +    if (is_secure) {
>> > +        return true;
>> > +    }
>> > +
>> > +    switch (policy->insecure_types) {
>> > +    case COMPAT_POLICY_SECURITY_ACCEPT:
>> > +        return true;
>> > +
>> > +    case COMPAT_POLICY_SECURITY_REJECT:
>> > +        error_setg(errp, "Type '%s' does not provide a security boundary "
>> > +                   "to protect against untrusted data or actions", typename);
>> > +        return false;
>> > +
>> > +    case COMPAT_POLICY_SECURITY_WARN:
>> > +        warn_report("Type '%s' does not provide a security boundary "
>> > +                    "to protect against untrusted data or actions", typename);
>> > +        return true;
>> > +
>> > +    default:
>> > +        g_assert_not_reached();
>> > +    }
>> > +}
>> > +
>> > +
>> >  const char *qapi_enum_lookup(const QEnumLookup *lookup, int val)
>> >  {
>> >      assert(val >= 0 && val < lookup->size);
>> 
>> 
>> [*] So I digress in a footnote.  Sue me ;)
>> 
>> While examining the QAPI schema, I found near object-add:
>> 
>>     ##
>>     # @qom-list-properties:
>>     #     List properties associated with a QOM object.
>>     #
>>     # @typename: the type name of an object
>>     [...]
>>     ##
>>     # @object-add:
>>     #     Create a QOM object.
>>     #
>>     # Errors:
>>     #     - If @qom-type is not a valid class name
>>     [...]
>>     ##
>>     # @ObjectOptions:
>>     #     Describes the options of a user creatable QOM object.
>>     #
>>     # @qom-type: the class name for the object to be created
>> 
>> We use "QOM type" and "QOM class".  This is pretty bad; we should pick
>> one and stick with it.
>
> Probably "type" since there is no concept of a "class" in QAPI,
> it is just a schema for describing types and their relationships.
>
> The 'class' is an internal QOM implementation detail of the
> public QAPI 'type'.

Yes.  And I don't like it much there.

>> And near device_add:
>> 
>>     ##
>>     # @device-list-properties:
>>     #     List properties associated with a device.
>>     #
>>     # @typename: the type name of a device
>>     [...]
>>     ##
>>     # @device_add:
>>     #     Add a device.
>>     #
>>     # @driver: the name of the new device's driver
>> 
>> We use "driver" and "device type".  Similarly bad.
>
> Kind of wish we just used a plain 'type' in both -object and -device,
> but changing that is not worth the disruption. At least the docs
> could refer to 'QOM type' generally.

Makes sense.

Thank you!



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

end of thread, other threads:[~2026-10-28  9:24 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-17 16:05 [PULL 00/14] QOM security status patches Daniel P. Berrangé
2026-09-17 16:05 ` [PULL 01/14] qom: add tracking of security state of object types Daniel P. Berrangé
2026-09-17 16:05 ` [PULL 02/14] qapi: add 'insecure-types' option for -compat argument Daniel P. Berrangé
2026-10-27  9:46   ` Markus Armbruster
2026-10-27 14:47     ` Daniel P. Berrangé
2026-10-28  9:23       ` Markus Armbruster
2026-09-17 16:05 ` [PULL 03/14] qom: add helper API for checking object class security policy compliance Daniel P. Berrangé
2026-09-17 16:05 ` [PULL 04/14] system: check security for accelerator types Daniel P. Berrangé
2026-09-17 16:05 ` [PULL 05/14] system: report acclerator security status in help output Daniel P. Berrangé
2026-09-17 16:05 ` [PULL 06/14] system: check security for machine types Daniel P. Berrangé
2026-09-17 16:05 ` [PULL 07/14] system: report machine security status in help output Daniel P. Berrangé
2026-09-17 16:05 ` [PULL 08/14] system: check security of device types Daniel P. Berrangé
2026-09-17 16:05 ` [PULL 09/14] system: report device security status in help output Daniel P. Berrangé
2026-09-17 16:05 ` [PULL 10/14] hw/core: report security status in query-machines Daniel P. Berrangé
2026-09-17 16:05 ` [PULL 11/14] qom: refactor data passing for QOM list filtering Daniel P. Berrangé
2026-09-17 16:05 ` [PULL 12/14] qom: report & filter on security status in qom-list-types Daniel P. Berrangé
2026-09-17 16:05 ` [PULL 13/14] docs: expand security docs with info about security status Daniel P. Berrangé
2026-09-17 16:05 ` [PULL 14/14] machine: add helpers for declaring secure/insecure machine types Daniel P. Berrangé
2026-09-17 21:50 ` [PULL 00/14] QOM security status patches Richard Henderson

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.