[PATCH <RFC> 00/15] Encode object type security status in code

Daniel P. Berrangé posted 15 patches 2 weeks, 4 days ago
Patches applied successfully (tree, apply log)
git fetch https://github.com/patchew-project/qemu tags/patchew/20250909165726.3814465-1-berrange@redhat.com
Maintainers: Paolo Bonzini <pbonzini@redhat.com>, Richard Henderson <richard.henderson@linaro.org>, Peter Maydell <peter.maydell@linaro.org>, Eduardo Habkost <eduardo@habkost.net>, Marcel Apfelbaum <marcel.apfelbaum@gmail.com>, "Philippe Mathieu-Daudé" <philmd@linaro.org>, Yanan Wang <wangyanan55@huawei.com>, Zhao Liu <zhao1.liu@intel.com>, "Michael S. Tsirkin" <mst@redhat.com>, Sergio Lopez <slp@redhat.com>, Stefano Stabellini <sstabellini@kernel.org>, Anthony PERARD <anthony@xenproject.org>, Paul Durrant <paul@xen.org>, "Edgar E. Iglesias" <edgar.iglesias@gmail.com>, Beniamino Galvani <b.galvani@gmail.com>, Strahinja Jankovic <strahinja.p.jankovic@gmail.com>, Jason Wang <jasowang@redhat.com>, Alistair Francis <alistair@alistair23.me>, Pavel Pisa <pisa@cmp.felk.cvut.cz>, Francisco Iglesias <francisco.iglesias@amd.com>, Vikram Garhwal <vikram.garhwal@bytedance.com>, Dmitry Fleytman <dmitry.fleytman@gmail.com>, Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>, Stefan Weil <sw@weilnetz.de>, Bernhard Beschow <shentey@gmail.com>, "Cédric Le Goater" <clg@kaod.org>, Steven Lee <steven_lee@aspeedtech.com>, Troy Lee <leetroy@gmail.com>, Jamin Lin <jamin_lin@aspeedtech.com>, Andrew Jeffery <andrew@codeconstruct.com.au>, Joel Stanley <joel@jms.id.au>, Sriram Yagnaraman <sriram.yagnaraman@ericsson.com>, Helge Deller <deller@gmx.de>, Thomas Huth <huth@tuxfamily.org>, Subbaraya Sundeep <sundeep.lkml@gmail.com>, Jan Kiszka <jan.kiszka@web.de>, Tyrone Ting <kfting@nuvoton.com>, Hao Wu <wuhaotsh@google.com>, Max Filippov <jcmvbkbc@gmail.com>, Jiri Pirko <jiri@resnulli.us>, Nicholas Piggin <npiggin@gmail.com>, Harsh Prateek Bora <harshpb@linux.ibm.com>, Sven Schnelle <svens@stackframe.org>, Rob Herring <robh@kernel.org>, David Hildenbrand <david@redhat.com>, Ilya Leoshkevich <iii@linux.ibm.com>, Halil Pasic <pasic@linux.ibm.com>, Christian Borntraeger <borntraeger@linux.ibm.com>, Eric Farman <farman@linux.ibm.com>, Matthew Rosato <mjrosato@linux.ibm.com>, "Daniel P. Berrangé" <berrange@redhat.com>, Eric Blake <eblake@redhat.com>, Markus Armbruster <armbru@redhat.com>
There is a newer version of this series
accel/kvm/kvm-all.c            |  1 +
accel/tcg/tcg-all.c            |  1 +
docs/system/security.rst       | 41 +++++++++++++++++++++
hw/arm/virt.c                  |  1 +
hw/arm/xen-pvh.c               |  1 +
hw/core/machine-qmp-cmds.c     |  2 ++
hw/core/machine.c              | 66 ++++++++++++++++++++++++++++++++++
hw/core/null-machine.c         |  2 +-
hw/i386/isapc.c                |  2 +-
hw/i386/microvm.c              |  1 +
hw/i386/pc_piix.c              |  4 +--
hw/i386/xen/xen-pvh.c          |  1 +
hw/i386/xen/xen_pvdevice.c     |  1 +
hw/net/allwinner-sun8i-emac.c  |  1 +
hw/net/allwinner_emac.c        |  3 +-
hw/net/cadence_gem.c           |  1 +
hw/net/can/can_kvaser_pci.c    |  1 +
hw/net/can/can_mioe3680_pci.c  |  1 +
hw/net/can/can_pcm3680_pci.c   |  1 +
hw/net/can/ctucan_pci.c        |  1 +
hw/net/can/xlnx-versal-canfd.c |  1 +
hw/net/can/xlnx-zynqmp-can.c   |  1 +
hw/net/dp8393x.c               |  1 +
hw/net/e1000.c                 |  1 +
hw/net/e1000e.c                |  1 +
hw/net/eepro100.c              |  1 +
hw/net/fsl_etsec/etsec.c       |  1 +
hw/net/ftgmac100.c             |  1 +
hw/net/igb.c                   |  1 +
hw/net/igbvf.c                 |  1 +
hw/net/imx_fec.c               |  2 ++
hw/net/lan9118.c               |  1 +
hw/net/lan9118_phy.c           |  1 +
hw/net/lance.c                 |  1 +
hw/net/lasi_i82596.c           |  1 +
hw/net/mcf_fec.c               |  1 +
hw/net/msf2-emac.c             |  1 +
hw/net/mv88w8618_eth.c         |  1 +
hw/net/ne2000-isa.c            |  1 +
hw/net/ne2000-pci.c            |  1 +
hw/net/npcm7xx_emc.c           |  1 +
hw/net/npcm_gmac.c             |  1 +
hw/net/npcm_pcs.c              |  1 +
hw/net/opencores_eth.c         |  1 +
hw/net/pcnet-pci.c             |  1 +
hw/net/rocker/rocker.c         |  1 +
hw/net/rtl8139.c               |  1 +
hw/net/smc91c111.c             |  1 +
hw/net/spapr_llan.c            |  1 +
hw/net/stellaris_enet.c        |  1 +
hw/net/sungem.c                |  1 +
hw/net/sunhme.c                |  1 +
hw/net/tulip.c                 |  1 +
hw/net/virtio-net.c            |  1 +
hw/net/vmxnet3.c               |  1 +
hw/net/xen_nic.c               |  1 +
hw/net/xgmac.c                 |  1 +
hw/net/xilinx_axienet.c        |  1 +
hw/net/xilinx_ethlite.c        |  1 +
hw/ppc/spapr.c                 |  1 +
hw/s390x/s390-virtio-ccw.c     |  1 +
hw/virtio/virtio-pci.c         |  3 ++
hw/xen/xen-pvh-common.c        |  1 +
hw/xenpv/xen_machine_pv.c      |  2 +-
include/hw/boards.h            | 18 +++++++++-
include/hw/i386/pc.h           |  5 ++-
include/qom/object.h           | 24 +++++++++++++
qapi/machine.json              |  9 ++++-
qom/object.c                   | 40 +++++++++++++++++----
system/qdev-monitor.c          | 10 ++++++
system/vl.c                    |  6 ++--
71 files changed, 275 insertions(+), 18 deletions(-)
[PATCH <RFC> 00/15] Encode object type security status in code
Posted by Daniel P. Berrangé 2 weeks, 4 days ago
Our docs/system/security.rst file loosely classifies code into that
applicable for 'virtualization' vs 'non-virtualization' use cases.
Only code relevant to the former group is eligible for security
bug handling. Peter's recent proposal pointed out that we are
increasingly hitting the limits of such a crude classification:

  https://lists.nongnu.org/archive/html/qemu-devel/2025-09/msg01520.html

