[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Xen-devel] [PATCH v10] run QEMU as non-root



On Thu, 2015-11-05 at 12:47 +0000, Stefano Stabellini wrote:
> diff --git a/docs/misc/qemu-deprivilege.txt b/docs/misc/qemu-
> deprivilege.txt
> new file mode 100644
> index 0000000..dde74ab
> --- /dev/null
> +++ b/docs/misc/qemu-deprivilege.txt
> @@ -0,0 +1,31 @@
> +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

I suppose we should integrate either this or suggestion #2 into osstest.
Will you send a patch?

I suppose ts-xen-install is the obvious place to do this, only quirk might
be making it idempotent (for convenience when running in standalone mode).
The adduser manpage suggests it already is:
   Â0ÂÂÂÂÂÂTheÂÂuser exists as specified. This can have 2 causes:
ÂÂÂÂÂÂÂÂÂÂÂÂÂÂThe user wasÂÂcreatedÂÂbyÂÂadduserÂÂorÂÂtheÂÂuserÂÂwas
ÂÂÂÂÂÂÂÂÂÂÂÂÂÂalreadyÂÂpresentÂÂonÂÂtheÂÂsystemÂÂbeforeÂÂadduser was
ÂÂÂÂÂÂÂÂÂÂÂÂÂÂinvoked. If adduser was returning 0 , invoking adduser
ÂÂÂÂÂÂÂÂÂÂÂÂÂÂaÂÂsecond time with the same parameters as before also
ÂÂÂÂÂÂÂÂÂÂÂÂÂÂreturns 0.

So hopefully that is trivial.

> 
> +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.
> diff --git a/tools/libxl/libxl.h b/tools/libxl/libxl.h
> index 168fedd..5edeb30 100644
> --- a/tools/libxl/libxl.h
> +++ b/tools/libxl/libxl.h
> @@ -199,6 +199,11 @@
> Â */
> Â#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.
> Â */
> diff --git a/tools/libxl/libxl_dm.c b/tools/libxl/libxl_dm.c
> index 9c9eaa3..151b6ed 100644
> --- a/tools/libxl/libxl_dm.c
> +++ b/tools/libxl/libxl_dm.c
> @@ -21,6 +21,8 @@
> Â
> Â#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)
> Â{
> @@ -722,6 +724,36 @@ libxl__detect_gfx_passthru_kind(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,
> @@ -740,9 +772,10 @@ static int
> libxl__build_device_model_args_new(libxl__gc *gc,
> ÂÂÂÂÂ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);
> @@ -1222,6 +1255,38 @@ static int
> libxl__build_device_model_args_new(libxl__gc *gc,
> ÂÂÂÂÂÂÂÂÂ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);
> diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
> index b00add0..952b668 100644
> --- a/tools/libxl/libxl_internal.h
> +++ b/tools/libxl/libxl_internal.h
> @@ -4018,6 +4018,11 @@ void libxl__bitmap_copy_best_effort(libxl__gc *gc,
> libxl_bitmap *dptr,
> ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ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
> Â
> Â/*
> diff --git a/tools/libxl/libxl_types.idl b/tools/libxl/libxl_types.idl
> index 4d78f86..6808f2b 100644
> --- a/tools/libxl/libxl_types.idl
> +++ b/tools/libxl/libxl_types.idl
> @@ -440,6 +440,7 @@ libxl_domain_build_info =
> Struct("domain_build_info",[
> ÂÂÂÂÂ("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),
> diff --git a/tools/libxl/xl_cmdimpl.c b/tools/libxl/xl_cmdimpl.c
> index 03442e1..2b6371d 100644
> --- a/tools/libxl/xl_cmdimpl.c
> +++ b/tools/libxl/xl_cmdimpl.c
> @@ -2201,6 +2201,9 @@ skip_vfb:
> ÂÂÂÂÂÂÂÂÂ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);ÂÂÂÂÂÂÂÂÂÂÂÂ\
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.