Xen Security Advisory 403 v3 (CVE-2022-26365,CVE-2022-33740,CVE-2022-33741,CVE-2022-33742) - Linux disk/nic frontends data leaks

Xen.org security team posted 1 patch 1 year, 9 months ago
Failed in applying to current master (apply log)
docs/man/xl-disk-configuration.5.pod.in    | 29 ++++++++++++++++++++++
docs/man/xl-network-configuration.5.pod.in |  9 +++++++
tools/include/libxl.h                      |  8 ++++++
tools/libs/light/libxl_disk.c              |  3 +++
tools/libs/light/libxl_nic.c               |  5 ++++
tools/libs/light/libxl_types.idl           |  6 +++--
tools/libs/util/libxlu_disk_l.l            |  3 +++
tools/xl/check-xl-disk-parse               | 26 +++++++++++++++++++
tools/xl/check-xl-vif-parse                | 18 ++++++++++++++
tools/xl/xl_parse.c                        |  4 +++
xen/include/public/io/blkif.h              |  8 ++++++
xen/include/public/io/netif.h              |  6 +++++
12 files changed, 123 insertions(+), 2 deletions(-)
Xen Security Advisory 403 v3 (CVE-2022-26365,CVE-2022-33740,CVE-2022-33741,CVE-2022-33742) - Linux disk/nic frontends data leaks
Posted by Xen.org security team 1 year, 9 months ago
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256

 Xen Security Advisory CVE-2022-26365,CVE-2022-33740,CVE-2022-33741,CVE-2022-33742 / XSA-403
                                          version 3

                  Linux disk/nic frontends data leaks

UPDATES IN VERSION 3
====================

Public release.

ISSUE DESCRIPTION
=================

Linux Block and Network PV device frontends don't zero memory regions before
sharing them with the backend (CVE-2022-26365, CVE-2022-33740).  Additionally
the granularity of the grant table doesn't allow sharing less than a 4K page,
leading to unrelated data residing in the same 4K page as data shared with a
backend being accessible by such backend (CVE-2022-33741, CVE-2022-33742).

IMPACT
======

An untrusted backend can access data not intended to be shared.  If such
mappings are made with write permissions the backend could also cause
malfunctions and/or crashes to consumers of contiguous data in the shared
pages.

VULNERABLE SYSTEMS
==================

All Linux guests using PV devices are vulnerable in case potentially
malicious PV device backends are being used.

MITIGATION
==========

There is no mitigation available other than not using PV devices in case
a backend is suspected to be potentially malicious.

CREDITS
=======

The issue related to not zeroing memory areas used for shared communications
was discovered by Roger Pau Monné of Citrix.

The issue related to leaking contiguous data in granted pages was disclosed
publicly.

RESOLUTION
==========

Applying the attached patches to Linux makes the disk and network frontends
capable of protecting themselves against potentially malicious backends.  The
signaling of whether a frontend should consider a backend as potentially
malicious can be done from either the Linux kernel command line or the
toolstack.

Two different patches are provided for each Xen branch, but only the first
patch will be applied to the official Xen repository for each branch.

For the xen-unstable branch patch 1 introduces a new field to the disk and nic
configurations that allow signaling on a per-device basis whether the backend
should be trusted.  This is an ABI incompatible change, and cannot be applied
to stable branches.  Patch 2 introduces support to libxl for
libxl_{disk,nic}_backend_untrusted environment variable to be used in order to
set whether disk and network frontends should be trusted in the absence of a
per-device setting.  Patch 2 is provided as a courtesy for users of stable
branches that might come to rely on this behavior.

For the stable branches (Xen 4.16.x - Xen 4.13.x) patch 1 introduces support to
libxl for libxl_{disk,nic}_backend_untrusted environment variable to be used in
order to set whether disk and network backends should be trusted.  Patch 2
reverts patch 1 and instead provides the more fine grained per-device options
that break the libxl ABI.

Note that applying patch 2 to any of the stable releases will require a rebuild
of any consumers of the libxl library, as it introduces an ABI breakage and
hence won't be applied to the official repository stable branches.  Users of
stable releases wanting to use the functionality provided by patch 2 will need
to apply it manually.

Regardless of the combinations of patches applied, in the absence of any
environment variable mentioned above backends will be trusted by default.

Note that patches for released versions are generally prepared to
apply to the stable branches, and may not apply cleanly to the most
recent release tarball.  Downstreams are encouraged to update to the
tip of the stable branch before applying these patches.

xsa403/xsa403-?.patch         xen-unstable
xsa403/xsa403-4.16-?.patch    Xen 4.16.x - Xen 4.15.x
xsa403/xsa403-4.14-?.patch    Xen 4.14.x - Xen 4.13.x
xsa403/xsa403-linux-*.patch   Linux 5.18

$ sha256sum xsa403*/*
f28624407a3f040456ef2c52a18d8dcf486274ea082335ea38c9791646f4989c  xsa403/xsa403-1.patch
e06451655775009ceaf460bbba65374c05203eed295ff43fc5fa32a8d390a94a  xsa403/xsa403-2.patch
5efb8af5ed5614f5e2e8d606a9debb3503cd9e114551525826fc5a7f9de91c02  xsa403/xsa403-4.14-1.patch
9ead8c6e4d694f3042c8d2fab4ea81619c4a9fc2aa7a0f485e9c873d927d283c  xsa403/xsa403-4.14-2.patch
ae778d5731ae663cca32d59ed9b1be51200b85c441771a9c6657c112e9550a15  xsa403/xsa403-4.16-1.patch
8ef7bd06f646fa72f22892d2b72ae44ff4e6c00d9817d52a71262be174862ee3  xsa403/xsa403-4.16-2.patch
8192d0c313448d7aa12c13d1632db3bd68835c19f60c237b87548d5c528852b0  xsa403/xsa403-linux-1.patch
4b288d3266f9396bedc7de823909aed4d1a89fe86b2edd1d625b0e32741688cf  xsa403/xsa403-linux-2.patch
dddf68625be516f0524fe7bb439272769cf7d612e15e00ac936bc047fd182f8a  xsa403/xsa403-linux-3.patch
4e38a50a0e5ec6e90d2fffef003f8eb93a68518f4636c15cd59568ddf1861988  xsa403/xsa403-linux-4.patch
$

DEPLOYMENT DURING EMBARGO
=========================

Deployment of patches or mitigations is NOT permitted (except where
all the affected systems and VMs are administered and used only by
organisations which are members of the Xen Project Security Issues
Predisclosure List).  Specifically, deployment on public cloud systems
is NOT permitted.

This is because the patches need to be applied in the affected guests.
Switching from PV to non-PV devices is observable by the guests and has
usually a bad performance impact.

Deployment is permitted only AFTER the embargo ends.


(Note: this during-embargo deployment notice is retained in
post-embargo publicly released Xen Project advisories, even though it
is then no longer applicable.  This is to enable the community to have
oversight of the Xen Project Security Team's decisionmaking.)

For more information about permissible uses of embargoed information,
consult the Xen Project community's agreed Security Policy:
  http://www.xenproject.org/security-policy.html
-----BEGIN PGP SIGNATURE-----

iQFABAEBCAAqFiEEI+MiLBRfRHX6gGCng/4UyVfoK9kFAmLEFf0MHHBncEB4ZW4u
b3JnAAoJEIP+FMlX6CvZSVkIALkao7hSqBVJhnVifpXpLn+mxfECoI6lgQ1sphz6
oJ7U2QxuI6j6gVSUPk3GglYjKurGBYZjBAX6fBU8po9Zdagz/iuOXCif41NHobP8
POscgXMjKR4HPE8liXNYzSbTAbn7qiyNCxBO5yGK/jPMIC8K9+0ed+9ese6VVXSj
4buiqlkLb9FP5xTCGbtt/raZoGVVRx+LLhwC8dlNXllEvI1cJIK18pfnPF+ZUQwL
kXAx2figt3ZE1yNVv4Efnp2bMvv/XUGNU6X/ONP7wCKChzTOGdMyPMBJ1r73ceAn
TSvVuWDBoiWCLVIY1leTjRx9xxbQq84htGG68i8nQrHckz8=
=Wl2G
-----END PGP SIGNATURE-----
From 3194ab2494f833dbfd1f0afdfb2f66711647ba29 Mon Sep 17 00:00:00 2001
From: Roger Pau Monne <roger.pau@citrix.com>
Date: Fri, 8 Apr 2022 10:21:11 +0200
Subject: [PATCH] tools/libxl: report trusted backend status to frontends
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Allow administrators to notify a frontend driver that it's backend
counterpart is not to be trusted, so the frontend can deploy whatever
mitigations required in order to secure itself.

Allow such option for disk and network frontends only, as those are
the only hardened ones currently supported.

This is part of XSA-403

Signed-off-by: Roger Pau Monné <roger.pau@citrix.com>
Reviewed-by: Anthony PERARD <anthony.perard@citrix.com>
---
 docs/man/xl-disk-configuration.5.pod.in    | 29 ++++++++++++++++++++++
 docs/man/xl-network-configuration.5.pod.in |  9 +++++++
 tools/include/libxl.h                      |  8 ++++++
 tools/libs/light/libxl_disk.c              |  3 +++
 tools/libs/light/libxl_nic.c               |  5 ++++
 tools/libs/light/libxl_types.idl           |  6 +++--
 tools/libs/util/libxlu_disk_l.l            |  3 +++
 tools/xl/check-xl-disk-parse               | 26 +++++++++++++++++++
 tools/xl/check-xl-vif-parse                | 18 ++++++++++++++
 tools/xl/xl_parse.c                        |  4 +++
 xen/include/public/io/blkif.h              |  8 ++++++
 xen/include/public/io/netif.h              |  6 +++++
 12 files changed, 123 insertions(+), 2 deletions(-)

diff --git a/docs/man/xl-disk-configuration.5.pod.in b/docs/man/xl-disk-configuration.5.pod.in
index 71d0e86e3d..95d039655a 100644
--- a/docs/man/xl-disk-configuration.5.pod.in
+++ b/docs/man/xl-disk-configuration.5.pod.in
@@ -344,6 +344,35 @@ can be used to disable "hole punching" for file based backends which
 were intentionally created non-sparse to avoid fragmentation of the
 file.
 
+=item B<trusted> / B<untrusted>
+
+=over 4
+
+=item Description
+
+Reports whether the backend should be trusted by the frontend
+
+=item Supported values
+
+trusted, untrusted
+
+=item Mandatory
+
+No
+
+=item Default value
+
+trusted
+
+=back
+
+An advisory setting for the frontend driver on whether the backend should be
+trusted.  The frontend should deploy whatever protections it has available to
+prevent an untrusted backend from accessing guest data not related to the I/O
+processing or causing malfunction to the frontend or the whole domain.
+
+Note frontends can ignore such recommendation.
+
 =back
 
 
diff --git a/docs/man/xl-network-configuration.5.pod.in b/docs/man/xl-network-configuration.5.pod.in
index cf92d7960c..f3e379bcf8 100644
--- a/docs/man/xl-network-configuration.5.pod.in
+++ b/docs/man/xl-network-configuration.5.pod.in
@@ -258,3 +258,12 @@ NOTE: This should not be set unless you have a reason to.
 Specifies the MTU (i.e. the maximum size of an IP payload, exclusing headers). The
 default value is 1500 but, if the VIF is attached to a bridge, it will be set to match
 unless overridden by this parameter.
+
+=head2 trusted / untrusted
+
+An advisory setting for the frontend driver on whether the backend should be
+trusted.  The frontend should deploy whatever protections it has available to
+prevent an untrusted backend from accessing guest data not related to the I/O
+processing or causing malfunction to the frontend or the whole domain.
+
+Note frontends can ignore such recommendation.
diff --git a/tools/include/libxl.h b/tools/include/libxl.h
index 51a9b6cfac..c8ff24f929 100644
--- a/tools/include/libxl.h
+++ b/tools/include/libxl.h
@@ -527,6 +527,14 @@
  */
 #define LIBXL_HAVE_MAX_GRANT_VERSION 1
 