Michael suggested that with the increased complexity, docs are not
going to be an effective way to convey the information, and we
need to re-consider embedding this info in code:

  https://lists.nongnu.org/archive/html/qemu-devel/2025-09/msg01566.html

This also allows users to validate a configuration's security status
when starting a guest, or modifying a running guest. This series is
an attempt to start the embedding process.

It starts with QOM, adding "bool secure" and "bool insecure"
properties to the TypeInfo struct, which get turned into flags
on the Type struct. This enables querying any ObjectClass to
ask whether or not it is declared secure or insecure.

By default no statement will be made about whether a class is
secure or insecure, reflecting our historical defaults. Over
time we should annotate as many classes as possible with an
explicit statement.

The "-machine" argument gains two new parameters

  * prohibit-insecure=yes|no  - a weak security boundary, only
    excluding stuff that is explicitly declared insecure,
    permiting stuff that is secure & anything without a stetement

  * require-secure=yes|no - a strong security boundary, only
    permitting stuff that is explicitly declared secure,
    excluding insecure stuff & anything without a statement

As illustration, I have added explicit annotations for many machine
types, some accelerators, all NICs (all insecure except xen,
e1000(e) and virtio), and all PCI virtio devices (all secure).

Example: TCG is explicitly insecure, KVM is explicitly secure,
         qtest has no statement:

  $ qemu-system-x86_64 -display none -machine pc,prohibit-insecure=yes -accel tcg
  qemu-system-x86_64: Type 'tcg-accel' is declared as insecure

  $ qemu-system-x86_64 -display none -machine pc,require-secure=yes -accel tcg
  qemu-system-x86_64: Type 'tcg-accel' is not declared as secure

  $ qemu-system-x86_64 -display none -machine pc,prohibit-insecure=yes -accel kvm
  ^Cqemu-system-x86_64: terminating on signal 2

  $ qemu-system-x86_64 -display none -machine pc,require-secure=yes -accel kvm
  ^Cqemu-system-x86_64: terminating on signal 2

  $ qemu-system-x86_64 -display none -machine pc,prohibit-insecure=yes -accel qtest
  ^Cqemu-system-x86_64: terminating on signal 2

  $ qemu-system-x86_64 -display none -machine pc,require-secure=yes -accel qtest
  qemu-system-x86_64: Type 'qtest-accel' is not declared as secure

Example: isapc machine type is explicitly insecure

  $ qemu-system-x86_64 -display none -machine isapc,require-secure=yes -accel kvm
  qemu-system-x86_64: Type 'isapc-machine' is not declared as secure

Example: devices which have no security statement are allowed if
         merely excluding insecure devices:

  $ qemu-system-x86_64 -display none -machine pc,prohibit-insecure=yes -accel kvm -device i6300esb
  ^Cqemu-system-x86_64: terminating on signal 2

Example: devices which have no security statement are rejected if
         requiring explicit security:

  $ qemu-system-x86_64 -display none -machine pc,require-secure=yes -accel kvm -device i6300esb
  qemu-system-x86_64: -device i6300esb: Type 'i6300esb' is not declared as secure

Example: checks also apply in HMP, rtl8139 is explicitly insecure,
         virtio is explicitly secure

  $ qemu-system-x86_64 -display none -machine pc,require-secure=yes -accel kvm -monitor stdio
  QEMU 10.1.50 monitor - type 'help' for more information
  (qemu) device_add rtl8139
  Error: Type 'rtl8139' is not declared as secure
  (qemu) device_add virtio-net

Example: checks also apply in QMP:

  $ ./scripts/qmp/qmp-shell-wrap qemu-system-x86_64 -display none -machine pc,require-secure=yes -accel kvm
  Welcome to the QMP low-level shell!
  Connected
  (QEMU) device_add driver=rtl8139
  {"error": {"class": "GenericError", "desc": "Type 'rtl8139' is not declared as secure"}}
  (QEMU) device_add driver=virtio-net
  {"return": {}}

Some questions....

  * Is using '-machine' the right place to express the policy ?

  * Can we change '-accel help' to report 'secure' / 'insecure'
    as we did for '-machine help' and '-device help'.

  * Should we have 'query-devices' for QMP to allow the 'secure'
    or 'insecure' status to be queried for every device.

  * Should we have 'query-accel' for QMP to allow the 'secure'
    or 'insecure' status to be queried for every accelerator.

  * Should we enforce checks for -object & object_add too ?
    Easy to add code for this, but do we need the ability to
    exclude some object backends of dubious code quality ?

  * Likewise for -chardev / -netdev / etc which are
    conceptual specializations of -object

  * BlockDriver structs don't use QOM, so we can't mark
    'vvfat' block backend as insecure

