@@ -1842,6 +1842,20 @@ Run the device model as user "username", instead of
xen-qemudepriv-domid$domid or xen-qemudepriv-shared or root. The
default is to use the first of these users which exists.
+=item B<device_model_restrict=BOOLEAN>
+
+Restrict the device model's access to hypervisor facilities (such as
+xenstore). The default is true if device_model_user is not `root` and
+the qemu in use supports this option (ie, when the restriction is both
+possible and beneficial), or false otherwise.
+
+If the option is set to true (1) but the restriction is not possible
+or not effective, the domain configuration is rejected.
+
+This option is ignored when a stub domain device model is in use,
+because in that situation the device model is restricted by virtue of
+being in its own domain.
+
=back
=head2 Keymaps
@@ -339,6 +339,13 @@ A PV console backend. Described in [console.txt](console.txt)
Information relating to device models running in the domain. $DOMID is
the target domain of the device model.
+#### ~/device-model/$DOMID/physmap [w]
+
+Information about an HVM domain's physical memory map. This is
+written as well as read by device models which may run at the same
+privilege level of the guest domain. When the device model ruus with
+system privilege, this path is INTERNAL.
+
#### ~/device-model/$DOMID[/$EMULATOR_ID]/* [INTERNAL]
Information relating to device models running in the domain. $DOMID is
@@ -478,6 +478,49 @@ static int domcreate_setdefault_dm_user(libxl__gc *gc,
return rc;
}
+static int domcreate_setdefault_dm_restrict(libxl__gc *gc,
+ libxl__domain_create_state *dcs)
+{
+ /* convenience aliases */
+ libxl_domain_config *const d_config = dcs->guest_config;
+ libxl_domain_build_info *b_info = &d_config->b_info;
+
+ if (!libxl_defbool_is_default(b_info->device_model_restrict) &&
+ !libxl_defbool_val(b_info->device_model_restrict))
+ /* explicitly false */
+ return 0;
+
+ if (b_info->type != LIBXL_DOMAIN_TYPE_HVM ||
+ libxl_defbool_val(b_info->device_model_stubdomain)) {
+ /* in theory we don't care, so default it to true for
+ * the benefit of future callers or in case of bugs */
+ libxl_defbool_setdefault(&b_info->device_model_restrict, 1);
+ return 0;
+ }
+
+ const char *dm = libxl__domain_device_model(gc, b_info);
+
+ const char *cannot_restrict =
+ !strcmp(b_info->device_model_user, "root")
+ ? "device model user is root" :
+ !libxl__dm_supported(gc, dm, libxl__dm_support_check__xsrestrict)
+ ? "device model does not support xs_restrict" :
+ !libxl__dm_supported(gc, dm, libxl__dm_support_check__emulator_id)
+ ? "device model does not support emulator_id" :
+ 0;
+
+ libxl_defbool_setdefault(&b_info->device_model_restrict, !cannot_restrict);
+
+ if (libxl_defbool_val(b_info->device_model_restrict) &&
+ cannot_restrict) {
+ LOG(ERROR, "device model restriction desired but not possible: %s",
+ cannot_restrict);
+ return ERROR_INVAL;
+ }
+
+ return 0;
+}
+
static void init_console_info(libxl__gc *gc,
libxl__device_console *console,
int dev_num)
@@ -1075,11 +1118,15 @@ static void domcreate_dm_support_checked(libxl__egc *egc,
rc = domcreate_setdefault_dm_user(gc, dcs);
if (rc) goto out;
+ rc = domcreate_setdefault_dm_restrict(gc, dcs);
+ if (rc) goto out;
+
/* run two qemus? */
if (d_config->c_info.type == LIBXL_DOMAIN_TYPE_HVM &&
!libxl_defbool_val(d_config->b_info.device_model_stubdomain) &&
- b_info->device_model_user &&
- strcmp(b_info->device_model_user, "root")) {
+ ((b_info->device_model_user &&
+ strcmp(b_info->device_model_user, "root")) ||
+ libxl_defbool_val(d_config->b_info.device_model_restrict))) {
rc = libxl__dm_emuidmap_add(gc, domid, b_state, EMUID_SPLIT);
if (rc) goto out;
}
@@ -420,6 +420,14 @@ static int libxl__build_device_model_args_old(libxl__gc *gc,
b_info->device_model_user);
return ERROR_INVAL;
}
+ if (libxl_defbool_val(b_info->device_model_restrict) &&
+ !libxl_defbool_val(b_info->device_model_stubdomain)) {
+ /* The dm support check ought to prevent this, but in case
+ * someone has done something odd, we double check. */
+ LOG(ERROR,
+ "device_model_restrict not supported by qemu-xen-traditional");
+ return ERROR_INVAL;
+ }
flexarray_vappend(dm_args, dm,
"-d", GCSPRINTF("%d", domid), NULL);
@@ -1238,8 +1246,14 @@ static int libxl__build_device_model_args_new(libxl__gc *gc,
}
if (state->emuidmap & (1u << EMUID_SPLIT)) {
flexarray_append(dm_args, "-xenopts");
- flexarray_append(dm_args,
- GCSPRINTF("emulator_id=%u", emuid));
+ flexarray_append(dm_args, GCSPRINTF("%semulator_id=%u",
+ libxl_defbool_val(b_info->device_model_restrict)
+ ? "xsrestrict=on," : "",
+ emuid));
+ } else {
+ /* xsrestrict only makes sense with split qemu because
+ * the pv devices need unrestricted access */
+ assert(!libxl_defbool_val(b_info->device_model_restrict));
}
}
flexarray_append(dm_args, NULL);
@@ -1760,11 +1774,17 @@ void libxl__spawn_local_dm(libxl__egc *egc, libxl__dm_spawn_state *dmss,
char **pass_stuff;
const char *dm;
int dm_state_fd = -1;
+ struct xs_permissions rwperm[2];
if (libxl_defbool_val(b_info->device_model_stubdomain)) {
abort();
}
+ rwperm[0].id = LIBXL_TOOLSTACK_DOMID;
+ rwperm[0].perms = XS_PERM_NONE;
+ rwperm[1].id = domid;
+ rwperm[1].perms = XS_PERM_WRITE;
+
rc = libxl__dm_emuidmap_add(gc, domid, state, emuid);
if (rc) goto out;
@@ -1804,6 +1824,12 @@ void libxl__spawn_local_dm(libxl__egc *egc, libxl__dm_spawn_state *dmss,
domid, emuid, "");
xs_mkdir(ctx->xsh, XBT_NULL, path);
+ if (libxl_defbool_val(b_info->device_model_restrict)) {
+ rc = libxl__xs_mknod(gc, XBT_NULL, GCSPRINTF("%s/physmap", path),
+ rwperm, 2);
+ if (rc) goto out;
+ }
+
if (b_info->type == LIBXL_DOMAIN_TYPE_HVM &&
b_info->device_model_version
== LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN_TRADITIONAL)
@@ -443,6 +443,7 @@ libxl_domain_build_info = Struct("domain_build_info",[
("device_model_ssidref", uint32),
("device_model_ssid_label", string),
("device_model_user", string),
+ ("device_model_restrict", libxl_defbool),
# extra parameters pass directly to qemu, NULL terminated
("extra", libxl_string_list),
@@ -2176,6 +2176,8 @@ skip_vfb:
}
}
+ xlu_cfg_get_defbool(config, "device_model_restrict",
+ &b_info->device_model_restrict, 0);
xlu_cfg_replace_string (config, "device_model_override",
&b_info->device_model, 0);