systemctl enable xen-watchdog.service
+QEMU Deprivilege
+================
+It is recommended to run QEMU as non-root.
+See docs/misc/qemu-deprivilege.txt for an explanation on what you need
+to do at installation time to run QEMU as a dedicated user.
+
+
History of options
==================
an HVM device model only. Each element in the list is passed as an
option to the device-model.
+=item B<device_model_user="username">
+
+Run the device model as user "username", instead of
+xen-qemudepriv-domid$domid or xen-qemudepriv-shared or root.
+
=back
=head2 Keymaps
--- /dev/null
+For security reasons, libxl tries to pass a non-root username to QEMU as
+argument. During initialization QEMU calls setuid and setgid with the
+user ID and the group ID of the user passed as argument.
+Libxl looks for the following users in this order:
+
+1) a user named "xen-qemuuser-domid$domid",
+Where $domid is the domid of the domain being created.
+This requires the reservation of 65535 uids from xen-qemuuser-domid1
+to xen-qemuuser-domid65535. To use this mechanism, you might want to
+create a large number of users at installation time. For example:
+
+for ((i=1; i<65536; i++))
+do
+ adduser --no-create-home --system xen-qemuuser-domid$i
+done
+
+You might want to consider passing --group to adduser to create a new
+group for each new user.
+
+
+2) a user named "xen-qemuuser-shared"
+As a fall back if both 1) fails, libxl will use a single user for
+all QEMU instances. The user is named xen-qemuuser-shared. This is
+less secure but still better than running QEMU as root. Using this is as
+simple as creating just one more user on your host:
+
+adduser --no-create-home --system xen-qemuuser-shared
+
+
+3) root
+As a last resort, libxl will start QEMU as root.
*/
#define LIBXL_HAVE_DEVICETREE_PASSTHROUGH 1
+/*
+ * libxl_domain_build_info has device_model_user to specify the user to
+ * run the device model with. See docs/misc/qemu-deprivilege.txt.
+ */
+#define LIBXL_HAVE_DEVICE_MODEL_USER 1
+
/*
* libxl_domain_build_info has the arm.gic_version field.
*/
#include <xc_dom.h>
#include <xen/hvm/e820.h>
+#include <sys/types.h>
+#include <pwd.h>
static const char *libxl_tapif_script(libxl__gc *gc)
{
return LIBXL_GFX_PASSTHRU_KIND_DEFAULT;
}
+/* return 1 if the user was found, 0 if it was not, -1 on error */
+static int libxl__dm_runas_helper(libxl__gc *gc, const char *username)
+{
+ struct passwd pwd, *user = NULL;
+ char *buf = NULL;
+ long buf_size;
+ int ret;
+
+ buf_size = sysconf(_SC_GETPW_R_SIZE_MAX);
+ if (buf_size < 0) {
+ LOGE(ERROR, "sysconf(_SC_GETPW_R_SIZE_MAX) returned error %ld",
+ buf_size);
+ return ERROR_FAIL;
+ }
+
+ while (1) {
+ buf = libxl__realloc(gc, buf, buf_size);
+ ret = getpwnam_r(username, &pwd, buf, buf_size, &user);
+ if (ret == ERANGE) {
+ buf_size += 128;
+ continue;
+ }
+ if (ret != 0)
+ return ERROR_FAIL;
+ if (user != NULL)
+ return 1;
+ return 0;
+ }
+}
+
static int libxl__build_device_model_args_new(libxl__gc *gc,
const char *dm, int guest_domid,
const libxl_domain_config *guest_config,
const char *keymap = dm_keymap(guest_config);
char *machinearg;
flexarray_t *dm_args, *dm_envs;
- int i, connection, devid;
+ int i, connection, devid, ret;
uint64_t ram_size;
const char *path, *chardev;
+ char *user = NULL;
dm_args = flexarray_make(gc, 16, 1);
dm_envs = flexarray_make(gc, 16, 1);
default:
break;
}
+
+ if (b_info->device_model_user) {
+ user = b_info->device_model_user;
+ goto end_search;
+ }
+
+ user = libxl__sprintf(gc, "%s%d", LIBXL_QEMU_USER_BASE, guest_domid);
+ ret = libxl__dm_runas_helper(gc, user);
+ if (ret < 0)
+ return ret;
+ if (ret > 0)
+ goto end_search;
+
+ user = LIBXL_QEMU_USER_SHARED;
+ ret = libxl__dm_runas_helper(gc, user);
+ if (ret < 0)
+ return ret;
+ if (ret > 0) {
+ LOG(WARN, "Could not find user %s%d, falling back to %s",
+ LIBXL_QEMU_USER_BASE, guest_domid, LIBXL_QEMU_USER_SHARED);
+ goto end_search;
+ }
+
+ user = NULL;
+ LOG(WARN, "Could not find user %s, starting QEMU as root",
+ LIBXL_QEMU_USER_SHARED);
+
+end_search:
+ if (user != NULL && strcmp(user, "root")) {
+ flexarray_append(dm_args, "-runas");
+ flexarray_append(dm_args, user);
+ }
}
flexarray_append(dm_args, NULL);
*args = (char **) flexarray_contents(dm_args);
const libxl_bitmap *sptr);
int libxl__count_physical_sockets(libxl__gc *gc, int *sockets);
+
+
+#define LIBXL_QEMU_USER_PREFIX "xen-qemuuser"
+#define LIBXL_QEMU_USER_BASE LIBXL_QEMU_USER_PREFIX"-domid"
+#define LIBXL_QEMU_USER_SHARED LIBXL_QEMU_USER_PREFIX"-shared"
#endif
/*
("device_model", string),
("device_model_ssidref", uint32),
("device_model_ssid_label", string),
+ ("device_model_user", string),
# extra parameters pass directly to qemu, NULL terminated
("extra", libxl_string_list),
xlu_cfg_replace_string(config, "device_model_stubdomain_seclabel",
&b_info->device_model_ssid_label, 0);
+ xlu_cfg_replace_string(config, "device_model_user",
+ &b_info->device_model_user, 0);
+
#define parse_extra_args(type) \
e = xlu_cfg_get_list_as_string_list(config, "device_model_args"#type, \
&b_info->extra##type, 0); \