The first one about '-machine' is probably the main blocker
from a design POV. Other things are just potential future
incremental work.

This series has had only 1/2 a day's work / thought put into
it, hence RFC status. It has been compiled and minimally tested
with the examples shown above. I have not pushed this through
CI nor considered tests yet. Still it gives a good illustration
of what's involved in recording security info in code.

Daniel P. Berrangé (15):
  qom: replace 'abstract' with 'flags'
  qom: add tracking of security state of object types
  machine: add 'require-secure' and 'prohibit-insecure' properties
  machine: check security for machine and accelerator 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 secure/insecure status in query-machines
  accel: mark 'kvm' as secure and 'tcg' as insecure
  hw/virtio: mark all virtio PCI devices as secure
  hw: mark x86, s390, ppc, arm versioned machine types as secure
  hw: declare Xen & microvm machines as secure, isapc as insecure
  hw/core: declare 'none' machine to be insecure
  hw/net: mark all NICs as insecure except e1000, e1000e & xen
  docs: expand security docs with info about secure/insecure markers

 accel/kvm/kvm-all.c            |  1 +
 accel/tcg/tcg-all.c            |  1 +
 docs/system/security.rst       | 41 +++++++++++++++++++++
 hw/arm/virt.c                  |  1 +
 hw/arm/xen-pvh.c               |  1 +
 hw/core/machine-qmp-cmds.c     |  2 ++
 hw/core/machine.c              | 66 ++++++++++++++++++++++++++++++++++
 hw/core/null-machine.c         |  2 +-
 hw/i386/isapc.c                |  2 +-
 hw/i386/microvm.c              |  1 +
 hw/i386/pc_piix.c              |  4 +--
 hw/i386/xen/xen-pvh.c          |  1 +
 hw/i386/xen/xen_pvdevice.c     |  1 +
 hw/net/allwinner-sun8i-emac.c  |  1 +
 hw/net/allwinner_emac.c        |  3 +-
 hw/net/cadence_gem.c           |  1 +
 hw/net/can/can_kvaser_pci.c    |  1 +
 hw/net/can/can_mioe3680_pci.c  |  1 +
 hw/net/can/can_pcm3680_pci.c   |  1 +
 hw/net/can/ctucan_pci.c        |  1 +
 hw/net/can/xlnx-versal-canfd.c |  1 +
 hw/net/can/xlnx-zynqmp-can.c   |  1 +
 hw/net/dp8393x.c               |  1 +
 hw/net/e1000.c                 |  1 +
 hw/net/e1000e.c                |  1 +
 hw/net/eepro100.c              |  1 +
 hw/net/fsl_etsec/etsec.c       |  1 +
 hw/net/ftgmac100.c             |  1 +
 hw/net/igb.c                   |  1 +
 hw/net/igbvf.c                 |  1 +
 hw/net/imx_fec.c               |  2 ++
 hw/net/lan9118.c               |  1 +
 hw/net/lan9118_phy.c           |  1 +
 hw/net/lance.c                 |  1 +
 hw/net/lasi_i82596.c           |  1 +
 hw/net/mcf_fec.c               |  1 +
 hw/net/msf2-emac.c             |  1 +
 hw/net/mv88w8618_eth.c         |  1 +
 hw/net/ne2000-isa.c            |  1 +
 hw/net/ne2000-pci.c            |  1 +
 hw/net/npcm7xx_emc.c           |  1 +
 hw/net/npcm_gmac.c             |  1 +
 hw/net/npcm_pcs.c              |  1 +
 hw/net/opencores_eth.c         |  1 +
 hw/net/pcnet-pci.c             |  1 +
 hw/net/rocker/rocker.c         |  1 +
 hw/net/rtl8139.c               |  1 +
 hw/net/smc91c111.c             |  1 +
 hw/net/spapr_llan.c            |  1 +
 hw/net/stellaris_enet.c        |  1 +
 hw/net/sungem.c                |  1 +
 hw/net/sunhme.c                |  1 +
 hw/net/tulip.c                 |  1 +
 hw/net/virtio-net.c            |  1 +
 hw/net/vmxnet3.c               |  1 +
 hw/net/xen_nic.c               |  1 +
 hw/net/xgmac.c                 |  1 +
 hw/net/xilinx_axienet.c        |  1 +
 hw/net/xilinx_ethlite.c        |  1 +
 hw/ppc/spapr.c                 |  1 +
 hw/s390x/s390-virtio-ccw.c     |  1 +
 hw/virtio/virtio-pci.c         |  3 ++
 hw/xen/xen-pvh-common.c        |  1 +
 hw/xenpv/xen_machine_pv.c      |  2 +-
 include/hw/boards.h            | 18 +++++++++-
 include/hw/i386/pc.h           |  5 ++-
 include/qom/object.h           | 24 +++++++++++++
 qapi/machine.json              |  9 ++++-
 qom/object.c                   | 40 +++++++++++++++++----
 system/qdev-monitor.c          | 10 ++++++
 system/vl.c                    |  6 ++--
 71 files changed, 275 insertions(+), 18 deletions(-)

-- 
2.50.1


Re: [PATCH <RFC> 00/15] Encode object type security status in code
Posted by Markus Armbruster 1 week, 3 days ago
Daniel P. Berrangé <berrange@redhat.com> writes:

> Our docs/system/security.rst file loosely classifies code into that
> applicable for 'virtualization' vs 'non-virtualization' use cases.
> Only code relevant to the former group is eligible for security
> bug handling. Peter's recent proposal pointed out that we are
> increasingly hitting the limits of such a crude classification:
>
>   https://lists.nongnu.org/archive/html/qemu-devel/2025-09/msg01520.html

Yes, we do.