+/*
+ * LIBXL_HAVE_{DISK,NIC}_TRUSTED indicates that the libxl_device_disk and
+ * libxl_device_nic structs have a field to signal whether the backend of the
+ * device is to be trusted.  Such information is propagated to the frontend.
+ */
+#define LIBXL_HAVE_DISK_TRUSTED 1
+#define LIBXL_HAVE_NIC_TRUSTED 1
+
 /*
  * libxl ABI compatibility
  *
diff --git a/tools/libs/light/libxl_disk.c b/tools/libs/light/libxl_disk.c
index a5ca77850f..9da2b2ed27 100644
--- a/tools/libs/light/libxl_disk.c
+++ b/tools/libs/light/libxl_disk.c
@@ -159,6 +159,7 @@ static int libxl__device_disk_setdefault(libxl__gc *gc, uint32_t domid,
     libxl_defbool_setdefault(&disk->discard_enable, !!disk->readwrite);
     libxl_defbool_setdefault(&disk->colo_enable, false);
     libxl_defbool_setdefault(&disk->colo_restore_enable, false);
+    libxl_defbool_setdefault(&disk->trusted, true);
 
     rc = libxl__resolve_domid(gc, disk->backend_domname, &disk->backend_domid);
     if (rc < 0) return rc;
@@ -395,6 +396,8 @@ static void device_disk_add(libxl__egc *egc, uint32_t domid,
         flexarray_append(front, GCSPRINTF("%d", device->devid));
         flexarray_append(front, "device-type");
         flexarray_append(front, disk->is_cdrom ? "cdrom" : "disk");
+        flexarray_append(front, "trusted");
+        flexarray_append(front, libxl_defbool_val(disk->trusted) ? "1" : "0");
 
         /*
          * Old PV kernel disk frontends before 2.6.26 rely on tool stack to
diff --git a/tools/libs/light/libxl_nic.c b/tools/libs/light/libxl_nic.c
index 0b9e70c9d1..d6bf06fc34 100644
--- a/tools/libs/light/libxl_nic.c
+++ b/tools/libs/light/libxl_nic.c
@@ -116,6 +116,8 @@ static int libxl__device_nic_setdefault(libxl__gc *gc, uint32_t domid,
         abort();
     }
 
+    libxl_defbool_setdefault(&nic->trusted, true);
+
     return rc;
 }
 
@@ -255,6 +257,9 @@ static int libxl__set_xenstore_nic(libxl__gc *gc, uint32_t domid,
     flexarray_append(back, "hotplug-status");
     flexarray_append(back, "");
 
+    flexarray_append(front, "trusted");
+    flexarray_append(front, libxl_defbool_val(nic->trusted) ? "1" : "0");
+
     return 0;
 }
 
diff --git a/tools/libs/light/libxl_types.idl b/tools/libs/light/libxl_types.idl
index 2a42da2f7d..89962218b4 100644
--- a/tools/libs/light/libxl_types.idl
+++ b/tools/libs/light/libxl_types.idl
@@ -712,7 +712,8 @@ libxl_device_disk = Struct("device_disk", [
     ("colo_port", integer),
     ("colo_export", string),
     ("active_disk", string),
-    ("hidden_disk", string)
+    ("hidden_disk", string),
+    ("trusted", libxl_defbool),
     ])
 
 libxl_device_nic = Struct("device_nic", [
@@ -780,7 +781,8 @@ libxl_device_nic = Struct("device_nic", [
     ("colo_filter_sec_redirector1_outdev", string),
     ("colo_filter_sec_rewriter0_queue", string),
     ("colo_checkpoint_host", string),
-    ("colo_checkpoint_port", string)
+    ("colo_checkpoint_port", string),
+    ("trusted", libxl_defbool),
     ])
 
 libxl_device_pci = Struct("device_pci", [
diff --git a/tools/libs/util/libxlu_disk_l.l b/tools/libs/util/libxlu_disk_l.l
index 3bd639aab0..e115460d99 100644
--- a/tools/libs/util/libxlu_disk_l.l
+++ b/tools/libs/util/libxlu_disk_l.l
@@ -208,6 +208,9 @@ colo-export=[^,]*,?	{ STRIP(','); SAVESTRING("colo-export", colo_export, FROMEQU
 active-disk=[^,]*,?	{ STRIP(','); SAVESTRING("active-disk", active_disk, FROMEQUALS); }
 hidden-disk=[^,]*,?	{ STRIP(','); SAVESTRING("hidden-disk", hidden_disk, FROMEQUALS); }
 
+trusted,?		{ libxl_defbool_set(&DPC->disk->trusted, true); }
+untrusted,?		{ libxl_defbool_set(&DPC->disk->trusted, false); }
+
  /* the target magic parameter, eats the rest of the string */
 
 target=.*	{ STRIP(','); SAVESTRING("target", pdev_path, FROMEQUALS); }
