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