> Michael suggested that with the increased complexity, docs are not
> going to be an effective way to convey the information, and we
> need to re-consider embedding this info in code:
>
>   https://lists.nongnu.org/archive/html/qemu-devel/2025-09/msg01566.html
>
> This also allows users to validate a configuration's security status
> when starting a guest, or modifying a running guest. This series is
> an attempt to start the embedding process.

I like the idea.

We have a long list of configuration choices that might / are known to
punch holes into security boundaries.  Documenting them is entirely
inadequate; telling users who got p0wned it's their own fault for having
missed this particlar drop in the sea of QEMU documentation reminds me
of Douglas Adams' “Beware of The Leopard“.

And we don't have even that!  Just handwavy talk about a "virtualization
use case".

We can and should do better.

> It starts with QOM, adding "bool secure" and "bool insecure"
> properties to the TypeInfo struct, which get turned into flags
> on the Type struct. This enables querying any ObjectClass to
> ask whether or not it is declared secure or insecure.

We should clearly document what "declared secure" actually means.
Here's my attempt at it: supported for use cases that require certain
security boundaries.

> By default no statement will be made about whether a class is
> secure or insecure, reflecting our historical defaults. Over
> time we should annotate as many classes as possible with an
> explicit statement.
>
> The "-machine" argument gains two new parameters
>
>   * prohibit-insecure=yes|no  - a weak security boundary, only
>     excluding stuff that is explicitly declared insecure,
>     permiting stuff that is secure & anything without a stetement

This isn't what users need.

>   * require-secure=yes|no - a strong security boundary, only
>     permitting stuff that is explicitly declared secure,
>     excluding insecure stuff & anything without a statement

This would be, if it covered everything accessible at the security
boundaries.  It doesn't for now: only QOM.

It might still be better than nothing.

However, it may well be unusable until enough of QOM is declared secure.

What would our advice to users be?  I'm afraid something complicated and
impermanent like "try require-secure=yes, and if you can't make it work
because parts of QOM you can't do without are still undeclared, fall
back to prohibit-insecure=yes, and be aware this avoids only some, but
not all security boundary death traps in either case."

This is an awful user interface.  But it's also a step towards the user
interface we want: a single, unchanging switch that ensures you're
running something that's fully supported for use cases that require
certain security boundaries.

A next step could be getting enough of QOM declared so we can move to a
single switch, with the (hopefully temporary) caveat about "only QOM".

We should clearly and prominently document the limitations at each step.

> As illustration, I have added explicit annotations for many machine
> types, some accelerators, all NICs (all insecure except xen,
> e1000(e) and virtio), and all PCI virtio devices (all secure).
>
> Example: TCG is explicitly insecure, KVM is explicitly secure,
>          qtest has no statement:
>
>   $ qemu-system-x86_64 -display none -machine pc,prohibit-insecure=yes -accel tcg
>   qemu-system-x86_64: Type 'tcg-accel' is declared as insecure

[...]

> Some questions....
>
>   * Is using '-machine' the right place to express the policy ?

Not sure.  The guest boundary is just one of several security boundaries
listed in docs/system/security.rst.  Some of them aren't really about
the guest / the machine.

Maybe -compat?  It lets you exclude unstable or deprecated bits from the
user interface.  Feels similar to excluding insecure bits.

>   * Can we change '-accel help' to report 'secure' / 'insecure'
>     as we did for '-machine help' and '-device help'.

No idea, guess it's at worst a matter of shaving the yak?

>   * Should we have 'query-devices' for QMP to allow the 'secure'
>     or 'insecure' status to be queried for every device.
>
>   * Should we have 'query-accel' for QMP to allow the 'secure'
>     or 'insecure' status to be queried for every accelerator.

I recommend qom-list-types.  Covers all of QOM, not just devices and
accelerators.

>   * Should we enforce checks for -object & object_add too ?
>     Easy to add code for this, but do we need the ability to
>     exclude some object backends of dubious code quality ?
>
>   * Likewise for -chardev / -netdev / etc which are
>     conceptual specializations of -object

I lean towards all of QOM, no ifs, no buts.

>   * BlockDriver structs don't use QOM, so we can't mark
>     'vvfat' block backend as insecure

I think this is the biggest gap.

> The first one about '-machine' is probably the main blocker
> from a design POV. Other things are just potential future
> incremental work.
>
> This series has had only 1/2 a day's work / thought put into
> it, hence RFC status. It has been compiled and minimally tested
> with the examples shown above. I have not pushed this through
> CI nor considered tests yet. Still it gives a good illustration
> of what's involved in recording security info in code.

Thanks for that!
Re: [PATCH <RFC> 00/15] Encode object type security status in code
Posted by Daniel P. Berrangé 1 week, 3 days ago
On Thu, Sep 18, 2025 at 01:35:56PM +0200, Markus Armbruster wrote:
> Daniel P. Berrangé <berrange@redhat.com> writes:

> > It starts with QOM, adding "bool secure" and "bool insecure"
> > properties to the TypeInfo struct, which get turned into flags
> > on the Type struct. This enables querying any ObjectClass to
> > ask whether or not it is declared secure or insecure.
> 
> We should clearly document what "declared secure" actually means.
> Here's my attempt at it: supported for use cases that require certain
> security boundaries.



> 
> > By default no statement will be made about whether a class is
> > secure or insecure, reflecting our historical defaults. Over
> > time we should annotate as many classes as possible with an
> > explicit statement.
> >
> > The "-machine" argument gains two new parameters
> >
> >   * prohibit-insecure=yes|no  - a weak security boundary, only
> >     excluding stuff that is explicitly declared insecure,
> >     permiting stuff that is secure & anything without a stetement
> 
> This isn't what users need.
> 
> >   * require-secure=yes|no - a strong security boundary, only
> >     permitting stuff that is explicitly declared secure,
> >     excluding insecure stuff & anything without a statement
> 
> This would be, if it covered everything accessible at the security
> boundaries.  It doesn't for now: only QOM.
> 
> It might still be better than nothing.
> 
> However, it may well be unusable until enough of QOM is declared secure.

Right, the problem is that for a while we'll have 3 buckets of
stuff (insecure, secure and "not sure yet"), when ideally we would
only have two buckets (insecure, secure).