diff --git a/tools/xl/check-xl-disk-parse b/tools/xl/check-xl-disk-parse
index 643f4f4ecb..18fb66940a 100755
--- a/tools/xl/check-xl-disk-parse
+++ b/tools/xl/check-xl-disk-parse
@@ -178,4 +178,30 @@ disk: {
 END
 one 0  cdrom no-discard vdev=hda target=/some/disk/image.iso
 
+# test setting trusted
+expected <<END
+disk: {
+    "pdev_path": "/some/disk/image.raw",
+    "vdev": "hda",
+    "format": "raw",
+    "readwrite": 1,
+    "trusted": "True"
+}
+
+END
+one 0  trusted vdev=hda target=/some/disk/image.raw
+
+# test setting untrusted
+expected <<END
+disk: {
+    "pdev_path": "/some/disk/image.raw",
+    "vdev": "hda",
+    "format": "raw",
+    "readwrite": 1,
+    "trusted": "False"
+}
+
+END
+one 0  untrusted vdev=hda target=/some/disk/image.raw
+
 complete
diff --git a/tools/xl/check-xl-vif-parse b/tools/xl/check-xl-vif-parse
index 04bd9463d8..d666408d4d 100755
--- a/tools/xl/check-xl-vif-parse
+++ b/tools/xl/check-xl-vif-parse
@@ -160,4 +160,22 @@ one $e rate=4296MB/s@4294s
 expected </dev/null
 one $e rate=@
 
+# test trusted setting
+expected <<END
+vif: {
+    "trusted": "True"
+}
+
+END
+one 0 trusted
+
+# test untrusted setting
+expected <<END
+vif: {
+    "trusted": "False"
+}
+
+END
+one 0 untrusted
+
 complete
diff --git a/tools/xl/xl_parse.c b/tools/xl/xl_parse.c
index b98c0de378..644ab8f8fd 100644
--- a/tools/xl/xl_parse.c
+++ b/tools/xl/xl_parse.c
@@ -565,6 +565,10 @@ int parse_nic_config(libxl_device_nic *nic, XLU_Config **config, char *token)
         nic->devid = parse_ulong(oparg);
     } else if (MATCH_OPTION("mtu", token, oparg)) {
         nic->mtu = parse_ulong(oparg);
+    } else if (!strcmp("trusted", token)) {
+        libxl_defbool_set(&nic->trusted, true);
+    } else if (!strcmp("untrusted", token)) {
+        libxl_defbool_set(&nic->trusted, false);
     } else {
         fprintf(stderr, "unrecognized argument `%s'\n", token);
         return 1;
diff --git a/xen/include/public/io/blkif.h b/xen/include/public/io/blkif.h
index 4cdba79aba..ab863f175a 100644
--- a/xen/include/public/io/blkif.h
+++ b/xen/include/public/io/blkif.h
@@ -363,6 +363,14 @@
  *      that the frontend requires that the logical block size is 512 as it
  *      is hardcoded (which is the case in some frontend implementations).
  *
+ * trusted
+ *      Values:         0/1 (boolean)
+ *      Default value:  1
+ *
+ *      A value of "0" indicates that the frontend should not trust the
+ *      backend, and should deploy whatever measures available to protect from
+ *      a malicious backend on the other end.
+ *
  *------------------------- Virtual Device Properties -------------------------
  *
  * device-type
diff --git a/xen/include/public/io/netif.h b/xen/include/public/io/netif.h
index 00dd258712..3509b096f8 100644
--- a/xen/include/public/io/netif.h
+++ b/xen/include/public/io/netif.h
@@ -160,6 +160,12 @@
  * be applied if it is set.
  */
 
+/*
+ * The setting of "trusted" node to "0" in the frontend path signals that the
+ * frontend should not trust the backend, and should deploy whatever measures
+ * available to protect from a malicious backend on the other end.
+ */
+
 /*
  * Control ring
  * ============
-- 
2.36.0

From b1119ca5b2b12d67f2204a3f110a80bc0d7485cb Mon Sep 17 00:00:00 2001
From: Roger Pau Monne <roger.pau@citrix.com>
Date: Thu, 30 Jun 2022 14:35:35 +0200
Subject: [PATCH] tools/libxl: env variable to signal whether disk/nic backend
 is trusted
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Introduce support in libxl for fetching the default backend trusted
option for disk and nic devices.

Users can set libxl_{disk,nic}_backend_untrusted environment variable
to notify libxl of whether the backends for disk and nic devices
should be trusted.  Such information is passed into the frontend so it
can take the appropriate measures.

This is part of XSA-403.

WARNING: this patch will never be applied to the intended
repository/branch because it's only for stable branches in order to
avoid breaking the libxl ABI.

Signed-off-by: Roger Pau Monné <roger.pau@citrix.com>
---
 tools/libs/light/libxl_disk.c | 5 ++++-
 tools/libs/light/libxl_nic.c  | 5 ++++-
 2 files changed, 8 insertions(+), 2 deletions(-)

diff --git a/tools/libs/light/libxl_disk.c b/tools/libs/light/libxl_disk.c
index 9da2b2ed27..ec17ed7297 100644
--- a/tools/libs/light/libxl_disk.c
+++ b/tools/libs/light/libxl_disk.c
@@ -159,7 +159,10 @@ static int libxl__device_disk_setdefault(libxl__gc *gc, uint32_t domid,
     libxl_defbool_setdefault(&disk->discard_enable, !!disk->readwrite);
     libxl_defbool_setdefault(&disk->colo_enable, false);
     libxl_defbool_setdefault(&disk->colo_restore_enable, false);
-    libxl_defbool_setdefault(&disk->trusted, true);
+    if (getenv("libxl_disk_backend_untrusted"))
+        libxl_defbool_setdefault(&disk->trusted, false);
+    else
+        libxl_defbool_setdefault(&disk->trusted, true);
 
     rc = libxl__resolve_domid(gc, disk->backend_domname, &disk->backend_domid);
     if (rc < 0) return rc;
diff --git a/tools/libs/light/libxl_nic.c b/tools/libs/light/libxl_nic.c
index d6bf06fc34..19f6ee1cd4 100644
--- a/tools/libs/light/libxl_nic.c
+++ b/tools/libs/light/libxl_nic.c
@@ -116,7 +116,10 @@ static int libxl__device_nic_setdefault(libxl__gc *gc, uint32_t domid,
         abort();
     }
 
-    libxl_defbool_setdefault(&nic->trusted, true);
+    if (getenv("libxl_nic_backend_untrusted"))
+        libxl_defbool_setdefault(&nic->trusted, false);
+    else
+        libxl_defbool_setdefault(&nic->trusted, true);
 
     return rc;
 }
-- 
2.37.0

From 340cb938b957a2baaaee1700a882148dc4c788bc Mon Sep 17 00:00:00 2001
From: Roger Pau Monne <roger.pau@citrix.com>
Date: Thu, 30 Jun 2022 14:35:35 +0200
Subject: [PATCH] tools/libxl: env variable to signal whether disk/nic backend
 is trusted
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Introduce support in libxl for fetching the default backend trusted
option for disk and nic devices.

Users can set libxl_{disk,nic}_backend_untrusted environment variable
to notify libxl of whether the backends for disk and nic devices
should be trusted.  Such information is passed into the frontend so it
can take the appropriate measures.

This is part of XSA-403.

Signed-off-by: Roger Pau Monné <roger.pau@citrix.com>
---
 tools/libxl/libxl_disk.c | 3 +++
 tools/libxl/libxl_nic.c  | 3 +++
 2 files changed, 6 insertions(+)

diff --git a/tools/libxl/libxl_disk.c b/tools/libxl/libxl_disk.c
index ddc1eec176..36862bbbcb 100644
--- a/tools/libxl/libxl_disk.c
+++ b/tools/libxl/libxl_disk.c
@@ -395,6 +395,9 @@ static void device_disk_add(libxl__egc *egc, uint32_t domid,
         flexarray_append(front, GCSPRINTF("%d", device->devid));
         flexarray_append(front, "device-type");
         flexarray_append(front, disk->is_cdrom ? "cdrom" : "disk");
+        flexarray_append(front, "trusted");
+        flexarray_append(front, getenv("libxl_disk_backend_untrusted") ? "0"
+                                                                       : "1");
 
         /*
          * Old PV kernel disk frontends before 2.6.26 rely on tool stack to
diff --git a/tools/libxl/libxl_nic.c b/tools/libxl/libxl_nic.c
index 07880b39e1..4d09fb8b46 100644
--- a/tools/libxl/libxl_nic.c
+++ b/tools/libxl/libxl_nic.c
@@ -237,6 +237,9 @@ static int libxl__set_xenstore_nic(libxl__gc *gc, uint32_t domid,
     flexarray_append(front, GCSPRINTF(
                                     LIBXL_MAC_FMT, LIBXL_MAC_BYTES(nic->mac)));
 
+    flexarray_append(front, "trusted");
+    flexarray_append(front, getenv("libxl_nic_backend_untrusted") ? "0" : "1");
+
     return 0;
 }
 
-- 
2.37.0

From ed1e0c364641a52fdfeac4b41f52f1c07479156c Mon Sep 17 00:00:00 2001
From: Roger Pau Monne <roger.pau@citrix.com>
Date: Fri, 8 Apr 2022 10:21:11 +0200
Subject: [PATCH] tools/libxl: report trusted backend status to frontends
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Allow administrators to notify a frontend driver that it's backend
counterpart is not to be trusted, so the frontend can deploy whatever
mitigations required in order to secure itself.

Allow such option for disk and network frontends only, as those are
the only hardened ones currently supported.

This is part of XSA-403

WARNING: this patch will never be applied to the intended
repository/branch because it breaks the libxl ABI.

Signed-off-by: Roger Pau Monné <roger.pau@citrix.com>
Reviewed-by: Anthony PERARD <anthony.perard@citrix.com>
---
 docs/man/xl-disk-configuration.5.pod    | 29 +++++++++++++++++++++++++
 docs/man/xl-network-configuration.5.pod |  9 ++++++++
 tools/libxl/check-xl-disk-parse         | 26 ++++++++++++++++++++++
 tools/libxl/check-xl-vif-parse          | 18 +++++++++++++++
 tools/libxl/libxl.h                     |  8 +++++++
 tools/libxl/libxl_disk.c                |  4 ++--
 tools/libxl/libxl_nic.c                 |  4 +++-
 tools/libxl/libxl_types.idl             |  6 +++--
 tools/libxl/libxlu_disk_l.l             |  3 +++
 tools/xl/xl_parse.c                     |  2 ++
 xen/include/public/io/blkif.h           |  8 +++++++
 xen/include/public/io/netif.h           |  6 +++++
 12 files changed, 118 insertions(+), 5 deletions(-)

diff --git a/docs/man/xl-disk-configuration.5.pod b/docs/man/xl-disk-configuration.5.pod
index 46feedb95e..af62a25683 100644
--- a/docs/man/xl-disk-configuration.5.pod
+++ b/docs/man/xl-disk-configuration.5.pod
@@ -344,6 +344,35 @@ can be used to disable "hole punching" for file based backends which
 were intentionally created non-sparse to avoid fragmentation of the
 file.
 
+=item B<trusted> / B<untrusted>
+
+=over 4
+
+=item Description
+
+Reports whether the backend should be trusted by the frontend
+
+=item Supported values
+
+trusted, untrusted
+
+=item Mandatory
+
+No
+
+=item Default value
+
+trusted
+
+=back
+
+An advisory setting for the frontend driver on whether the backend should be
+trusted.  The frontend should deploy whatever protections it has available to
+prevent an untrusted backend from accessing guest data not related to the I/O
+processing or causing malfunction to the frontend or the whole domain.
+
+Note frontends can ignore such recommendation.
+
 =back
 
 
diff --git a/docs/man/xl-network-configuration.5.pod b/docs/man/xl-network-configuration.5.pod
index 0ac24c4a18..d323cdacd9 100644
--- a/docs/man/xl-network-configuration.5.pod
+++ b/docs/man/xl-network-configuration.5.pod
@@ -249,3 +249,12 @@ on the underlying netback implementation.
 Specifies the devid manually instead of letting xl choose the lowest index available.
 
 NOTE: This should not be set unless you have a reason to.
+
+=head2 trusted / untrusted
+
+An advisory setting for the frontend driver on whether the backend should be
+trusted.  The frontend should deploy whatever protections it has available to
+prevent an untrusted backend from accessing guest data not related to the I/O
+processing or causing malfunction to the frontend or the whole domain.
+
+Note frontends can ignore such recommendation.
diff --git a/tools/libxl/check-xl-disk-parse b/tools/libxl/check-xl-disk-parse
index 643f4f4ecb..18fb66940a 100755
--- a/tools/libxl/check-xl-disk-parse
+++ b/tools/libxl/check-xl-disk-parse
@@ -178,4 +178,30 @@ disk: {
 END
 one 0  cdrom no-discard vdev=hda target=/some/disk/image.iso
 
+# test setting trusted
+expected <<END
+disk: {
+    "pdev_path": "/some/disk/image.raw",
+    "vdev": "hda",
+    "format": "raw",
+    "readwrite": 1,
+    "trusted": "True"
+}
+
+END
+one 0  trusted vdev=hda target=/some/disk/image.raw
+
+# test setting untrusted
+expected <<END
+disk: {
+    "pdev_path": "/some/disk/image.raw",
+    "vdev": "hda",
+    "format": "raw",
+    "readwrite": 1,
+    "trusted": "False"
+}
+
+END
+one 0  untrusted vdev=hda target=/some/disk/image.raw
+
 complete
diff --git a/tools/libxl/check-xl-vif-parse b/tools/libxl/check-xl-vif-parse
index 02c6dbaeb6..66f6fcbdb3 100755
--- a/tools/libxl/check-xl-vif-parse
+++ b/tools/libxl/check-xl-vif-parse
@@ -210,4 +210,22 @@ one $e rate=4296MB/s@4294s
 expected </dev/null
 one $e rate=@
 
+# test trusted setting
+expected <<END
+vif: {
+    "trusted": "True"
+}
+
+END
+one 0 trusted
+
+# test untrusted setting
+expected <<END
+vif: {
+    "trusted": "False"
+}
+
+END
+one 0 untrusted
+
 complete
diff --git a/tools/libxl/libxl.h b/tools/libxl/libxl.h
index 1cd6c38e83..865506d1dd 100644
--- a/tools/libxl/libxl.h
+++ b/tools/libxl/libxl.h
@@ -438,6 +438,14 @@
  */
 #define LIBXL_HAVE_CREATEINFO_PASSTHROUGH 1
 
+/*
+ * LIBXL_HAVE_{DISK,NIC}_TRUSTED indicates that the libxl_device_disk and
+ * libxl_device_nic structs have a field to signal whether the backend of the
+ * device is to be trusted.  Such information is propagated to the frontend.
+ */
+#define LIBXL_HAVE_DISK_TRUSTED 1
+#define LIBXL_HAVE_NIC_TRUSTED 1
+
 /*
  * libxl ABI compatibility
  *
diff --git a/tools/libxl/libxl_disk.c b/tools/libxl/libxl_disk.c
index 36862bbbcb..5b5041d391 100644
--- a/tools/libxl/libxl_disk.c
+++ b/tools/libxl/libxl_disk.c
@@ -159,6 +159,7 @@ static int libxl__device_disk_setdefault(libxl__gc *gc, uint32_t domid,
     libxl_defbool_setdefault(&disk->discard_enable, !!disk->readwrite);
     libxl_defbool_setdefault(&disk->colo_enable, false);
     libxl_defbool_setdefault(&disk->colo_restore_enable, false);
+    libxl_defbool_setdefault(&disk->trusted, true);
 
     rc = libxl__resolve_domid(gc, disk->backend_domname, &disk->backend_domid);
     if (rc < 0) return rc;
@@ -396,8 +397,7 @@ static void device_disk_add(libxl__egc *egc, uint32_t domid,
         flexarray_append(front, "device-type");
         flexarray_append(front, disk->is_cdrom ? "cdrom" : "disk");
         flexarray_append(front, "trusted");
-        flexarray_append(front, getenv("libxl_disk_backend_untrusted") ? "0"
-                                                                       : "1");
+        flexarray_append(front, libxl_defbool_val(disk->trusted) ? "1" : "0");
 
         /*
          * Old PV kernel disk frontends before 2.6.26 rely on tool stack to
diff --git a/tools/libxl/libxl_nic.c b/tools/libxl/libxl_nic.c
index 4d09fb8b46..a93f5a2d64 100644
--- a/tools/libxl/libxl_nic.c
+++ b/tools/libxl/libxl_nic.c
@@ -113,6 +113,8 @@ static int libxl__device_nic_setdefault(libxl__gc *gc, uint32_t domid,
         abort();
     }
 
+    libxl_defbool_setdefault(&nic->trusted, true);
+
     return rc;
 }
 
@@ -238,7 +240,7 @@ static int libxl__set_xenstore_nic(libxl__gc *gc, uint32_t domid,
                                     LIBXL_MAC_FMT, LIBXL_MAC_BYTES(nic->mac)));
 
     flexarray_append(front, "trusted");
-    flexarray_append(front, getenv("libxl_nic_backend_untrusted") ? "0" : "1");
+    flexarray_append(front, libxl_defbool_val(nic->trusted) ? "1" : "0");
 
     return 0;
 }
diff --git a/tools/libxl/libxl_types.idl b/tools/libxl/libxl_types.idl
index 9d3f05f399..e391dd8911 100644
--- a/tools/libxl/libxl_types.idl
+++ b/tools/libxl/libxl_types.idl
@@ -698,7 +698,8 @@ libxl_device_disk = Struct("device_disk", [
     ("colo_port", integer),
     ("colo_export", string),
     ("active_disk", string),
-    ("hidden_disk", string)
+    ("hidden_disk", string),
+    ("trusted", libxl_defbool),
     ])
 
 libxl_device_nic = Struct("device_nic", [
@@ -766,7 +767,8 @@ libxl_device_nic = Struct("device_nic", [
     ("colo_filter_sec_redirector1_outdev", string),
     ("colo_filter_sec_rewriter0_queue", string),
     ("colo_checkpoint_host", string),
-    ("colo_checkpoint_port", string)
+    ("colo_checkpoint_port", string),
+    ("trusted", libxl_defbool),
     ])
 
 libxl_device_pci = Struct("device_pci", [
diff --git a/tools/libxl/libxlu_disk_l.l b/tools/libxl/libxlu_disk_l.l
index 7a46f4a30c..082bb2ce78 100644
--- a/tools/libxl/libxlu_disk_l.l
+++ b/tools/libxl/libxlu_disk_l.l
@@ -208,6 +208,9 @@ colo-export=[^,]*,?	{ STRIP(','); SAVESTRING("colo-export", colo_export, FROMEQU
 active-disk=[^,]*,?	{ STRIP(','); SAVESTRING("active-disk", active_disk, FROMEQUALS); }
 hidden-disk=[^,]*,?	{ STRIP(','); SAVESTRING("hidden-disk", hidden_disk, FROMEQUALS); }
 
+trusted,?		{ libxl_defbool_set(&DPC->disk->trusted, true); }
+untrusted,?		{ libxl_defbool_set(&DPC->disk->trusted, false); }
+
  /* the target magic parameter, eats the rest of the string */
 
 target=.*	{ STRIP(','); SAVESTRING("target", pdev_path, FROMEQUALS); }
diff --git a/tools/xl/xl_parse.c b/tools/xl/xl_parse.c
index 34ac20773d..20aae80b59 100644
--- a/tools/xl/xl_parse.c
+++ b/tools/xl/xl_parse.c
@@ -563,6 +563,8 @@ int parse_nic_config(libxl_device_nic *nic, XLU_Config **config, char *token)
         fprintf(stderr, "the accel parameter for vifs is currently not supported\n");
     } else if (MATCH_OPTION("devid", token, oparg)) {
         nic->devid = parse_ulong(oparg);
+    } else if (!strcmp("untrusted", token)) {
+        libxl_defbool_set(&nic->trusted, false);
     } else {
         fprintf(stderr, "unrecognized argument `%s'\n", token);
         return 1;
diff --git a/xen/include/public/io/blkif.h b/xen/include/public/io/blkif.h
index 4cdba79aba..ab863f175a 100644
--- a/xen/include/public/io/blkif.h
+++ b/xen/include/public/io/blkif.h
@@ -363,6 +363,14 @@
  *      that the frontend requires that the logical block size is 512 as it
  *      is hardcoded (which is the case in some frontend implementations).
  *
+ * trusted
+ *      Values:         0/1 (boolean)
+ *      Default value:  1
+ *
+ *      A value of "0" indicates that the frontend should not trust the
+ *      backend, and should deploy whatever measures available to protect from
+ *      a malicious backend on the other end.
+ *
  *------------------------- Virtual Device Properties -------------------------
  *
  * device-type
diff --git a/xen/include/public/io/netif.h b/xen/include/public/io/netif.h
index 9fcf91a2fe..3af987d262 100644
--- a/xen/include/public/io/netif.h
+++ b/xen/include/public/io/netif.h
@@ -160,6 +160,12 @@
  * be applied if it is set.
  */
 
+/*
+ * The setting of "trusted" node to "0" in the frontend path signals that the
+ * frontend should not trust the backend, and should deploy whatever measures
+ * available to protect from a malicious backend on the other end.
+ */
+
 /*
  * Control ring
  * ============
-- 
2.37.0

From 8c6791798de4b68923e422f565581af1ee74124c Mon Sep 17 00:00:00 2001
From: Roger Pau Monne <roger.pau@citrix.com>
Date: Thu, 30 Jun 2022 14:35:35 +0200
Subject: [PATCH] tools/libxl: env variable to signal whether disk/nic backend
 is trusted
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Introduce support in libxl for fetching the default backend trusted
option for disk and nic devices.

Users can set libxl_{disk,nic}_backend_untrusted environment variable
to notify libxl of whether the backends for disk and nic devices
should be trusted.  Such information is passed into the frontend so it
can take the appropriate measures.

This is part of XSA-403.

Signed-off-by: Roger Pau Monné <roger.pau@citrix.com>
---
 tools/libs/light/libxl_disk.c | 3 +++
 tools/libs/light/libxl_nic.c  | 3 +++
 2 files changed, 6 insertions(+)

diff --git a/tools/libs/light/libxl_disk.c b/tools/libs/light/libxl_disk.c
index 93936d0dd0..0aaf6afce8 100644
--- a/tools/libs/light/libxl_disk.c
+++ b/tools/libs/light/libxl_disk.c
@@ -395,6 +395,9 @@ static void device_disk_add(libxl__egc *egc, uint32_t domid,
         flexarray_append(front, GCSPRINTF("%d", device->devid));
         flexarray_append(front, "device-type");
         flexarray_append(front, disk->is_cdrom ? "cdrom" : "disk");
+        flexarray_append(front, "trusted");
+        flexarray_append(front, getenv("libxl_disk_backend_untrusted") ? "0"
+                                                                       : "1");
 
         /*
          * Old PV kernel disk frontends before 2.6.26 rely on tool stack to
diff --git a/tools/libs/light/libxl_nic.c b/tools/libs/light/libxl_nic.c
index 0b9e70c9d1..34c3fe6df0 100644
--- a/tools/libs/light/libxl_nic.c
+++ b/tools/libs/light/libxl_nic.c
@@ -255,6 +255,9 @@ static int libxl__set_xenstore_nic(libxl__gc *gc, uint32_t domid,
     flexarray_append(back, "hotplug-status");
     flexarray_append(back, "");
 
+    flexarray_append(front, "trusted");
+    flexarray_append(front, getenv("libxl_nic_backend_untrusted") ? "0" : "1");
+
     return 0;
 }
 
-- 
2.37.0

From c4eb527ce4e66b4229e302d3079907ead9e50477 Mon Sep 17 00:00:00 2001
From: Roger Pau Monne <roger.pau@citrix.com>
Date: Fri, 8 Apr 2022 10:21:11 +0200
Subject: [PATCH] tools/libxl: report trusted backend status to frontends
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Allow administrators to notify a frontend driver that it's backend
counterpart is not to be trusted, so the frontend can deploy whatever
mitigations required in order to secure itself.

Allow such option for disk and network frontends only, as those are
the only hardened ones currently supported.

This is part of XSA-403

WARNING: this patch will never be applied to the intended
repository/branch because it breaks the libxl ABI.

Signed-off-by: Roger Pau Monné <roger.pau@citrix.com>
Reviewed-by: Anthony PERARD <anthony.perard@citrix.com>
---
 docs/man/xl-disk-configuration.5.pod.in    | 29 ++++++++++++++++++++++
 docs/man/xl-network-configuration.5.pod.in |  9 +++++++
 tools/include/libxl.h                      |  8 ++++++
 tools/libs/light/libxl_disk.c              |  4 +--
 tools/libs/light/libxl_nic.c               |  4 ++-
 tools/libs/light/libxl_types.idl           |  6 +++--
 tools/libs/util/libxlu_disk_l.l            |  3 +++
 tools/xl/check-xl-disk-parse               | 26 +++++++++++++++++++
 tools/xl/check-xl-vif-parse                | 18 ++++++++++++++
 tools/xl/xl_parse.c                        |  4 +++
 xen/include/public/io/blkif.h              |  8 ++++++
 xen/include/public/io/netif.h              |  6 +++++
 12 files changed, 120 insertions(+), 5 deletions(-)

diff --git a/docs/man/xl-disk-configuration.5.pod.in b/docs/man/xl-disk-configuration.5.pod.in
index 71d0e86e3d..95d039655a 100644
--- a/docs/man/xl-disk-configuration.5.pod.in
+++ b/docs/man/xl-disk-configuration.5.pod.in
@@ -344,6 +344,35 @@ can be used to disable "hole punching" for file based backends which
 were intentionally created non-sparse to avoid fragmentation of the
 file.
 
+=item B<trusted> / B<untrusted>
+
+=over 4
+
+=item Description
+
+Reports whether the backend should be trusted by the frontend
+
+=item Supported values
+
+trusted, untrusted
+
+=item Mandatory
+
+No
+
+=item Default value
+
+trusted
+
+=back
+
+An advisory setting for the frontend driver on whether the backend should be
+trusted.  The frontend should deploy whatever protections it has available to
+prevent an untrusted backend from accessing guest data not related to the I/O
+processing or causing malfunction to the frontend or the whole domain.
+
+Note frontends can ignore such recommendation.
+
 =back
 
 
diff --git a/docs/man/xl-network-configuration.5.pod.in b/docs/man/xl-network-configuration.5.pod.in
index cf92d7960c..f3e379bcf8 100644
--- a/docs/man/xl-network-configuration.5.pod.in
+++ b/docs/man/xl-network-configuration.5.pod.in
@@ -258,3 +258,12 @@ NOTE: This should not be set unless you have a reason to.
 Specifies the MTU (i.e. the maximum size of an IP payload, exclusing headers). The
 default value is 1500 but, if the VIF is attached to a bridge, it will be set to match
 unless overridden by this parameter.
+
+=head2 trusted / untrusted
+
+An advisory setting for the frontend driver on whether the backend should be
+trusted.  The frontend should deploy whatever protections it has available to
+prevent an untrusted backend from accessing guest data not related to the I/O
+processing or causing malfunction to the frontend or the whole domain.
+
+Note frontends can ignore such recommendation.
diff --git a/tools/include/libxl.h b/tools/include/libxl.h
index 2bbbd21f0b..705fc88452 100644
--- a/tools/include/libxl.h
+++ b/tools/include/libxl.h
@@ -527,6 +527,14 @@
  */
 #define LIBXL_HAVE_MAX_GRANT_VERSION 1
 
+/*
+ * LIBXL_HAVE_{DISK,NIC}_TRUSTED indicates that the libxl_device_disk and
+ * libxl_device_nic structs have a field to signal whether the backend of the
+ * device is to be trusted.  Such information is propagated to the frontend.
+ */
+#define LIBXL_HAVE_DISK_TRUSTED 1
+#define LIBXL_HAVE_NIC_TRUSTED 1
+
 /*
  * libxl ABI compatibility
  *
diff --git a/tools/libs/light/libxl_disk.c b/tools/libs/light/libxl_disk.c
index 0aaf6afce8..83a2d70fc9 100644
--- a/tools/libs/light/libxl_disk.c
+++ b/tools/libs/light/libxl_disk.c
@@ -159,6 +159,7 @@ static int libxl__device_disk_setdefault(libxl__gc *gc, uint32_t domid,
     libxl_defbool_setdefault(&disk->discard_enable, !!disk->readwrite);
     libxl_defbool_setdefault(&disk->colo_enable, false);
     libxl_defbool_setdefault(&disk->colo_restore_enable, false);
+    libxl_defbool_setdefault(&disk->trusted, true);
 
     rc = libxl__resolve_domid(gc, disk->backend_domname, &disk->backend_domid);
     if (rc < 0) return rc;
@@ -396,8 +397,7 @@ static void device_disk_add(libxl__egc *egc, uint32_t domid,
         flexarray_append(front, "device-type");
         flexarray_append(front, disk->is_cdrom ? "cdrom" : "disk");
         flexarray_append(front, "trusted");
-        flexarray_append(front, getenv("libxl_disk_backend_untrusted") ? "0"
-                                                                       : "1");
+        flexarray_append(front, libxl_defbool_val(disk->trusted) ? "1" : "0");
 
         /*
          * Old PV kernel disk frontends before 2.6.26 rely on tool stack to
diff --git a/tools/libs/light/libxl_nic.c b/tools/libs/light/libxl_nic.c
index 34c3fe6df0..d6bf06fc34 100644
--- a/tools/libs/light/libxl_nic.c
+++ b/tools/libs/light/libxl_nic.c
@@ -116,6 +116,8 @@ static int libxl__device_nic_setdefault(libxl__gc *gc, uint32_t domid,
         abort();
     }
 
+    libxl_defbool_setdefault(&nic->trusted, true);
+
     return rc;
 }
 
@@ -256,7 +258,7 @@ static int libxl__set_xenstore_nic(libxl__gc *gc, uint32_t domid,
     flexarray_append(back, "");
 
     flexarray_append(front, "trusted");
-    flexarray_append(front, getenv("libxl_nic_backend_untrusted") ? "0" : "1");
+    flexarray_append(front, libxl_defbool_val(nic->trusted) ? "1" : "0");
 
     return 0;
 }
diff --git a/tools/libs/light/libxl_types.idl b/tools/libs/light/libxl_types.idl
index 2a42da2f7d..89962218b4 100644
--- a/tools/libs/light/libxl_types.idl
+++ b/tools/libs/light/libxl_types.idl
@@ -712,7 +712,8 @@ libxl_device_disk = Struct("device_disk", [
     ("colo_port", integer),
     ("colo_export", string),
     ("active_disk", string),
-    ("hidden_disk", string)
+    ("hidden_disk", string),
+    ("trusted", libxl_defbool),
     ])
 
 libxl_device_nic = Struct("device_nic", [
@@ -780,7 +781,8 @@ libxl_device_nic = Struct("device_nic", [
     ("colo_filter_sec_redirector1_outdev", string),
     ("colo_filter_sec_rewriter0_queue", string),
     ("colo_checkpoint_host", string),
-    ("colo_checkpoint_port", string)
+    ("colo_checkpoint_port", string),
+    ("trusted", libxl_defbool),
     ])
 
 libxl_device_pci = Struct("device_pci", [
diff --git a/tools/libs/util/libxlu_disk_l.l b/tools/libs/util/libxlu_disk_l.l
index 3bd639aab0..e115460d99 100644
--- a/tools/libs/util/libxlu_disk_l.l
+++ b/tools/libs/util/libxlu_disk_l.l
@@ -208,6 +208,9 @@ colo-export=[^,]*,?	{ STRIP(','); SAVESTRING("colo-export", colo_export, FROMEQU
 active-disk=[^,]*,?	{ STRIP(','); SAVESTRING("active-disk", active_disk, FROMEQUALS); }
 hidden-disk=[^,]*,?	{ STRIP(','); SAVESTRING("hidden-disk", hidden_disk, FROMEQUALS); }
 
+trusted,?		{ libxl_defbool_set(&DPC->disk->trusted, true); }
+untrusted,?		{ libxl_defbool_set(&DPC->disk->trusted, false); }
+
  /* the target magic parameter, eats the rest of the string */
 
 target=.*	{ STRIP(','); SAVESTRING("target", pdev_path, FROMEQUALS); }
diff --git a/tools/xl/check-xl-disk-parse b/tools/xl/check-xl-disk-parse
index 643f4f4ecb..18fb66940a 100755
--- a/tools/xl/check-xl-disk-parse
+++ b/tools/xl/check-xl-disk-parse
@@ -178,4 +178,30 @@ disk: {
 END
 one 0  cdrom no-discard vdev=hda target=/some/disk/image.iso
 
+# test setting trusted
+expected <<END
+disk: {
+    "pdev_path": "/some/disk/image.raw",
+    "vdev": "hda",
+    "format": "raw",
+    "readwrite": 1,
+    "trusted": "True"
+}
+
+END
+one 0  trusted vdev=hda target=/some/disk/image.raw
+
+# test setting untrusted
+expected <<END
+disk: {
+    "pdev_path": "/some/disk/image.raw",
+    "vdev": "hda",
+    "format": "raw",
+    "readwrite": 1,
+    "trusted": "False"
+}
+
+END
+one 0  untrusted vdev=hda target=/some/disk/image.raw
+
 complete
diff --git a/tools/xl/check-xl-vif-parse b/tools/xl/check-xl-vif-parse
index 02c6dbaeb6..66f6fcbdb3 100755
--- a/tools/xl/check-xl-vif-parse
+++ b/tools/xl/check-xl-vif-parse
@@ -210,4 +210,22 @@ one $e rate=4296MB/s@4294s
 expected </dev/null
 one $e rate=@
 
+# test trusted setting
+expected <<END
+vif: {
+    "trusted": "True"
+}
+
+END
+one 0 trusted
+
+# test untrusted setting
+expected <<END
+vif: {
+    "trusted": "False"
+}
+
+END
+one 0 untrusted
+
 complete
diff --git a/tools/xl/xl_parse.c b/tools/xl/xl_parse.c
index b98c0de378..644ab8f8fd 100644
--- a/tools/xl/xl_parse.c
+++ b/tools/xl/xl_parse.c
@@ -565,6 +565,10 @@ int parse_nic_config(libxl_device_nic *nic, XLU_Config **config, char *token)
         nic->devid = parse_ulong(oparg);
     } else if (MATCH_OPTION("mtu", token, oparg)) {
         nic->mtu = parse_ulong(oparg);
+    } else if (!strcmp("trusted", token)) {
+        libxl_defbool_set(&nic->trusted, true);
+    } else if (!strcmp("untrusted", token)) {
+        libxl_defbool_set(&nic->trusted, false);
     } else {
         fprintf(stderr, "unrecognized argument `%s'\n", token);
         return 1;
diff --git a/xen/include/public/io/blkif.h b/xen/include/public/io/blkif.h
index 4cdba79aba..ab863f175a 100644
--- a/xen/include/public/io/blkif.h
+++ b/xen/include/public/io/blkif.h
@@ -363,6 +363,14 @@
  *      that the frontend requires that the logical block size is 512 as it
  *      is hardcoded (which is the case in some frontend implementations).
  *
+ * trusted
+ *      Values:         0/1 (boolean)
+ *      Default value:  1
+ *
+ *      A value of "0" indicates that the frontend should not trust the
+ *      backend, and should deploy whatever measures available to protect from
+ *      a malicious backend on the other end.
+ *
  *------------------------- Virtual Device Properties -------------------------
  *
  * device-type
diff --git a/xen/include/public/io/netif.h b/xen/include/public/io/netif.h
index 00dd258712..3509b096f8 100644
--- a/xen/include/public/io/netif.h
+++ b/xen/include/public/io/netif.h
@@ -160,6 +160,12 @@
  * be applied if it is set.
  */
 
+/*
+ * The setting of "trusted" node to "0" in the frontend path signals that the
+ * frontend should not trust the backend, and should deploy whatever measures
+ * available to protect from a malicious backend on the other end.
+ */
+
 /*
  * Control ring
  * ============
-- 
2.37.0

From d85839c78ae259bc6d5e3c2955ee1602c6cd6f00 Mon Sep 17 00:00:00 2001
From: Roger Pau Monne <roger.pau@citrix.com>
Date: Wed, 30 Mar 2022 09:03:48 +0200
Subject: [PATCH 1/4] xen/blkfront: fix leaking data in shared pages
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

When allocating pages to be used for shared communication with the
backend always zero them, this avoids leaking unintended data present
on the pages.

This is CVE-2022-26365, part of XSA-403.

Signed-off-by: Roger Pau Monné <roger.pau@citrix.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Juergen Gross <jgross@suse.com>
---
 drivers/block/xen-blkfront.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c
index 91d74dacb1b1..0f2b4cb952a5 100644
--- a/drivers/block/xen-blkfront.c
+++ b/drivers/block/xen-blkfront.c
@@ -313,7 +313,7 @@ static int fill_grant_buffer(struct blkfront_ring_info *rinfo, int num)
 			goto out_of_memory;
 
 		if (info->feature_persistent) {
-			granted_page = alloc_page(GFP_NOIO);
+			granted_page = alloc_page(GFP_NOIO | __GFP_ZERO);
 			if (!granted_page) {
 				kfree(gnt_list_entry);
 				goto out_of_memory;
@@ -1689,7 +1689,7 @@ static int setup_blkring(struct xenbus_device *dev,
 	for (i = 0; i < info->nr_ring_pages; i++)
 		rinfo->ring_ref[i] = GRANT_INVALID_REF;
 
-	sring = alloc_pages_exact(ring_size, GFP_NOIO);
+	sring = alloc_pages_exact(ring_size, GFP_NOIO | __GFP_ZERO);
 	if (!sring) {
 		xenbus_dev_fatal(dev, -ENOMEM, "allocating shared ring");
 		return -ENOMEM;
@@ -2208,7 +2208,8 @@ static int blkfront_setup_indirect(struct blkfront_ring_info *rinfo)
 
 		BUG_ON(!list_empty(&rinfo->indirect_pages));
 		for (i = 0; i < num; i++) {
-			struct page *indirect_page = alloc_page(GFP_KERNEL);
+			struct page *indirect_page = alloc_page(GFP_KERNEL |
+			                                        __GFP_ZERO);
 			if (!indirect_page)
 				goto out_of_memory;
 			list_add(&indirect_page->lru, &rinfo->indirect_pages);
-- 
2.36.0

From 26d56758b63dfe891b630d2b3dbcbcef71200e3b Mon Sep 17 00:00:00 2001
From: Roger Pau Monne <roger.pau@citrix.com>
Date: Wed, 6 Apr 2022 17:38:04 +0200
Subject: [PATCH 2/4] xen/netfront: fix leaking data in shared pages
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

When allocating pages to be used for shared communication with the
backend always zero them, this avoids leaking unintended data present
on the pages.

This is CVE-2022-33740, part of XSA-403.

Signed-off-by: Roger Pau Monné <roger.pau@citrix.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Juergen Gross <jgross@suse.com>
---
 drivers/net/xen-netfront.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c
index e2b4a1893a13..af3296171d86 100644
--- a/drivers/net/xen-netfront.c
+++ b/drivers/net/xen-netfront.c
@@ -273,7 +273,8 @@ static struct sk_buff *xennet_alloc_one_rx_buffer(struct netfront_queue *queue)
 	if (unlikely(!skb))
 		return NULL;
 
-	page = page_pool_dev_alloc_pages(queue->page_pool);
+	page = page_pool_alloc_pages(queue->page_pool,
+				     GFP_ATOMIC | __GFP_NOWARN | __GFP_ZERO);
 	if (unlikely(!page)) {
 		kfree_skb(skb);
 		return NULL;
-- 
2.36.0

From 59f46c68c442a348a5678a2ea874863579290143 Mon Sep 17 00:00:00 2001
From: Roger Pau Monne <roger.pau@citrix.com>
Date: Thu, 7 Apr 2022 12:20:06 +0200
Subject: [PATCH 3/4] xen/netfront: force data bouncing when backend is
 untrusted
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Bounce all data on the skbs to be transmitted into zeroed pages if the
backend is untrusted. This avoids leaking data present in the pages
shared with the backend but not part of the skb fragments.  This
requires introducing a new helper in order to allocate skbs with a
size multiple of XEN_PAGE_SIZE so we don't leak contiguous data on the
granted pages.

Reporting whether the backend is to be trusted can be done using a
module parameter, or from the xenstore frontend path as set by the
toolstack when adding the device.

This is CVE-2022-33741, part of XSA-403.

Signed-off-by: Roger Pau Monné <roger.pau@citrix.com>
Reviewed-by: Juergen Gross <jgross@suse.com>
---
 drivers/net/xen-netfront.c | 49 ++++++++++++++++++++++++++++++++++++--
 1 file changed, 47 insertions(+), 2 deletions(-)

diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c
index af3296171d86..e25bd689b32b 100644
--- a/drivers/net/xen-netfront.c
+++ b/drivers/net/xen-netfront.c
@@ -66,6 +66,10 @@ module_param_named(max_queues, xennet_max_queues, uint, 0644);
 MODULE_PARM_DESC(max_queues,
 		 "Maximum number of queues per virtual interface");
 
+static bool __read_mostly xennet_trusted = true;
+module_param_named(trusted, xennet_trusted, bool, 0644);
+MODULE_PARM_DESC(trusted, "Is the backend trusted");
+
 #define XENNET_TIMEOUT  (5 * HZ)
 
 static const struct ethtool_ops xennet_ethtool_ops;
@@ -175,6 +179,9 @@ struct netfront_info {
 	/* Is device behaving sane? */
 	bool broken;
 
+	/* Should skbs be bounced into a zeroed buffer? */
+	bool bounce;
+
 	atomic_t rx_gso_checksum_fixup;
 };
 
@@ -668,6 +675,33 @@ static int xennet_xdp_xmit(struct net_device *dev, int n,
 	return nxmit;
 }
 
+struct sk_buff *bounce_skb(const struct sk_buff *skb)
+{
+	unsigned int headerlen = skb_headroom(skb);
+	/* Align size to allocate full pages and avoid contiguous data leaks */
+	unsigned int size = ALIGN(skb_end_offset(skb) + skb->data_len,
+				  XEN_PAGE_SIZE);
+	struct sk_buff *n = alloc_skb(size, GFP_ATOMIC | __GFP_ZERO);
+
+	if (!n)
+		return NULL;
+
+	if (!IS_ALIGNED((uintptr_t)n->head, XEN_PAGE_SIZE)) {
+		WARN_ONCE(1, "misaligned skb allocated\n");
+		kfree_skb(n);
+		return NULL;
+	}
+
+	/* Set the data pointer */
+	skb_reserve(n, headerlen);
+	/* Set the tail pointer and length */
+	skb_put(n, skb->len);
+
+	BUG_ON(skb_copy_bits(skb, -headerlen, n->head, headerlen + skb->len));
+
+	skb_copy_header(n, skb);
+	return n;
+}
 
 #define MAX_XEN_SKB_FRAGS (65536 / XEN_PAGE_SIZE + 1)
 
@@ -721,9 +755,13 @@ static netdev_tx_t xennet_start_xmit(struct sk_buff *skb, struct net_device *dev
 
 	/* The first req should be at least ETH_HLEN size or the packet will be
 	 * dropped by netback.
+	 *
+	 * If the backend is not trusted bounce all data to zeroed pages to
+	 * avoid exposing contiguous data on the granted page not belonging to
+	 * the skb.
 	 */
-	if (unlikely(PAGE_SIZE - offset < ETH_HLEN)) {
-		nskb = skb_copy(skb, GFP_ATOMIC);
+	if (np->bounce || unlikely(PAGE_SIZE - offset < ETH_HLEN)) {
+		nskb = bounce_skb(skb);
 		if (!nskb)
 			goto drop;
 		dev_consume_skb_any(skb);
@@ -2247,6 +2285,10 @@ static int talk_to_netback(struct xenbus_device *dev,
 
 	info->netdev->irq = 0;
 
+	/* Check if backend is trusted. */
+	info->bounce = !xennet_trusted ||
+		       !xenbus_read_unsigned(dev->nodename, "trusted", 1);
+
 	/* Check if backend supports multiple queues */
 	max_queues = xenbus_read_unsigned(info->xbdev->otherend,
 					  "multi-queue-max-queues", 1);
@@ -2414,6 +2456,9 @@ static int xennet_connect(struct net_device *dev)
 		return err;
 	if (np->netback_has_xdp_headroom)
 		pr_info("backend supports XDP headroom\n");
+	if (np->bounce)
+		dev_info(&np->xbdev->dev,
+			 "bouncing transmitted data to zeroed pages\n");
 
 	/* talk_to_netback() sets the correct number of queues */
 	num_queues = dev->real_num_tx_queues;
-- 
2.36.0

From 61b37abec0d18dca4617d86a3d279f96114e27e2 Mon Sep 17 00:00:00 2001
From: Roger Pau Monne <roger.pau@citrix.com>
Date: Thu, 7 Apr 2022 13:04:24 +0200
Subject: [PATCH 4/4] xen/blkfront: force data bouncing when backend is
 untrusted
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Split the current bounce buffering logic used with persistent grants
into it's own option, and allow enabling it independently of
persistent grants.  This allows to reuse the same code paths to
perform the bounce buffering required to avoid leaking contiguous data
in shared pages not part of the request fragments.

Reporting whether the backend is to be trusted can be done using a
module parameter, or from the xenstore frontend path as set by the
toolstack when adding the device.

This is CVE-2022-33742, part of XSA-403.

Signed-off-by: Roger Pau Monné <roger.pau@citrix.com>
Reviewed-by: Juergen Gross <jgross@suse.com>
---
 drivers/block/xen-blkfront.c | 49 +++++++++++++++++++++++++-----------
 1 file changed, 34 insertions(+), 15 deletions(-)

diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c
index 0f2b4cb952a5..257706c3646e 100644
--- a/drivers/block/xen-blkfront.c
+++ b/drivers/block/xen-blkfront.c
@@ -152,6 +152,10 @@ static unsigned int xen_blkif_max_ring_order;
 module_param_named(max_ring_page_order, xen_blkif_max_ring_order, int, 0444);
 MODULE_PARM_DESC(max_ring_page_order, "Maximum order of pages to be used for the shared ring");
 
+static bool __read_mostly xen_blkif_trusted = true;
+module_param_named(trusted, xen_blkif_trusted, bool, 0644);
+MODULE_PARM_DESC(trusted, "Is the backend trusted");
+
 #define BLK_RING_SIZE(info)	\
 	__CONST_RING_SIZE(blkif, XEN_PAGE_SIZE * (info)->nr_ring_pages)
 
@@ -210,6 +214,7 @@ struct blkfront_info
 	unsigned int feature_discard:1;
 	unsigned int feature_secdiscard:1;
 	unsigned int feature_persistent:1;
+	unsigned int bounce:1;
 	unsigned int discard_granularity;
 	unsigned int discard_alignment;
 	/* Number of 4KB segments handled */
@@ -312,7 +317,7 @@ static int fill_grant_buffer(struct blkfront_ring_info *rinfo, int num)
 		if (!gnt_list_entry)
 			goto out_of_memory;
 
-		if (info->feature_persistent) {
+		if (info->bounce) {
 			granted_page = alloc_page(GFP_NOIO | __GFP_ZERO);
 			if (!granted_page) {
 				kfree(gnt_list_entry);
@@ -332,7 +337,7 @@ static int fill_grant_buffer(struct blkfront_ring_info *rinfo, int num)
 	list_for_each_entry_safe(gnt_list_entry, n,
 	                         &rinfo->grants, node) {
 		list_del(&gnt_list_entry->node);
-		if (info->feature_persistent)
+		if (info->bounce)
 			__free_page(gnt_list_entry->page);
 		kfree(gnt_list_entry);
 		i--;
@@ -378,7 +383,7 @@ static struct grant *get_grant(grant_ref_t *gref_head,
 	/* Assign a gref to this page */
 	gnt_list_entry->gref = gnttab_claim_grant_reference(gref_head);
 	BUG_ON(gnt_list_entry->gref == -ENOSPC);
-	if (info->feature_persistent)
+	if (info->bounce)
 		grant_foreign_access(gnt_list_entry, info);
 	else {
 		/* Grant access to the GFN passed by the caller */
@@ -402,7 +407,7 @@ static struct grant *get_indirect_grant(grant_ref_t *gref_head,
 	/* Assign a gref to this page */
 	gnt_list_entry->gref = gnttab_claim_grant_reference(gref_head);
 	BUG_ON(gnt_list_entry->gref == -ENOSPC);
-	if (!info->feature_persistent) {
+	if (!info->bounce) {
 		struct page *indirect_page;
 
 		/* Fetch a pre-allocated page to use for indirect grefs */
@@ -705,7 +710,7 @@ static int blkif_queue_rw_req(struct request *req, struct blkfront_ring_info *ri
 		.grant_idx = 0,
 		.segments = NULL,
 		.rinfo = rinfo,
-		.need_copy = rq_data_dir(req) && info->feature_persistent,
+		.need_copy = rq_data_dir(req) && info->bounce,
 	};
 
 	/*
@@ -983,11 +988,12 @@ static void xlvbd_flush(struct blkfront_info *info)
 {
 	blk_queue_write_cache(info->rq, info->feature_flush ? true : false,
 			      info->feature_fua ? true : false);
-	pr_info("blkfront: %s: %s %s %s %s %s\n",
+	pr_info("blkfront: %s: %s %s %s %s %s %s %s\n",
 		info->gd->disk_name, flush_info(info),
 		"persistent grants:", info->feature_persistent ?
 		"enabled;" : "disabled;", "indirect descriptors:",
-		info->max_indirect_segments ? "enabled;" : "disabled;");
+		info->max_indirect_segments ? "enabled;" : "disabled;",
+		"bounce buffer:", info->bounce ? "enabled" : "disabled;");
 }
 
 static int xen_translate_vdev(int vdevice, int *minor, unsigned int *offset)
@@ -1209,7 +1215,7 @@ static void blkif_free_ring(struct blkfront_ring_info *rinfo)
 	if (!list_empty(&rinfo->indirect_pages)) {
 		struct page *indirect_page, *n;
 
-		BUG_ON(info->feature_persistent);
+		BUG_ON(info->bounce);
 		list_for_each_entry_safe(indirect_page, n, &rinfo->indirect_pages, lru) {
 			list_del(&indirect_page->lru);
 			__free_page(indirect_page);
@@ -1226,7 +1232,7 @@ static void blkif_free_ring(struct blkfront_ring_info *rinfo)
 							  0UL);
 				rinfo->persistent_gnts_c--;
 			}
-			if (info->feature_persistent)
+			if (info->bounce)
 				__free_page(persistent_gnt->page);
 			kfree(persistent_gnt);
 		}
@@ -1247,7 +1253,7 @@ static void blkif_free_ring(struct blkfront_ring_info *rinfo)
 		for (j = 0; j < segs; j++) {
 			persistent_gnt = rinfo->shadow[i].grants_used[j];
 			gnttab_end_foreign_access(persistent_gnt->gref, 0UL);
-			if (info->feature_persistent)
+			if (info->bounce)
 				__free_page(persistent_gnt->page);
 			kfree(persistent_gnt);
 		}
@@ -1437,7 +1443,7 @@ static int blkif_completion(unsigned long *id,
 	data.s = s;
 	num_sg = s->num_sg;
 
-	if (bret->operation == BLKIF_OP_READ && info->feature_persistent) {
+	if (bret->operation == BLKIF_OP_READ && info->bounce) {
 		for_each_sg(s->sg, sg, num_sg, i) {
 			BUG_ON(sg->offset + sg->length > PAGE_SIZE);
 
@@ -1496,7 +1502,7 @@ static int blkif_completion(unsigned long *id,
 				 * Add the used indirect page back to the list of
 				 * available pages for indirect grefs.
 				 */
-				if (!info->feature_persistent) {
+				if (!info->bounce) {
 					indirect_page = s->indirect_grants[i]->page;
 					list_add(&indirect_page->lru, &rinfo->indirect_pages);
 				}
@@ -1787,6 +1793,10 @@ static int talk_to_blkback(struct xenbus_device *dev,
 	if (!info)
 		return -ENODEV;
 
+	/* Check if backend is trusted. */
+	info->bounce = !xen_blkif_trusted ||
+		       !xenbus_read_unsigned(dev->nodename, "trusted", 1);
+
 	max_page_order = xenbus_read_unsigned(info->xbdev->otherend,
 					      "max-ring-page-order", 0);
 	ring_page_order = min(xen_blkif_max_ring_order, max_page_order);
@@ -2198,10 +2208,10 @@ static int blkfront_setup_indirect(struct blkfront_ring_info *rinfo)
 	if (err)
 		goto out_of_memory;
 
-	if (!info->feature_persistent && info->max_indirect_segments) {
+	if (!info->bounce && info->max_indirect_segments) {
 		/*
-		 * We are using indirect descriptors but not persistent
-		 * grants, we need to allocate a set of pages that can be
+		 * We are using indirect descriptors but don't have a bounce
+		 * buffer, we need to allocate a set of pages that can be
 		 * used for mapping indirect grefs
 		 */
 		int num = INDIRECT_GREFS(grants) * BLK_RING_SIZE(info);
@@ -2302,6 +2312,8 @@ static void blkfront_gather_backend_features(struct blkfront_info *info)
 		info->feature_persistent =
 			!!xenbus_read_unsigned(info->xbdev->otherend,
 					       "feature-persistent", 0);
+	if (info->feature_persistent)
+		info->bounce = true;
 
 	indirect_segments = xenbus_read_unsigned(info->xbdev->otherend,
 					"feature-max-indirect-segments", 0);
@@ -2570,6 +2582,13 @@ static void blkfront_delay_work(struct work_struct *work)
 	struct blkfront_info *info;
 	bool need_schedule_work = false;
 
+	/*
+	 * Note that when using bounce buffers but not persistent grants
+	 * there's no need to run blkfront_delay_work because grants are
+	 * revoked in blkif_completion or else an error is reported and the
+	 * connection is closed.
+	 */
+
 	mutex_lock(&blkfront_mutex);
 
 	list_for_each_entry(info, &info_list, info_list) {
-- 
2.36.0