I agree that for people running VMs, ideally require-secure=yes is
what they should be using.

The "not sure yet" bucket is a bit like schrodinger's cat in a box.

If we only had require-secure=yes, and that was insufficient for
the user, they'd be left with no way to exclude stuff that is
/definitely/ insecure. The prohibit-insecure=yes is at least
telling them they're not using something that is a terribly
bad idea.

In practice most of the stuff in the 'not sure yet' bucket will
be stuff that you'll only want to use in combniation with TCG,
and thus your VM will be in the 'insecure' bucket anyway.

There is a 2nd less critical use case for prohibit-insecure=yes
in relation to security report triage.

If someone submits a security report and it relies on a config
that is blocked by prohibit-insecure=yes, then we can categorically
declare it out of scope for CVE handling.

Similarly the require-secure=yes is categorically in-scope.

The 'do not bucket' is where we have to do case-by-case
analysis of the reoprt to decide whether it is in scope or
not.

> What would our advice to users be?  I'm afraid something complicated and
> impermanent like "try require-secure=yes, and if you can't make it work
> because parts of QOM you can't do without are still undeclared, fall
> back to prohibit-insecure=yes, and be aware this avoids only some, but
> not all security boundary death traps in either case."
> 
> This is an awful user interface.  But it's also a step towards the user
> interface we want: a single, unchanging switch that ensures you're
> running something that's fully supported for use cases that require
> certain security boundaries.
> 
> A next step could be getting enough of QOM declared so we can move to a
> single switch, with the (hopefully temporary) caveat about "only QOM".

Maybe the right answer is to just declare everything insecure
by default and focus on just annotating stuff for the secure
bucket as quickly as possible.

The lazy option would be to take everything that is built in
a RHEL distro build and label it as secure. We know Red Hat
is already on the hook for fixing CVEs in any such component
and sending fixes upstream. So by following the RHEL allow
list initially we should be implying any new burden for the
upstream. 

That would enable require-secure=yes for a useful amount of
code needed for secure KVM guests on x86, s390x, aarch64,
ppc64 and perhaps riscv. 


> > Some questions....
> >
> >   * Is using '-machine' the right place to express the policy ?
> 
> Not sure.  The guest boundary is just one of several security boundaries
> listed in docs/system/security.rst.  Some of them aren't really about
> the guest / the machine.
> 
> Maybe -compat?  It lets you exclude unstable or deprecated bits from the
> user interface.  Feels similar to excluding insecure bits.

Oh I forgot about -compat entirely. That does indeed feel like
a better place.

> >   * Can we change '-accel help' to report 'secure' / 'insecure'
> >     as we did for '-machine help' and '-device help'.
> 
> No idea, guess it's at worst a matter of shaving the yak?
> 
> >   * Should we have 'query-devices' for QMP to allow the 'secure'
> >     or 'insecure' status to be queried for every device.
> >
> >   * Should we have 'query-accel' for QMP to allow the 'secure'
> >     or 'insecure' status to be queried for every accelerator.
> 
> I recommend qom-list-types.  Covers all of QOM, not just devices and
> accelerators.

Yep that works, and is already reporting the 'abstract' property
so putting a'secure' property alongside fits nicely.


With regards,
Daniel
-- 
|: https://berrange.com      -o-    https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org         -o-            https://fstop138.berrange.com :|
|: https://entangle-photo.org    -o-    https://www.instagram.com/dberrange :|


Re: [PATCH <RFC> 00/15] Encode object type security status in code
Posted by Markus Armbruster 1 week, 3 days ago
Daniel P. Berrangé <berrange@redhat.com> writes:

> On Thu, Sep 18, 2025 at 01:35:56PM +0200, Markus Armbruster wrote:
>> Daniel P. Berrangé <berrange@redhat.com> writes:
>
>> > It starts with QOM, adding "bool secure" and "bool insecure"
>> > properties to the TypeInfo struct, which get turned into flags
>> > on the Type struct. This enables querying any ObjectClass to
>> > ask whether or not it is declared secure or insecure.
>> 
>> We should clearly document what "declared secure" actually means.
>> Here's my attempt at it: supported for use cases that require certain
>> security boundaries.
>
>
>
>> 
>> > By default no statement will be made about whether a class is
>> > secure or insecure, reflecting our historical defaults. Over
>> > time we should annotate as many classes as possible with an
>> > explicit statement.
>> >
>> > The "-machine" argument gains two new parameters
>> >
>> >   * prohibit-insecure=yes|no  - a weak security boundary, only
>> >     excluding stuff that is explicitly declared insecure,
>> >     permiting stuff that is secure & anything without a stetement
>> 
>> This isn't what users need.
>> 
>> >   * require-secure=yes|no - a strong security boundary, only
>> >     permitting stuff that is explicitly declared secure,
>> >     excluding insecure stuff & anything without a statement
>> 
>> This would be, if it covered everything accessible at the security
>> boundaries.  It doesn't for now: only QOM.
>> 
>> It might still be better than nothing.
>> 
>> However, it may well be unusable until enough of QOM is declared secure.
>
> Right, the problem is that for a while we'll have 3 buckets of
> stuff (insecure, secure and "not sure yet"), when ideally we would
> only have two buckets (insecure, secure).
>
> I agree that for people running VMs, ideally require-secure=yes is
> what they should be using.
>
> The "not sure yet" bucket is a bit like schrodinger's cat in a box.
>
> If we only had require-secure=yes, and that was insufficient for
> the user, they'd be left with no way to exclude stuff that is
> /definitely/ insecure.

Yes.  I mentioned this fallback below.

>                        The prohibit-insecure=yes is at least
> telling them they're not using something that is a terribly
> bad idea.

It rules out known bad, but not "maybe terribly bad, we just don't
know".

> In practice most of the stuff in the 'not sure yet' bucket will
> be stuff that you'll only want to use in combniation with TCG,
> and thus your VM will be in the 'insecure' bucket anyway.
>
> There is a 2nd less critical use case for prohibit-insecure=yes
> in relation to security report triage.
>
> If someone submits a security report and it relies on a config
> that is blocked by prohibit-insecure=yes, then we can categorically
> declare it out of scope for CVE handling.
>
> Similarly the require-secure=yes is categorically in-scope.
>
> The 'do not bucket' is where we have to do case-by-case
> analysis of the reoprt to decide whether it is in scope or
> not.

Yes.

By the way, two booleans is a rather awkward encoding of three states.
What about require-secure=yes/no/feeling-lucky?  We may want something
better than feeling-lucky, it's merely the first one that crossed my
mind :)

>> What would our advice to users be?  I'm afraid something complicated and
>> impermanent like "try require-secure=yes, and if you can't make it work
>> because parts of QOM you can't do without are still undeclared, fall
>> back to prohibit-insecure=yes, and be aware this avoids only some, but
>> not all security boundary death traps in either case."
>> 
>> This is an awful user interface.  But it's also a step towards the user
>> interface we want: a single, unchanging switch that ensures you're
>> running something that's fully supported for use cases that require
>> certain security boundaries.
>> 
>> A next step could be getting enough of QOM declared so we can move to a
>> single switch, with the (hopefully temporary) caveat about "only QOM".
>
> Maybe the right answer is to just declare everything insecure
> by default and focus on just annotating stuff for the secure
> bucket as quickly as possible.

Annotating something as known insecure has value, but we can do that
even with just one flag:

    .secure = true;

means "declared secure",

    .secure = false;

means "declared insecure", and nothing means "undecided".

Initializing .secure = false doesn't *do* anything (false is the
default), but it would still be a fine way to annotate.

> The lazy option would be to take everything that is built in
> a RHEL distro build and label it as secure. We know Red Hat
> is already on the hook for fixing CVEs in any such component
> and sending fixes upstream. So by following the RHEL allow
> list initially we should be implying any new burden for the
> upstream.

Do you mean no new burden?

> That would enable require-secure=yes for a useful amount of
> code needed for secure KVM guests on x86, s390x, aarch64,
> ppc64 and perhaps riscv. 

[...]
Re: [PATCH <RFC> 00/15] Encode object type security status in code
Posted by Daniel P. Berrangé 1 week, 3 days ago
On Thu, Sep 18, 2025 at 04:44:31PM +0200, Markus Armbruster wrote:
> Daniel P. Berrangé <berrange@redhat.com> writes:
> 
> > On Thu, Sep 18, 2025 at 01:35:56PM +0200, Markus Armbruster wrote:
> >> Daniel P. Berrangé <berrange@redhat.com> writes:
> >
> >> > It starts with QOM, adding "bool secure" and "bool insecure"
> >> > properties to the TypeInfo struct, which get turned into flags
> >> > on the Type struct. This enables querying any ObjectClass to
> >> > ask whether or not it is declared secure or insecure.
> >> 
> >> We should clearly document what "declared secure" actually means.
> >> Here's my attempt at it: supported for use cases that require certain
> >> security boundaries.
> >
> >
> >
> >> 
> >> > By default no statement will be made about whether a class is
> >> > secure or insecure, reflecting our historical defaults. Over
> >> > time we should annotate as many classes as possible with an
> >> > explicit statement.
> >> >
> >> > The "-machine" argument gains two new parameters
> >> >
> >> >   * prohibit-insecure=yes|no  - a weak security boundary, only
> >> >     excluding stuff that is explicitly declared insecure,
> >> >     permiting stuff that is secure & anything without a stetement
> >> 
> >> This isn't what users need.
> >> 
> >> >   * require-secure=yes|no - a strong security boundary, only
> >> >     permitting stuff that is explicitly declared secure,
> >> >     excluding insecure stuff & anything without a statement


> 
> By the way, two booleans is a rather awkward encoding of three states.
> What about require-secure=yes/no/feeling-lucky?  We may want something
> better than feeling-lucky, it's merely the first one that crossed my
> mind :)

Yeah, this is mostly me being lazy - by the time I realized that
an enum would have been better, I didn't want to rewrite it, so I
just sent this RFC as is.

> >> What would our advice to users be?  I'm afraid something complicated and
> >> impermanent like "try require-secure=yes, and if you can't make it work
> >> because parts of QOM you can't do without are still undeclared, fall
> >> back to prohibit-insecure=yes, and be aware this avoids only some, but
> >> not all security boundary death traps in either case."
> >> 
> >> This is an awful user interface.  But it's also a step towards the user
> >> interface we want: a single, unchanging switch that ensures you're
> >> running something that's fully supported for use cases that require
> >> certain security boundaries.
> >> 
> >> A next step could be getting enough of QOM declared so we can move to a
> >> single switch, with the (hopefully temporary) caveat about "only QOM".
> >
> > Maybe the right answer is to just declare everything insecure
> > by default and focus on just annotating stuff for the secure
> > bucket as quickly as possible.
> 
> Annotating something as known insecure has value, but we can do that
> even with just one flag:
> 
>     .secure = true;
> 
> means "declared secure",
> 
>     .secure = false;
> 
> means "declared insecure", and nothing means "undecided".
> 
> Initializing .secure = false doesn't *do* anything (false is the
> default), but it would still be a fine way to annotate.

I'm fine with that, as long as we don't need to be able to
programmatically query that distinction. From an external
view, '= false' and <unset> would be undistinguishable
and both be considered 'insecure'.

It would mean we, as maintainers, would know what files
are yet to be evaluated for their security status which
is still useful.

> 
> > The lazy option would be to take everything that is built in
> > a RHEL distro build and label it as secure. We know Red Hat
> > is already on the hook for fixing CVEs in any such component
> > and sending fixes upstream. So by following the RHEL allow
> > list initially we should be implying any new burden for the
> > upstream.
> 
> Do you mean no new burden?

Sigh, yes. No new burden.

> 
> > That would enable require-secure=yes for a useful amount of
> > code needed for secure KVM guests on x86, s390x, aarch64,
> > ppc64 and perhaps riscv. 
> 
> [...]
> 

With regards,
Daniel
-- 
|: https://berrange.com      -o-    https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org         -o-            https://fstop138.berrange.com :|
|: https://entangle-photo.org    -o-    https://www.instagram.com/dberrange :|


Re: [PATCH <RFC> 00/15] Encode object type security status in code
Posted by Daniel P. Berrangé 1 week, 4 days ago
Ping: anyone have thoughts on this idea of annotating security
status of our code against QOM classes ?

On Tue, Sep 09, 2025 at 05:57:11PM +0100, Daniel P. Berrangé wrote:
> Our docs/system/security.rst file loosely classifies code into that
> applicable for 'virtualization' vs 'non-virtualization' use cases.
> Only code relevant to the former group is eligible for security
> bug handling. Peter's recent proposal pointed out that we are
> increasingly hitting the limits of such a crude classification:
> 
>   https://lists.nongnu.org/archive/html/qemu-devel/2025-09/msg01520.html
> 
> Michael suggested that with the increased complexity, docs are not
> going to be an effective way to convey the information, and we
> need to re-consider embedding this info in code:
> 
>   https://lists.nongnu.org/archive/html/qemu-devel/2025-09/msg01566.html
> 
> This also allows users to validate a configuration's security status
> when starting a guest, or modifying a running guest. This series is
> an attempt to start the embedding process.
> 
> It starts with QOM, adding "bool secure" and "bool insecure"
> properties to the TypeInfo struct, which get turned into flags
> on the Type struct. This enables querying any ObjectClass to
> ask whether or not it is declared secure or insecure.
> 
> By default no statement will be made about whether a class is
> secure or insecure, reflecting our historical defaults. Over
> time we should annotate as many classes as possible with an
> explicit statement.
> 
> The "-machine" argument gains two new parameters
> 
>   * prohibit-insecure=yes|no  - a weak security boundary, only
>     excluding stuff that is explicitly declared insecure,
>     permiting stuff that is secure & anything without a stetement
> 
>   * require-secure=yes|no - a strong security boundary, only
>     permitting stuff that is explicitly declared secure,
>     excluding insecure stuff & anything without a statement
> 
> As illustration, I have added explicit annotations for many machine
> types, some accelerators, all NICs (all insecure except xen,
> e1000(e) and virtio), and all PCI virtio devices (all secure).
> 
> Example: TCG is explicitly insecure, KVM is explicitly secure,
>          qtest has no statement:
> 
>   $ qemu-system-x86_64 -display none -machine pc,prohibit-insecure=yes -accel tcg
>   qemu-system-x86_64: Type 'tcg-accel' is declared as insecure
> 
>   $ qemu-system-x86_64 -display none -machine pc,require-secure=yes -accel tcg
>   qemu-system-x86_64: Type 'tcg-accel' is not declared as secure
> 
>   $ qemu-system-x86_64 -display none -machine pc,prohibit-insecure=yes -accel kvm
>   ^Cqemu-system-x86_64: terminating on signal 2
> 
>   $ qemu-system-x86_64 -display none -machine pc,require-secure=yes -accel kvm
>   ^Cqemu-system-x86_64: terminating on signal 2
> 
>   $ qemu-system-x86_64 -display none -machine pc,prohibit-insecure=yes -accel qtest
>   ^Cqemu-system-x86_64: terminating on signal 2
> 
>   $ qemu-system-x86_64 -display none -machine pc,require-secure=yes -accel qtest
>   qemu-system-x86_64: Type 'qtest-accel' is not declared as secure
> 
> Example: isapc machine type is explicitly insecure
> 
>   $ qemu-system-x86_64 -display none -machine isapc,require-secure=yes -accel kvm
>   qemu-system-x86_64: Type 'isapc-machine' is not declared as secure
> 
> Example: devices which have no security statement are allowed if
>          merely excluding insecure devices:
> 
>   $ qemu-system-x86_64 -display none -machine pc,prohibit-insecure=yes -accel kvm -device i6300esb
>   ^Cqemu-system-x86_64: terminating on signal 2
> 
> Example: devices which have no security statement are rejected if
>          requiring explicit security:
> 
>   $ qemu-system-x86_64 -display none -machine pc,require-secure=yes -accel kvm -device i6300esb
>   qemu-system-x86_64: -device i6300esb: Type 'i6300esb' is not declared as secure
> 
> Example: checks also apply in HMP, rtl8139 is explicitly insecure,
>          virtio is explicitly secure
> 
>   $ qemu-system-x86_64 -display none -machine pc,require-secure=yes -accel kvm -monitor stdio
>   QEMU 10.1.50 monitor - type 'help' for more information
>   (qemu) device_add rtl8139
>   Error: Type 'rtl8139' is not declared as secure
>   (qemu) device_add virtio-net
> 
> Example: checks also apply in QMP:
> 
>   $ ./scripts/qmp/qmp-shell-wrap qemu-system-x86_64 -display none -machine pc,require-secure=yes -accel kvm
>   Welcome to the QMP low-level shell!
>   Connected
>   (QEMU) device_add driver=rtl8139
>   {"error": {"class": "GenericError", "desc": "Type 'rtl8139' is not declared as secure"}}
>   (QEMU) device_add driver=virtio-net
>   {"return": {}}
> 
> Some questions....
> 
>   * Is using '-machine' the right place to express the policy ?
> 
>   * Can we change '-accel help' to report 'secure' / 'insecure'
>     as we did for '-machine help' and '-device help'.
> 
>   * Should we have 'query-devices' for QMP to allow the 'secure'
>     or 'insecure' status to be queried for every device.
> 
>   * Should we have 'query-accel' for QMP to allow the 'secure'
>     or 'insecure' status to be queried for every accelerator.
> 
>   * Should we enforce checks for -object & object_add too ?
>     Easy to add code for this, but do we need the ability to
>     exclude some object backends of dubious code quality ?
> 
>   * Likewise for -chardev / -netdev / etc which are
>     conceptual specializations of -object
> 
>   * BlockDriver structs don't use QOM, so we can't mark
>     'vvfat' block backend as insecure
> 
> The first one about '-machine' is probably the main blocker
> from a design POV. Other things are just potential future
> incremental work.
> 
> This series has had only 1/2 a day's work / thought put into
> it, hence RFC status. It has been compiled and minimally tested
> with the examples shown above. I have not pushed this through
> CI nor considered tests yet. Still it gives a good illustration
> of what's involved in recording security info in code.
> 
> Daniel P. Berrangé (15):
>   qom: replace 'abstract' with 'flags'
>   qom: add tracking of security state of object types
>   machine: add 'require-secure' and 'prohibit-insecure' properties
>   machine: check security for machine and accelerator 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 secure/insecure status in query-machines
>   accel: mark 'kvm' as secure and 'tcg' as insecure
>   hw/virtio: mark all virtio PCI devices as secure
>   hw: mark x86, s390, ppc, arm versioned machine types as secure
>   hw: declare Xen & microvm machines as secure, isapc as insecure
>   hw/core: declare 'none' machine to be insecure
>   hw/net: mark all NICs as insecure except e1000, e1000e & xen
>   docs: expand security docs with info about secure/insecure markers
> 
>  accel/kvm/kvm-all.c            |  1 +
>  accel/tcg/tcg-all.c            |  1 +
>  docs/system/security.rst       | 41 +++++++++++++++++++++
>  hw/arm/virt.c                  |  1 +
>  hw/arm/xen-pvh.c               |  1 +
>  hw/core/machine-qmp-cmds.c     |  2 ++
>  hw/core/machine.c              | 66 ++++++++++++++++++++++++++++++++++
>  hw/core/null-machine.c         |  2 +-
>  hw/i386/isapc.c                |  2 +-
>  hw/i386/microvm.c              |  1 +
>  hw/i386/pc_piix.c              |  4 +--
>  hw/i386/xen/xen-pvh.c          |  1 +
>  hw/i386/xen/xen_pvdevice.c     |  1 +
>  hw/net/allwinner-sun8i-emac.c  |  1 +
>  hw/net/allwinner_emac.c        |  3 +-
>  hw/net/cadence_gem.c           |  1 +
>  hw/net/can/can_kvaser_pci.c    |  1 +
>  hw/net/can/can_mioe3680_pci.c  |  1 +
>  hw/net/can/can_pcm3680_pci.c   |  1 +
>  hw/net/can/ctucan_pci.c        |  1 +
>  hw/net/can/xlnx-versal-canfd.c |  1 +
>  hw/net/can/xlnx-zynqmp-can.c   |  1 +
>  hw/net/dp8393x.c               |  1 +
>  hw/net/e1000.c                 |  1 +
>  hw/net/e1000e.c                |  1 +
>  hw/net/eepro100.c              |  1 +
>  hw/net/fsl_etsec/etsec.c       |  1 +
>  hw/net/ftgmac100.c             |  1 +
>  hw/net/igb.c                   |  1 +
>  hw/net/igbvf.c                 |  1 +
>  hw/net/imx_fec.c               |  2 ++
>  hw/net/lan9118.c               |  1 +
>  hw/net/lan9118_phy.c           |  1 +
>  hw/net/lance.c                 |  1 +
>  hw/net/lasi_i82596.c           |  1 +
>  hw/net/mcf_fec.c               |  1 +
>  hw/net/msf2-emac.c             |  1 +
>  hw/net/mv88w8618_eth.c         |  1 +
>  hw/net/ne2000-isa.c            |  1 +
>  hw/net/ne2000-pci.c            |  1 +
>  hw/net/npcm7xx_emc.c           |  1 +
>  hw/net/npcm_gmac.c             |  1 +
>  hw/net/npcm_pcs.c              |  1 +
>  hw/net/opencores_eth.c         |  1 +
>  hw/net/pcnet-pci.c             |  1 +
>  hw/net/rocker/rocker.c         |  1 +
>  hw/net/rtl8139.c               |  1 +
>  hw/net/smc91c111.c             |  1 +
>  hw/net/spapr_llan.c            |  1 +
>  hw/net/stellaris_enet.c        |  1 +
>  hw/net/sungem.c                |  1 +
>  hw/net/sunhme.c                |  1 +
>  hw/net/tulip.c                 |  1 +
>  hw/net/virtio-net.c            |  1 +
>  hw/net/vmxnet3.c               |  1 +
>  hw/net/xen_nic.c               |  1 +
>  hw/net/xgmac.c                 |  1 +
>  hw/net/xilinx_axienet.c        |  1 +
>  hw/net/xilinx_ethlite.c        |  1 +
>  hw/ppc/spapr.c                 |  1 +
>  hw/s390x/s390-virtio-ccw.c     |  1 +
>  hw/virtio/virtio-pci.c         |  3 ++
>  hw/xen/xen-pvh-common.c        |  1 +
>  hw/xenpv/xen_machine_pv.c      |  2 +-
>  include/hw/boards.h            | 18 +++++++++-
>  include/hw/i386/pc.h           |  5 ++-
>  include/qom/object.h           | 24 +++++++++++++
>  qapi/machine.json              |  9 ++++-
>  qom/object.c                   | 40 +++++++++++++++++----
>  system/qdev-monitor.c          | 10 ++++++
>  system/vl.c                    |  6 ++--
>  71 files changed, 275 insertions(+), 18 deletions(-)
> 
> -- 
> 2.50.1
> 

With regards,
Daniel
-- 
|: https://berrange.com      -o-    https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org         -o-            https://fstop138.berrange.com :|
|: https://entangle-photo.org    -o-    https://www.instagram.com/dberrange :|


Re: [PATCH <RFC> 00/15] Encode object type security status in code
Posted by Peter Maydell 1 week, 4 days ago
On Tue, 16 Sept 2025 at 17:43, Daniel P. Berrangé <berrange@redhat.com> wrote:
>
> Ping: anyone have thoughts on this idea of annotating security
> status of our code against QOM classes ?

I don't object to it, but I don't think we should
block making our security policy clearer about
coverage on instituting this kind of framework
and marking-up of code.

thanks
-- PMM